#ifdef JA2_PRECOMPILED_HEADERS #include "JA2 SGP ALL.H" #elif defined( WIZ8_PRECOMPILED_HEADERS ) #include "WIZ8 SGP ALL.H" #else #include #include #include "types.h" #include "string.h" #include "debug.h" #include "fileman.h" #include "himage.h" #include "impTGA.h" #include "pcx.h" #include "STCI.h" #include "wcheck.h" #include "Compression.h" #include "vobject.h" #endif // This is the color substituted to keep a 24bpp -> 16bpp color // from going transparent (0x0000) -- DB #define BLACK_SUBSTITUTE 0x0001 UINT16 gusAlphaMask = 0; UINT16 gusRedMask = 0; UINT16 gusGreenMask = 0; UINT16 gusBlueMask = 0; INT16 gusRedShift = 0; INT16 gusBlueShift = 0; INT16 gusGreenShift = 0; // this funky union is used for fast 16-bit pixel format conversions typedef union { struct { UINT16 usLower; UINT16 usHigher; }; UINT32 uiValue; } SplitUINT32; HIMAGE CreateImage( SGPFILENAME ImageFile, UINT16 fContents ) { HIMAGE hImage = NULL; SGPFILENAME Extension; CHAR8 ExtensionSep[] = "."; STR StrPtr; UINT32 iFileLoader; // Depending on extension of filename, use different image readers // Get extension StrPtr = strstr( ImageFile, ExtensionSep ); if ( StrPtr == NULL ) { // No extension given, use default internal loader extension DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "No extension given, using default" ); strcat( ImageFile, ".PCX" ); strcpy( Extension, ".PCX" ); } else { strcpy( Extension, StrPtr+1 ); } // Determine type from Extension do { iFileLoader = UNKNOWN_FILE_READER; if ( _stricmp( Extension, "PCX" ) == 0 ) { iFileLoader = PCX_FILE_READER; break; } if ( _stricmp( Extension, "TGA" ) == 0 ) { iFileLoader = TGA_FILE_READER; break; } if ( _stricmp( Extension, "STI" ) == 0 ) { iFileLoader = STCI_FILE_READER; break; } } while ( FALSE ); // Determine if resource exists before creating image structure if ( !FileExists( ImageFile ) ) { //If in debig, make fatal! #ifdef JA2 #ifdef _DEBUG //FatalError( "Resource file %s does not exist.", ImageFile ); #endif #endif DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, String("Resource file %s does not exist.", ImageFile) ); return( NULL ); } // Create memory for image structure hImage = (HIMAGE)MemAlloc( sizeof( image_type ) ); AssertMsg( hImage, "Failed to allocate memory for hImage in CreateImage"); // Initialize some values memset( hImage, 0, sizeof( image_type ) ); //hImage->fFlags = 0; // Set data pointers to NULL //hImage->pImageData = NULL; //hImage->pPalette = NULL; //hImage->pui16BPPPalette = NULL; // Set filename and loader strcpy( hImage->ImageFile, ImageFile ); hImage->iFileLoader = iFileLoader; if ( !LoadImageData( hImage, fContents ) ) { return( NULL ); } // All is fine, image is loaded and allocated, return pointer return( hImage ); } BOOLEAN DestroyImage( HIMAGE hImage ) { Assert( hImage != NULL ); // First delete contents ReleaseImageData( hImage, IMAGE_ALLDATA );//hImage->fFlags ); // Now free structure MemFree( hImage ); return( TRUE ); } BOOLEAN ReleaseImageData( HIMAGE hImage, UINT16 fContents ) { Assert( hImage != NULL ); if ( (fContents & IMAGE_PALETTE) && (hImage->fFlags & IMAGE_PALETTE) ) { //Destroy palette if( hImage->pPalette != NULL ) { MemFree( hImage->pPalette ); hImage->pPalette = NULL; } if ( hImage->pui16BPPPalette != NULL ) { MemFree( hImage->pui16BPPPalette ); hImage->pui16BPPPalette = NULL; } // Remove contents flag hImage->fFlags = hImage->fFlags ^ IMAGE_PALETTE; } if ( (fContents & IMAGE_BITMAPDATA) && (hImage->fFlags & IMAGE_BITMAPDATA) ) { //Destroy image data Assert( hImage->pImageData != NULL ); MemFree( hImage->pImageData ); hImage->pImageData = NULL; if (hImage->usNumberOfObjects > 0) { MemFree( hImage->pETRLEObject ); } // Remove contents flag hImage->fFlags = hImage->fFlags ^ IMAGE_BITMAPDATA; } if ( (fContents & IMAGE_APPDATA) && (hImage->fFlags & IMAGE_APPDATA) ) { // get rid of the APP DATA if ( hImage->pAppData != NULL ) { MemFree( hImage->pAppData ); hImage->fFlags &= (~IMAGE_APPDATA); } } return( TRUE ); } BOOLEAN LoadImageData( HIMAGE hImage, UINT16 fContents ) { BOOLEAN fReturnVal = FALSE; Assert( hImage != NULL ); // Switch on file loader switch( hImage->iFileLoader ) { case TGA_FILE_READER: fReturnVal = LoadTGAFileToImage( hImage, fContents ); break; case PCX_FILE_READER: fReturnVal = LoadPCXFileToImage( hImage, fContents ); break; case STCI_FILE_READER: fReturnVal = LoadSTCIFileToImage( hImage, fContents ); break; default: DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "Unknown image loader was specified." ); } if ( !fReturnVal ) { DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "Error occured while reading image data." ); } return( fReturnVal ); } BOOLEAN CopyImageToBuffer( HIMAGE hImage, UINT32 fBufferType, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect ) { // Use blitter based on type of image Assert( hImage != NULL ); if ( hImage->ubBitDepth == 8 && fBufferType == BUFFER_8BPP ) { #ifndef NO_ZLIB_COMPRESSION if ( hImage->fFlags & IMAGE_COMPRESSED ) { DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "Copying Compressed 8 BPP Imagery." ); return( Copy8BPPCompressedImageTo8BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) ); } #endif // Default do here DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "Copying 8 BPP Imagery." ); return ( Copy8BPPImageTo8BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) ); } if ( hImage->ubBitDepth == 8 && fBufferType == BUFFER_16BPP ) { #ifndef NO_ZLIB_COMPRESSION if ( hImage->fFlags & IMAGE_COMPRESSED ) { DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Copying Compressed 8 BPP Imagery to 16BPP Buffer." ); return ( Copy8BPPCompressedImageTo16BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) ); } #endif // Default do here DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Copying 8 BPP Imagery to 16BPP Buffer." ); return ( Copy8BPPImageTo16BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) ); } if ( hImage->ubBitDepth == 16 && fBufferType == BUFFER_16BPP ) { #ifndef NO_ZLIB_COMPRESSION if ( hImage->fFlags & IMAGE_COMPRESSED ) { DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Automatically Copying Compressed 16 BPP Imagery." ); return( Copy16BPPCompressedImageTo16BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) ); } #endif DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Automatically Copying 16 BPP Imagery." ); return( Copy16BPPImageTo16BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) ); } return( FALSE ); } #ifndef NO_ZLIB_COMPRESSION BOOLEAN Copy8BPPCompressedImageTo8BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect ) { UINT32 uiNumLines; UINT32 uiLineSize; UINT32 uiCnt; UINT8 * pDest; UINT32 uiDestStart; UINT8 * pScanLine; PTR pDecompPtr; UINT32 uiDecompressed; // Assertions Assert( hImage != NULL ); Assert( hImage->pCompressedImageData != NULL ); // Validations CHECKF( usX >= 0 ); CHECKF( usX < usDestWidth ); CHECKF( usY >= 0 ); CHECKF( usY < usDestHeight ); CHECKF( srcRect->iRight > srcRect->iLeft ); CHECKF( srcRect->iBottom > srcRect->iTop ); DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "8BPP to 8BPP Compressed Blitter Called!" ); // determine where to start Copying and rectangle size uiDestStart = usY * usDestWidth + usX; uiNumLines = srcRect->iBottom - srcRect->iTop; uiLineSize = srcRect->iRight - srcRect->iLeft; Assert( usDestWidth >= uiLineSize ); Assert( usDestHeight >= uiNumLines ); pDest = (UINT8 *) pDestBuf + uiDestStart; // Copying a portion of a compressed image is rather messy // because we have to decompress past all the data we want // to skip. // To keep memory requirements small and regular, we will // decompress one scanline at a time even if none of the data will // be blitted (but stop when the bottom line of the rectangle // to blit has been done). // initialize the decompression routines pDecompPtr = DecompressInit( hImage->pCompressedImageData, hImage->usWidth * hImage->usHeight ); CHECKF( pDecompPtr ); // Allocate memory for one scanline pScanLine = MemAlloc( hImage->usWidth ); CHECKF( pScanLine ); // go past all the scanlines we don't need to process for (uiCnt = 0; uiCnt < (UINT32) srcRect->iTop; uiCnt++) { uiDecompressed = Decompress( pDecompPtr, pScanLine, hImage->usWidth ); Assert( uiDecompressed == hImage->usWidth ); } // now we start Copying for (uiCnt = 0; uiCnt < uiNumLines - 1; uiCnt++) { // decompress a scanline uiDecompressed = Decompress( pDecompPtr, pScanLine, hImage->usWidth ); Assert( uiDecompressed == hImage->usWidth ); // and blit // memcpy( pDest, pScanLine + srcRect->iLeft, uiLineSize ); pDest += usDestWidth; } // decompress the last scanline and blit uiDecompressed = Decompress( pDecompPtr, pScanLine, hImage->usWidth ); Assert( uiDecompressed == hImage->usWidth ); // memcpy( pDest, pScanLine + srcRect->iLeft, uiLineSize ); DecompressFini( pDecompPtr ); return( TRUE ); } BOOLEAN Copy8BPPCompressedImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect ) { UINT32 uiNumLines; UINT32 uiLineSize; UINT32 uiLine; UINT32 uiCol; UINT16 * pDest; UINT16 * pDestTemp; UINT32 uiDestStart; UINT8 * pScanLine; UINT8 * pScanLineTemp; PTR pDecompPtr; UINT32 uiDecompressed; UINT16 * p16BPPPalette; // Assertions Assert( hImage != NULL ); Assert( hImage->pCompressedImageData != NULL ); DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Start check" ); // Validations CHECKF( usX >= 0 ); CHECKF( usX < usDestWidth ); CHECKF( usY >= 0 ); CHECKF( usY < usDestHeight ); CHECKF( srcRect->iRight > srcRect->iLeft ); CHECKF( srcRect->iBottom > srcRect->iTop ); DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "End check" ); p16BPPPalette = hImage->pui16BPPPalette; // determine where to start Copying and rectangle size uiDestStart = usY * usDestWidth + usX; uiNumLines = srcRect->iBottom - srcRect->iTop; uiLineSize = srcRect->iRight - srcRect->iLeft; Assert( usDestWidth >= uiLineSize ); Assert( usDestHeight >= uiNumLines ); pDest = (UINT16 *) pDestBuf; pDest += uiDestStart; DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, String( "Start Copying at %p", pDest ) ); // Copying a portion of a compressed image is rather messy // because we have to decompress past all the data we want // to skip. // To keep memory requirements small and regular, we will // decompress one scanline at a time even if none of the data will // be blitted (but stop when the bottom line of the rectangle // to blit has been done). // initialize the decompression routines pDecompPtr = DecompressInit( hImage->pCompressedImageData, hImage->usWidth * hImage->usHeight ); CHECKF( pDecompPtr ); // Allocate memory for one scanline pScanLine = MemAlloc( hImage->usWidth ); CHECKF( pScanLine ); // go past all the scanlines we don't need to process for (uiLine = 0; uiLine < (UINT32) srcRect->iTop; uiLine++) { DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Skipping scanline" ); uiDecompressed = Decompress( pDecompPtr, pScanLine, hImage->usWidth ); Assert( uiDecompressed == hImage->usWidth ); } DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Actually Copying" ); // now we start Copying for (uiLine = 0; uiLine < uiNumLines - 1; uiLine++) { // decompress a scanline uiDecompressed = Decompress( pDecompPtr, pScanLine, hImage->usWidth ); Assert( uiDecompressed == hImage->usWidth ); // set pointers and blit pDestTemp = pDest; pScanLineTemp = pScanLine + srcRect->iLeft; for (uiCol = 0; uiCol < uiLineSize; uiCol++ ) { *pDestTemp = p16BPPPalette[ *pScanLineTemp ]; pDestTemp++; pScanLineTemp++; } pDest += usDestWidth; } DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, String( "End Copying at %p", pDest ) ); DecompressFini( pDecompPtr ); return( TRUE ); } BOOLEAN Copy16BPPCompressedImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect ) { // 16BPP Compressed image has not been implemented yet DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "16BPP Compressed imagery blitter has not been implemented yet." ); return( FALSE ); } #endif //NO_ZLIB_COMPRESSION BOOLEAN Copy8BPPImageTo8BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect ) { UINT32 uiSrcStart, uiDestStart, uiNumLines, uiLineSize; UINT32 cnt; UINT8 *pDest, *pSrc; // Assertions Assert( hImage != NULL ); Assert( hImage->p16BPPData != NULL ); // Validations CHECKF( usX >= 0 ); CHECKF( usX < usDestWidth ); CHECKF( usY >= 0 ); CHECKF( usY < usDestHeight ); CHECKF( srcRect->iRight > srcRect->iLeft ); CHECKF( srcRect->iBottom > srcRect->iTop ); // Determine memcopy coordinates uiSrcStart = srcRect->iTop * hImage->usWidth + srcRect->iLeft; uiDestStart = usY * usDestWidth + usX; uiNumLines = ( srcRect->iBottom - srcRect->iTop ) + 1; uiLineSize = ( srcRect->iRight - srcRect->iLeft ) + 1; Assert( usDestWidth >= uiLineSize ); Assert( usDestHeight >= uiNumLines ); // Copy line by line pDest = ( UINT8*)pDestBuf + uiDestStart; pSrc = hImage->p8BPPData + uiSrcStart; for( cnt = 0; cnt < uiNumLines-1; cnt++ ) { memcpy( pDest, pSrc, uiLineSize ); pDest += usDestWidth; pSrc += hImage->usWidth; } // Do last line memcpy( pDest, pSrc, uiLineSize ); return( TRUE ); } BOOLEAN Copy16BPPImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect ) { UINT32 uiSrcStart, uiDestStart, uiNumLines, uiLineSize; UINT32 cnt; UINT16 *pDest, *pSrc; Assert( hImage != NULL ); Assert( hImage->p16BPPData != NULL ); // Validations CHECKF( usX >= 0 ); CHECKF( usX < hImage->usWidth ); CHECKF( usY >= 0 ); CHECKF( usY < hImage->usHeight ); CHECKF( srcRect->iRight > srcRect->iLeft ); CHECKF( srcRect->iBottom > srcRect->iTop ); // Determine memcopy coordinates uiSrcStart = srcRect->iTop * hImage->usWidth + srcRect->iLeft; uiDestStart = usY * usDestWidth + usX; uiNumLines = ( srcRect->iBottom - srcRect->iTop ) + 1; uiLineSize = ( srcRect->iRight - srcRect->iLeft ) + 1; CHECKF( usDestWidth >= uiLineSize ); CHECKF( usDestHeight >= uiNumLines ); // Copy line by line pDest = ( UINT16*)pDestBuf + uiDestStart; pSrc = hImage->p16BPPData + uiSrcStart; for( cnt = 0; cnt < uiNumLines-1; cnt++ ) { memcpy( pDest, pSrc, uiLineSize * 2 ); pDest += usDestWidth; pSrc += hImage->usWidth; } // Do last line memcpy( pDest, pSrc, uiLineSize * 2 ); return( TRUE ); } BOOLEAN Extract8BPPCompressedImageToBuffer( HIMAGE hImage, BYTE *pDestBuf ) { return( FALSE ); } BOOLEAN Extract16BPPCompressedImageToBuffer( HIMAGE hImage, BYTE *pDestBuf ) { return( FALSE ); } BOOLEAN Copy8BPPImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect ) { UINT32 uiSrcStart, uiDestStart, uiNumLines, uiLineSize; UINT32 rows, cols; UINT8 *pSrc, *pSrcTemp; UINT16 *pDest, *pDestTemp; UINT16 *p16BPPPalette; p16BPPPalette = hImage->pui16BPPPalette; // Assertions Assert( p16BPPPalette != NULL ); Assert( hImage != NULL ); // Validations CHECKF( hImage->p16BPPData != NULL ); CHECKF( usX >= 0 ); CHECKF( usX < usDestWidth ); CHECKF( usY >= 0 ); CHECKF( usY < usDestHeight ); CHECKF( srcRect->iRight > srcRect->iLeft ); CHECKF( srcRect->iBottom > srcRect->iTop ); // Determine memcopy coordinates uiSrcStart = srcRect->iTop * hImage->usWidth + srcRect->iLeft; uiDestStart = usY * usDestWidth + usX; uiNumLines = ( srcRect->iBottom - srcRect->iTop ); uiLineSize = ( srcRect->iRight - srcRect->iLeft ); CHECKF( usDestWidth >= uiLineSize ); CHECKF( usDestHeight >= uiNumLines ); // Convert to Pixel specification pDest = ( UINT16*)pDestBuf + uiDestStart; pSrc = hImage->p8BPPData + uiSrcStart; DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, String( "Start Copying at %p", pDest ) ); // For every entry, look up into 16BPP palette for( rows = 0; rows < uiNumLines-1; rows++ ) { pDestTemp = pDest; pSrcTemp = pSrc; for ( cols = 0; cols < uiLineSize; cols++ ) { *pDestTemp = p16BPPPalette[ *pSrcTemp ]; pDestTemp++; pSrcTemp++; } pDest += usDestWidth; pSrc += hImage->usWidth; } // Do last line DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, String( "End Copying at %p", pDest ) ); return( TRUE ); } UINT16 *Create16BPPPalette( SGPPaletteEntry *pPalette ) { UINT16 *p16BPPPalette, r16, g16, b16, usColor; UINT32 cnt; UINT8 r,g,b; Assert( pPalette != NULL ); p16BPPPalette = MemAlloc( sizeof( UINT16 ) * 256 ); for ( cnt = 0; cnt < 256; cnt++ ) { r = pPalette[ cnt ].peRed; g = pPalette[ cnt ].peGreen; b = pPalette[ cnt ].peBlue; if(gusRedShift < 0) r16=((UINT16)r>>abs(gusRedShift)); else r16=((UINT16)r<>abs(gusGreenShift)); else g16=((UINT16)g<>abs(gusBlueShift)); else b16=((UINT16)b< 255) for all three. mono=FALSE. 2) To "darken" a palette, do the same with less than 100% ( < 255) values. mono=FALSE. 3) To create a "glow" palette, select mono=TRUE, and pass the color in the RGB parameters. 4) For gamma correction, pass in weighted values for each color. **********************************************************************************************/ UINT16 *Create16BPPPaletteShaded( SGPPaletteEntry *pPalette, UINT32 rscale, UINT32 gscale, UINT32 bscale, BOOLEAN mono) { UINT16 *p16BPPPalette, r16, g16, b16, usColor; UINT32 cnt, lumin; UINT32 rmod, gmod, bmod; UINT8 r,g,b; Assert( pPalette != NULL ); p16BPPPalette = MemAlloc( sizeof( UINT16 ) * 256 ); for ( cnt = 0; cnt < 256; cnt++ ) { if(mono) { lumin=(pPalette[ cnt ].peRed*299/1000)+ (pPalette[ cnt ].peGreen*587/1000)+(pPalette[ cnt ].peBlue*114/1000); rmod=(rscale*lumin)/256; gmod=(gscale*lumin)/256; bmod=(bscale*lumin)/256; } else { rmod = (rscale*pPalette[ cnt ].peRed/256); gmod = (gscale*pPalette[ cnt ].peGreen/256); bmod = (bscale*pPalette[ cnt ].peBlue/256); } r = (UINT8)__min(rmod, 255); g = (UINT8)__min(gmod, 255); b = (UINT8)__min(bmod, 255); if(gusRedShift < 0) r16=((UINT16)r>>(-gusRedShift)); else r16=((UINT16)r<>(-gusGreenShift)); else g16=((UINT16)g<>(-gusBlueShift)); else b16=((UINT16)b<>abs(gusRedShift)); else r16=((UINT16)r<>abs(gusGreenShift)); else g16=((UINT16)g<>abs(gusBlueShift)); else b16=((UINT16)b<>gusRedShift); if(gusGreenShift < 0) g=((UINT32)g16<>gusGreenShift); if(gusBlueShift < 0) b=((UINT32)b16<>gusBlueShift); r &= 0x000000ff; g &= 0x000000ff; b &= 0x000000ff; val = FROMRGB(r,g,b); return(val); } //***************************************************************************** // // ConvertToPaletteEntry // // Parameter List : Converts from RGB to SGPPaletteEntry // // Return Value pointer to the SGPPaletteEntry // // Modification History : // Dec 15th 1996 -> modified for use by Wizardry // //***************************************************************************** SGPPaletteEntry *ConvertRGBToPaletteEntry(UINT8 sbStart, UINT8 sbEnd, UINT8 *pOldPalette) { UINT16 Index; SGPPaletteEntry *pPalEntry; SGPPaletteEntry *pInitEntry; pPalEntry = (SGPPaletteEntry *)MemAlloc(sizeof(SGPPaletteEntry) * 256); pInitEntry = pPalEntry; DbgMessage(TOPIC_HIMAGE, DBG_LEVEL_0, "Converting RGB palette to SGPPaletteEntry"); for(Index=0; Index <= (sbEnd-sbStart);Index++) { pPalEntry->peRed = *(pOldPalette + (Index*3)); pPalEntry->peGreen = *(pOldPalette + (Index*3) + 1); pPalEntry->peBlue = *(pOldPalette + (Index*3) + 2); pPalEntry->peFlags = 0; pPalEntry++; } return pInitEntry; } BOOLEAN GetETRLEImageData( HIMAGE hImage, ETRLEData *pBuffer ) { // Assertions Assert( hImage != NULL ); Assert( pBuffer != NULL ); // Create memory for data pBuffer->usNumberOfObjects = hImage->usNumberOfObjects; // Create buffer for objects pBuffer->pETRLEObject = MemAlloc( sizeof( ETRLEObject ) * pBuffer->usNumberOfObjects ); CHECKF( pBuffer->pETRLEObject != NULL ); // Copy into buffer memcpy( pBuffer->pETRLEObject, hImage->pETRLEObject, sizeof( ETRLEObject ) * pBuffer->usNumberOfObjects ); // Allocate memory for pixel data pBuffer->pPixData = MemAlloc( hImage->uiSizePixData ); CHECKF( pBuffer->pPixData != NULL ); pBuffer->uiSizePixData = hImage->uiSizePixData; // Copy into buffer memcpy( pBuffer->pPixData, hImage->pPixData8, pBuffer->uiSizePixData ); return( TRUE ); } void ConvertRGBDistribution565To555( UINT16 * p16BPPData, UINT32 uiNumberOfPixels ) { UINT16 * pPixel; UINT32 uiLoop; SplitUINT32 Pixel; pPixel = p16BPPData; for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++) { // If the pixel is completely black, don't bother converting it -- DB if(*pPixel!=0) { // we put the 16 pixel bits in the UPPER word of uiPixel, so that we can // right shift the blue value (at the bottom) into the LOWER word to protect it Pixel.usHigher = *pPixel; Pixel.uiValue >>= 5; // get rid of the least significant bit of green Pixel.usHigher >>= 1; // now shift back into the upper word Pixel.uiValue <<= 5; // and copy back *pPixel = Pixel.usHigher | gusAlphaMask; } pPixel++; } } void ConvertRGBDistribution565To655( UINT16 * p16BPPData, UINT32 uiNumberOfPixels ) { UINT16 * pPixel; UINT32 uiLoop; SplitUINT32 Pixel; pPixel = p16BPPData; for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++) { // we put the 16 pixel bits in the UPPER word of uiPixel, so that we can // right shift the blue value (at the bottom) into the LOWER word to protect it Pixel.usHigher = *pPixel; Pixel.uiValue >>= 5; // get rid of the least significant bit of green Pixel.usHigher >>= 1; // shift to the right some more... Pixel.uiValue >>= 5; // so we can left-shift the red value alone to give it an extra bit Pixel.usHigher <<= 1; // now shift back and copy Pixel.uiValue <<= 10; *pPixel = Pixel.usHigher; pPixel++; } } void ConvertRGBDistribution565To556( UINT16 * p16BPPData, UINT32 uiNumberOfPixels ) { UINT16 * pPixel; UINT32 uiLoop; SplitUINT32 Pixel; pPixel = p16BPPData; for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++) { // we put the 16 pixel bits in the UPPER word of uiPixel, so that we can // right shift the blue value (at the bottom) into the LOWER word to protect it Pixel.usHigher = *pPixel; Pixel.uiValue >>= 5; // get rid of the least significant bit of green Pixel.usHigher >>= 1; // shift back into the upper word Pixel.uiValue <<= 5; // give blue an extra bit (blank in the least significant spot) Pixel.usHigher <<= 1; // copy back *pPixel = Pixel.usHigher; pPixel++; } } void ConvertRGBDistribution565ToAny( UINT16 * p16BPPData, UINT32 uiNumberOfPixels ) { UINT16 * pPixel; UINT32 uiRed, uiGreen, uiBlue, uiTemp, uiLoop; pPixel = p16BPPData; for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++) { // put the 565 RGB 16-bit value into a 32-bit RGB value uiRed = (*pPixel) >> 11; uiGreen = (*pPixel & 0x07E0) >> 5; uiBlue = (*pPixel & 0x001F); uiTemp = FROMRGB(uiRed,uiGreen,uiBlue); // then convert the 32-bit RGB value to whatever 16 bit format is used *pPixel = Get16BPPColor( uiTemp ); pPixel++; } }