/*++ 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 "pclxle.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_dwDRCOutputBuffSize(0), m_OddPixelStart(eOddPixelZero), m_FirstBit(eBitZero), m_pxlo(NULL), m_pubOutputBuff(NULL), m_pubRLEOutputBuff(NULL), m_pubDRCOutputBuff(NULL), m_pubDRCPrevOutputBuff(NULL), m_CMode(eNoCompression) { #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")); // // DRCPrevOutputBuff and OutputBuff are contiguous. if (m_pubOutputBuff) MemFree(m_pubOutputBuff); if (m_pubRLEOutputBuff) MemFree(m_pubRLEOutputBuff); if (m_pubDRCOutputBuff) MemFree(m_pubDRCOutputBuff); } // // 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:: BSetCompressionType( CompressMode CMode) /*++ Routine Description: Set compression type. Arguments: CompressMode {eNoCompression, eRLECompression, eDeltaRowCompression} Return Value: TRUE if it succeeded. Note: --*/ { XL_VERBOSE(("BMPConv: BSetCompressionType.\n")); m_CMode = CMode; return TRUE; } CompressMode BMPConv:: GetCompressionType(VOID) /*++ Routine Description: CompressMode Arguments: Return Value: Note: --*/ { XL_VERBOSE(("BMPConv: BGetRLEStatus\n")); return m_CMode; } 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); m_dwWidth = ((dwcbSrcSize << 3 ) + dwInputBPP - 1) / dwInputBPP; dwcbDstSize = ((UlBPPtoNum(m_OutputBPP) * m_dwWidth + 31 ) >> 5 ) << 2; // // Allocate destination buffer // if (NULL == m_pubOutputBuff || NULL == m_pubDRCPrevOutputBuff) { // // Allocate main and previous output buffer for DRC. // m_pubOutputBuff = (PBYTE)MemAlloc(dwcbDstSize * 2); if (NULL == m_pubOutputBuff) { XL_ERR(("BMPConv::PubConvertBMP: m_pubOutputBuff[0x%x] allocation failed..\n", dwcbDstSize)); return NULL; } m_dwOutputBuffSize = dwcbDstSize; // // Zero init seed row. // PCL XL exception about DRC. // 1) the seed row is initialized to zeroes and contains the number // of bytes defined by SourceWidth in the BeginImage operator. // m_pubDRCPrevOutputBuff = m_pubOutputBuff + dwcbDstSize; m_dwDRCPrevOutputBuffSize = dwcbDstSize; memset(m_pubDRCPrevOutputBuff, 0, m_dwDRCPrevOutputBuffSize); } // // Allocate RLE destination buffer if RLE is on. // if (m_CMode == eRLECompression && NULL == m_pubRLEOutputBuff) { m_pubRLEOutputBuff = (PBYTE)MemAlloc(dwcbDstSize * 3); m_dwRLEOutputBuffSize = dwcbDstSize * 3; if (NULL == m_pubRLEOutputBuff) { XL_ERR(("BMPConv::PubConvertBMP: m_pubOutputBuff[0x%x] allocation failed..\n", dwcbDstSize)); MemFree(m_pubOutputBuff); m_pubOutputBuff = NULL; m_dwOutputBuffSize = 0; m_pubDRCPrevOutputBuff = NULL; m_dwDRCPrevOutputBuffSize = 0; return NULL; } } // // Allocate DRC destination buffer if DRC is on. // if (m_CMode == eDeltaRowCompression && NULL == m_pubDRCOutputBuff) { m_pubDRCOutputBuff = (PBYTE)MemAlloc(dwcbDstSize * 3); m_dwDRCOutputBuffSize = dwcbDstSize * 3; if (NULL == m_pubDRCOutputBuff) { XL_ERR(("BMPConv::PubConvertBMP: m_pubOutputBuff[0x%x] allocation failed..\n", dwcbDstSize)); MemFree(m_pubOutputBuff); m_pubOutputBuff = NULL; m_pubDRCPrevOutputBuff = NULL; MemFree(m_pubRLEOutputBuff); m_pubRLEOutputBuff = NULL; 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_CMode == eRLECompression) { if (BCompressRLE()) pubRet = m_pubRLEOutputBuff; else pubRet = NULL; } else if (m_CMode == eDeltaRowCompression) { if (BCompressDRC()) pubRet = m_pubDRCOutputBuff; else pubRet = NULL; // // Update seed row for DRC. // CopyMemory(m_pubDRCPrevOutputBuff, m_pubOutputBuff, m_dwDRCPrevOutputBuffSize); } 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, dwInputBPP, dwWidth; 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; } BOOL BMPConv:: BCompressDRC( VOID) /*++ Routine Description: This function is called to compress a scan line of data using delta row compression. Arguments: Return Value: Number of compressed bytes or -1 if too large for buffer Note: A return value of 0 is valid since it implies the two lines are identical. --*/ { BYTE *pbI; BYTE *pbO; /* Record output location */ BYTE *pbOEnd; /* As far as we will go in the output buffer */ BYTE *pbIEnd; BYTE *pbStart; BYTE *pb; int iDelta; int iOffset; // index of current data stream int iSize; /* Number of bytes in the run */ int iSrcSize; // // The control byte has the following format: // Number of delta bytes: Bits 5-7 indicate the number of consecutive // replacement bytes that follow the commands byte. The actual number // of of replacement bytes is always one more than the value // (000 = 1, 111 = 8). If more than 8 delta bytes are needed, // additional command byte/delta bytes are added. // [ (Command Byte) (1-8 Delta Bytes) ] // [ (Command Byte) (1-8 Delta Bytes) ] . . . // Offset: Bits 0-4 show where to position the replacement byte string. // This is the offset: it specifies a byte placement, counting from left // to right from the current byte position. The current byte is the // first unaltered byte that follows the last replacement bytes; at the // beginning of a row, the current byte immediately follows the left // raster margin. Bits 0-4 allow a maximum value of 31, but larger // offsets are possible. A value of 0 to 30 indicates the delta bytes // are offset from the 1st to the 31st bytes. // A value of 31 indicates that an additional offset byte follows the // command byte. // // To summarize, bits 0-4 have the following meaning: // 0 to 30: the offset is 0 to 30. // 31: the offset is 31 or greater. If the offset is 31, an additional // offset byte follows the command byte. The offset in the command bytes // is added to the offset bytes. If the offset byte is 0, the offset is // 31; if the offset byte is 255 additional offset bytes follow. // The last offset byte will have a value less than 255. All the offset // bytes are added to the offset in the command byte to get the offset // value. For example, if there are two offset bytes, and the last // byte contains 175, the total offset would be: 31+255+175=461. // /* * Limit the amount of data we will generate. For performance * reasons we will ignore the effects of an offset value * greater than 30 since it implies we were able to already skip * that many bytes. However, for safety sake we will reduce the * max allowable size by 2 bytes. */ XL_VERBOSE(("BMPConv: BCompressDRC\n")); m_dwDRCOutputDataSize = 0; if ( NULL == m_pubDRCOutputBuff || NULL == m_pubDRCPrevOutputBuff || NULL == m_pubOutputBuff ) return FALSE; pbI = m_pubOutputBuff; /* Working copy */ iSrcSize = (UlBPPtoNum(m_OutputBPP) * m_dwWidth + 7) >> 3; pbIEnd = m_pubOutputBuff + iSrcSize; pbO = m_pubDRCOutputBuff; /* Working copy */ pbOEnd = m_pubDRCOutputBuff + m_dwDRCOutputBuffSize - 2; // // m_pubDRCPrevOutputBuff is continuously followed by m_putOutputBuff. // Both has m_dwOutputBuffSize size of memory. // iDelta = (int)(m_pubDRCPrevOutputBuff - m_pubOutputBuff); pbStart = m_pubOutputBuff; // // PCL XL exception. // 2) the delta row is preceded by a 2-byte byte count which // indicates the number of bytes to follow for the delta row. // The byte count is expected to be in LSB MSB order. // *((PWORD)pbO) = 0x0000; pbO += 2; // // this is the main loop for compressing the data // while (pbI < pbIEnd) { // fast skip for matching dwords // if (!((ULONG_PTR)pbI & 3)) { while (pbI <= (pbIEnd-4) && *(DWORD *)pbI == *(DWORD *)&pbI[iDelta]) pbI += 4; if (pbI >= pbIEnd) break; } // test for non-matching bytes and output the necessary compression string // if (*pbI != pbI[iDelta]) { // determine the run length pb = pbI; do { pb++; } while (pb < pbIEnd && *pb != pb[iDelta]); iSize = (int)(pb - pbI); // Lets make sure we have room in the buffer before // we continue this, this compression algorithm adds // 1 byte for every 8 bytes of data worst case. // if (((iSize * 9 + 7) >> 3) > (pbOEnd - pbO)) // gives tighter code return FALSE; iOffset = (int)(pbI - pbStart); if (iOffset > 30) { if (iSize < 8) *pbO++ = ((iSize-1) << 5) + 31; else *pbO++ = (7 << 5) + 31; iOffset -= 31; while (iOffset >= 255) { iOffset -= 255; *pbO++ = 255; } *pbO++ = (BYTE)iOffset; if (iSize > 8) goto FastEightByteRun; } else if (iSize > 8) { *pbO++ = (7 << 5) + iOffset; FastEightByteRun: while (1) { CopyMemory(pbO,pbI,8); pbI += 8; pbO += 8; if ((iSize -= 8) <= 8) break; *pbO++ = (7 << 5); } *pbO++ = (iSize-1) << 5; } else *pbO++ = ((iSize-1) << 5) + iOffset; CopyMemory (pbO,pbI,iSize); pbI += iSize; pbO += iSize; pbStart = pbI; } pbI++; } // // PCL XL exception. // 2) the delta row is preceded by a 2-byte byte count which // indicates the number of bytes to follow for the delta row. // The byte count is expected to be in LSB MSB order. // m_dwDRCOutputDataSize = (DWORD)(pbO - m_pubDRCOutputBuff); (*(PWORD)m_pubDRCOutputBuff) = (WORD)m_dwDRCOutputDataSize - 2; return TRUE; } DWORD BMPConv:: DwGetDstSize(VOID) /*++ Routine Description: Returns the size of destination bitmap. Arguments: Return Value: Note: --*/ { XL_VERBOSE(("BMPConv: DwGetDstSize\n")); if (m_CMode == eDeltaRowCompression) return m_dwDRCOutputDataSize; else if (m_CMode == eRLECompression) 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); pubDst += 3; } } 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); 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; }