You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1698 lines
77 KiB
1698 lines
77 KiB
/****************************************************************************/
|
|
/* abdapi.cpp */
|
|
/* */
|
|
/* Bitmap Decompression API functions */
|
|
/* */
|
|
/* Copyright(C) Microsoft Corporation 1996-1999 */
|
|
/****************************************************************************/
|
|
|
|
#include <adcg.h>
|
|
extern "C" {
|
|
#define TRC_GROUP TRC_GROUP_CORE
|
|
#define TRC_FILE "abdapi"
|
|
#include <atrcapi.h>
|
|
}
|
|
#define TSC_HR_FILEID TSC_HR_ABDAPI_CPP
|
|
|
|
#include <abdapi.h>
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* 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 <bdcom.c>
|
|
|
|
/****************************************************************************/
|
|
/* 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 <bdcom.c>
|
|
|
|
/****************************************************************************/
|
|
/* 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 <bdcom.c>
|
|
|
|
/****************************************************************************/
|
|
/* 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 <bdcom.c>
|
|
|
|
/****************************************************************************/
|
|
/* 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 */
|
|
|