/*++ Copyright (c) 2000 Microsoft Corporation Module Name: bmpcvt.cpp Abstract: Bitmap conversion object Environment: Windows Whistler Revision History: 08/23/99 Created it. --*/ #include "xlpdev.h" #include "xldebug.h" #include "xlbmpcvt.h" BPP NumToBPP( ULONG ulBPP) /*++ Routine Description: Converts Bits per pixel to BPP enum. Arguments: Bits per pixel. Return Value: BPP enum Note: BPP enum is defined in xlbmpcvt.h. --*/ { BPP Bpp; switch (ulBPP) { case 1: Bpp = e1bpp; break; case 4: Bpp = e4bpp; break; case 8: Bpp = e8bpp; break; case 16: Bpp = e16bpp; break; case 24: Bpp = e24bpp; break; case 32: Bpp = e32bpp; break; } return Bpp; } ULONG UlBPPtoNum( BPP Bpp) /*++ Routine Description: Converts BPP enum to bits per pixel. Arguments: BPP enum Return Value: Bits per pixel. Note: BPP enum is defined in xlbmpcvt.h. --*/ { ULONG ulRet; switch (Bpp) { case e1bpp: ulRet = 1; break; case e4bpp: ulRet = 4; break; case e8bpp: ulRet = 8; break; case e16bpp: ulRet = 16; break; case e24bpp: ulRet = 24; break; case e32bpp: ulRet = 32; break; } return ulRet; } // // Constructor/Destructor // BMPConv:: BMPConv( VOID ): /*++ Routine Description: BMPConv constructor Arguments: Return Value: Note: Initializes values. There is no memory allocation. --*/ m_flags(0), m_dwOutputBuffSize(0), m_dwRLEOutputBuffSize(0), m_OddPixelStart(eOddPixelZero), m_FirstBit(eBitZero), m_pxlo(NULL), m_pubOutputBuff(NULL), m_pubRLEOutputBuff(NULL) { #if DBG SetDbgLevel(DBG_WARNING); #endif XL_VERBOSE(("BMPConv: Ctor\n")); } BMPConv:: ~BMPConv( VOID ) /*++ Routine Description: BMPConv destructor Arguments: Return Value: Note: m_pubOutputBuff and m_pubRLEOutputBuff are allocaed ConvertBMP. ConvertBMP is scaline base bitmap conversion function. --*/ { XL_VERBOSE(("BMPConv: Dtor\n")); if (m_pubOutputBuff) MemFree(m_pubOutputBuff); if (m_pubRLEOutputBuff) MemFree(m_pubRLEOutputBuff); } // // Public functions // #if DBG VOID BMPConv:: SetDbgLevel( DWORD dwLevel) /*++ Routine Description: Arguments: Return Value: Note: --*/ { m_dbglevel = dwLevel; } #endif BOOL BMPConv:: BSetInputBPP( BPP InputBPP) /*++ Routine Description: Sets source bitmap BPP in BMPConv. Arguments: Source bitmap BPP enum (bits per pixel) Return Value: TRUE if succeeded. Note: --*/ { XL_VERBOSE(("BMPConv: BSetInputBPP\n")); m_flags |= BMPCONV_SET_INPUTBPP; m_InputBPP = InputBPP; return TRUE; } BOOL BMPConv:: BSetOutputBPP( BPP OutputBPP) /*++ Routine Description: Sets destination bimtap BPP in BMPConv. Arguments: Destination bitmap BPP enum Return Value: TRUE if succeeded. Note: --*/ { XL_VERBOSE(("BMPConv: BSetOutputBPP\n")); m_OutputBPP = OutputBPP; return TRUE; } BOOL BMPConv:: BSetOutputBMPFormat( OutputFormat BitmapFormat) /*++ Routine Description: Sets output bitmap format (GrayScale/Palette/RGB/CMYK). Arguments: OutputFormat enum. Return Value: TRUE if succeeded. Note: --*/ { XL_VERBOSE(("BMPConv: BSetOutputBMPFormat\n")); m_OutputFormat = BitmapFormat; return TRUE; } BOOL BMPConv:: BSetRLECompress( BOOL bRLEOn) /*++ Routine Description: Enable/Disable RLE compression. Arguments: Boolean value to enable RLE. Return Value: TRUE if it succeeded. Note: --*/ { XL_VERBOSE(("BMPConv: BSetRLECompress\n")); if (bRLEOn) m_flags |= BMPCONV_RLE_ON; else m_flags &= ~BMPCONV_RLE_ON; return TRUE; } BOOL BMPConv:: BGetRLEStatus(VOID) /*++ Routine Description: Returns RLE on/off. Arguments: Return Value: TRUE if RLE is on. Note: --*/ { XL_VERBOSE(("BMPConv: BGetRLEStatus\n")); return (m_flags & BMPCONV_RLE_ON)?TRUE:FALSE; } BOOL BMPConv:: BSetXLATEOBJ( XLATEOBJ *pxlo) /*++ Routine Description: Sets XLATEOBJ in BMPConv. Arguments: A pointer to XLATEOBJ. Return Value: Note: --*/ { XL_VERBOSE(("BMPConv: BSetXLATEOBJ\n")); // // XL_ERRor check // if (NULL == pxlo) { XL_ERR(("BMPConv::BSetXLATEOBJ: an invalid parameter.\n")); return FALSE; } m_pxlo = pxlo; m_flags |= DwCheckXlateObj(pxlo, m_InputBPP); return TRUE; } PBYTE BMPConv:: PubConvertBMP( PBYTE pubSrc, DWORD dwcbSrcSize) /*++ Routine Description: Scaline base bitmap conversion function. Arguments: pubSrc - a pointer to the source bitmap. dwcbSrcSize - the size of the source bitmap. Return Value: A pointer to the destination bitmap. Note: The pointer to the destination bitmap is stored in BMPConv. It is going to be freed in the BMPConv destructor. --*/ { DWORD dwcbDstSize, dwInputBPP; LONG lWidth, lHeight; PBYTE pubRet = NULL; XL_VERBOSE(("BMPConv: BConvertBMP\n")); // // Calculate the number of pixels and the size of dest buffer // Output data has to be DWORD aligned on PCL-XL. // dwInputBPP = UlBPPtoNum(m_InputBPP); lWidth = ((dwcbSrcSize << 3 ) + dwInputBPP - 1) / dwInputBPP; dwcbDstSize = ((UlBPPtoNum(m_OutputBPP) * lWidth + 31 ) >> 5 ) << 2; // // Allocate destination buffer // if (NULL == m_pubOutputBuff) { m_pubOutputBuff = (PBYTE)MemAlloc(dwcbDstSize); m_dwOutputBuffSize = dwcbDstSize; if (NULL == m_pubOutputBuff) { XL_ERR(("BMPConv::PubConvertBMP: m_pubOutputBuff[0x%x] allocation failed..\n", dwcbDstSize)); return NULL; } } // // Allocate RLE destination buffer if RLE is on. // if (m_flags & BMPCONV_RLE_ON && NULL == m_pubRLEOutputBuff) { dwcbDstSize *= 3; m_pubRLEOutputBuff = (PBYTE)MemAlloc(dwcbDstSize); m_dwRLEOutputBuffSize = dwcbDstSize; if (NULL == m_pubRLEOutputBuff) { XL_ERR(("BMPConv::PubConvertBMP: m_pubOutputBuff[0x%x] allocation failed..\n", dwcbDstSize)); MemFree(m_pubOutputBuff); return NULL; } } // // Converrt source bitmap to destination. // Source and Destination format is set by SetXXX functions. // if (BConversionProc(pubSrc, (dwcbSrcSize * 8 + dwInputBPP - 1) / dwInputBPP)) { if (m_flags & BMPCONV_RLE_ON) { if (BCompressRLE()) pubRet = m_pubRLEOutputBuff; else pubRet = NULL; } else pubRet = m_pubOutputBuff; } else pubRet = NULL; return pubRet; } BOOL BMPConv:: BCompressRLE( VOID) /*++ Routine Description: RLE compression function Arguments: Return Value: TRUE if it succeeded. Note: --*/ { DWORD dwSrcSize, dwDstSize, dwCount, dwErr; PBYTE pubSrcBuff, pubDstBuff, pubLiteralNum; BYTE ubCurrentData; BOOL bLiteral; XL_VERBOSE(("BMPConv: BCompressRLE\n")); if ( NULL == m_pubRLEOutputBuff || NULL == m_pubOutputBuff ) return FALSE; // // // PCL XL Run Length Encoding Compression Method (eRLECompression) // The PCL XL RLE compression method employs control bytes followed by data // bytes. Each // control byte in the compressed data sequence is a signed, two's // complement byte. // If bit 7 of the control byte is zero (0 <= control byte <= 127) the bytes // following are literal. // Literal bytes are simply uncompressed data bytes. The number of literal // bytes following a control // byte is one plus the value of the control byte. Thus, a control byte of 0 // means 1 literal byte // follows; a control byte of 6 means 7 literal bytes follow; and so on. // If bit 7 of the control byte is 1 (-127 <= control byte <= -1), the byte // following the control byte // will occur two or more times as decompressed data. A byte following a // control byte in this range // is called a repeat byte. The control byte39s absolute value plus one is // the number of times the byte // following will occur in the decompressed sequence of bytes. For example, // a control byte of -5 // means the subsequent byte will occur 6 times as decompressed data. // A control byte of -128 is ignored and is not included in the decompressed // data. The byte // following a control byte of 128 is treated as the next control byte. // It is more efficient to code two consecutive identical bytes as a // repeated byte, unless these bytes // are preceded and followed by literal bytes. Three-byte repeats should // always be encoded using a // repeat control byte. // // Literal byte <= 127 // Repeated byte <= 128 // bLiteral = FALSE; dwCount = 1; dwSrcSize = m_dwOutputBuffSize; pubSrcBuff = m_pubOutputBuff; pubDstBuff = m_pubRLEOutputBuff; m_dwRLEOutputDataSize = 0; while (dwSrcSize > 0 && m_dwRLEOutputDataSize + 2 < m_dwRLEOutputBuffSize) { ubCurrentData = *pubSrcBuff++; while (dwSrcSize > dwCount && ubCurrentData == *pubSrcBuff && dwCount < 128 ) { dwCount++; pubSrcBuff++; } if (dwCount > 1) { bLiteral = FALSE; *pubDstBuff++ = 1-(char)dwCount; *pubDstBuff++ = ubCurrentData; m_dwRLEOutputDataSize += 2; } else { if (bLiteral) { (*pubLiteralNum) ++; *pubDstBuff++ = ubCurrentData; m_dwRLEOutputDataSize ++; if (*pubLiteralNum == 127) { bLiteral = FALSE; } } else { bLiteral = TRUE; pubLiteralNum = pubDstBuff; *pubDstBuff++ = 0; *pubDstBuff++ = ubCurrentData; m_dwRLEOutputDataSize += 2; } } dwSrcSize -= dwCount; dwCount = 1; } if (dwSrcSize == 0) return TRUE; else return FALSE; } DWORD BMPConv:: DwGetDstSize(VOID) /*++ Routine Description: Returns the size of destination bitmap. Arguments: Return Value: Note: --*/ { XL_VERBOSE(("BMPConv: DwGetDstSize\n")); if (m_flags & BMPCONV_RLE_ON) return m_dwRLEOutputDataSize; else return m_dwOutputBuffSize; } // // Scanline basis DIB conversion functions // BOOL BMPConv:: BCopy( PBYTE pubSrc, DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. Simple copy for 1BPP, 4,8BPP palette image. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return TRUE if succeeded, otherwise FALSE. --*/ { DWORD dwByteIndex, dwBitIndex, dwSrcBytes, dwSrcRemainderBits; XL_VERBOSE(("BMPConv: BCopy\n")); if (m_InputBPP == e8bpp || m_FirstBit == eBitZero) { dwSrcBytes = (dwSrcPixelNum * (DWORD)UlBPPtoNum(m_InputBPP) + 7) >> 3; CopyMemory(m_pubOutputBuff, pubSrc, dwSrcBytes); } else { // // m_InputBPP is either 1 or 4, m_FirstBit is in [1,7]. // ASSERT((m_InputBPP == e1bpp) || (m_InputBPP == e4bpp)); ASSERT(m_FirstBit != eBitZero); dwSrcBytes = (dwSrcPixelNum * (DWORD)UlBPPtoNum(m_InputBPP)) >> 3; dwSrcRemainderBits = (dwSrcPixelNum * (DWORD)UlBPPtoNum(m_InputBPP)) % 8; // // Now dwSrcBytes is the number of full bytes we need to copy from the source, // dwSrcRemainderBits is the number of remaining bits after dwSrcBytes number // of bytes in the source we need to copy. // // We first copy the full bytes from source. // for (dwByteIndex = 0; dwByteIndex < dwSrcBytes; dwByteIndex++) { // // Compose the destination byte from two adjacent source bytes. // m_pubOutputBuff[dwByteIndex] = (BYTE)(pubSrc[dwByteIndex] << ((DWORD)m_FirstBit)) | (BYTE)(pubSrc[dwByteIndex+1] >> (8 - (DWORD)m_FirstBit)); } if (dwSrcRemainderBits) { // // Now copy the remaining source bits. There are 2 cases: // // (1) the remaining source bits are in 1 byte; // (2) the remaining source bits run across 2 bytes; // if (((DWORD)m_FirstBit + dwSrcRemainderBits - 1) < 8) m_pubOutputBuff[dwByteIndex] = (BYTE)(pubSrc[dwByteIndex] << ((DWORD)m_FirstBit)); else m_pubOutputBuff[dwByteIndex] = (BYTE)(pubSrc[dwByteIndex] << ((DWORD)m_FirstBit)) | (BYTE)(pubSrc[dwByteIndex+1] >> (8 - (DWORD)m_FirstBit)); } } return TRUE; } BOOL BMPConv:: B4BPPtoCMYK( PBYTE pubSrc, DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. 4BPP to CMYK. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return TRUE if succeeded, otherwise FALSE. --*/ { PDWORD pdwColorTable; PBYTE pubDst; DWORD dwConvSize; ULONG ulIndex; XL_VERBOSE(("BMPConv: B4BPPtoCMYK\n")); pdwColorTable = GET_COLOR_TABLE(m_pxlo); if (pdwColorTable == NULL) return FALSE; dwConvSize = (DWORD)m_OddPixelStart; dwSrcPixelNum += dwConvSize; pubDst = m_pubOutputBuff; while (dwConvSize < dwSrcPixelNum) { ulIndex = (dwConvSize++ & 1) ? pdwColorTable[*pubSrc++ & 0x0F] : pdwColorTable[*pubSrc >> 4]; pubDst[0] = CYAN(ulIndex); pubDst[1] = MAGENTA(ulIndex); pubDst[2] = YELLOW(ulIndex); pubDst[3] = BLACK(ulIndex); pubDst += 4; } return TRUE; } BOOL BMPConv:: B4BPPtoRGB( PBYTE pubSrc, DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. 4BPP to RGB. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return TRUE if succeeded, otherwise FALSE. --*/ { PDWORD pdwColorTable; DWORD dwConvSize; ULONG ulIndex; PBYTE pubDst; XL_VERBOSE(("BMPConv: B4BPPtoRGB\n")); pdwColorTable = GET_COLOR_TABLE(m_pxlo); if (pdwColorTable == NULL) return FALSE; dwConvSize = m_OddPixelStart; dwSrcPixelNum += dwConvSize; pubDst = m_pubOutputBuff; while (dwConvSize < dwSrcPixelNum) { ulIndex = (dwConvSize++ & 1) ? pdwColorTable[*pubSrc++ & 0x0F] : pdwColorTable[*pubSrc >> 4]; pubDst[0] = RED(ulIndex); pubDst[1] = GREEN(ulIndex); pubDst[2] = BLUE(ulIndex); pubDst += 3; } return TRUE; } BOOL BMPConv:: B4BPPtoGray( PBYTE pubSrc, DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. 4BPP to Gray. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return TRUE if succeeded, otherwise FALSE. --*/ { PDWORD pdwColorTable; ULONG ulIndex; DWORD dwConvSize; PBYTE pubDst; XL_VERBOSE(("BMPConv: B4BPPtoGray\n")); pdwColorTable = GET_COLOR_TABLE(m_pxlo); if (pdwColorTable == NULL) return FALSE; dwConvSize = m_OddPixelStart; dwSrcPixelNum += dwConvSize; pubDst = m_pubOutputBuff; while (dwConvSize < dwSrcPixelNum) { ulIndex = (dwConvSize++ & 1) ? pdwColorTable[*pubSrc++ & 0x0F] : pdwColorTable[*pubSrc >> 4]; *pubDst++ = DWORD2GRAY(ulIndex); } return TRUE; } BOOL BMPConv:: B8BPPtoGray( IN PBYTE pubSrc, IN DWORD dwSrcPixelNum ) /*++ Routine Description: DIB conversion function - 8BPP to grayscale. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return TRUE if succeeded, otherwise FALSE. --*/ { PDWORD pdwColorTable; DWORD dwColor; PBYTE pubDst; XL_VERBOSE(("BMPConv: B8BPPtoGray\n")); pdwColorTable = GET_COLOR_TABLE(m_pxlo); if (pdwColorTable == NULL) return FALSE; pubDst = m_pubOutputBuff; while (dwSrcPixelNum--) { dwColor = pdwColorTable[*pubSrc++]; *pubDst++ = DWORD2GRAY(dwColor); } return TRUE; } BOOL BMPConv:: B8BPPtoRGB( IN PBYTE pubSrc, IN DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. 8BPP to RGB. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return the size of translated destination bitmap --*/ { PDWORD pdwColorTable; ULONG ulIndex; PBYTE pubDst; XL_VERBOSE(("BMPConv: B8BPPtoRGB\n")); pdwColorTable = GET_COLOR_TABLE(m_pxlo); if (pdwColorTable == NULL) return FALSE; pubDst = m_pubOutputBuff; while (dwSrcPixelNum--) { ulIndex = pdwColorTable[*pubSrc++]; pubDst[0] = RED(ulIndex); pubDst[1] = GREEN(ulIndex); pubDst[2] = BLUE(ulIndex); pubDst += 3; } return TRUE; } BOOL BMPConv:: B8BPPtoCMYK( IN PBYTE pubSrc, IN DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. 8BPP to CMYK. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return the size of translated destination bitmap --*/ { PDWORD pdwColorTable; ULONG ulIndex; PBYTE pubDst; XL_VERBOSE(("BMPConv: B8BPPtoCMYK\n")); pdwColorTable = GET_COLOR_TABLE(m_pxlo); if (pdwColorTable == NULL) return FALSE; pubDst = m_pubOutputBuff; while (dwSrcPixelNum--) { ulIndex = pdwColorTable[*pubSrc++]; pubDst[0] = CYAN(ulIndex); pubDst[1] = MAGENTA(ulIndex); pubDst[2] = YELLOW(ulIndex); pubDst[3] = BLACK(ulIndex); pubDst += 4; } return TRUE; } BOOL BMPConv:: B16BPPtoGray( IN PBYTE pubSrc, IN DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. 16BPP to 8 bits gray. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return TRUE if succeeded, otherwise FALSE. --*/ { DWORD dwColor; PBYTE pubDst = m_pubOutputBuff; XL_VERBOSE(("BMPConv: B16BPPtoGray\n")); while (dwSrcPixelNum--) { dwColor = XLATEOBJ_iXlate(m_pxlo, *((PWORD) pubSrc)); pubSrc += 2; *pubDst++ = DWORD2GRAY(dwColor); } return TRUE; } BOOL BMPConv:: B16BPPtoRGB( IN PBYTE pubSrc, IN DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. 16BPP to RGB. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return TRUE if succeeded, otherwise FALSE. --*/ { DWORD dwColor; PBYTE pubDst = m_pubOutputBuff; XL_VERBOSE(("BMPConv: B16BPPtoRGB\n")); while (dwSrcPixelNum--) { dwColor = XLATEOBJ_iXlate(m_pxlo, *((PWORD) pubSrc)); pubSrc += 2; pubDst[0] = RED(dwColor); pubDst[1] = GREEN(dwColor); pubDst[2] = BLUE(dwColor); pubDst += 3; } return TRUE; } BOOL BMPConv:: B24BPPtoGray( IN PBYTE pubSrc, IN DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. 24BPP to 8 bits gray. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return TRUE if succeeded, otherwise FALSE. --*/ { DWORD dwColor; PBYTE pubDst = m_pubOutputBuff; XL_VERBOSE(("BMPConv: B24BPPtoGray\n")); if (! (m_flags & BMPCONV_CHECKXLATEOBJ)) { // // No special conversion is necessary. // Pure 24BPP RGB image. // while (dwSrcPixelNum--) { *pubDst++ = RGB2GRAY(pubSrc[0], pubSrc[1], pubSrc[2]); pubSrc += 3; } } else if (m_flags & BMPCONV_BGR) { while (dwSrcPixelNum--) { *pubDst++ = RGB2GRAY(pubSrc[2], pubSrc[1], pubSrc[0]); pubSrc += 3; } } else { ASSERT(m_flags & BMPCONV_XLATE); while (dwSrcPixelNum--) { dwColor = ((DWORD) pubSrc[0] ) | ((DWORD) pubSrc[1] << 8) | ((DWORD) pubSrc[2] << 16); pubSrc += 3; dwColor = XLATEOBJ_iXlate(m_pxlo, dwColor); *pubDst++ = DWORD2GRAY(dwColor); } } return TRUE; } BOOL BMPConv:: B24BPPtoRGB( IN PBYTE pubSrc, IN DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. 24BPP to RGB. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return TRUE if succeeded, otherwise FALSE. --*/ { DWORD dwColor; PBYTE pubDst = m_pubOutputBuff; XL_VERBOSE(("BMPConv: B24BPPtoRGB\n")); if (! (m_flags & BMPCONV_CHECKXLATEOBJ)) { // // No special conversion is necessary. // Pure 24BPP RGB image. // CopyMemory(m_pubOutputBuff, pubSrc, dwSrcPixelNum * 3); } else if (m_flags & BMPCONV_BGR) { while (dwSrcPixelNum--) { pubDst[0] = pubSrc[2]; pubDst[1] = pubSrc[1]; pubDst[2] = pubSrc[0]; pubSrc += 3; pubDst += 3; } } else if (m_flags & BMPCONV_XLATE) { while (dwSrcPixelNum--) { dwColor = ((DWORD) pubSrc[0] ) | ((DWORD) pubSrc[1] << 8) | ((DWORD) pubSrc[2] << 16); pubSrc += 3; dwColor = XLATEOBJ_iXlate(m_pxlo, dwColor); pubDst[0] = RED(dwColor); pubDst[1] = GREEN(dwColor); pubDst[2] = BLUE(dwColor); pubDst += 3; } } return TRUE; } BOOL BMPConv:: B32BPPtoGray( IN PBYTE pubSrc, IN DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. 32BPP to 8 bits Gray. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return TRUE if succeeded, otherwise FALSE. --*/ { DWORD dwColor; BYTE ubCyan, ubMagenta, ubYellow, ubBlack; PBYTE pubDst = m_pubOutputBuff; XL_VERBOSE(("BMPConv: B24BPPtoGray\n")); if (! (m_flags & BMPCONV_CHECKXLATEOBJ)) { // // No special conversion is necessary. // Source bitmap is a pure 32BPP CMYK image. // while (dwSrcPixelNum--) { ubCyan = *pubSrc++; ubMagenta = *pubSrc++; ubYellow = *pubSrc++; ubBlack = *pubSrc++; *pubDst++ = RGB2GRAY(255 - min(255, (ubCyan + ubBlack)), 255 - min(255, (ubMagenta + ubBlack)), 255 - min(255, (ubYellow + ubBlack))); } } else if (m_flags & BMPCONV_32BPP_RGB) { while (dwSrcPixelNum--) { *pubDst++ = RGB2GRAY(pubSrc[0], pubSrc[1], pubSrc[2]); pubSrc += 4; } } else if (m_flags & BMPCONV_32BPP_BGR) { while (dwSrcPixelNum--) { *pubDst++ = RGB2GRAY(pubSrc[0], pubSrc[1], pubSrc[2]); pubSrc += 4; } } else { ASSERT(m_flags & BMPCONV_XLATE); while (dwSrcPixelNum--) { dwColor = XLATEOBJ_iXlate(m_pxlo, *((PDWORD) pubSrc)); pubSrc += 4; *pubDst++ = DWORD2GRAY(dwColor); } } return TRUE; } BOOL BMPConv:: B32BPPtoRGB( IN PBYTE pubSrc, IN DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. 32BPP to RGB. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return TRUE if succeeded, otherwise FALSE. --*/ { DWORD dwColor; BYTE ubCyan, ubMagenta, ubYellow, ubBlack; PBYTE pubDst = m_pubOutputBuff; XL_VERBOSE(("BMPConv: B32BPPtoRGB\n")); if (! (m_flags & BMPCONV_CHECKXLATEOBJ)) { // // No special conversion is necessary. // Source bitmap is a pure 32BPP CMYK image. // while (dwSrcPixelNum--) { ubCyan = pubSrc[0]; ubMagenta = pubSrc[1]; ubYellow = pubSrc[2]; ubBlack = pubSrc[3]; pubSrc += 4; ubCyan += ubBlack; ubMagenta += ubBlack; ubYellow += ubBlack; pubDst[0] = 255 - min(255, ubCyan); pubDst[1] = 255 - min(255, ubMagenta); pubDst[2] = 255 - min(255, ubYellow); pubDst += 3; } } else if (m_flags & BMPCONV_32BPP_RGB) { while (dwSrcPixelNum--) { pubDst[0] = pubSrc[0]; pubDst[1] = pubSrc[1]; pubDst[2] = pubSrc[2]; pubSrc += 4; pubDst += 3; } } else if (m_flags & BMPCONV_32BPP_BGR) { while (dwSrcPixelNum--) { pubDst[0] = pubSrc[2]; pubDst[1] = pubSrc[1]; pubDst[2] = pubSrc[0]; pubSrc += 4; pubDst += 3; } } else { ASSERT(m_flags & BMPCONV_XLATE); while (dwSrcPixelNum--) { dwColor = XLATEOBJ_iXlate(m_pxlo, *((PDWORD) pubSrc)); pubSrc += 4; pubDst[0] = RED(dwColor); pubDst[1] = GREEN(dwColor); pubDst[2] = BLUE(dwColor); } } return TRUE; } BOOL BMPConv:: B32BPPtoCMYK( IN PBYTE pubSrc, IN DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. 32BPP to CMYK. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return TRUE if succeeded, otherwise FALSE. --*/ { DWORD dwColor; PBYTE pubDst = m_pubOutputBuff; XL_VERBOSE(("BMPConv: B32BPPtoCMYK\n")); if (! (m_flags & BMPCONV_CHECKXLATEOBJ)) { // // No special conversion is necessary. // Source bitmap is a pure 32BPP CMYK image. // CopyMemory(m_pubOutputBuff, pubSrc, dwSrcPixelNum * 4); } else { ASSERT(m_flags & BMPCONV_XLATE); while (dwSrcPixelNum--) { dwColor = XLATEOBJ_iXlate(m_pxlo, *((PDWORD) pubSrc)); pubSrc += 4; pubDst[0] = 255 - RED(dwColor); pubDst[1] = 255 - GREEN(dwColor); pubDst[2] = 255 - BLUE(dwColor); pubDst[3] = 0; pubDst += 4; } } return TRUE; } BOOL BMPConv:: BArbtoGray( PBYTE pubSrc, DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. Arbitray bitmap to 8 bits Gray scale. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return TRUE if succeeded, otherwise FALSE. --*/ { DWORD dwColor; PDWORD pdwSrc; PBYTE pubDst = m_pubOutputBuff; XL_VERBOSE(("BMPConv: BArbtoGray\n")); pdwSrc = (PDWORD) pubSrc; while (dwSrcPixelNum--) { dwColor = XLATEOBJ_iXlate(m_pxlo, *pdwSrc++); *pubDst++ = DWORD2GRAY(dwColor); } return TRUE; } BOOL BMPConv:: BArbtoRGB( PBYTE pubSrc, DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. Arbitraty bitmap to RGB. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return TRUE if succeeded, otherwise FALSE. --*/ { DWORD dwColor; PDWORD pdwSrc; PBYTE pubDst = m_pubOutputBuff; XL_VERBOSE(("BMPConv: BArbtoRGB\n")); pdwSrc = (PDWORD) pubSrc; while (dwSrcPixelNum--) { dwColor = XLATEOBJ_iXlate(m_pxlo, *pdwSrc++); pubDst[0] = RED(dwColor); pubDst[1] = GREEN(dwColor); pubDst[2] = BLUE(dwColor); pubDst += 3; } return TRUE; } #ifdef WINNT_40 BOOL BMPConv:: B24BPPToImageMask( PBYTE pubSrc, DWORD dwSrcPixelNum) /*++ Routine Description: DIB conversion function. 24 bpp bitmaps with only one non-white color to image mask. Can happen on NT4, where GDI does not optimize for that case. Arguments: pubSrc - Source DIB buffer dwSrcPixelNum - the number of source pixel Return Value: Return TRUE if succeeded, otherwise FALSE. --*/ { DWORD dwColor; PDWORD pdwSrc; BYTE ubDest = 0; DWORD dwIndex = 0; DWORD dwTransp = (m_flags & BMPCONV_SRC_COPY) ? RGB_WHITE : RGB_BLACK; PBYTE pubDst = m_pubOutputBuff; XL_VERBOSE(("BMPConv: B24BPPToImageMask\n")); while (dwSrcPixelNum--) { if (! (m_flags & BMPCONV_CHECKXLATEOBJ)) { // // No special conversion is necessary, 24BPP RGB image. // dwColor = ((DWORD) pubSrc[0] ) | ((DWORD) pubSrc[1] << 8) | ((DWORD) pubSrc[2] << 16); } else if (m_flags & BMPCONV_BGR) { // // convert 24BPP BGR to RGB. // dwColor = ((DWORD) pubSrc[2] ) | ((DWORD) pubSrc[1] << 8) | ((DWORD) pubSrc[0] << 16); } else if (m_flags & BMPCONV_XLATE) { dwColor = ((DWORD) pubSrc[0] ) | ((DWORD) pubSrc[1] << 8) | ((DWORD) pubSrc[2] << 16); pubSrc += 3; dwColor = XLATEOBJ_iXlate(m_pxlo, dwColor); } ubDest = ubDest << 1; dwIndex++; pubSrc += 3; if (dwColor != dwTransp) ubDest |= 0x01; if (dwIndex == 8) // one byte completed ? { *pubDst++ = ubDest; dwIndex = 0; ubDest = 0; } } if (dwIndex != 0) // flush leftover bits *pubDst = ubDest; return TRUE; } #endif BOOL BMPConv:: BConversionProc( PBYTE pubSrc, DWORD dwSrcPixelNum) /*++ Routine Description: Return a pointer to the appropriate DIB conversion function Arguments: pBMPAttrrib - Points to a BMPATTRUTE structure Return Value: Pointer to a DIB conversion function --*/ { //PVOID pfnDibConv[7][4] = { // Gray Scale, Palette, RGB, CMYK //----------------------------------------------------------------------- //{BCopy, BCopy, NULL, NULL}, // 1bpp //{B4BPPtoGray, BCopy, B4BPPtoRGB, B4BPPtoCMYK}, // 4bpp //{B8BPPtoGray, BCopy, B8BPPtoRGB, B8BPPtoCMYK}, // 8bpp //{B16BPPtoGray, NULL, B16BPPtoRGB, NULL}, // 16bpp //{B24BPPtoGray, NULL, B24BPPtoRGB, NULL}, // 24bpp //{B32BPPtoGray, NULL, B32BPPtoRGB, B32BPPtoCMYK},// 32bpp //{BArbtoGray, NULL, BArbtoRGB, NULL} // Arbitrary //}; XL_VERBOSE(("BMPConv: BConversionProc\n")); // // special case for NT4: GDI passes all bitmaps as 24 bpp, even 1 bpp bitmaps // that can be better treated through image masks // #if 0 // #ifdef WINNT_40 if (m_flags & BMPCONV_2COLOR_24BPP) { return B24BPPToImageMask; } #endif BOOL bRet = FALSE; // // Zero init for DWORD alignment // ZeroMemory(m_pubOutputBuff, m_dwOutputBuffSize); switch (m_InputBPP) { case e1bpp: switch(m_OutputFormat) { case eOutputGray: case eOutputPal: BCopy(pubSrc, dwSrcPixelNum); bRet = TRUE; break; case eOutputRGB: case eOutputCMYK: break; } break; case e4bpp: switch(m_OutputFormat) { case eOutputGray: B4BPPtoGray(pubSrc, dwSrcPixelNum); bRet = TRUE; break; case eOutputPal: BCopy(pubSrc, dwSrcPixelNum); bRet = TRUE; break; case eOutputRGB: B4BPPtoRGB(pubSrc, dwSrcPixelNum); bRet = TRUE; break; case eOutputCMYK: B4BPPtoCMYK(pubSrc, dwSrcPixelNum); bRet = TRUE; break; } break; case e8bpp: switch(m_OutputFormat) { case eOutputGray: B8BPPtoGray(pubSrc, dwSrcPixelNum); bRet = TRUE; break; case eOutputPal: BCopy(pubSrc, dwSrcPixelNum); bRet = TRUE; break; case eOutputRGB: B8BPPtoRGB(pubSrc, dwSrcPixelNum); bRet = TRUE; break; case eOutputCMYK: B8BPPtoCMYK(pubSrc, dwSrcPixelNum); bRet = TRUE; break; } break; case e16bpp: switch(m_OutputFormat) { case eOutputGray: B16BPPtoGray(pubSrc, dwSrcPixelNum); bRet = TRUE; break; case eOutputPal: BCopy(pubSrc, dwSrcPixelNum); bRet = TRUE; break; break; case eOutputRGB: B16BPPtoRGB(pubSrc, dwSrcPixelNum); bRet = TRUE; break; case eOutputCMYK: XL_ERR(("BMPConv::BConversionProc: 16 to CMYK is not supported yet.\n")); break; } break; case e24bpp: switch(m_OutputFormat) { case eOutputGray: B24BPPtoGray(pubSrc, dwSrcPixelNum); bRet = TRUE; break; case eOutputPal: break; case eOutputRGB: B24BPPtoRGB(pubSrc, dwSrcPixelNum); bRet = TRUE; break; case eOutputCMYK: break; } break; case e32bpp: switch(m_OutputFormat) { case eOutputGray: B32BPPtoGray(pubSrc, dwSrcPixelNum); bRet = TRUE; break; case eOutputPal: break; case eOutputRGB: B32BPPtoRGB(pubSrc, dwSrcPixelNum); bRet = TRUE; break; case eOutputCMYK: B32BPPtoCMYK(pubSrc, dwSrcPixelNum); bRet = TRUE; break; } break; default: switch(m_OutputFormat) { case eOutputGray: BArbtoGray(pubSrc, dwSrcPixelNum); bRet = TRUE; break; case eOutputPal: break; case eOutputRGB: BArbtoRGB(pubSrc, dwSrcPixelNum); bRet = TRUE; break; case eOutputCMYK: XL_ERR(("BMPConv::BConversionProc: Arb to CMYK is not supported yet.\n")); break; } } return bRet; } DWORD BMPConv:: DwCheckXlateObj( IN XLATEOBJ *pxlo, IN BPP InputBPP) /*++ Routine Description: Determines the type of converison. *Palette *RGB *BGR *CMYK *Call XLATEOBJ_XXX function. Arguments: Return Value: Note: --*/ { DWORD dwRet; DWORD Dst[4]; XL_VERBOSE(("BMPConv: DwCheckXlateObj\n")); // // Init dwRet // dwRet = 0; switch (InputBPP) { case e16bpp: dwRet = BMPCONV_XLATE; break; case e24bpp: if (pxlo->iSrcType == PAL_RGB) dwRet = 0; else if (pxlo->iSrcType == PAL_BGR) dwRet = BMPCONV_BGR; { Dst[0] = XLATEOBJ_iXlate(pxlo, 0x000000FF); Dst[1] = XLATEOBJ_iXlate(pxlo, 0x0000FF00); Dst[2] = XLATEOBJ_iXlate(pxlo, 0x00FF0000); if ((Dst[0] == 0x000000FF) && (Dst[1] == 0x0000FF00) && (Dst[2] == 0x00FF0000) ) { dwRet = 0; } else if ((Dst[0] == 0x00FF0000) && (Dst[1] == 0x0000FF00) && (Dst[2] == 0x000000FF) ) { dwRet = BMPCONV_BGR; } } break; case e32bpp: if (pxlo->flXlate & XO_FROM_CMYK) dwRet = 0; else { // // Translate all 4 bytes from the DWORD // Dst[0] = XLATEOBJ_iXlate(pxlo, 0x000000FF); Dst[1] = XLATEOBJ_iXlate(pxlo, 0x0000FF00); Dst[2] = XLATEOBJ_iXlate(pxlo, 0x00FF0000); Dst[3] = XLATEOBJ_iXlate(pxlo, 0xFF000000); if ((Dst[0] == 0x000000FF) && (Dst[1] == 0x0000FF00) && (Dst[2] == 0x00FF0000) && (Dst[3] == 0x00000000)) { // // If translate result is same (4th byte will be zero) then // we done with it except if 32bpp then we have to skip one // source byte for every 3 bytes // dwRet = BMPCONV_32BPP_RGB; } else if ((Dst[0] == 0x00FF0000) && (Dst[1] == 0x0000FF00) && (Dst[2] == 0x000000FF) && (Dst[3] == 0x00000000)) { // // Simply swap the R and B component // dwRet = BMPCONV_32BPP_BGR; } } } return dwRet; }