home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
VSCPPv8.zip
/
VACPP
/
IBMCPP
/
samples
/
TOOLKIT
/
MM
/
MMIOPROC
/
MMOTPROC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-17
|
87KB
|
1,713 lines
/********************** START OF SPECIFICATIONS *************************/
/* */
/* SOURCE FILE NAME: MMOTPROC.C */
/* */
/* DESCRIPTIVE NAME: Multi-Media I/O Procedure for M-Motion Video */
/* */
/* COPYRIGHT: */
/* Copyright (c) IBM Corporation 1990, 1993 */
/* All Rights Reserved */
/* */
/* STATUS: MMPM/2 Release 1.10 */
/* */
/* ABSTRACT: This file contains the MMIO */
/* IOProc for M-Motion Still Video files. */
/* */
/* This IOProc is intended to be a sample for how IOprocs */
/* can be written, and is most applicable to Image data. */
/* Note that there are many areas that are specific to the */
/* M-Motion Still Video Image file format. These sections */
/* and structures should be changed as necessary for use */
/* with other image file formats. */
/* */
/* Note also that this image IOProc uses large buffering */
/* schemes, due to the ordering of image data (top-down) */
/* in the file, whereas the MMIO function and messages rely */
/* on this data being made available in the normal OS/2 PM */
/* bottom-up form. This forces the IOproc to pre-read, */
/* buffer and flip image data before it can supply the data */
/* to the application. It must perform the reverse order */
/* when writing (get the data, buffer it, flip and write to */
/* to disk. */
/* */
/*********************** END OF SPECIFICATIONS **************************/
/************************************************************************/
/* Put all #defines here */
/************************************************************************/
#define INCL_32 /* force 32 bit compile */
#define INCL_GPIBITMAPS
#define INCL_DOSFILEMGR
#define INCL_WIN
#define INCL_GPI
#define INCL_PM
#define MEMCHECK
/************************************************************************/
/* Put all #includes here */
/************************************************************************/
#include <os2.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <os2medef.h>
#include <mmioos2.h>
#include "mmotproc.h"
/************************************************************************/
/* MMOT IOProc */
/* */
/* ARGUMENTS: */
/* */
/* PSZ pmmioStr - pointer to MMIOINFO block */
/* USHORT usMsg - MMIO message being sent */
/* LONG lParam1 - filename or other parameter depending on message */
/* LONG lParam2 - used with some messages as values */
/* */
/* */
/* RETURN: */
/* */
/* MMIOM_OPEN */
/* Success - MMIO_SUCCESS (0) */
/* Failure - MMIO_ERROR (-1) */
/* */
/* MMIOM_READ */
/* Success - Returns the number of bytes actually */
/* read. Return 0L if no more bytes can */
/* be read. */
/* Failure - MMIO_ERROR (-1) */
/* */
/* MMIOM_WRITE */
/* Success - Returns the number of bytes actually */
/* written. */
/* Failure - MMIO_ERROR (-1) */
/* */
/* MMIOM_SEEK */
/* Success - Returns the new file position */
/* Failure - MMIO_ERROR (-1) */
/* */
/* MMIOM_CLOSE */
/* Success - MMIO_SUCCESS (0) */
/* Failure - MMIO_ERROR (-1) */
/* Other - MMIO_WARNING, file was closed but the */
/* IOProc expected additional data */
/* */
/* MMIOM_GETFORMATNAME */
/* Success - Returns the number of bytes read into */
/* the buffer (size of format name) */
/* Failure - Return 0 */
/* */
/* MMIOM_GETFORMATINFO */
/* Success - MMIO_SUCCESS (0) */
/* Failure - MMIO_ERROR (-1) */
/* */
/* MMIOM_QUERYHEADERLENGTH */
/* Success - Returns the size of the header in bytes */
/* Failure - Return 0 */
/* */
/* MMIOM_IDENTIFYFILE */
/* Success - MMIO_SUCCESS (0) */
/* Failure - MMIO_ERROR (-1) */
/* */
/* MMIOM_GETHEADER */
/* Success - Returns number of bytes copied into */
/* the header structure. */
/* Failure - Return 0 */
/* Other - If length passed in was not large */
/* enough to hold header then, */
/* MMIOERR_INVALID_BUFFER_LENGTH is set */
/* in ulErrorRet. */
/* - If header is bad, */
/* MMIOERR_INVALID_STRUCTURE is set in */
/* ulErrorRet */
/* */
/* MMIOM_SETHEADER */
/* Success - Returns number of bytes written */
/* Failure - Return 0 */
/* Other - If header is bad, */
/* MMIOERR_INVALID_STRUCTURE is set in */
/* ulErrorRet */
/* */
/* DESCRIPTION: */
/* */
/* This routine will translate IBM M-Motion YUV Video data into */
/* OS/2 2.0 memory bitmap data and back again. The IOProc is part */
/* of OS/2 MultiMedia Extentions File Format Conversion Utility. */
/* */
/* GLOBAL VARS REFERENCED: */
/* */
/* None */
/* */
/* GLOBAL VARS MODIFIED: */
/* */
/* None */
/* */
/* NOTES: */
/* */
/* None */
/* */
/* SIDE EFFECTS: */
/* */
/* None */
/* */
/************************************************************************/
LONG EXPENTRY IOProc_Entry (PVOID pmmioStr,
USHORT usMsg,
LONG lParam1,
LONG lParam2)
{
PMMIOINFO pmmioinfo; /* MMIOINFO block */
pmmioinfo = (PMMIOINFO) pmmioStr;
switch (usMsg)
{
/*#############################################################*
* When Closing the file, perform the following:
* 1) Setup Variables
* 2) Process the Image buffer
* 3) Compress the Image to appropriate format
*#############################################################*/
case MMIOM_CLOSE:
{
/************************************************************
* Declare local variables.
************************************************************/
PMMFILESTATUS pVidInfo; /* MMotionIOProc instance data */
ULONG ulHeight; /* Image height */
USHORT usBitCount;
/* Image width, including overflow in 1bpp & 4bpp */
ULONG ulImgPelWidth;
PBYTE lpYUVLine; /* One line of packed YUV */
LONG lYUVBytesPerLine;
ULONG ulMaxPelWidth; /* # pels on 4-pel boundaries */
/* # pels on a YUV line in the output file */
ULONG ulYUVPelWidth;
ULONG ulRGBMaxBytesPerLine; /* #bytes on 4-pel bounds */
PBYTE lpRGBLine; /* One line of 24bit RGB */
PBYTE lpImgBufPtr; /* Current loc in RGB image buf*/
LONG lRGBBytesPerLine; /* #bytes on a line in image */
ULONG ulRowCount; /* loop counter */
LONG lBytesWritten; /* #bytes output on a write */
LONG lRetCode;
USHORT rc;
/***********************************************************
* Check for valid MMIOINFO block.
***********************************************************/
if (!pmmioinfo)
return (MMIO_ERROR);
/***********************************************************
* Set up our working file status variable.
***********************************************************/
pVidInfo = (PMMFILESTATUS)pmmioinfo->pExtraInfoStruct;
/***********************************************************
* Assume success for the moment....
***********************************************************/
lRetCode = MMIO_SUCCESS;
/************************************************************
* see if we are in Write mode and have a buffer to write out.
* We have no image buffer in UNTRANSLATED mode.
************************************************************/
if ((pmmioinfo->ulFlags & MMIO_WRITE) && (pVidInfo->lpImgBuf))
{
/*******************************************************
* The buffer should be in palettized or 24-bit RGB
* We must convert it to YUV to be written to the file.
*******************************************************
* The buffer should be complete. If not, then we
* should still close, but can flag an error to the
* user that the data may be corrupted. The only way
* we can estimate if this is true is to check the final
* position. If not at the end...
*******************************************************/
if (pVidInfo->lImgBytePos !=
(LONG)pVidInfo->ulImgTotalBytes)
{
lRetCode = MMIO_WARNING;
}
/*******************************************************
* Set up width and height of image in the buffer.
*******************************************************/
ulHeight = pVidInfo->mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cy;
usBitCount =
pVidInfo->mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cBitCount;
/*******************************************************
* Get the line width in YUV pels and packed bytes.
*******************************************************/
ulYUVPelWidth = pVidInfo->mmotHeader.mmXlen;
lYUVBytesPerLine = (LONG)(ulYUVPelWidth * 3) >> 1;
/*******************************************************
* This changes from OS/2 PM bottom-up bitmap form
* to M-Motion's top-down form. Flip all pad, boundary
* bytes as well
*******************************************************/
ImgBufferFlip ((PBYTE)pVidInfo->lpImgBuf,
pVidInfo->ulImgPaddedBytesPerLine,
ulHeight);
/*******************************************************
* Determine number of POSSIBLE pels on a line, tho some
* may be overflow in 1bpp and 4bpp modes.
*
* From that, we can calc the number of RGB pels we will
* create to represent this line.
*******************************************************/
ulImgPelWidth = (pVidInfo->ulImgPelBytesPerLine << 3) /
usBitCount;
lRGBBytesPerLine = ulImgPelWidth * 3;
/*******************************************************
* Ensure the width is on a 4-pel boundary, necessary for
* M-Motion. We will buffer with black
* *** THIS IS ONLY NECESSARY FOR M-MOTION IMAGES
*******************************************************/
if (ulImgPelWidth % 4)
ulMaxPelWidth = (((ulImgPelWidth >> 2) + 1) << 2);
else
ulMaxPelWidth = ulImgPelWidth;
/* #RGB bytes/line = #pels * 3 bytes/pel */
ulRGBMaxBytesPerLine = ulMaxPelWidth * 3;
/*******************************************************
* Create a buffer for one line of RGB data, accounting for
* the 4-pel boundary required. Extra bytes won't be used.
*******************************************************/
if (DosAllocMem ((PPVOID) &lpRGBLine,
ulRGBMaxBytesPerLine,
fALLOC))
return (MMIO_ERROR);
/*******************************************************
* Create a buffer for one line of YUV data.
*******************************************************/
if (DosAllocMem ((PPVOID) &lpYUVLine,
lYUVBytesPerLine,
fALLOC))
return (MMIO_ERROR);
/*******************************************************
* Zero out RGB buffer to cover for any extra black pels
* needed at the end.
*******************************************************/
memset (lpRGBLine, 0, ulRGBMaxBytesPerLine);
/*******************************************************
* Initialize start position of RGB buffer.
*******************************************************/
lpImgBufPtr = pVidInfo->lpImgBuf;
/*******************************************************
* Process Image Buffer - Save to file
* Place "your" processing code here, if full image
* buffering is performed.
* For MMotion:
* Loop
* 1.Convert and copy a line of 1bpp, 4bpp, 8 bpp or
* 24bpp data into a temporary 24 bpp RGB line.
* This line may contain overflow garbage
* pels from 1bpp and 4bpp modes (where
* width does not fall on even byte boundaries.)
* 2.Convert the temporary RGB line contents into a
* YUV line. ONLY that data necessary converted.
* Overflow from bitmap data ignored.
* 3.Write the YUV line to the file
*******************************************************/
for (ulRowCount = 0;
ulRowCount < ulHeight;
ulRowCount++)
{
/***************************************************
* Convert 1 line of Image data into RGB data
***************************************************/
switch (usBitCount)
{
case 1:
{
/* Convert 1bpp padded image buffer into 24-bit */
/* RGB line buffer, w/pads */
Convert1BitTo24Bit (
(PBYTE)lpImgBufPtr,
(PRGB) lpRGBLine,
(PRGB) &(pVidInfo->rgbPalette),
pVidInfo->ulImgPelBytesPerLine);
break;
}
case 4:
{
/* Convert data from app buffer into 24-bit and */
/* copy into image buffer */
Convert4BitTo24Bit (
(PBYTE)lpImgBufPtr,
(PRGB) lpRGBLine,
(PRGB) &(pVidInfo->rgbPalette),
pVidInfo->ulImgPelBytesPerLine);
break;
}
case 8:
{
/* Convert data from app buffer into 24-bit and */
/* copy into image buffer */
Convert8BitTo24Bit (
(PBYTE)lpImgBufPtr,
(PRGB) lpRGBLine,
(PRGB) &(pVidInfo->rgbPalette),
pVidInfo->ulImgPelBytesPerLine);
break;
}
case 24:
{
/* Copy raw RGB data from the image buffer into */
/* the temporary */
/* RGB line. Only copy those pels necessary. */
/* No conversion required */
memcpy ((PVOID) lpRGBLine,
(PVOID) lpImgBufPtr,
ulYUVPelWidth * 3);
break;
}
} /* end of Switch for Bit Conversion block */
/***************************************************
* Convert one line at a time from RGB to YUV.
***************************************************/
ConvertOneLineRGBtoYUV (lpRGBLine,
lpYUVLine,
ulYUVPelWidth);
/***************************************************
* Write out line of YUV data to the file.
***************************************************/
lBytesWritten = mmioWrite (pVidInfo->hmmioSS,
(PVOID) lpYUVLine,
lYUVBytesPerLine);
/* Check if error or EOF */
if (lBytesWritten != lYUVBytesPerLine)
{
lRetCode = lBytesWritten;
break;
}
/***************************************************
* Make sure bitmap image buffer pointer is correct
* for next line to be converted. Move forward ALL
* the bytes in the bitmap line, including overflow
* and pad bytes.
***************************************************/
lpImgBufPtr += pVidInfo->ulImgPaddedBytesPerLine;
}
/*******************************************************
* Free temp buffers.
*******************************************************/
if (lpRGBLine)
{
DosFreeMem ((PVOID) lpRGBLine);
}
if (lpYUVLine)
{
DosFreeMem ((PVOID) lpYUVLine);
}
} /* end IF WRITE & IMAGE BUFFER block */
/***********************************************************
* Free the RGB buffer, if it exists, that was created
* for the translated READ operations.
***********************************************************/
if (pVidInfo->lpRGBBuf)
{
DosFreeMem ((PVOID) pVidInfo->lpRGBBuf);
}
/***********************************************************
* Free the IMG buffer, if it exists, that was created
* for the translated WRITE operations.
***********************************************************/
if (pVidInfo->lpImgBuf)
{
DosFreeMem ((PVOID) pVidInfo->lpImgBuf);
}
/***********************************************************
* Close the file with mmioClose.
***********************************************************/
rc = mmioClose (pVidInfo->hmmioSS, 0);
DosFreeMem ((PVOID) pVidInfo);
if (rc != MMIO_SUCCESS)
return (rc);
return (lRetCode);
} /* end case of MMIOM_CLOSE */
/*#############################################################*
* Get the NLS format Information.
*#############################################################*/
case MMIOM_GETFORMATINFO:
{
/***********************************************************
* Declare local variables.
***********************************************************/
PMMFORMATINFO pmmformatinfo;
/************************************************************
* Set pointer to MMFORMATINFO structure.
************************************************************/
pmmformatinfo = (PMMFORMATINFO) lParam1;
/************************************************************
* Fill in the values for the MMFORMATINFO structure.
************************************************************/
pmmformatinfo->ulStructLen = sizeof (MMFORMATINFO);
pmmformatinfo->fccIOProc = FOURCC_MMOT;
pmmformatinfo->ulIOProcType = MMIO_IOPROC_FILEFORMAT;
pmmformatinfo->ulMediaType = MMIO_MEDIATYPE_IMAGE;
pmmformatinfo->ulFlags = MMIO_CANREADTRANSLATED |
MMIO_CANREADUNTRANSLATED |
MMIO_CANWRITETRANSLATED |
MMIO_CANWRITEUNTRANSLATED |
MMIO_CANREADWRITEUNTRANSLATED |
MMIO_CANSEEKTRANSLATED |
MMIO_CANSEEKUNTRANSLATED;
strcpy ((PSZ) pmmformatinfo->szDefaultFormatExt, pszMotionExt);
if (GetNLSData( &pmmformatinfo->ulCodePage,
&pmmformatinfo->ulLanguage ))
{
return( -1L );
}
if (GetFormatStringLength( FOURCC_MMOT,
&(pmmformatinfo->lNameLength) ))
{
return( -1L );
}
/************************************************************
* Return success back to the application.
************************************************************/
return (MMIO_SUCCESS);
} /* end case of MMIOM_GETFORMATINFO */
/*#############################################################*
* Get the NLS format name.
*#############################################################*/
case MMIOM_GETFORMATNAME:
{
LONG lBytesCopied;
/************************************************************
* Copy the M-Motion format string into buffer supplied by
* lParam1. Only put in the amount of my string up to the
* allocated amount which is in lParam2. Leave enough room
* for the NULL termination.
************************************************************/
lBytesCopied = GetFormatString( FOURCC_MMOT,
(char *)lParam1,
lParam2 );
return (lBytesCopied);
} /* end case of MMIOM_GETFORMATNAME */
/*#############################################################*
* Get the file header.
*#############################################################*/
case MMIOM_GETHEADER:
{
/************************************************************
* Declare local variables.
************************************************************/
PMMFILESTATUS pVidInfo;
/************************************************************
* Check for valid MMIOINFO block.
************************************************************/
if (!pmmioinfo)
return (0);
/************************************************************
* Set up our working file status variable.
************************************************************/
pVidInfo = (PMMFILESTATUS)pmmioinfo->pExtraInfoStruct;
/**************************************************
* Getheader only valid in READ or READ/WRITE mode.
* There is no header to get in WRITE mode. We
* must also have a valid file handle to read from
**************************************************/
if ((pmmioinfo->ulFlags & MMIO_WRITE) ||
(!(pVidInfo->hmmioSS)))
return (0);
/************************************************************
* Check for Translation mode.
************************************************************/
if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER))
{
/********************************************************
* Translation is off.
********************************************************/
if (lParam2 < sizeof (MMOTIONHEADER))
{
pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
return (0);
}
if (!lParam1)
{
pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
return (0);
}
/********************************************************
* Read in first 16 bytes to fill up MMotion header.
********************************************************/
memcpy ((PVOID) lParam1,
(PVOID)&pVidInfo->mmotHeader,
sizeof (MMOTIONHEADER));
/* Indicate that the header has been set, which */
/* is meaningless in read mode, but allows the */
/* application to do writes in read/write mode */
pVidInfo->bSetHeader = TRUE;
return (sizeof (MMOTIONHEADER));
} /* end IF NOT TRANSLATED block */
/******************
* TRANSLATION IS ON
******************/
if (lParam2 < sizeof (MMIMAGEHEADER))
{
pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
return (0);
}
if (!lParam1)
{
pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
return (0);
}
memcpy ((PVOID)lParam1,
(PVOID)&pVidInfo->mmImgHdr,
sizeof (MMIMAGEHEADER));
return (sizeof (MMIMAGEHEADER));
} /* end case of MMIOM_GETHEADER */
/*#############################################################*
* Identify whether this file can be processed.
*#############################################################*/
case MMIOM_IDENTIFYFILE:
{
/************************************************************
* Declare local variables.
************************************************************/
MMOTIONHEADER mmotHeader; /* MMotion structure variable*/
HMMIO hmmioTemp; /* MMIO File Handle */
ULONG ulWidth;
ULONG ulHeight;
ULONG ulRequiredFileLength;
ULONG ulActualFileLength;
BOOL fValidMMotionFile = FALSE;
ULONG ulTempFlags = MMIO_READ | MMIO_DENYWRITE |
MMIO_NOIDENTIFY;
/* flags used for temp open */
/* and close */
/************************************************************
* We need either a file name (lParam1) or file handle (lParam2)
************************************************************/
if (!lParam1 && !lParam2)
return (MMIO_ERROR);
/* Copy the file handle, assuming one was provided... */
hmmioTemp = (HMMIO)lParam2;
/************************************************************
* If no handle, then open the file using the string name
************************************************************/
if (!hmmioTemp)
{
if (!(hmmioTemp = mmioOpen ((PSZ) lParam1,
NULL,
ulTempFlags)))
{
return (MMIO_ERROR);
}
}
/************************************************************
* Read in enough bytes to check out file.
************************************************************/
if (sizeof (MMOTIONHEADER) !=
mmioRead (hmmioTemp,
(PVOID) &mmotHeader,
(ULONG) sizeof (MMOTIONHEADER)))
{
/********************************************************
* Fail so close file and then return.
********************************************************/
if (!lParam2) /* Don't close handle if provided to us */
mmioClose (hmmioTemp, 0);
return (MMIO_ERROR);
}
/************************************************************
* Close file before returning.
************************************************************/
if (!lParam2) /* Don't close handle if provided to us */
mmioClose (hmmioTemp, 0);
/************************************************************
* Check validity of file and return result.
************************************************************/
if (memcmp (mmotHeader.mmID, "YUV12C", 6) == 0)
{
ulWidth = mmotHeader.mmXlen;
ulHeight = mmotHeader.mmYlen;
/* Calculate what the length of the file SHOULD be based on the */
/* header contents */
ulRequiredFileLength = (((ulWidth >> 2) * 6) * ulHeight) +
sizeof (MMOTIONHEADER);
/* Query what the ACTUAL length of the file is */
ulActualFileLength = (ULONG)mmioSeek (hmmioTemp, 0, SEEK_END);
/* If these don't match, then it isn't a VALID M-Motion file */
/* - regardless of what the header says. */
if (ulRequiredFileLength == ulActualFileLength)
fValidMMotionFile = TRUE;
else
fValidMMotionFile = FALSE;
} /* end header check block */
/************************************************************
* Close file before returning.
************************************************************/
if (!lParam2) /* Don't close handle if provided to us */
mmioClose (hmmioTemp, 0);
if (fValidMMotionFile)
return (MMIO_SUCCESS);
else
return (MMIO_ERROR);
} /* end case of MMIOM_IDENTIFYFILE */
/*#############################################################*/
/*#############################################################*/
case MMIOM_OPEN:
{
/************************************************************
* Declare local variables
************************************************************/
PMMFILESTATUS pVidInfo; /* pointer to a MMOTION file */
/* status structure that we will*/
/* use for this file instance */
MMIMAGEHEADER MMImgHdr;
ULONG ulRequiredFileLength;
ULONG ulActualFileLength;
ULONG ulWidth;
ULONG ulHeight;
PBYTE lpYUVBuf;
ULONG ulRowCount;
ULONG ulRGBBytesPerLine;
ULONG ulYUVBytesPerLine;
LONG rc;
HMMIO hmmioSS;
PBYTE lpRGBBufPtr;
FOURCC fccStorageSystem; /* SS I/O Proc FOURCC */
MMIOINFO mmioinfoSS; /* I/O info block for SS ref*/
PSZ pszFileName = (CHAR *)lParam1; /* get the filename from */
/* parameter */
/************************************************************
* Check for valid MMIOINFO block.
************************************************************/
if (!pmmioinfo)
return (MMIO_ERROR);
/************************************************************
* If flags show read and write then send back an error. We
* only support reading or writing but not both at the same
* time on the same file.
************************************************************/
if ((pmmioinfo->ulFlags & MMIO_READWRITE) &&
((pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA) ||
(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER)))
{
return (MMIO_ERROR);
}
/*********************************************************
* Determine the storage system/child IOProc that actually
* obtains the data for us. The M-Motion data may be contained
* in a memory (RAM) file, as a component in a database or
* library (a Compound file), or as a stand-alone disk file.
*
* While the Application uses this M-Motion IOProc to obtain
* untranslated (MMotion) or translated (Bitmap) data,
* the IOProc must obtain it's data from something that
* reads and writes to a storage media. The exact storage
* media is immaterial - so long as the read and write
* operations generate data that LOOKS like it is part
* of a standard file.
*********************************************************/
if (!pmmioinfo->fccChildIOProc)
{
/* Need to determine SS if create from pmmioinfo and filename. */
if (pmmioinfo->ulFlags & MMIO_CREATE)
{
if (mmioDetermineSSIOProc( pszFileName,
pmmioinfo,
&fccStorageSystem,
NULL ))
{
fccStorageSystem = FOURCC_DOS;
}
}
else
{
if (mmioIdentifyStorageSystem( pszFileName,
pmmioinfo,
&fccStorageSystem ))
{
return (MMIO_ERROR);
}
}
if (!fccStorageSystem)
{
return (MMIO_ERROR);
}
else
{
pmmioinfo->fccChildIOProc = fccStorageSystem;
}
} /* end storage system identification block */
/**************************************************************
* Direct the open to the specific storage system necessary
**************************************************************/
memset( &mmioinfoSS, '\0', sizeof(MMIOINFO));
memmove( &mmioinfoSS, pmmioinfo, sizeof(MMIOINFO));
mmioinfoSS.pIOProc = NULL;
mmioinfoSS.fccIOProc = pmmioinfo->fccChildIOProc;
mmioinfoSS.ulFlags |= MMIO_NOIDENTIFY;
/************************************************************
* Try to open the file. Add the NO IDENTIFY flag to
* ENSURE THAT WE DON'T LOOP RECURSIVELY!!!
************************************************************/
hmmioSS = mmioOpen (pszFileName,
&mmioinfoSS,
mmioinfoSS.ulFlags);
/************************************************************
* Check if a DELETE was requested - mmioOpen returns a 1,
* so we much check this separately
************************************************************/
if (pmmioinfo->ulFlags & MMIO_DELETE)
{
/* was the delete successful? */
if (!hmmioSS)
{
pmmioinfo->ulErrorRet = MMIOERR_DELETE_FAILED;
return (MMIO_ERROR);
}
else
{
return (MMIO_SUCCESS);
}
}
/************************************************************
* Check the return code from the open call for an error.
* If not delete, then the open should have worked.
************************************************************/
if (!hmmioSS)
return (MMIO_ERROR);
/************************************************************
* Allocate memory for one MMotion FileStatus structures
************************************************************/
DosAllocMem ((PPVOID) &pVidInfo,
sizeof (MMFILESTATUS),
fALLOC);
/************************************************************
* Ensure the allocate was successful. If not, then
* close the file and return open as unsucessful...
************************************************************/
if (!pVidInfo)
{
mmioClose (hmmioSS, 0);
return (MMIO_ERROR);
}
pVidInfo->hmmioSS = hmmioSS;
/************************************************************
* Store pointer to our MMFILESTATUS structure in
* pExtraInfoStruct field that is provided for our use.
************************************************************/
pmmioinfo->pExtraInfoStruct = (PVOID)pVidInfo;
/************************************************************
* Set the fields of the FileStatus structure that the
* IOProc is responsible for.
************************************************************/
InitFileStruct (pVidInfo);
/*********************************************************
* If this is a read, we need to check that is a M-Motion
* file and perhaps get the data.
*********************************************************/
if (pmmioinfo->ulFlags & MMIO_READ)
{
/*********************************************************
* First we must get some basic information from the file
* Read in data to fill up the MMOTIONHEADER structure.
*
* If the read is unsuccessful, this is not a M-Motion file
* and we should return a failure on the open
*********************************************************/
if (sizeof (MMOTIONHEADER) !=
mmioRead (pVidInfo->hmmioSS,
(PVOID) &pVidInfo->mmotHeader,
(ULONG) sizeof (MMOTIONHEADER)))
{
mmioClose (pVidInfo->hmmioSS, 0);
DosFreeMem ((PVOID) pVidInfo);
return (MMIO_ERROR);
}
/* Ensure this IS an MMotion file header before we continue */
if (strcmp (pVidInfo->mmotHeader.mmID, "YUV12C"))
{
mmioClose (pVidInfo->hmmioSS, 0);
DosFreeMem ((PVOID) pVidInfo);
return (MMIO_ERROR);
}
/********************************************************
* Set up width and height of image.
********************************************************/
ulWidth = (ULONG)pVidInfo->mmotHeader.mmXlen;
ulHeight = (ULONG)pVidInfo->mmotHeader.mmYlen;
/* Calculate what the length of the file SHOULD be based on the */
/* header contents */
ulRequiredFileLength = (((ulWidth >> 2) * 6) * ulHeight) +
sizeof (MMOTIONHEADER);
/* Query what the ACTUAL length of the file is, */
/* then move back to just after the header. */
ulActualFileLength = (ULONG)mmioSeek (pVidInfo->hmmioSS,
0, SEEK_END);
mmioSeek (pVidInfo->hmmioSS, sizeof (MMOTIONHEADER), SEEK_SET);
/* If these don't match, then it isn't a VALID M-Motion file */
/* - regardless of what the header says. */
if (ulRequiredFileLength != ulActualFileLength)
{
mmioClose (pVidInfo->hmmioSS, 0);
DosFreeMem ((PVOID) pVidInfo);
return (MMIO_ERROR);
}
/************************************************************
* If the app intends to read in translation mode, we must
* allocate and set-up the buffer that will contain the RGB data
*
* We must also read in the data to insure that the first
* read, seek, or get-header operation will have data
* to use. This is ONLY NECESSARY FOR TRANSLATED MODE
* operations, since we must process reads/writes pretending
* the image is stored from the Bottom-up.
*
************************************************************
************************************************************
* Fill out the MMIMAGEHEADER structure.
************************************************************/
MMImgHdr.ulHeaderLength = sizeof (MMIMAGEHEADER);
MMImgHdr.ulContentType = MMIO_IMAGE_PHOTO;
MMImgHdr.ulMediaType = MMIO_MEDIATYPE_IMAGE;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cbFix =
sizeof (BITMAPINFOHEADER2);
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cx = ulWidth;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cy = ulHeight;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cPlanes = 1;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cBitCount = 24;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.ulCompression =
BCA_UNCOMP;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cbImage =
ulWidth * ulHeight * 3;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cxResolution = 0L;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cyResolution = 0L;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cclrUsed = 0L;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cclrImportant = 0L;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.usUnits = 0L;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.usReserved = 0L;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.usRecording =
BRA_BOTTOMUP;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.usRendering =
BRH_NOTHALFTONED;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cSize1 = 0L;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cSize2 = 0L;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.ulColorEncoding = 0L;
MMImgHdr.mmXDIBHeader.BMPInfoHeader2.ulIdentifier = 0L;
/************************************************************
* Copy the image header into private area for later use.
* This will be returned on a mmioGetHeader () call
************************************************************/
pVidInfo->mmImgHdr = MMImgHdr;
/********************************************************
* YUV Bytes/Line are = 1 1/2 times the number of pels
********************************************************/
ulYUVBytesPerLine = ulWidth + (ulWidth >> 1);
/********************************************************
* RGB Bytes/Line are = 2* YUV bytes/line
********************************************************/
ulRGBBytesPerLine = (ulYUVBytesPerLine << 1);
/********************************************************
* Determine total bytes in image
********************************************************/
pVidInfo->ulRGBTotalBytes = ulWidth * ulHeight * 3;
/********************************************************
* MMotion Images are ALWAYS on 4-pel boundaries, which also
* makes them on 4-byte/LONG boundaries which is used for
* Bitmaps. Therefore, there are no extra pad bytes necessary
********************************************************/
pVidInfo->ulImgPaddedBytesPerLine = ulWidth * 3;
pVidInfo->ulImgTotalBytes = pVidInfo->ulRGBTotalBytes;
/*********************************************************
* For translated data READ mode, we must allocate a buffer,
* then get the YUV data from the file and load the RGB
* buffer.
* PLACE FORMAT SPECIFIC CODE HERE TO LOAD IMAGE INTO BUFFER
* The code below is M-Motion format specific.
*********************************************************/
if (pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)
{
/********************************************************
* Get space for full image buffer.
* This will be retained until the file is closed.
********************************************************/
if (DosAllocMem ((PPVOID) &(pVidInfo->lpRGBBuf),
pVidInfo->ulRGBTotalBytes,
fALLOC))
{
mmioClose (pVidInfo->hmmioSS, 0);
DosFreeMem ((PVOID) pVidInfo);
return (MMIO_ERROR);
}
/********************************************************
* Get temporary space for one line YUV Buffer.
********************************************************/
if (DosAllocMem ((PPVOID) &lpYUVBuf,
ulYUVBytesPerLine,
fALLOC))
{
mmioClose (pVidInfo->hmmioSS, 0);
DosFreeMem ((PVOID) pVidInfo);
return (MMIO_ERROR);
}
/********************************************************
* Initialize beginning buffer position
********************************************************/
lpRGBBufPtr = pVidInfo->lpRGBBuf;
/********************************************************
* Read in YUV data one line at a time, converting
* from YUV to RGB, then placing in the image buffer
********************************************************/
for (ulRowCount = 0;
ulRowCount < ulHeight;
ulRowCount++)
{
/****************************************************
* Read in one line.
****************************************************/
rc = mmioRead (pVidInfo->hmmioSS,
(PVOID) lpYUVBuf,
(ULONG) ulYUVBytesPerLine);
/****************************************************
* Convert one line at a time.
****************************************************/
ConvertOneLineYUVtoRGB (lpYUVBuf,
lpRGBBufPtr,
ulYUVBytesPerLine);
/****************************************************
* Make sure buffer ptr is correct for next convert.
****************************************************/
lpRGBBufPtr += (LONG)ulRGBBytesPerLine;
} /* end of FOR loop to read YUV data */
DosFreeMem (lpYUVBuf);
/********************************************************
* This changes from M-Motion's top-down form to OS/2
* PM's bottom-up bitmap form.
********************************************************/
ImgBufferFlip (pVidInfo->lpRGBBuf,
pVidInfo->ulImgPaddedBytesPerLine,
ulHeight);
/********************************************************
* RGB Buffer now full, set position pointers to the
* beginning of the buffer.
********************************************************/
pVidInfo->lImgBytePos = 0;
} /* end IF TRANSLATED block */
} /* end IF READ block */
return (MMIO_SUCCESS);
} /* end case of MMIOM_OPEN */
/*#############################################################*/
/*#############################################################*/
case MMIOM_QUERYHEADERLENGTH:
{
/************************************************************
* If there is no MMIOINFO block then return an error.
************************************************************/
if (!pmmioinfo)
return (0);
/************************************************************
* If header is in translated mode then return the media
* type specific structure size.
************************************************************/
if (pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER)
return (sizeof (MMIMAGEHEADER));
else
/********************************************************
* Header is not in translated mode so return the size
* of the MMotion header.
********************************************************/
return (sizeof (MMOTIONHEADER));
break;
} /* end case of MMIOM_QUERYHEADERLENGTH */
/*#############################################################*/
/*#############################################################*/
case MMIOM_READ:
{
/************************************************************
* Declare Local Variables
************************************************************/
PMMFILESTATUS pVidInfo;
LONG rc;
LONG lBytesToRead;
/************************************************************
* Check for valid MMIOINFO block.
************************************************************/
if (!pmmioinfo)
return (MMIO_ERROR);
/************************************************************
* Set up our working file status variable.
************************************************************/
pVidInfo = (PMMFILESTATUS)pmmioinfo->pExtraInfoStruct;
/************************************************************
* Is Translate Data off?
************************************************************/
if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA))
{
/********************************************************
* Since no translation, provide exact number of bytes req
********************************************************/
if (!lParam1)
return (MMIO_ERROR);
rc = mmioRead (pVidInfo->hmmioSS,
(PVOID) lParam1,
(ULONG) lParam2);
return (rc);
}
/************************************************************
* Otherwise, Translate Data is on...
************************************************************/
/************************************************************
* Ensure we do NOT write more data out than is remaining
* in the buffer. The length of read was requested in
* image bytes, so confirm that there are that many of
* virtual bytes remaining.
************************************************************/
if ((ULONG)(pVidInfo->lImgBytePos + lParam2) >
pVidInfo->ulImgTotalBytes)
lBytesToRead =
pVidInfo->ulImgTotalBytes - pVidInfo->lImgBytePos;
else
lBytesToRead = (ULONG)lParam2;
/************************************************************
* Perform this block on ALL reads. The image data should
* be in the RGB buffer at this point, and can be handed
* to the application.
*
* Conveniently, the virtual image position is the same
* as the RGB buffer position, since both are 24 bit-RGB
************************************************************/
memcpy ((PVOID)lParam1,
&(pVidInfo->lpRGBBuf[pVidInfo->lImgBytePos]),
lBytesToRead);
/************************************************************
* Move RGB Buffer pointer forward by number of bytes read.
* The Img buffer pos is identical, since both are 24 bits
************************************************************/
pVidInfo->lImgBytePos += lBytesToRead;
return (lBytesToRead);
} /* end case of MMIOM_READ */
/*#############################################################*/
/*#############################################################*/
case MMIOM_SEEK:
{
/************************************************************
* Set up locals.
************************************************************/
PMMFILESTATUS pVidInfo;
LONG lNewFilePosition;
LONG lPosDesired;
SHORT sSeekMode;
/************************************************************
* Check to make sure MMIOINFO block is valid.
************************************************************/
if (!pmmioinfo)
return (MMIO_ERROR);
/************************************************************
* Set up our working file status variable.
************************************************************/
pVidInfo = (PMMFILESTATUS)pmmioinfo->pExtraInfoStruct;
lPosDesired = lParam1;
sSeekMode = (SHORT)lParam2;
/************************************************************
* Is Translate Data on?
************************************************************/
if (pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)
{
/********************************************************
* Attempt to move the Image buffer pointer to the
* desired location. App sends SEEK requests in
* positions relative to the image planes & bits/pel
* We must also convert this to RGB positions
********************************************************/
switch (sSeekMode)
{
case SEEK_SET:
{
lNewFilePosition = lPosDesired;
break;
}
case SEEK_CUR:
{
lNewFilePosition = pVidInfo->lImgBytePos + lPosDesired;
break;
}
case SEEK_END:
{
lNewFilePosition =
pVidInfo->ulImgTotalBytes += lPosDesired;
break;
}
default :
return (MMIO_ERROR);
}
/********************************************************
* Make sure seek did not go before start of file.
* If so, then don't change anything, just return an error
********************************************************/
if (lNewFilePosition < 0)
{
return (MMIO_ERROR);
}
/********************************************************
* Make sure seek did not go past the end of file.
********************************************************/
if (lNewFilePosition > (LONG)pVidInfo->ulImgTotalBytes)
lNewFilePosition = pVidInfo->ulImgTotalBytes;
pVidInfo->lImgBytePos = lNewFilePosition;
return (pVidInfo->lImgBytePos);
} /* end IF DATA TRANSLATED */
/************************************************************
* Translate Data is OFF...
************************************************************
* if this is a seek from the beginning of the file,
* we must account for and pass the header
************************************************************/
if (lParam2==SEEK_SET)
lPosDesired += MMOTION_HEADER_SIZE;
lNewFilePosition = mmioSeek (pVidInfo->hmmioSS,
lPosDesired,
sSeekMode);
/********************************************
* Ensure we did not move to within the header
********************************************/
if ((lNewFilePosition != MMIO_ERROR) &&
(lNewFilePosition < MMOTION_HEADER_SIZE))
{
lNewFilePosition = mmioSeek (pVidInfo->hmmioSS,
(LONG)MMOTION_HEADER_SIZE,
SEEK_SET);
}
/************************************************************
* Return new position. Always remove the length of the
* header from the this position value
************************************************************/
if (lNewFilePosition != MMIO_ERROR)
lNewFilePosition -= MMOTION_HEADER_SIZE;
return (lNewFilePosition);
} /* end case of MMIOM_SEEK */
/*#############################################################*/
/*#############################################################*/
case MMIOM_SETHEADER:
{
/************************************************************
* Declare local variables.
************************************************************/
PMMIMAGEHEADER pMMImgHdr;
PMMFILESTATUS pVidInfo;
USHORT usNumColors;
ULONG ulImgBitsPerLine;
ULONG ulImgBytesPerLine;
ULONG ulBytesWritten;
ULONG ulWidth;
ULONG ul4PelWidth;
ULONG ulHeight;
USHORT usPlanes;
USHORT usBitCount;
USHORT usPadBytes;
/************************************************************
* Check for valid MMIOINFO block.
************************************************************/
if (!pmmioinfo)
return (MMIO_ERROR);
/************************************************************
* Set up our working variable MMFILESTATUS.
************************************************************/
pVidInfo = (PMMFILESTATUS) pmmioinfo->pExtraInfoStruct;
/************************************************************
* Only allow this function if we are in WRITE mode
* And only if we have not already set the header
************************************************************/
if ((!(pmmioinfo->ulFlags & MMIO_WRITE)) ||
(!(pVidInfo->hmmioSS)) ||
(pVidInfo->bSetHeader))
return (0);
/********************************************************
* Make sure lParam1 is a valid pointer
********************************************************/
if (!lParam1)
{
pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
return (0);
}
/************************************************************
* Header is not in translated mode.
************************************************************/
if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER))
{
/********************************************************
* Make sure lParam2 is correct size
********************************************************/
if (lParam2 != MMOTION_HEADER_SIZE)
{
pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
return (0);
}
/********************************************************
* Ensure that the header at least begins with "YUV12C"
********************************************************/
if (strncmp ((char *)lParam1, "YUV12C", 6))
{
pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
return (0);
}
/********************************************************
* Take 16 byte buffer (lParam1), write to file and .
* copy to internal structure.
********************************************************/
memcpy ((PVOID)&pVidInfo->mmotHeader,
(PVOID)lParam1, (ULONG) MMOTION_HEADER_SIZE);
ulBytesWritten = mmioWrite (pVidInfo->hmmioSS,
(PVOID) lParam1,
(ULONG) MMOTION_HEADER_SIZE);
/*********************************
* Check for an error on the write..
*********************************/
if (ulBytesWritten != MMOTION_HEADER_SIZE)
return (0); /* 0 indicates error */
/*********************************
* Success...
*********************************/
pVidInfo->bSetHeader = TRUE;
return (sizeof (MMOTIONHEADER));
} /* end IF NOT TRANSLATED block */
/************************************************************
* Header is translated.
************************************************************/
/************************************************************
* Create local pointer media specific structure.
************************************************************/
pMMImgHdr = (PMMIMAGEHEADER) lParam1;
/************************************************************
* Check for validity of header contents supplied
************************************************************
* -- Length must be that of the standard header
* -- NO Compression
* 1 plane
* 24, 8, 4 or 1 bpp
************************************************************/
usBitCount = pMMImgHdr->mmXDIBHeader.BMPInfoHeader2.cBitCount;
if ((pMMImgHdr->mmXDIBHeader.BMPInfoHeader2.ulCompression !=
BCA_UNCOMP) ||
(pMMImgHdr->mmXDIBHeader.BMPInfoHeader2.cPlanes != 1) ||
(! ((usBitCount == 24) || (usBitCount == 8) ||
(usBitCount == 4) || (usBitCount == 1)))
)
{
pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
return (0);
}
if (lParam2 != sizeof (MMIMAGEHEADER))
{
pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
return (0);
}
/************************************************************
* Complete MMOTIONHEADER.
************************************************************/
memcpy ((PVOID)&pVidInfo->mmotHeader.mmID, "YUV12C", 6);
pVidInfo->mmotHeader.mmXorg = 0;
pVidInfo->mmotHeader.mmYorg = 0;
/********************************************************
* Ensure we will save stuff on 4-pel boundaries when
* we actually convert to YUV and pack the bits.
* We DON'T change what the user is actually going to
* give us. HE thinks he is on 1-pel boundaries,
* and that is how we buffer the RGB data.
********************************************************/
ulWidth = pMMImgHdr->mmXDIBHeader.BMPInfoHeader2.cx;
ulHeight = pMMImgHdr->mmXDIBHeader.BMPInfoHeader2.cy;
if (ulWidth % 4)
ul4PelWidth = (((ulWidth >> 2) + 1) << 2);
else
ul4PelWidth = ulWidth;
pVidInfo->mmotHeader.mmXlen = (USHORT) ul4PelWidth;
pVidInfo->mmotHeader.mmYlen = (USHORT) ulHeight;
/************************************************************
* Write the MMotion Header.
************************************************************/
ulBytesWritten = mmioWrite (pVidInfo->hmmioSS,
(PVOID) &pVidInfo->mmotHeader,
(ULONG) MMOTION_HEADER_SIZE);
/***************************************
* Check for an error on the write...
***************************************/
if (ulBytesWritten != MMOTION_HEADER_SIZE)
return (0);
/************************************************************
* Flag that MMIOM_SETHEADER has been done. It can only
* be done ONCE for a file. All future attempts will
* be flagged as errors.
************************************************************/
pVidInfo->bSetHeader = TRUE;
/************************************************************
* Create copy of MMIMAGEHEADER for future use.
************************************************************/
pVidInfo->mmImgHdr = *pMMImgHdr;
/************************************************************
* Check bitcount, set palette if less than 24.
************************************************************/
if (usBitCount < 24)
{
/*********************************************************
* Find out how many colors are in the palette.
*********************************************************/
usNumColors = (USHORT)(1 << usBitCount);
/*********************************************************
* Take the RGB2 Palette and convert it to an RGB palette
* Place the converted palette in MMFILESTATUS struct
*********************************************************/
RGB2_To_RGB (pVidInfo->mmImgHdr.bmiColors,
(PRGB) &(pVidInfo->rgbPalette),
usNumColors);
}
/*********************************************************
* We must allocate the buffer. The app will load the
* buffer on subsequent write calls
*********************************************************/
usPlanes = pVidInfo->mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cPlanes;
/********************************************************
* Determine total Image size
********************************************************
* Find bits-per-line BEFORE padding and 1bpp or 4bpp pel overflow
********************************************************/
ulImgBitsPerLine = ulWidth * usPlanes * usBitCount;
ulImgBytesPerLine = ulImgBitsPerLine >> 3;
/********************************************************
* Account for extra pels not on an even byte boundary
* for 1bpp and 4bpp
********************************************************/
if (ulImgBitsPerLine % 8)
ulImgBytesPerLine ++;
pVidInfo->ulImgPelBytesPerLine = ulImgBytesPerLine;
/********************************************************
* Ensure the row length in bytes accounts for byte padding.
* All bitmap data rows are aligned on LONG/4-BYTE boundaries.
* The data FROM an application should always appear in this form
********************************************************/
usPadBytes = (USHORT)(ulImgBytesPerLine % 4);
if (usPadBytes)
ulImgBytesPerLine += 4 - usPadBytes;
pVidInfo->ulImgPaddedBytesPerLine = ulImgBytesPerLine;
pVidInfo->ulImgTotalBytes = ulImgBytesPerLine * ulHeight;
/********************************************************
* Get space for full image buffer.
********************************************************/
if (DosAllocMem ((PPVOID) &(pVidInfo->lpImgBuf),
pVidInfo->ulImgTotalBytes,
fALLOC))
return (MMIO_ERROR);
/********************************************************
* Set up initial pointer value within RGB buffer & image
********************************************************/
pVidInfo->lImgBytePos = 0;
return (sizeof (MMIMAGEHEADER));
} /* end case of MMIOM_SETHEADER */
/*#############################################################*/
/*#############################################################*/
case MMIOM_WRITE:
{
/************************************************************
* Declare Local Variables.
************************************************************/
PMMFILESTATUS pVidInfo;
USHORT usBitCount;
LONG lBytesWritten;
ULONG ulImgBytesToWrite;
/************************************************************
* Check for valid MMIOINFO block.
************************************************************/
if (!pmmioinfo)
return (MMIO_ERROR);
/************************************************************
* Set up our working variable MMFILESTATUS.
************************************************************/
pVidInfo = (PMMFILESTATUS) pmmioinfo->pExtraInfoStruct;
/************************************************************
* See if a SetHeader has been done on this file.
************************************************************/
if ((!pVidInfo) || (!pVidInfo->bSetHeader))
{
return (MMIO_ERROR);
}
if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA))
{
/********************************************************
* Translation is off, take amount of bytes sent and
* write to the file.
********************************************************
* Ensure that there is a data buffer to write from
********************************************************/
if (!lParam1)
return (MMIO_ERROR);
lBytesWritten = mmioWrite (pVidInfo->hmmioSS,
(PVOID) lParam1,
(ULONG) lParam2);
return (lBytesWritten);
}
/************************************************************
************************************************************
* Translation is on.
************************************************************
************************************************************
************************************************************
* Set up local variables
************************************************************/
usBitCount =
pVidInfo->mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cBitCount;
/************************************************************
* Ensure we do not attempt to write past the end of the
* buffer...
************************************************************/
if ((ULONG)(pVidInfo->lImgBytePos + lParam2) >
pVidInfo->ulImgTotalBytes)
ulImgBytesToWrite =
pVidInfo->ulImgTotalBytes - pVidInfo->lImgBytePos;
else
ulImgBytesToWrite = (ULONG)lParam2;
/************************************************************
* Write the data into the image buffer. It will be converted to
* RGB, then YUV when the file is closed. This allows the
* application to seek to arbitrary positions within the
* image in terms of the bits/pel, etc they are writing.
************************************************************/
memcpy (&(pVidInfo->lpImgBuf[pVidInfo->lImgBytePos]),
(PVOID)lParam1,
ulImgBytesToWrite);
/* Update current position in the image buffer */
pVidInfo->lImgBytePos += ulImgBytesToWrite;
return (ulImgBytesToWrite);
} /* end case of MMIOM_WRITE */
/*
* If the IOProc has a child IOProc, then pass the message on to the Child, otherwise
* return Unsupported Message
*/
default:
{
/*
* Declare Local Variables.
*/
PMMFILESTATUS pVidInfo;
LONG lRC;
/************************************************************
* Check for valid MMIOINFO block.
************************************************************/
if (!pmmioinfo)
return (MMIO_ERROR);
/************************************************************
* Set up our working variable MMFILESTATUS.
************************************************************/
pVidInfo = (PMMFILESTATUS) pmmioinfo->pExtraInfoStruct;
if (pVidInfo != NULL && pVidInfo->hmmioSS)
{
lRC = mmioSendMessage (pVidInfo->hmmioSS,
usMsg,
lParam1,
lParam2);
if (!lRC)
pmmioinfo->ulErrorRet = mmioGetLastError (pVidInfo->hmmioSS);
return (lRC);
}
else
{
if (pmmioinfo != NULL)
pmmioinfo->ulErrorRet = MMIOERR_UNSUPPORTED_MESSAGE;
return (MMIOERR_UNSUPPORTED_MESSAGE);
}
} /* end case of Default */
} /* end SWITCH statement for MMIO messages */
return (0);
} /* end of window procedure */