|
|
/****************************************************************************/ /* */ /* abdcom.c */ /* */ /* Copyright (c) Data Connection Limited 1998 */ /* */ /* */ /* Bitmap decompression routine and macros for 16 and 24bpp protocol */ /* */ /****************************************************************************/
#ifdef BC_TRACE
#define BCTRACE TRC_DBG
#else
#define BCTRACE(string)
#endif
/****************************************************************************/ /* We use the same helper macros as the 8bpp code except for STORE_FGBG. */ /****************************************************************************/ /****************************************************************************/ /* Macro to store an FGBG image at destbuf */ /* */ /* xorPel is either the value 0 or an expression containing the local */ /* variable destbuf. */ /* */ /* THIS MEANS THAT xorPel HAS A DIFFERENT VALUE EVERY TIME destbuf IS */ /* CHANGED. */ /* */ /* fgPel is a BC_PIXEL and the FG color to XOR with xorbyte */ /* fgbgChar is a bitmask telling which color to put where */ /* */ /* 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 */ /****************************************************************************/ #undef STORE_FGBG
#define STORE_FGBG(xorPelIn, fgbgChar, fgPel, bits) \
{ \ DCUINT numbits = bits; \ BC_PIXEL xorPel; \ BD_CHECK_WRITE_N_BYTES( destbuf, pEndDst, max(1, min(numbits, 8)) * BC_PIXEL_LEN, hr ) \ \ xorPel = BC_GET_PIXEL(xorPelIn); \ if (fgbgChar & 0x01) \ { \ BC_SET_PIXEL(destbuf, xorPel ^ fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, xorPel); \ } \ BC_TO_NEXT_PIXEL(destbuf); \ \ if (--numbits > 0) \ { \ xorPel = BC_GET_PIXEL(xorPelIn); \ if (fgbgChar & 0x02) \ { \ BC_SET_PIXEL(destbuf, xorPel ^ fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, xorPel) \ } \ BC_TO_NEXT_PIXEL(destbuf); \ \ if (--numbits > 0) \ { \ xorPel = BC_GET_PIXEL(xorPelIn); \ if (fgbgChar & 0x04) \ { \ BC_SET_PIXEL(destbuf, xorPel ^ fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, xorPel) \ } \ BC_TO_NEXT_PIXEL(destbuf); \ \ if (--numbits > 0) \ { \ xorPel = BC_GET_PIXEL(xorPelIn); \ if (fgbgChar & 0x08) \ { \ BC_SET_PIXEL(destbuf, xorPel ^ fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, xorPel); \ } \ BC_TO_NEXT_PIXEL(destbuf); \ \ if (--numbits > 0) \ { \ xorPel = BC_GET_PIXEL(xorPelIn); \ if (fgbgChar & 0x10) \ { \ BC_SET_PIXEL(destbuf, xorPel ^ fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, xorPel); \ } \ BC_TO_NEXT_PIXEL(destbuf); \ \ if (--numbits > 0) \ { \ xorPel = BC_GET_PIXEL(xorPelIn); \ if (fgbgChar & 0x20) \ { \ BC_SET_PIXEL(destbuf, xorPel ^ fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, xorPel); \ } \ BC_TO_NEXT_PIXEL(destbuf); \ \ if (--numbits > 0) \ { \ xorPel = BC_GET_PIXEL(xorPelIn); \ if (fgbgChar & 0x40) \ { \ BC_SET_PIXEL(destbuf, xorPel ^ fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, xorPel); \ } \ BC_TO_NEXT_PIXEL(destbuf); \ \ if (--numbits > 0) \ { \ xorPel = BC_GET_PIXEL(xorPelIn); \ if (fgbgChar & 0x80) \ { \ BC_SET_PIXEL(destbuf, xorPel ^ fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, xorPel); \ } \ BC_TO_NEXT_PIXEL(destbuf); \ } \ } \ } \ } \ } \ } \ } \ }
#define STORE_LINE1_FGBG(fgbgChar, fgPel, bits) \
{ \ DCUINT numbits = bits; \ BD_CHECK_WRITE_N_BYTES( destbuf, pEndDst, max(1, min(numbits, 8)) * BC_PIXEL_LEN, hr ) \ \ if (fgbgChar & 0x01) \ { \ BC_SET_PIXEL(destbuf, fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, 0); \ } \ BC_TO_NEXT_PIXEL(destbuf); \ \ if (--numbits > 0) \ { \ if (fgbgChar & 0x02) \ { \ BC_SET_PIXEL(destbuf, fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, 0) \ } \ BC_TO_NEXT_PIXEL(destbuf); \ \ if (--numbits > 0) \ { \ if (fgbgChar & 0x04) \ { \ BC_SET_PIXEL(destbuf, fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, 0) \ } \ BC_TO_NEXT_PIXEL(destbuf); \ \ if (--numbits > 0) \ { \ if (fgbgChar & 0x08) \ { \ BC_SET_PIXEL(destbuf, fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, 0); \ } \ BC_TO_NEXT_PIXEL(destbuf); \ \ if (--numbits > 0) \ { \ if (fgbgChar & 0x10) \ { \ BC_SET_PIXEL(destbuf, fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, 0); \ } \ BC_TO_NEXT_PIXEL(destbuf); \ \ if (--numbits > 0) \ { \ if (fgbgChar & 0x20) \ { \ BC_SET_PIXEL(destbuf, fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, 0); \ } \ BC_TO_NEXT_PIXEL(destbuf); \ \ if (--numbits > 0) \ { \ if (fgbgChar & 0x40) \ { \ BC_SET_PIXEL(destbuf, fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, 0); \ } \ BC_TO_NEXT_PIXEL(destbuf); \ \ if (--numbits > 0) \ { \ if (fgbgChar & 0x80) \ { \ BC_SET_PIXEL(destbuf, fgPel); \ } \ else \ { \ BC_SET_PIXEL(destbuf, 0); \ } \ BC_TO_NEXT_PIXEL(destbuf); \ } \ } \ } \ } \ } \ } \ } \ }
/****************************************************************************/ /* Decompression function begins here */ /****************************************************************************/ /****************************************************************************/ /* */ /* PDCUINT8 pSrc */ /* PDCUINT8 pDstBuffer */ /* DCUINT srcDataSize total bytes in image */ /* DCUINT rowDelta scanline length in bytes */ /* */ /****************************************************************************/ { HRESULT hr = S_OK; DCUINT codeLength; DCINT pixelLength; DCUINT8 bitMask; DCUINT8 decode; DCUINT8 decodeLite; DCUINT8 decodeMega; BC_PIXEL fgPel = BC_DEFAULT_FGPEL; BC_PIXEL pixelA; BC_PIXEL pixelB; PDCUINT8 destbuf = pDstBuffer; PDCUINT8 endSrc = pSrc + srcDataSize; PDCUINT8 pEndDst = pDstBuffer + dstBufferSize; DCBOOL backgroundNeedsPel = FALSE; DCBOOL firstLine = TRUE;
DC_BEGIN_FN(BC_FN_NAME);
/************************************************************************/ /* Loop processing the input */ /************************************************************************/ while (pSrc < endSrc) { /********************************************************************/ /* While we are processing the first line we should keep a look out */ /* for the end of the line */ /********************************************************************/ if (firstLine) { if ((DCUINT)(destbuf - pDstBuffer) >= rowDelta) { firstLine = FALSE; backgroundNeedsPel = FALSE; } }
/********************************************************************/ /* Get the decode */ /********************************************************************/ BD_CHECK_READ_ONE_BYTE(pSrc, endSrc, 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, endSrc, codeLength, hr); } else { BD_CHECK_READ_N_BYTES(pSrc+1, endSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } BCTRACE((TB, _T("Background run %u"),codeLength));
if (!firstLine) { if (backgroundNeedsPel) { BD_CHECK_WRITE_N_BYTES(destbuf, pEndDst, BC_PIXEL_LEN, hr); BD_CHECK_READ_N_BYTES_2ENDED(destbuf - rowDelta, pDstBuffer, pEndDst, BC_PIXEL_LEN, hr) BC_SET_PIXEL(destbuf, BC_GET_PIXEL(destbuf - rowDelta) ^ fgPel); BC_TO_NEXT_PIXEL(destbuf); codeLength--; }
BD_CHECK_WRITE_N_BYTES(destbuf, pEndDst, BC_PIXEL_LEN * codeLength, hr);
while (codeLength-- > 0) { BD_CHECK_READ_N_BYTES_2ENDED(destbuf - rowDelta, pDstBuffer, pEndDst, BC_PIXEL_LEN, hr) BC_SET_PIXEL(destbuf, BC_GET_PIXEL(destbuf - rowDelta)); BC_TO_NEXT_PIXEL(destbuf); } } else { if (backgroundNeedsPel) { BD_CHECK_WRITE_N_BYTES(destbuf, pEndDst, BC_PIXEL_LEN, hr); BC_SET_PIXEL(destbuf, fgPel); BC_TO_NEXT_PIXEL(destbuf); codeLength--; } BD_CHECK_WRITE_N_BYTES(destbuf, pEndDst, BC_PIXEL_LEN * codeLength, hr); while (codeLength-- > 0) { /********************************************************/ /* On the first line BG colour means 0 */ /********************************************************/ BC_SET_PIXEL(destbuf, (BC_PIXEL)0); BC_TO_NEXT_PIXEL(destbuf); } } /****************************************************************/ /* 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, endSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { if (decode == CODE_FG_BG_IMAGE) { EXTRACT_LENGTH_FGBG(pSrc, endSrc, codeLength, hr); } else { EXTRACT_LENGTH_FGBG_LITE(pSrc, endSrc, codeLength, hr); } }
if ((decodeLite == CODE_SET_FG_FG_BG) || (decodeMega == CODE_MEGA_MEGA_SET_FGBG)) { BD_CHECK_READ_N_BYTES(pSrc, endSrc, BC_PIXEL_LEN, hr); fgPel = BC_GET_PIXEL(pSrc); BC_TO_NEXT_PIXEL(pSrc); BCTRACE((TB, _T("Set FGBG image %u, fgPel %06lx"), codeLength, (DCUINT32)fgPel)); } else { BCTRACE((TB, _T("FGBG image %u"),codeLength)); }
while (codeLength > 8) { /************************************************************/ /* A FGBG image is a set of bitmasks describing the */ /* positions of the FG and BG colors. */ /************************************************************/ BD_CHECK_READ_ONE_BYTE(pSrc, endSrc, hr); bitMask = *pSrc++; if (!firstLine) { BD_CHECK_READ_N_BYTES_2ENDED(destbuf - rowDelta, pDstBuffer, pEndDst, BC_PIXEL_LEN, hr) STORE_FGBG((destbuf - rowDelta), bitMask, fgPel, 8); } else { STORE_LINE1_FGBG(bitMask, fgPel, 8); } codeLength -= 8; } if (codeLength > 0) { BD_CHECK_READ_ONE_BYTE(pSrc, endSrc, hr); bitMask = *pSrc++; if (!firstLine) { BD_CHECK_READ_N_BYTES_2ENDED(destbuf - rowDelta, pDstBuffer, pEndDst, BC_PIXEL_LEN, hr) STORE_FGBG((destbuf - rowDelta), bitMask, fgPel, codeLength); } else { STORE_LINE1_FGBG(bitMask, fgPel, 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, endSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { if (decode == CODE_FG_RUN) { EXTRACT_LENGTH(pSrc, endSrc, codeLength, hr); } else { EXTRACT_LENGTH_LITE(pSrc, endSrc, codeLength, hr); } }
/****************************************************************/ /* Push the old fgPel down to the ALT position */ /****************************************************************/ if ((decodeLite == CODE_SET_FG_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_SET_FG_RUN)) { BD_CHECK_READ_N_BYTES(pSrc, endSrc, BC_PIXEL_LEN, hr); BCTRACE((TB, _T("Set FG run %u"),codeLength)); fgPel = BC_GET_PIXEL(pSrc); BC_TO_NEXT_PIXEL(pSrc); } else { BCTRACE((TB, _T("FG run %u"),codeLength)); }
BD_CHECK_WRITE_N_BYTES(destbuf, pEndDst, BC_PIXEL_LEN * codeLength, hr) while (codeLength-- > 0) { if (!firstLine) { BD_CHECK_READ_N_BYTES_2ENDED(destbuf - rowDelta, pDstBuffer, pEndDst, BC_PIXEL_LEN, hr) BC_SET_PIXEL(destbuf, BC_GET_PIXEL(destbuf - rowDelta) ^ fgPel); BC_TO_NEXT_PIXEL(destbuf); } else { BC_SET_PIXEL(destbuf, fgPel); BC_TO_NEXT_PIXEL(destbuf); } } 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, endSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH_LITE(pSrc, endSrc, codeLength, hr); } BCTRACE((TB, _T("Dithered run %u"),codeLength));
BD_CHECK_READ_N_BYTES(pSrc, endSrc, BC_PIXEL_LEN * 2, hr); pixelA = BC_GET_PIXEL(pSrc); BC_TO_NEXT_PIXEL(pSrc); pixelB = BC_GET_PIXEL(pSrc); BC_TO_NEXT_PIXEL(pSrc);
BD_CHECK_WRITE_N_BYTES(destbuf, pEndDst, 2 * codeLength * BC_PIXEL_LEN, hr) while (codeLength-- > 0) { BC_SET_PIXEL(destbuf, pixelA); BC_TO_NEXT_PIXEL(destbuf);
BC_SET_PIXEL(destbuf, pixelB); BC_TO_NEXT_PIXEL(destbuf); } 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, endSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH(pSrc, endSrc, codeLength, hr); } BCTRACE((TB, _T("Color image %u"),codeLength));
/****************************************************************/ /* Just copy the pixel values across */ /****************************************************************/ pixelLength = (codeLength * BC_PIXEL_LEN); BD_CHECK_READ_N_BYTES(pSrc, endSrc, pixelLength, hr); BD_CHECK_WRITE_N_BYTES(destbuf, pEndDst, pixelLength, hr); while (pixelLength-- > 0) { *destbuf++ = *pSrc++; }
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, endSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH(pSrc, endSrc, codeLength, hr); } BCTRACE((TB, _T("Color run %u"),codeLength));
BD_CHECK_READ_N_BYTES(pSrc, endSrc, BC_PIXEL_LEN, hr); pixelA = BC_GET_PIXEL(pSrc); BC_TO_NEXT_PIXEL(pSrc);
BD_CHECK_WRITE_N_BYTES(destbuf, pEndDst, codeLength * BC_PIXEL_LEN, hr) while (codeLength-- > 0) { BC_SET_PIXEL(destbuf, pixelA); BC_TO_NEXT_PIXEL(destbuf); } continue; }
/********************************************************************/ /* If we get here then the code must be a special one */ /********************************************************************/ BCTRACE((TB, _T("Special code %x"),decodeMega)); switch (decodeMega) { case CODE_BLACK: BD_CHECK_WRITE_N_BYTES(destbuf, pEndDst, BC_PIXEL_LEN, hr) BC_SET_PIXEL(destbuf, (BC_PIXEL)0); BC_TO_NEXT_PIXEL(destbuf); break;
case CODE_WHITE: BD_CHECK_WRITE_N_BYTES(destbuf, pEndDst, BC_PIXEL_LEN, hr) BC_SET_PIXEL(destbuf, BC_DEFAULT_FGPEL); BC_TO_NEXT_PIXEL(destbuf); 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) { BD_CHECK_READ_N_BYTES_2ENDED(destbuf - rowDelta, pDstBuffer, pEndDst, BC_PIXEL_LEN, hr) STORE_FGBG((destbuf - rowDelta), SPECIAL_FGBG_CODE_1, fgPel, 8); } else { STORE_LINE1_FGBG(SPECIAL_FGBG_CODE_1, fgPel, 8); } break;
case CODE_SPECIAL_FGBG_2: if (!firstLine) { BD_CHECK_READ_N_BYTES_2ENDED(destbuf - rowDelta, pDstBuffer, pEndDst, BC_PIXEL_LEN, hr) STORE_FGBG((destbuf - rowDelta), SPECIAL_FGBG_CODE_2, fgPel, 8); } else { STORE_LINE1_FGBG(SPECIAL_FGBG_CODE_2, fgPel, 8); } break;
default: { TRC_ERR((TB, _T("Invalid compression data %x"),decodeMega)); } break; } pSrc++;
}
BCTRACE((TB, _T("Decompressed to %u bytes"), destbuf - pDstBuffer)); #if 0
#ifdef DC_DEBUG
if ((destbuf - pDstBuffer) != decompLen) { TRC_ABORT((TB, _T("calculated decomp len %d != actual len %d"), decompLen, (destbuf - pDstBuffer) )); } #endif
#endif
DC_EXIT_POINT: DC_END_FN(); return hr; }
|