/****************************************************************************/ /* abdapi.cpp */ /* */ /* Bitmap Decompression API functions */ /* */ /* Copyright(C) Microsoft Corporation 1996-1999 */ /****************************************************************************/ #include extern "C" { #define TRC_GROUP TRC_GROUP_CORE #define TRC_FILE "abdapi" #include } #define TSC_HR_FILEID TSC_HR_ABDAPI_CPP #include /****************************************************************************/ /* */ /* See abdapi.h for descriptions of compression codes. */ /* */ /****************************************************************************/ /****************************************************************************/ /* We shouldn't have OS_WINDOWS macros in an "a" file, but this file */ /* generates lots of "conditional expression is constant" warnings due */ /* to the optimised nature of the code (lots of macros). */ /* */ /* The pragmatic (no pun intended) solution to this is to disable this */ /* warning for the whole file in a way that won't affect other OSs. */ /****************************************************************************/ #ifdef OS_WINDOWS #pragma warning (push) #pragma warning (disable: 4127) #endif /****************************************************************************/ /* Name: BDMemcpy */ /* */ /* Purpose: Copies a given number of bytes from source to destination. */ /* Source and destination may overlap, but copy is always */ /* performed upwards (from start address onwards). */ /* */ /* Params: pDst - pointer to destination */ /* pSrc - pointer to source data */ /* count - number of bytes to copy */ /****************************************************************************/ _inline DCVOID DCINTERNAL BDMemcpy(PDCUINT8 pDst, PDCUINT8 pSrc, DCUINT count) { #if defined(DC_DEBUG) || defined(DC_NO_UNALIGNED) || defined(_M_IA64) DCUINT i; #endif DC_BEGIN_FN("BDMemcpy"); /************************************************************************/ /* Bitmap decompression deliberately does overlapped memcpys, e.g. */ /* from the previous bitmap row to the current bitmap row for more than */ /* one row. */ /* */ /* When using the intrinsic memcpy (in the retail build) this works */ /* fine (in the current implementation of the MS compiler), as the copy */ /* always goes upwards through memory. However, if we use the MSVC */ /* run-time library (in the debug build) then memcpy appears to check */ /* for overlap and performs the copy so as to avoid clashing of src and */ /* dst (i.e. effectively performs a memmove). Therefore this does not */ /* do what we want, so manually copy the bytes in a debug build. */ /* */ /* This solution is a little unsatisfactory, as the operation of memset */ /* is officially undefined, but the performance-critical nature of */ /* this bit of code means that we really do want to use a memcpy. */ /* */ /* For non-Intel platforms, cannot rely on the above - so always use */ /* manual version. */ /* */ /************************************************************************/ #if defined(DC_DEBUG) || defined(DC_NO_UNALIGNED) || defined(_M_IA64) /************************************************************************/ /* Debug build implementation. */ /************************************************************************/ for (i = 0; i < count; i++) { *pDst++ = *pSrc++; } #else /************************************************************************/ /* Retail build implementation. */ /************************************************************************/ DC_MEMCPY(pDst, pSrc, count); #endif DC_END_FN(); return; } /****************************************************************************/ /* Utility macros for decoding codes */ /****************************************************************************/ #define BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr, \ (TB, _T("Decompress reads one byte end of buffer; [p=0x%x pEnd=0x%x]"), \ (pBuffer), (pEnd) )) #define BD_CHECK_READ_ONE_BYTE_2ENDED(pBuffer, pStart, pEnd, hr ) \ CHECK_READ_ONE_BYTE_2ENDED(pBuffer, pStart, pEnd, hr, (TB, _T("Decompress reads one byte off end of buffer; [p=0x%x pStart=0x%x pEnd=0x%x]"), \ (pBuffer), (pStart), (pEnd) )) #define BD_CHECK_WRITE_ONE_BYTE(pBuffer, pEnd, hr ) \ CHECK_WRITE_ONE_BYTE(pBuffer, pEnd, hr, (TB, _T("Decompress writes one byte off end of buffer; [p=0x%x pEnd=0x%x]"), \ (pBuffer), (pEnd) )) #define BD_CHECK_READ_N_BYTES(pBuffer, pEnd, N, hr ) \ CHECK_READ_N_BYTES(pBuffer, pEnd, N, hr, (TB, _T("Decompress reads off end of buffer; [p=0x%x pEnd=0x%x N=%u]"), \ (pBuffer), (pEnd), (ULONG)(N))) #define BD_CHECK_READ_N_BYTES_2ENDED(pBuffer, pStart, pEnd, N, hr ) \ CHECK_READ_N_BYTES_2ENDED(pBuffer, pStart, pEnd, N, hr, (TB, _T("Decompress reads off end of buffer; [p=0x%x pStart=0x%x pEnd=0x%x N=%u]"), \ (pBuffer), (pStart), (pEnd), (ULONG)(N) )) #define BD_CHECK_WRITE_N_BYTES(pBuffer, pEnd, N, hr ) \ CHECK_WRITE_N_BYTES(pBuffer, pEnd, N, hr, (TB, _T("Decompress write off end of buffer; [p=0x%x pEnd=0x%x N=%u]"), \ (pBuffer), (pEnd), (ULONG)(N))) /****************************************************************************/ /* Macros to extract the length from order codes */ /****************************************************************************/ #define EXTRACT_LENGTH(pBuffer, pEnd, length, hr) \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ & MAX_LENGTH_ORDER; \ if (length == 0) \ { \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ + MAX_LENGTH_ORDER + 1; \ } #define EXTRACT_LENGTH_LITE(pBuffer, pEnd, length, hr ) \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ & MAX_LENGTH_ORDER_LITE; \ if (length == 0) \ { \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ + MAX_LENGTH_ORDER_LITE + 1; \ } #define EXTRACT_LENGTH_FGBG(pBuffer, pEnd, length, hr ) \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ & MAX_LENGTH_ORDER; \ if (length == 0) \ { \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ + 1; \ } \ else \ { \ length = length << 3; \ } #define EXTRACT_LENGTH_FGBG_LITE(pBuffer, pEnd, length, hr) \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ & MAX_LENGTH_ORDER_LITE; \ if (length == 0) \ { \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ + 1; \ } \ else \ { \ length = length << 3; \ } /****************************************************************************/ /* Macro to store an FGBG image */ /* This macro expects that the function defines pDst, pEndDst, hr */ /* If there is not enough data to write the full run, this will set error */ /* and quit */ /****************************************************************************/ #define STORE_FGBG(xorbyte, fgbgChar, fgChar, bits) \ { \ DCUINT numbits = bits; \ BD_CHECK_WRITE_N_BYTES( pDst, pEndDst, max(1, min(numbits, 8)), hr ) \ if (fgbgChar & 0x01) \ { \ *pDst++ = (DCUINT8)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ if (--numbits > 0) \ { \ if (fgbgChar & 0x02) \ { \ *pDst++ = (DCUINT8)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ if (--numbits > 0) \ { \ if (fgbgChar & 0x04) \ { \ *pDst++ = (DCUINT8)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ if (--numbits > 0) \ { \ if (fgbgChar & 0x08) \ { \ *pDst++ = (DCUINT8)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ if (--numbits > 0) \ { \ if (fgbgChar & 0x10) \ { \ *pDst++ = (DCUINT8)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ if (--numbits > 0) \ { \ if (fgbgChar & 0x20) \ { \ *pDst++ = (DCUINT8)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ if (--numbits > 0) \ { \ if (fgbgChar & 0x40) \ { \ *pDst++ = (DCUINT8)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ if (--numbits > 0) \ { \ if (fgbgChar & 0x80) \ { \ *pDst++ = (DCUINT8)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ } \ } \ } \ } \ } \ } \ } \ } #ifdef DC_HICOLOR /****************************************************************************/ /* 8bpp decompression */ /****************************************************************************/ _inline HRESULT DCAPI BDDecompressBitmap8( PDCUINT8 pSrc, PDCUINT8 pDstBuffer, DCUINT compressedDataSize, DCUINT dstBufferSize, DCUINT8 bitmapBitsPerPel, DCUINT16 rowDelta) { HRESULT hr = S_OK; DCUINT codeLength; DCUINT8 codeByte; DCUINT8 codeByte2; DCUINT8 decode; DCUINT8 decodeLite; DCUINT8 decodeMega; DCUINT8 fgChar; PDCUINT8 pDst; PDCUINT8 pEndSrc; PDCUINT8 pEndDst; DCBOOL backgroundNeedsPel; DCBOOL firstLine; UNREFERENCED_PARAMETER( bitmapBitsPerPel); DC_BEGIN_FN("BDDecompressBitmap8"); pEndSrc = pSrc + compressedDataSize; pDst = pDstBuffer; pEndDst = pDst + dstBufferSize; fgChar = 0xFF; backgroundNeedsPel = FALSE; firstLine = TRUE; /************************************************************************/ /* */ /* Main decompression loop */ /* */ /************************************************************************/ while (pSrc < pEndSrc) { /********************************************************************/ /* While we are processing the first line we should keep a look out */ /* for the end of the line */ /********************************************************************/ if (firstLine) { if ((DCUINT)(pDst - pDstBuffer) >= rowDelta) { firstLine = FALSE; backgroundNeedsPel = FALSE; } } /********************************************************************/ /* Get the decode */ /********************************************************************/ BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr ); decode = (DCUINT8)(*pSrc & CODE_MASK); decodeLite = (DCUINT8)(*pSrc & CODE_MASK_LITE); decodeMega = (DCUINT8)(*pSrc); /********************************************************************/ /* BG RUN */ /********************************************************************/ if ((decode == CODE_BG_RUN) || (decodeMega == CODE_MEGA_MEGA_BG_RUN)) { if (decode == CODE_BG_RUN) { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } else { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } TRC_DBG((TB, _T("Background run %u"),codeLength)); if (!firstLine) { if (backgroundNeedsPel) { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); BD_CHECK_READ_ONE_BYTE_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, hr); *pDst++ = (DCUINT8)(*(pDst - rowDelta) ^ fgChar); codeLength--; } BD_CHECK_READ_N_BYTES_2ENDED(pDst-rowDelta, pDstBuffer, pEndDst, codeLength, hr) BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr) BDMemcpy(pDst, pDst-rowDelta, codeLength); pDst += codeLength; } else { if (backgroundNeedsPel) { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr) *pDst++ = fgChar; codeLength--; } BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr) DC_MEMSET(pDst, 0x00, codeLength); pDst += codeLength; } /****************************************************************/ /* A follow on BG run will need a pel inserted */ /****************************************************************/ backgroundNeedsPel = TRUE; continue; } /********************************************************************/ /* For any of the other runtypes a follow on BG run does not need */ /* a FG pel inserted */ /********************************************************************/ backgroundNeedsPel = FALSE; /********************************************************************/ /* FGBG IMAGE */ /********************************************************************/ if ((decode == CODE_FG_BG_IMAGE) || (decodeLite == CODE_SET_FG_FG_BG) || (decodeMega == CODE_MEGA_MEGA_FGBG) || (decodeMega == CODE_MEGA_MEGA_SET_FGBG)) { if ((decodeMega == CODE_MEGA_MEGA_FGBG) || (decodeMega == CODE_MEGA_MEGA_SET_FGBG)) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { if (decode == CODE_FG_BG_IMAGE) { EXTRACT_LENGTH_FGBG(pSrc, pEndSrc, codeLength, hr); } else { EXTRACT_LENGTH_FGBG_LITE(pSrc, pEndSrc, codeLength, hr); } } if ((decodeLite == CODE_SET_FG_FG_BG) || (decodeMega == CODE_MEGA_MEGA_SET_FGBG)) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); fgChar = *pSrc++; TRC_DBG((TB, _T("Set FGBG image %u"),codeLength)); } else { TRC_DBG((TB, _T("FGBG image %u"),codeLength)); } while (codeLength > 8) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); codeByte = *pSrc++; if (firstLine) { STORE_FGBG(0x00, codeByte, fgChar, 8); } else { BD_CHECK_READ_ONE_BYTE_2ENDED( pDst -rowDelta, pDstBuffer, pEndDst, hr ) STORE_FGBG(*(pDst - rowDelta), codeByte, fgChar, 8); } codeLength -= 8; } if (codeLength > 0) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); codeByte = *pSrc++; if (firstLine) { STORE_FGBG(0x00, codeByte, fgChar, codeLength); } else { BD_CHECK_READ_ONE_BYTE_2ENDED( pDst -rowDelta, pDstBuffer, pEndDst, hr ) STORE_FGBG(*(pDst - rowDelta), codeByte, fgChar, codeLength); } } continue; } /********************************************************************/ /* FG RUN */ /********************************************************************/ if ((decode == CODE_FG_RUN) || (decodeLite == CODE_SET_FG_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_SET_FG_RUN)) { if ((decodeMega == CODE_MEGA_MEGA_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_SET_FG_RUN)) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { if (decode == CODE_FG_RUN) { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } else { EXTRACT_LENGTH_LITE(pSrc, pEndSrc, codeLength, hr); } } /****************************************************************/ /* Push the old fgChar down to the ALT position */ /****************************************************************/ if ((decodeLite == CODE_SET_FG_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_SET_FG_RUN)) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); TRC_DBG((TB, _T("Set FG run %u"),codeLength)); fgChar = *pSrc++; } else { TRC_DBG((TB, _T("FG run %u"),codeLength)); } BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr) while (codeLength-- > 0) { if (!firstLine) { BD_CHECK_READ_ONE_BYTE_2ENDED((pDst -rowDelta), pDstBuffer, pEndDst, hr) *pDst++ = (DCUINT8)(*(pDst - rowDelta) ^ fgChar); } else { *pDst++ = fgChar; } } continue; } /********************************************************************/ /* DITHERED RUN */ /********************************************************************/ if ((decodeLite == CODE_DITHERED_RUN) || (decodeMega == CODE_MEGA_MEGA_DITHER)) { if (decodeMega == CODE_MEGA_MEGA_DITHER) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH_LITE(pSrc, pEndSrc, codeLength, hr); } TRC_DBG((TB, _T("Dithered run %u"),codeLength)); BD_CHECK_READ_N_BYTES(pSrc, pEndSrc, 2, hr); codeByte = *pSrc++; codeByte2 = *pSrc++; BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength * 2, hr) while (codeLength-- > 0) { *pDst++ = codeByte; *pDst++ = codeByte2; } continue; } /********************************************************************/ /* COLOR IMAGE */ /********************************************************************/ if ((decode == CODE_COLOR_IMAGE) || (decodeMega == CODE_MEGA_MEGA_CLR_IMG)) { if (decodeMega == CODE_MEGA_MEGA_CLR_IMG) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } TRC_DBG((TB, _T("Color image %u"),codeLength)); BD_CHECK_READ_N_BYTES(pSrc, pEndSrc, codeLength, hr) BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr) BDMemcpy(pDst, pSrc, codeLength); pDst += codeLength; pSrc += codeLength; continue; } /********************************************************************/ /* COLOR RUN */ /********************************************************************/ if ((decode == CODE_COLOR_RUN) || (decodeMega == CODE_MEGA_MEGA_COLOR_RUN)) { if (decodeMega == CODE_MEGA_MEGA_COLOR_RUN) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } TRC_DBG((TB, _T("Color run %u"),codeLength)); BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr) codeByte = *pSrc++; BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr) DC_MEMSET(pDst, codeByte, codeLength); pDst += codeLength; continue; } /********************************************************************/ /* If we get here then the code must be a special one */ /********************************************************************/ TRC_DBG((TB, _T("Special code %#x"),decodeMega)); switch (decodeMega) { case CODE_BLACK: { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); *pDst++ = 0x00; } break; case CODE_WHITE: { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); *pDst++ = 0xFF; } break; /****************************************************************/ /* Ignore the unreachable code warnings that follow */ /* Simply because we use the STORE_FGBG macro with a constant */ /* value */ /****************************************************************/ case CODE_SPECIAL_FGBG_1: { if (firstLine) { STORE_FGBG(0x00, SPECIAL_FGBG_CODE_1, fgChar, 8); } else { BD_CHECK_READ_ONE_BYTE_2ENDED(pDst-rowDelta, pDstBuffer, pEndDst, hr); STORE_FGBG(*(pDst - rowDelta), SPECIAL_FGBG_CODE_1, fgChar, 8); } } break; case CODE_SPECIAL_FGBG_2: { if (firstLine) { STORE_FGBG(0x00, SPECIAL_FGBG_CODE_2, fgChar, 8); } else { BD_CHECK_READ_ONE_BYTE_2ENDED(pDst-rowDelta, pDstBuffer, pEndDst, hr); STORE_FGBG(*(pDst - rowDelta), SPECIAL_FGBG_CODE_2, fgChar, 8); } } break; default: { TRC_ERR((TB, _T("Invalid compression data %x"),decodeMega)); } break; } pSrc++; } TRC_DBG((TB, _T("Decompressed to %d"), pDst-pDstBuffer)); DC_EXIT_POINT: DC_END_FN(); return hr; } /****************************************************************************/ /* 15bpp decompression */ /****************************************************************************/ _inline HRESULT DCAPI BDDecompressBitmap15(PDCUINT8 pSrc, PDCUINT8 pDstBuffer, DCUINT srcDataSize, DCUINT dstBufferSize, DCUINT16 rowDelta) /****************************************************************************/ /* Function name */ /****************************************************************************/ #define BC_FN_NAME "BDDecompressBitmap15" /****************************************************************************/ /* Data type of a pixel */ /****************************************************************************/ #define BC_PIXEL DCUINT16 /****************************************************************************/ /* Length in bytes of a pixel */ /****************************************************************************/ #define BC_PIXEL_LEN 2 /****************************************************************************/ /* Default fgPel */ /****************************************************************************/ #define BC_DEFAULT_FGPEL 0x0000FF7F /****************************************************************************/ /* Macro to move to the next pixel in the buffer (modifies pPos) */ /****************************************************************************/ #define BC_TO_NEXT_PIXEL(pPos) pPos += 2 /****************************************************************************/ /* Macro to returns the value of the pixel at pPos (doesn't modify pPos) */ /****************************************************************************/ #define BC_GET_PIXEL(pPos) ((DCUINT16) (((PDCUINT8)(pPos))[1]) | \ (DCUINT16) ((((PDCUINT8)(pPos))[0]) << 8) ) /****************************************************************************/ /* Macro to insert a pixel value pel at position pPos (doesn't modify pPos) */ /* */ /* pel may well be an expression (e.g. a BC_GET_PIXEL macro) so evaluate */ /* it once into a local variable. */ /****************************************************************************/ #define BC_SET_PIXEL(pPos, pel) \ { \ BC_PIXEL val = pel; \ (((PDCUINT8)(pPos))[1]) = (DCUINT8)( (val) & 0x00FF); \ (((PDCUINT8)(pPos))[0]) = (DCUINT8)(((val)>>8) & 0x00FF); \ } /****************************************************************************/ /* Include the function body */ /****************************************************************************/ #include /****************************************************************************/ /* Undefine everything */ /****************************************************************************/ #undef BC_FN_NAME #undef BC_PIXEL #undef BC_PIXEL_LEN #undef BC_TO_NEXT_PIXEL #undef BC_GET_PIXEL #undef BC_SET_PIXEL #undef BC_DEFAULT_FGPEL /****************************************************************************/ /* 16bpp decompression */ /****************************************************************************/ _inline HRESULT DCAPI BDDecompressBitmap16(PDCUINT8 pSrc, PDCUINT8 pDstBuffer, DCUINT srcDataSize, DCUINT dstBufferSize, DCUINT16 rowDelta) /****************************************************************************/ /* Function name */ /****************************************************************************/ #define BC_FN_NAME "BDDecompressBitmap16" /****************************************************************************/ /* Data type of a pixel */ /****************************************************************************/ #define BC_PIXEL DCUINT16 /****************************************************************************/ /* Length in bytes of a pixel */ /****************************************************************************/ #define BC_PIXEL_LEN 2 /****************************************************************************/ /* Default fgPel */ /****************************************************************************/ #define BC_DEFAULT_FGPEL 0x0000FFFF /****************************************************************************/ /* Macro to move to the next pixel in the buffer (modifies pPos) */ /****************************************************************************/ #define BC_TO_NEXT_PIXEL(pPos) pPos += 2 /****************************************************************************/ /* Macro to returns the value of the pixel at pPos (doesn't modify pPos) */ /****************************************************************************/ #define BC_GET_PIXEL(pPos) ((DCUINT16) (((PDCUINT8)(pPos))[1]) | \ (DCUINT16) ((((PDCUINT8)(pPos))[0]) << 8) ) /****************************************************************************/ /* Macro to insert a pixel value pel at position pPos (doesn't modify pPos) */ /* */ /* pel may well be an expression (e.g. a BC_GET_PIXEL macro) so evaluate */ /* it once into a local variable. */ /****************************************************************************/ #define BC_SET_PIXEL(pPos, pel) \ { \ BC_PIXEL val = pel; \ (((PDCUINT8)(pPos))[1]) = (DCUINT8)( (val) & 0x00FF); \ (((PDCUINT8)(pPos))[0]) = (DCUINT8)(((val)>>8) & 0x00FF); \ } /****************************************************************************/ /* Include the function body */ /****************************************************************************/ #include /****************************************************************************/ /* Undefine everything */ /****************************************************************************/ #undef BC_FN_NAME #undef BC_PIXEL #undef BC_PIXEL_LEN #undef BC_TO_NEXT_PIXEL #undef BC_GET_PIXEL #undef BC_SET_PIXEL #undef BC_DEFAULT_FGPEL /****************************************************************************/ /* 24bpp decompression */ /****************************************************************************/ _inline HRESULT DCAPI BDDecompressBitmap24(PDCUINT8 pSrc, PDCUINT8 pDstBuffer, DCUINT srcDataSize, DCUINT dstBufferSize, DCUINT16 rowDelta) /****************************************************************************/ /* Function name */ /****************************************************************************/ #define BC_FN_NAME "BDDecompressBitmap24" /****************************************************************************/ /* Data type of a pixel */ /****************************************************************************/ #define BC_PIXEL DCUINT32 /****************************************************************************/ /* Length in bytes of a pixel */ /****************************************************************************/ #define BC_PIXEL_LEN 3 /****************************************************************************/ /* Default fgPel */ /****************************************************************************/ #define BC_DEFAULT_FGPEL 0x00FFFFFF /****************************************************************************/ /* Macro to move to the next pixel in the buffer (modifies pPos) */ /****************************************************************************/ #define BC_TO_NEXT_PIXEL(pPos) pPos += 3 /****************************************************************************/ /* Macro to returns the value of the pixel at pPos (doesn't modify pPos) */ /****************************************************************************/ #define BC_GET_PIXEL(pPos) ( \ (DCUINT32) ( (DCUINT16)(((PDCUINT8)(pPos))[2]) ) | \ (DCUINT32) (((DCUINT16)(((PDCUINT8)(pPos))[1])) << 8) | \ (DCUINT32) (((DCUINT32)(((PDCUINT8)(pPos))[0])) << 16) ) /****************************************************************************/ /* Macro to insert a pixel value pel at position pPos (doesn't modify pPos) */ /* */ /* pel may well be an expression (e.g. a BC_GET_PIXEL macro) so evaluate */ /* it once into a local variable. */ /****************************************************************************/ #define BC_SET_PIXEL(pPos, pel) \ { \ BC_PIXEL val = pel; \ (((PDCUINT8)(pPos))[2]) = (DCUINT8)((val) & 0x000000FF); \ (((PDCUINT8)(pPos))[1]) = (DCUINT8)(((val)>>8) & 0x000000FF); \ (((PDCUINT8)(pPos))[0]) = (DCUINT8)(((val)>>16) & 0x000000FF); \ } /****************************************************************************/ /* Include the function body */ /****************************************************************************/ #include /****************************************************************************/ /* Undefine everything */ /****************************************************************************/ #undef BC_FN_NAME #undef BC_PIXEL #undef BC_PIXEL_LEN #undef BC_TO_NEXT_PIXEL #undef BC_GET_PIXEL #undef BC_SET_PIXEL #undef BC_DEFAULT_FGPEL /****************************************************************************/ /* 32bpp decompression */ /****************************************************************************/ _inline HRESULT DCAPI BDDecompressBitmap32(PDCUINT8 pSrc, PDCUINT8 pDstBuffer, DCUINT srcDataSize, DCUINT dstBufferSize, DCUINT16 rowDelta) /****************************************************************************/ /* Function name */ /****************************************************************************/ #define BC_FN_NAME "BDDecompressBitmap32" /****************************************************************************/ /* Data type of a pixel */ /****************************************************************************/ #define BC_PIXEL DCUINT32 /****************************************************************************/ /* Length in bytes of a pixel */ /****************************************************************************/ #define BC_PIXEL_LEN 4 /****************************************************************************/ /* Default fgPel */ /****************************************************************************/ #define BC_DEFAULT_FGPEL 0xFFFFFFFF /****************************************************************************/ /* Macro to move to the next pixel in the buffer (modifies pPos) */ /****************************************************************************/ #define BC_TO_NEXT_PIXEL(pPos) pPos += 4 /****************************************************************************/ /* Macro to returns the value of the pixel at pPos (doesn't modify pPos) */ /****************************************************************************/ #define BC_GET_PIXEL(pPos) ( \ (DCUINT32) ( (DCUINT16)(((PDCUINT8)(pPos))[3]) ) | \ (DCUINT32) (((DCUINT16)(((PDCUINT8)(pPos))[2])) << 8) | \ (DCUINT32) (((DCUINT32)(((PDCUINT8)(pPos))[1])) << 16) | \ (DCUINT32) (((DCUINT32)(((PDCUINT8)(pPos))[0])) << 24)) /****************************************************************************/ /* Macro to insert a pixel value pel at position pPos (doesn't modify pPos) */ /* */ /* pel may well be an expression (e.g. a BC_GET_PIXEL macro) so evaluate */ /* it once into a local variable. */ /****************************************************************************/ #define BC_SET_PIXEL(pPos, pel) \ { \ BC_PIXEL val = pel; \ (((PDCUINT8)(pPos))[3]) = (DCUINT8)((val) & 0x000000FF); \ (((PDCUINT8)(pPos))[2]) = (DCUINT8)(((val)>>8) & 0x000000FF); \ (((PDCUINT8)(pPos))[1]) = (DCUINT8)(((val)>>16) & 0x000000FF); \ (((PDCUINT8)(pPos))[0]) = (DCUINT8)(((val)>>24) & 0x000000FF); \ } /****************************************************************************/ /* Include the function body */ /****************************************************************************/ #include /****************************************************************************/ /* Undefine everything */ /****************************************************************************/ #undef BC_FN_NAME #undef BC_PIXEL #undef BC_PIXEL_LEN #undef BC_TO_NEXT_PIXEL #undef BC_GET_PIXEL #undef BC_SET_PIXEL #undef BC_DEFAULT_FGPEL /****************************************************************************/ /* Name: BD_DecompressBitmap */ /* */ /* Purpose: Decompresses compressed bitmap data */ /* */ /* Params: IN - pCompressedData: pointer to compressed bitmap data */ /* OUT - pDstBitmap: pointer to buffer for decompressed data */ /* IN - srcDataSize: the compressed data size */ /* IN - bitmapBitsPerPel: the bits per pel of the data */ /****************************************************************************/ HRESULT DCAPI BD_DecompressBitmap( PDCUINT8 pCompressedData, PDCUINT8 pDstBuffer, DCUINT srcDataSize, DCUINT dstBufferSize, DCUINT noBCHeader, DCUINT8 bitmapBitsPerPel, DCUINT16 bitmapWidth, DCUINT16 bitmapHeight) { HRESULT hr = S_OK; PDCUINT8 pSrc; DCUINT16 rowDelta; DCUINT compressedDataSize; PTS_CD_HEADER pCompDataHeader; #ifdef DC_NO_UNALIGNED TS_CD_HEADER compDataHeader; #endif #ifdef DC_DEBUG DCUINT32 decompLen; #endif UNREFERENCED_PARAMETER( bitmapHeight); DC_BEGIN_FN("BD_DecompressBitmap"); TRC_ASSERT( (pCompressedData != NULL), (TB, _T("Invalid pCompressedData(%p)"), pCompressedData) ); TRC_ASSERT( (pDstBuffer != NULL), (TB, _T("Invalid pDstBuffer(%p)"), pDstBuffer) ); TRC_ASSERT( (srcDataSize != 0), (TB, _T("Invalid srcDataSize(%u)"), srcDataSize) ); TRC_ASSERT( (dstBufferSize != 0), (TB, _T("Invalid dstBufferSize(%u)"), dstBufferSize) ); #ifdef DC_HICOLOR #ifdef DC_DEBUG /************************************************************************/ /* Check the decompression buffer is big enough */ /************************************************************************/ { decompLen = bitmapWidth * bitmapHeight * ((bitmapBitsPerPel + 7) / 8); if (IsBadWritePtr(pDstBuffer, decompLen)) { TRC_ABORT((TB, _T("Decompression buffer %p not big enough for") \ _T(" bitmap length %d"), pDstBuffer, decompLen )); } } #endif #else TRC_ASSERT( (bitmapBitsPerPel == 8), (TB, _T("Invalid bitmapBitsPerPel(%u)"), bitmapBitsPerPel) ); #endif /************************************************************************/ /* Initialize variables before main loop. */ /* */ /* No bitmap compression header included */ /************************************************************************/ if (noBCHeader) { compressedDataSize = srcDataSize; pSrc = pCompressedData; rowDelta = TS_BYTES_IN_SCANLINE(bitmapWidth, bitmapBitsPerPel); } else { /************************************************************************/ /* Work out the location in the source data of each component. */ /* Make sure this is naturally aligned (for RISC platforms) */ /************************************************************************/ BD_CHECK_READ_N_BYTES(pCompressedData, (PBYTE)pCompressedData + srcDataSize, sizeof(TS_CD_HEADER), hr); #ifdef DC_NO_UNALIGNED DC_MEMCPY(&compDataHeader, pCompressedData, sizeof(TS_CD_HEADER)); pCompDataHeader = &compDataHeader; #else pCompDataHeader = (PTS_CD_HEADER)pCompressedData; #endif /********************************************************************/ /* Bitmap compression header included */ /********************************************************************/ compressedDataSize = pCompDataHeader->cbCompMainBodySize; BD_CHECK_READ_N_BYTES(pCompressedData, pCompressedData + srcDataSize, compressedDataSize + sizeof(TS_CD_HEADER), hr); pSrc = pCompressedData + sizeof(TS_CD_HEADER); rowDelta = pCompDataHeader->cbScanWidth; if (rowDelta != TS_BYTES_IN_SCANLINE(bitmapWidth, bitmapBitsPerPel)) { TRC_ABORT((TB, _T("rowDelta in TS_CD_HEADER incorrect ") _T("[got %u expected %u]"), rowDelta, TS_BYTES_IN_SCANLINE(bitmapWidth, bitmapBitsPerPel))); hr = E_TSC_CORE_LENGTH; DC_QUIT; } } /************************************************************************/ /* Call the appropriate decompress function, based on the color depth */ /************************************************************************/ switch (bitmapBitsPerPel) { case 32: { hr = BDDecompressBitmap32 (pSrc, pDstBuffer, compressedDataSize, dstBufferSize, rowDelta); } break; case 24: { hr = BDDecompressBitmap24 (pSrc, pDstBuffer, compressedDataSize, dstBufferSize, rowDelta); } break; case 16: { hr = BDDecompressBitmap16 (pSrc, pDstBuffer, compressedDataSize, dstBufferSize, rowDelta); } break; case 15: { hr = BDDecompressBitmap15 (pSrc, pDstBuffer, compressedDataSize, dstBufferSize, rowDelta); } break; case 8: default: { hr = BDDecompressBitmap8 (pSrc, pDstBuffer, compressedDataSize, dstBufferSize, bitmapBitsPerPel, rowDelta); } break; } DC_EXIT_POINT: return hr; } #else /****************************************************************************/ /* Name: BD_DecompressBitmap */ /* */ /* Purpose: Decompresses compressed bitmap data */ /* */ /* Params: IN - pCompressedData: pointer to compressed bitmap data */ /* OUT - pDstBitmap: pointer to buffer for decompressed data */ /* IN - srcDataSize: the compressed data size */ /* IN - bitmapBitsPerPel: the bits per pel of the data */ /****************************************************************************/ HRESULT DCAPI BD_DecompressBitmap( PDCUINT8 pCompressedData, PDCUINT8 pDstBuffer, DCUINT srcDataSize, DCUINT dstBufferSize, DCUINT noBCHeader, DCUINT8 bitmapBitsPerPel, DCUINT16 bitmapWidth, DCUINT16 bitmapHeight ) { HRESULT hr = S_OK; UNREFERENCED_PARAMETER(bitmapHeight); #ifdef DC_NO_UNALIGNED TS_CD_HEADER compDataHeader; #endif PTS_CD_HEADER pCompDataHeader; DCUINT compressedDataSize; DCUINT codeLength; DCUINT8 codeByte; DCUINT8 codeByte2; DCUINT8 decode; DCUINT8 decodeLite; DCUINT8 decodeMega; DCUINT8 fgChar; PDCUINT8 pSrc; PDCUINT8 pDst; PDCUINT8 pEndSrc; PDCUINT8 pEndDst; DCBOOL backgroundNeedsPel; DCBOOL firstLine; DCUINT rowDelta; DC_BEGIN_FN("BD_DecompressBitmap"); TRC_ASSERT( (pCompressedData != NULL), (TB, _T("Invalid pCompressedData(%p)"), pCompressedData) ); TRC_ASSERT( (pDstBuffer != NULL), (TB, _T("Invalid pDstBuffer(%p)"), pDstBuffer) ); TRC_ASSERT( (srcDataSize != 0), (TB, _T("Invalid srcDataSize(%u)"), srcDataSize) ); TRC_ASSERT( (dstBufferSize != 0), (TB, _T("Invalid dstBufferSize(%u)"), dstBufferSize) ); TRC_ASSERT( (bitmapBitsPerPel == 8), (TB, _T("Invalid bitmapBitsPerPel(%u)"), bitmapBitsPerPel) ); /************************************************************************/ /* Trace the important parameters. */ /************************************************************************/ TRC_DBG((TB, _T("pData(%p) pDst(%p) cbSrc(%u) cbDst(%u)"), pCompressedData, pDstBuffer, srcDataSize, dstBufferSize)); /************************************************************************/ /* Initialize variables before main loop. */ /************************************************************************/ // no bitmap compression header included if (noBCHeader) { compressedDataSize = srcDataSize; pSrc = pCompressedData; rowDelta = TS_BYTES_IN_SCANLINE(bitmapWidth, bitmapBitsPerPel); } // bitmap compression header included else { /************************************************************************/ /* Work out the location in the source data of each component. */ /* Make sure this is naturally aligned (for RISC platforms) */ /************************************************************************/ BD_CHECK_READ_N_BYTES(pCompressedData, pCompressedData + srcDataSize, sizeof(TS_CD_HEADER), hr); #ifdef DC_NO_UNALIGNED DC_MEMCPY(&compDataHeader, pCompressedData, sizeof(TS_CD_HEADER)); pCompDataHeader = &compDataHeader; #else pCompDataHeader = (PTS_CD_HEADER)pCompressedData; #endif compressedDataSize = pCompDataHeader->cbCompMainBodySize; BD_CHECK_READ_N_BYTES(pCompressedData, pCompressedData + srcDataSize, compressedDataSize + sizeof(TS_CD_HEADER), hr); pSrc = pCompressedData + sizeof(TS_CD_HEADER); rowDelta = pCompDataHeader->cbScanWidth; if (rowDelta != TS_BYTES_IN_SCANLINE(bitmapWidth, bitmapBitsPerPel)) { TRC_ABORT((TB, _T("rowDelta in TS_CD_HEADER incorrect ") _T("[got %u expected %u]"), rowDelta, TS_BYTES_IN_SCANLINE(bitmapWidth, bitmapBitsPerPel))); hr = E_TSC_CORE_LENGTH; DC_QUIT; } } pEndSrc = pSrc + compressedDataSize; pDst = pDstBuffer; pEndDst = pDst + dstBufferSize; fgChar = 0xFF; backgroundNeedsPel = FALSE; firstLine = TRUE; /************************************************************************/ /* */ /* Main decompression loop */ /* */ /************************************************************************/ while(pSrc < pEndSrc) { /********************************************************************/ /* While we are processing the first line we should keep a look out */ /* for the end of the line */ /********************************************************************/ if (firstLine) { if ((DCUINT)(pDst - pDstBuffer) >= rowDelta) { firstLine = FALSE; backgroundNeedsPel = FALSE; } } /********************************************************************/ /* Get the decode */ /********************************************************************/ BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); decode = (DCUINT8)(*pSrc & CODE_MASK); decodeLite = (DCUINT8)(*pSrc & CODE_MASK_LITE); decodeMega = (DCUINT8)(*pSrc); /********************************************************************/ /* BG RUN */ /********************************************************************/ if ((decode == CODE_BG_RUN) || (decodeMega == CODE_MEGA_MEGA_BG_RUN)) { if (decode == CODE_BG_RUN) { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } else { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } TRC_DBG((TB, _T("Background run %u"),codeLength)); if (!firstLine) { if (backgroundNeedsPel) { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); BD_CHECK_READ_ONE_BYTE_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, hr); *pDst++ = (DCUINT8)(*(pDst - rowDelta) ^ fgChar); codeLength--; } BD_CHECK_READ_N_BYTES_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, codeLength, hr); BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr); BDMemcpy(pDst, pDst-rowDelta, codeLength); pDst += codeLength; } else { if (backgroundNeedsPel) { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); *pDst++ = fgChar; codeLength--; } BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr); DC_MEMSET(pDst, 0x00, codeLength); pDst += codeLength; } /****************************************************************/ /* A follow on BG run will need a pel inserted */ /****************************************************************/ backgroundNeedsPel = TRUE; continue; } /********************************************************************/ /* For any of the other runtypes a follow on BG run does not need */ /* a FG pel inserted */ /********************************************************************/ backgroundNeedsPel = FALSE; /********************************************************************/ /* FGBG IMAGE */ /********************************************************************/ if ((decode == CODE_FG_BG_IMAGE) || (decodeLite == CODE_SET_FG_FG_BG) || (decodeMega == CODE_MEGA_MEGA_FGBG) || (decodeMega == CODE_MEGA_MEGA_SET_FGBG)) { if ((decodeMega == CODE_MEGA_MEGA_FGBG) || (decodeMega == CODE_MEGA_MEGA_SET_FGBG)) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { if (decode == CODE_FG_BG_IMAGE) { EXTRACT_LENGTH_FGBG(pSrc, pEndSrc, codeLength, hr); } else { EXTRACT_LENGTH_FGBG_LITE(pSrc, pEndSrc, codeLength, hr); } } if ((decodeLite == CODE_SET_FG_FG_BG) || (decodeMega == CODE_MEGA_MEGA_SET_FGBG)) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); fgChar = *pSrc++; TRC_DBG((TB, _T("Set FGBG image %u"),codeLength)); } else { TRC_DBG((TB, _T("FGBG image %u"),codeLength)); } while (codeLength > 8) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); codeByte = *pSrc++; if (firstLine) { STORE_FGBG(0x00, codeByte, fgChar, 8); } else { BD_CHECK_READ_ONE_BYTE_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, hr) STORE_FGBG(*(pDst - rowDelta), codeByte, fgChar, 8); } codeLength -= 8; } if (codeLength > 0) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); codeByte = *pSrc++; if (firstLine) { STORE_FGBG(0x00, codeByte, fgChar, codeLength); } else { BD_CHECK_READ_ONE_BYTE_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, hr) STORE_FGBG(*(pDst - rowDelta), codeByte, fgChar, codeLength); } } continue; } /********************************************************************/ /* FG RUN */ /********************************************************************/ if ((decode == CODE_FG_RUN) || (decodeLite == CODE_SET_FG_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_SET_FG_RUN)) { if ((decodeMega == CODE_MEGA_MEGA_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_SET_FG_RUN)) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { if (decode == CODE_FG_RUN) { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } else { EXTRACT_LENGTH_LITE(pSrc, pEndSrc, codeLength, hr); } } /****************************************************************/ /* Push the old fgChar down to the ALT position */ /****************************************************************/ if ((decodeLite == CODE_SET_FG_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_SET_FG_RUN)) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); TRC_DBG((TB, _T("Set FG run %u"),codeLength)); fgChar = *pSrc++; } else { TRC_DBG((TB, _T("FG run %u"),codeLength)); } BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr) while (codeLength-- > 0) { if (!firstLine) { BD_CHECK_READ_ONE_BYTE_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, hr) *pDst++ = (DCUINT8)(*(pDst - rowDelta) ^ fgChar); } else { *pDst++ = fgChar; } } continue; } /********************************************************************/ /* DITHERED RUN */ /********************************************************************/ if ((decodeLite == CODE_DITHERED_RUN) || (decodeMega == CODE_MEGA_MEGA_DITHER)) { if (decodeMega == CODE_MEGA_MEGA_DITHER) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH_LITE(pSrc, pEndSrc, codeLength, hr); } TRC_DBG((TB, _T("Dithered run %u"),codeLength)); BD_CHECK_READ_N_BYTES(pSrc, pEndSrc, 2, hr); codeByte = *pSrc++; codeByte2 = *pSrc++; BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength * 2, hr) while (codeLength-- > 0) { *pDst++ = codeByte; *pDst++ = codeByte2; } continue; } /********************************************************************/ /* COLOR IMAGE */ /********************************************************************/ if ((decode == CODE_COLOR_IMAGE) || (decodeMega == CODE_MEGA_MEGA_CLR_IMG)) { if (decodeMega == CODE_MEGA_MEGA_CLR_IMG) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } TRC_DBG((TB, _T("Color image %u"),codeLength)); BD_CHECK_READ_N_BYTES(pSrc, pEndSrc, codeLength, hr); BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr); BDMemcpy(pDst, pSrc, codeLength); pDst += codeLength; pSrc += codeLength; continue; } /********************************************************************/ /* PACKED COLOR IMAGE */ /********************************************************************/ if ((decode == CODE_PACKED_COLOR_IMAGE) || (decodeMega == CODE_MEGA_MEGA_PACKED_CLR)) { if (decodeMega == CODE_MEGA_MEGA_PACKED_CLR) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } TRC_DBG((TB, _T("Packed color %u"),codeLength)); if (bitmapBitsPerPel == 4) { DCUINT worklen = (codeLength)/2; DCUINT8 workchar; BD_CHECK_READ_N_BYTES(pSrc, pEndSrc, worklen, hr); BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, worklen * 2, hr); while (worklen--) { workchar = *pSrc++; *pDst++ = (DCUINT8)(workchar >> 4); *pDst++ = (DCUINT8)(workchar & 0x0F); } if (codeLength & 0x0001) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); *pDst++ = (DCUINT8)(*pSrc++>>4); } } else { TRC_ERR((TB, _T("Don't support packed color for 8bpp"))); } continue; } /********************************************************************/ /* COLOR RUN */ /********************************************************************/ if ((decode == CODE_COLOR_RUN) || (decodeMega == CODE_MEGA_MEGA_COLOR_RUN)) { if (decodeMega == CODE_MEGA_MEGA_COLOR_RUN) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } TRC_DBG((TB, _T("Color run %u"),codeLength)); BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); codeByte = *pSrc++; BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr); DC_MEMSET(pDst, codeByte, codeLength); pDst += codeLength; continue; } /********************************************************************/ /* If we get here then the code must be a special one */ /********************************************************************/ TRC_DBG((TB, _T("Special code %#x"),decodeMega)); switch (decodeMega) { case CODE_BLACK: { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); *pDst++ = 0x00; } break; case CODE_WHITE: { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); *pDst++ = 0xFF; } break; /****************************************************************/ /* Ignore the unreachable code warnings that follow */ /* Simply because we use the STORE_FGBG macro with a constant */ /* value */ /****************************************************************/ case CODE_SPECIAL_FGBG_1: { if (firstLine) { STORE_FGBG(0x00, SPECIAL_FGBG_CODE_1, fgChar, 8); } else { BD_CHECK_READ_ONE_BYTE_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, hr) STORE_FGBG(*(pDst - rowDelta), SPECIAL_FGBG_CODE_1, fgChar, 8); } } break; case CODE_SPECIAL_FGBG_2: { if (firstLine) { STORE_FGBG(0x00, SPECIAL_FGBG_CODE_2, fgChar, 8); } else { BD_CHECK_READ_ONE_BYTE_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, hr) STORE_FGBG(*(pDst - rowDelta), SPECIAL_FGBG_CODE_2, fgChar, 8); } } break; default: { TRC_ERR((TB, _T("Invalid compression data %x"),decodeMega)); } break; } pSrc++; } TRC_DBG((TB, _T("Decompressed to %d"), pDst-pDstBuffer)); DC_EXIT_POINT: DC_END_FN(); return hr; } #endif #ifdef OS_WINDOWS #pragma warning (default: 4127) #endif /* OS_WINDOWS */