Source code of Windows XP (NT5)
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.

839 lines
20 KiB

  1. // Copyright (C) Microsoft Corporation 1990-1997, All Rights reserved.
  2. #include "header.h"
  3. #include "cpaldc.h"
  4. #include "gif.h"
  5. #include "hha_strtable.h"
  6. #include "hhctrl.h"
  7. #define GIF_HDR_SIZE 6
  8. #define MAX_BUFFER_SIZE (2L * MAXSIZE)
  9. #define END_INFO (plzData->ClearCode+1)
  10. #define FIRST_ENTRY (plzData->ClearCode+2)
  11. #define HASH_SIZE 5003
  12. STATIC int GetImagePalette(IFFPTR piff, LPBYTE pal);
  13. STATIC FSERR GetInit(PCSTR pszFileName, IFFPTR piff, UINT GetFlag);
  14. STATIC void GIFFreeMemory(IFFPTR piff);
  15. STATIC void SetUserParams(IFFPTR);
  16. STATIC int IFF_PackLine(PBYTE ToBuff, const BYTE* FromBuff, int Pixels, int Bits);
  17. STATIC LZDATA* LZInitialize(int CharSize);
  18. STATIC void LZCleanUp(LZDATA*);
  19. STATIC int LZExpand(LZDATA*, PBYTE, PBYTE, unsigned, unsigned);
  20. STATIC void BitmapHeaderFromIff(IFFPTR piff, LPBITMAPINFOHEADER pbih);
  21. STATIC IFFPTR GifOpen(PCSTR pszFileName);
  22. STATIC void GifClose(IFFPTR piff);
  23. STATIC int GifGetLine(int NumLines, PBYTE Buffer, IFFPTR piff);
  24. INLINE void InvertLine(LPBYTE Buffer, int DimX);
  25. INLINE int ColorsFromBitDepth(int bitsperpixel);
  26. INLINE int ScanLineWidth(int width, int bitcount);
  27. static const int InterlaceMultiplier[] = { 8, 8, 4, 2 };
  28. static const int InterlaceOffset[] = { 0, 4, 2, 1 };
  29. void BitmapHeaderFromIff(IFFPTR piff, LPBITMAPINFOHEADER pbih)
  30. {
  31. pbih->biSize = sizeof(BITMAPINFOHEADER);
  32. pbih->biWidth = piff->DimX;
  33. pbih->biHeight = piff->DimY;
  34. pbih->biPlanes = 1;
  35. pbih->biCompression = 0;
  36. pbih->biXPelsPerMeter= 0;
  37. pbih->biYPelsPerMeter= 0;
  38. pbih->biClrImportant = 0;
  39. switch (piff->Class) {
  40. case IFFCL_BILEVEL:
  41. pbih->biBitCount = 1;
  42. pbih->biClrUsed = 2;
  43. break;
  44. case IFFCL_PALETTE:
  45. if (piff->Bits <= 4) {
  46. pbih->biBitCount = 4;
  47. pbih->biClrUsed = 16;
  48. }
  49. else {
  50. pbih->biBitCount = 8;
  51. pbih->biClrUsed = 256;
  52. }
  53. break;
  54. case IFFCL_GRAY:
  55. pbih->biBitCount = 8;
  56. pbih->biClrUsed = 256;
  57. break;
  58. }
  59. pbih->biSizeImage = (pbih->biWidth * pbih->biBitCount + 31) / 32;
  60. pbih->biSizeImage *= 4 * pbih->biHeight;
  61. }
  62. BOOL LoadGif(PCSTR pszFile, HBITMAP* phbmp, HPALETTE* phpal, CHtmlHelpControl* phhctrl)
  63. {
  64. IFFPTR piff = GifOpen(pszFile);
  65. if (!piff)
  66. return FALSE;
  67. CMem memBmi(sizeof(BITMAPINFOHEADER) +
  68. sizeof(RGBQUAD) * (piff->Bits > 8 ? 0 : 256));
  69. PBITMAPINFO pbmi = (PBITMAPINFO) memBmi.pb;
  70. PBITMAPINFOHEADER pbih = (PBITMAPINFOHEADER) pbmi;
  71. BitmapHeaderFromIff(piff, pbih);
  72. if (pbih->biBitCount)
  73. pbih->biBitCount = 8; // filter always returns 256-color image
  74. ASSERT(pbih->biBitCount);
  75. // Read in the palette
  76. if (pbih->biBitCount && phpal) {
  77. CMem memPal(768);
  78. int cColors = ColorsFromBitDepth(pbih->biBitCount);
  79. if (piff->Class == IFFCL_PALETTE || piff->Class == IFFCL_BILEVEL) {
  80. GetImagePalette(piff, memPal.pb);
  81. for (int i = 0; i < cColors; i++) {
  82. pbmi->bmiColors[i].rgbRed = memPal.pb[i * 3];
  83. pbmi->bmiColors[i].rgbGreen = memPal.pb[i * 3 + 1];
  84. pbmi->bmiColors[i].rgbBlue = memPal.pb[i * 3 + 2];
  85. pbmi->bmiColors[i].rgbReserved = 0;
  86. }
  87. }
  88. else {
  89. for (int i = 0; i < cColors; i++) {
  90. pbmi->bmiColors[i].rgbRed =
  91. pbmi->bmiColors[i].rgbGreen =
  92. pbmi->bmiColors[i].rgbBlue = (BYTE) i;
  93. pbmi->bmiColors[i].rgbReserved = 0;
  94. }
  95. }
  96. *phpal = CreateBIPalette(pbih);
  97. }
  98. CPalDC dc;
  99. if (phpal && *phpal)
  100. dc.SelectPal(*phpal);
  101. int cbLineWidth = ScanLineWidth(pbih->biWidth, pbih->biBitCount);
  102. PBYTE pBits;
  103. *phbmp = CreateDIBSection(dc.m_hdc, pbmi, DIB_RGB_COLORS,
  104. (void**) &pBits, NULL, 0);
  105. if (!*phbmp)
  106. goto ErrorReturn;
  107. if (piff->Sequence == IFFSEQ_INTERLACED) {
  108. int InterPass = 0;
  109. int InterLine = InterlaceOffset[InterPass];
  110. for (int i = 0; i < pbih->biHeight; i++) {
  111. int TmpLine = InterlaceMultiplier[InterPass] * InterLine + InterlaceOffset[InterPass];
  112. // Small images will skip one or more passes
  113. while (TmpLine >= pbih->biHeight) {
  114. InterPass++;
  115. InterLine = 0;
  116. TmpLine = InterlaceOffset[InterPass];
  117. if (TmpLine >= pbih->biHeight)
  118. TmpLine = pbih->biHeight - 1;
  119. }
  120. PBYTE pbBits = pBits +
  121. ((pbih->biHeight - 1) - TmpLine) * cbLineWidth;
  122. ASSERT(pbBits <= (pBits + ((pbih->biHeight - 1) * cbLineWidth)));
  123. if (GifGetLine(1, pbBits, piff) == IFFERR_NONE) {
  124. InterLine++;
  125. }
  126. else {
  127. goto ErrorReturn;
  128. }
  129. }
  130. }
  131. else {
  132. for (int i = 0; i < pbih->biHeight; i++) {
  133. PBYTE pbBits = pBits +
  134. ((pbih->biHeight - 1) - i) * cbLineWidth;
  135. int result = GifGetLine(1, pbBits, piff);
  136. if (result != IFFERR_NONE) {
  137. goto ErrorReturn;
  138. }
  139. }
  140. }
  141. GifClose(piff);
  142. return TRUE;
  143. ErrorReturn:
  144. if (phhctrl)
  145. phhctrl->AuthorMsg(IDSHHA_GIF_CORRUPT, pszFile);
  146. else
  147. doAuthorMsg(IDSHHA_GIF_CORRUPT, pszFile);
  148. GifClose(piff);
  149. if (phpal && *phpal) {
  150. dc.SelectPal(NULL);
  151. DeleteObject(*phpal);
  152. }
  153. return FALSE;
  154. }
  155. STATIC IFFPTR GifOpen(PCSTR pszFileName)
  156. {
  157. IFFPTR piff = (IFFPTR) lcCalloc(sizeof(IFF_FID));
  158. UINT GetFlag = 0;
  159. piff->Error = IFFERR_NONE;
  160. piff->PackMode = IFFPM_NORMALIZED;
  161. piff->linelen = -1;
  162. if ((piff->Error = GetInit(pszFileName, piff, GetFlag)) != FSERR_NONE) {
  163. if (piff->prstream) {
  164. delete piff->prstream;
  165. }
  166. GIFFreeMemory(piff);
  167. lcFree(piff);
  168. return NULL;
  169. }
  170. SetUserParams(piff);
  171. switch (piff->Class) {
  172. case IFFCL_BILEVEL:
  173. piff->LineBytes = (piff->DimX + 7) / 8;
  174. piff->LineOffset = piff->DimX;
  175. break;
  176. case IFFCL_RGB:
  177. piff->LineBytes = piff->DimX * 3;
  178. piff->LineOffset = piff->LineBytes;
  179. break;
  180. default:
  181. piff->LineBytes = piff->DimX;
  182. piff->LineOffset = piff->LineBytes;
  183. break;
  184. }
  185. return piff;
  186. }
  187. STATIC void GifClose(IFFPTR piff)
  188. {
  189. if (piff->prstream)
  190. delete piff->prstream;
  191. GIFFreeMemory(piff);
  192. lcFree(piff);
  193. }
  194. STATIC int GifGetLine(int NumLines, PBYTE Buffer, IFFPTR piff)
  195. {
  196. int Count, RetCnt;
  197. int UserWidth;
  198. LPBYTE ptr;
  199. if (piff == NULL)
  200. return (IFFERR_PARAMETER);
  201. if (piff->PackMode == IFFPM_PACKED)
  202. UserWidth = piff->BytesPerLine;
  203. else
  204. UserWidth = piff->DimX;
  205. do {
  206. // if there are uncompressed lines in the buffer, just copy them
  207. if (piff->StripLines > 0) {
  208. ptr = piff->DecompBuffer + ((piff->ActualLinesPerStrip - piff->StripLines) * piff->BytesPerLine);
  209. if (piff->PackMode == IFFPM_PACKED) {
  210. IFF_PackLine(Buffer, ptr, piff->DimX, piff->Bits);
  211. if (piff->BlackOnWhite)
  212. InvertLine(Buffer, piff->DimX);
  213. }
  214. else
  215. memcpy(Buffer, ptr, piff->DimX);
  216. piff->StripLines--;
  217. NumLines--;
  218. piff->curline++;
  219. Buffer += UserWidth;
  220. }
  221. else {
  222. // decompress a strip, first get enough compressed data
  223. if (!piff->ReadItAll) {
  224. // copy already read lines to beginning of comp buffer
  225. if (piff->BytesInRWBuffer)
  226. memcpy(piff->RWBuffer, piff->rw_ptr, piff->BytesInRWBuffer);
  227. piff->rw_ptr = piff->RWBuffer + piff->BytesInRWBuffer;
  228. // read compressed blocks until comp buffer is full
  229. while (piff->BytesInRWBuffer < (piff->CompBufferSize - 256)) {
  230. BYTE BlockSize = piff->prstream->cget();
  231. if (piff->prstream->m_fEndOfFile) {
  232. piff->Error = IFFERR_IO_READ;
  233. return piff->Error;
  234. }
  235. if (BlockSize == 0) {
  236. piff->ReadItAll = 1;
  237. break;
  238. }
  239. Count = BlockSize;
  240. if (!piff->prstream->doRead(piff->rw_ptr, BlockSize)) {
  241. piff->Error = IFFERR_IO_READ;
  242. return piff->Error;
  243. }
  244. piff->BytesInRWBuffer += Count;
  245. piff->rw_ptr += Count;
  246. }
  247. piff->rw_ptr = piff->RWBuffer;
  248. }
  249. // copy back already decompressed bytes to beginning of decomp buffer
  250. if (piff->BytesLeft)
  251. memcpy(piff->DecompBuffer, piff->dcmp_ptr, piff->BytesLeft);
  252. piff->dcmp_ptr = piff->DecompBuffer + piff->BytesLeft;
  253. // decompress to fill the decomp buffer
  254. Count = piff->DecompBufferSize;
  255. ASSERT(piff->plzData);
  256. RetCnt = LZExpand(piff->plzData, piff->dcmp_ptr, piff->rw_ptr, Count, piff->BytesInRWBuffer);
  257. if (RetCnt <= 0)
  258. return IFFERR_IMAGE;
  259. piff->BytesInRWBuffer -= RetCnt;
  260. piff->rw_ptr += RetCnt;
  261. piff->StripLines = Count / piff->BytesPerLine;
  262. piff->BytesLeft = Count % piff->BytesPerLine;
  263. piff->ActualLinesPerStrip = piff->StripLines;
  264. piff->dcmp_ptr = piff->DecompBuffer + piff->StripLines * piff->BytesPerLine;
  265. }
  266. } while (NumLines);
  267. return IFFERR_NONE;
  268. }
  269. STATIC void SetUserParams(IFFPTR piff)
  270. {
  271. int i;
  272. BOOL fIsPalette;
  273. piff->BlackOnWhite = FALSE;
  274. fIsPalette = TRUE;
  275. if (piff->Bits == 1) {
  276. if (piff->Palette == NULL)
  277. fIsPalette = FALSE;
  278. else {
  279. if (piff->Palette[0] == piff->Palette[1] &&
  280. piff->Palette[1] == piff->Palette[2] &&
  281. piff->Palette[0] == 0 &&
  282. piff->Palette[3] == piff->Palette[4] &&
  283. piff->Palette[4] == piff->Palette[5] &&
  284. piff->Palette[3] == 255)
  285. fIsPalette = FALSE;
  286. if (piff->Palette[0] == piff->Palette[1] &&
  287. piff->Palette[1] == piff->Palette[2] &&
  288. piff->Palette[0] == 255 &&
  289. piff->Palette[3] == piff->Palette[4] &&
  290. piff->Palette[4] == piff->Palette[5] &&
  291. piff->Palette[3] == 0)
  292. {
  293. piff->BlackOnWhite = TRUE;
  294. fIsPalette = FALSE;
  295. }
  296. }
  297. if (!fIsPalette)
  298. piff->Class = IFFCL_BILEVEL;
  299. }
  300. if (fIsPalette) {
  301. for (i = 0; i < piff->PaletteSize / 3; i++)
  302. if (piff->Palette[i * 3] != piff->Palette[i * 3 + 1] ||
  303. piff->Palette[i * 3 + 1] != piff->Palette[i * 3 + 2] ||
  304. piff->Palette[i * 3] != (BYTE)i)
  305. break;
  306. if (i == piff->PaletteSize / 3) {
  307. for (i = 0; i < piff->PaletteSize / 3; i++)
  308. piff->Palette[i] = piff->Palette[i * 3];
  309. piff->PaletteSize /= 3;
  310. piff->Class = IFFCL_GRAY;
  311. }
  312. else
  313. piff->Class = IFFCL_PALETTE;
  314. }
  315. }
  316. STATIC int GetImagePalette(IFFPTR piff, LPBYTE Pal)
  317. {
  318. if (piff->PaletteSize > 0)
  319. memcpy (Pal, piff->Palette, (unsigned) piff->PaletteSize);
  320. else
  321. return IFFERR_NOTAVAILABLE;
  322. return IFFERR_NONE;
  323. }
  324. STATIC FSERR GetInit(PCSTR pszFileName, IFFPTR piff, UINT GetFlag)
  325. {
  326. BYTE Buffer[13];
  327. piff->prstream = new CStream(pszFileName);
  328. if (!piff->prstream->fInitialized) {
  329. GIFFreeMemory(piff);
  330. return FSERR_CANT_OPEN;
  331. }
  332. if (!piff->prstream->doRead(Buffer, GIF_HDR_SIZE)) {
  333. GIFFreeMemory(piff);
  334. piff->Error = IFFERR_IO_READ;
  335. return FSERR_TRUNCATED;
  336. }
  337. if (((Buffer[0] != 'G') || (Buffer[1] != 'I') || (Buffer[2] != 'F') ||
  338. (Buffer[3] != '8') || (Buffer[5] != 'a')) ||
  339. ((Buffer[4] != '7') && (Buffer[4] != '9'))) {
  340. GIFFreeMemory(piff);
  341. piff->Error = IFFERR_HEADER;
  342. return FSERR_INVALID_FORMAT;
  343. }
  344. piff->prstream->read(&piff->lsd, sizeof(LSD));
  345. piff->Bits = (int) (piff->lsd.b.ceGCT + 1);
  346. piff->PaletteSize = 3 * (1 << piff->Bits);
  347. if (piff->lsd.b.fGCT) {
  348. piff->Palette = (PBYTE) lcMalloc(piff->PaletteSize);
  349. if (!piff->prstream->doRead(piff->Palette, piff->PaletteSize)) {
  350. GIFFreeMemory(piff);
  351. piff->Error = IFFERR_IO_READ;
  352. return FSERR_TRUNCATED;
  353. }
  354. }
  355. for (;;) {
  356. if (piff->prstream->m_fEndOfFile) {
  357. piff->Error = IFFERR_IO_READ;
  358. return FSERR_CORRUPTED_FILE;
  359. }
  360. Buffer[0] = piff->prstream->cget();
  361. switch (*Buffer) {
  362. case 0x21: // control extension
  363. if (!piff->prstream->doRead(Buffer, 2)) {
  364. GIFFreeMemory(piff);
  365. piff->Error = IFFERR_IO_READ;
  366. return FSERR_TRUNCATED;
  367. }
  368. switch (*Buffer) {
  369. case 0xFF: // Application Specific Block
  370. case 0xF9: // Graphics Control Extension
  371. case 0x01: // Plain Text Extension
  372. case 0xFE: // Comment Extension
  373. while (Buffer[1] != 0) {
  374. piff->prstream->seek((long) Buffer[1], SK_CUR);
  375. if (piff->prstream->m_fEndOfFile) {
  376. piff->Error = IFFERR_IO_READ;
  377. return FSERR_CORRUPTED_FILE;
  378. }
  379. Buffer[1] = piff->prstream->cget();
  380. }
  381. break;
  382. default:
  383. ASSERT_COMMENT(FALSE, "The following code needs verification");
  384. piff->prstream->seek(Buffer[1] + 1, SK_CUR);
  385. break;
  386. }
  387. break;
  388. case 0x3B: // end of file
  389. return FSERR_NONE;
  390. case 0x2C:
  391. if (!piff->prstream->doRead((Buffer + 1), 9)) {
  392. GIFFreeMemory(piff);
  393. piff->Error = IFFERR_IO_READ;
  394. return FSERR_TRUNCATED;
  395. }
  396. short IntData[2];
  397. memcpy(IntData, Buffer + 5, 2 * sizeof(short));
  398. INTELSWAP16 (IntData[0]);
  399. INTELSWAP16 (IntData[1]);
  400. piff->DimX = IntData[0];
  401. piff->DimY = IntData[1];
  402. if (Buffer[9] & 0x40)
  403. piff->Sequence = IFFSEQ_INTERLACED;
  404. else
  405. piff->Sequence = IFFSEQ_TOPDOWN;
  406. if (Buffer[9] & 0x80) {
  407. piff->Bits = (Buffer[9] & 0x07) + 1;
  408. int Size = (3 * (1 << piff->Bits));
  409. // Ignore local color table for now
  410. piff->prstream->seek(Size, SK_CUR);
  411. }
  412. BYTE CodeSize = piff->prstream->cget();
  413. piff->BytesPerLine = piff->DimX;
  414. piff->CompBufferSize = MAX_BUFFER_SIZE;
  415. piff->DecompBufferSize = (MAX_BUFFER_SIZE >> 1) + (MAX_BUFFER_SIZE >> 2);
  416. // calculate the number of lines in a strip
  417. piff->StripLines = 0;
  418. piff->LinesPerStrip = piff->DecompBufferSize / piff->BytesPerLine;
  419. piff->DecompBufferSize = (piff->LinesPerStrip * piff->BytesPerLine);
  420. piff->BytesInRWBuffer = 0;
  421. piff->BytesLeft = 0;
  422. piff->RWBuffer = (PBYTE) lcMalloc(piff->CompBufferSize);
  423. piff->DecompBuffer = (PBYTE) lcMalloc(piff->DecompBufferSize);
  424. piff->rw_ptr = piff->RWBuffer;
  425. piff->dcmp_ptr = piff->DecompBuffer;
  426. piff->curline = 0;
  427. piff->plzData = LZInitialize(CodeSize);
  428. if (piff->plzData == NULL) {
  429. GIFFreeMemory(piff);
  430. piff->Error = IFFERR_MEMORY;
  431. return FSERR_INSF_MEMORY;
  432. }
  433. return FSERR_NONE;
  434. }
  435. }
  436. return FSERR_NONE;
  437. }
  438. STATIC void GIFFreeMemory(IFFPTR piff)
  439. {
  440. if (piff->plzData != NULL)
  441. LZCleanUp(piff->plzData);
  442. if (piff->Palette)
  443. lcClearFree(&piff->Palette);
  444. if (piff->RWBuffer)
  445. lcClearFree(&piff->RWBuffer);
  446. if (piff->DecompBuffer)
  447. lcClearFree(&piff->DecompBuffer);
  448. piff->plzData = NULL;
  449. return;
  450. }
  451. INLINE void InvertLine(LPBYTE Buffer, int DimX)
  452. {
  453. int il = (DimX + 7) >> 3;
  454. for (int i = 0; i < il; i++)
  455. *Buffer++ = 255 - *Buffer;
  456. }
  457. FSERR SetupForRead(int pos, int iWhichImage, IFF_FID* piff)
  458. {
  459. piff->prstream->seek(pos);
  460. BYTE CodeSize = piff->prstream->cget();
  461. piff->BytesPerLine = piff->DimX;
  462. piff->CompBufferSize = MAX_BUFFER_SIZE;
  463. piff->DecompBufferSize = (MAX_BUFFER_SIZE >> 1) + (MAX_BUFFER_SIZE >> 2);
  464. // calculate the number of lines in a strip
  465. piff->StripLines = 0;
  466. piff->LinesPerStrip = piff->DecompBufferSize / piff->BytesPerLine;
  467. piff->DecompBufferSize = (piff->LinesPerStrip * piff->BytesPerLine);
  468. piff->BytesInRWBuffer = 0;
  469. piff->BytesLeft = 0;
  470. if (piff->RWBuffer)
  471. lcFree(piff->RWBuffer);
  472. piff->RWBuffer = (PBYTE) lcMalloc(piff->CompBufferSize);
  473. if (piff->DecompBuffer)
  474. lcFree(piff->DecompBuffer);
  475. piff->DecompBuffer = (PBYTE) lcMalloc(piff->DecompBufferSize);
  476. piff->rw_ptr = piff->RWBuffer;
  477. piff->dcmp_ptr = piff->DecompBuffer;
  478. piff->curline = 0;
  479. if (piff->plzData)
  480. LZCleanUp(piff->plzData);
  481. piff->plzData = LZInitialize(CodeSize);
  482. if (piff->plzData == NULL) {
  483. GIFFreeMemory(piff);
  484. piff->Error = IFFERR_MEMORY;
  485. return FSERR_UNSUPPORTED_GIF_FORMAT;
  486. }
  487. // piff->Sequence = pGifImage->fInterlaced ? IFFSEQ_INTERLACED : IFFSEQ_TOPDOWN;
  488. return FSERR_NONE;
  489. }
  490. int IFF_PackLine(PBYTE ToBuff, const BYTE* FromBuff, int Pixels, int Bits)
  491. {
  492. int Mask;
  493. int PMask;
  494. int Pix;
  495. int Shift;
  496. int i;
  497. switch (Bits) {
  498. case 1:
  499. case 4:
  500. Mask = ((8 / Bits) - 1);
  501. Pix = 0;
  502. Shift = (WORD) (8 - Bits);
  503. PMask = (WORD) (0xFF >> Shift);
  504. for (i = 0; i < Pixels; i++)
  505. {
  506. Pix |= *FromBuff++ & PMask;
  507. if ((i & Mask) == Mask)
  508. {
  509. *ToBuff++ = (BYTE) Pix;
  510. Pix = 0;
  511. }
  512. else
  513. Pix <<= Bits;
  514. }
  515. if ((i & Mask) != 0)
  516. {
  517. while ((++i & Mask) != 0)
  518. Pix <<= Bits;
  519. *ToBuff = (BYTE) Pix;
  520. }
  521. return (Pixels + Mask) / (Mask + 1);
  522. break;
  523. case 8: // degenerate case
  524. memcpy(ToBuff, FromBuff, Pixels);
  525. return Pixels;
  526. default:
  527. IASSERT_COMMENT(FALSE, "Invalid bit depth");
  528. break;
  529. }
  530. return 0;
  531. }
  532. INLINE void ExpandReset(LZDATA* plzData)
  533. {
  534. plzData->BitPos = 0;
  535. plzData->CurBits = plzData->CharSize + 1;
  536. plzData->OutString = 0;
  537. plzData->CodeJump = (1 << plzData->CurBits) - 1;
  538. plzData->CodeJump++;
  539. }
  540. INLINE unsigned GetNextCode(LZDATA* plzData)
  541. {
  542. unsigned short code;
  543. int newbitpos;
  544. code = (unsigned short) (*plzData->CodeInput | (plzData->CodeInput[1] << 8));
  545. code >>= plzData->BitPos; // ditch previous bits
  546. code &= 0xFFFF >> (16 - plzData->CurBits); // ditch next bits
  547. newbitpos = plzData->BitPos + plzData->CurBits;
  548. if (newbitpos > 7)
  549. ++plzData->CodeInput; // used up at least one * byte
  550. if (newbitpos >= 16)
  551. ++plzData->CodeInput; // used up two bytes
  552. if (newbitpos > 16) { // need more bits
  553. code |= (*plzData->CodeInput << (32 - newbitpos)) >> (16 - plzData->CurBits);
  554. code &= 0xFFFF >> (16 - plzData->CurBits); // ditch next bits
  555. }
  556. plzData->BitPos = newbitpos & 7;
  557. return code; // need mask in 32 bit
  558. }
  559. STATIC int LZExpand(LZDATA* plzData, LPBYTE ToBuff, LPBYTE FromBuff, unsigned ToCnt, unsigned FromCnt)
  560. {
  561. unsigned cnt;
  562. LPBYTE outbuff = ToBuff;
  563. int code, incode;
  564. ASSERT(plzData);
  565. plzData->CodeInput = FromBuff;
  566. cnt = ToCnt;
  567. while (plzData->OutString > 0 && cnt > 0) {
  568. *outbuff++ = plzData->Stack[--plzData->OutString];
  569. cnt--;
  570. }
  571. while (cnt > 0) {
  572. if ((code = GetNextCode(plzData)) == END_INFO)
  573. break;
  574. if (code == plzData->ClearCode) {
  575. ZeroMemory(plzData->CodeTable, sizeof(int*) * HASH_SIZE);
  576. for (int i = 0; i < HASH_SIZE; i++) {
  577. // plzData->CodeTable[i] = 0;
  578. plzData->StringTable[i] = (unsigned char) i;
  579. }
  580. plzData->CurBits = plzData->CharSize + 1; // start beginning
  581. plzData->TableEntry = FIRST_ENTRY;
  582. plzData->OutString = 0;
  583. plzData->CodeJump = (1 << plzData->CurBits) - 1;
  584. plzData->CodeJump++;
  585. plzData->LastChar = plzData->OldCode = GetNextCode(plzData);
  586. if (plzData->OldCode == END_INFO)
  587. break;
  588. *outbuff++ = (unsigned char) plzData->LastChar; // output a code
  589. cnt--;
  590. }
  591. else {
  592. if ((incode = code) >= plzData->TableEntry) { // is_in_code_table ?
  593. plzData->Stack[plzData->OutString++] = (unsigned char) plzData->LastChar; /* not in table */
  594. code = plzData->OldCode;
  595. }
  596. while (code >= plzData->ClearCode) { // need decoding
  597. if ((plzData->OutString >= (1L << 12)) || (code > HASH_SIZE))
  598. return -1;
  599. plzData->Stack[plzData->OutString++] = plzData->StringTable[code];
  600. code = plzData->CodeTable[code];
  601. }
  602. if (code < 0 || code > HASH_SIZE || plzData->TableEntry >= HASH_SIZE) {
  603. // pretend that we decoded all data.
  604. return min((int) (plzData->CodeInput - FromBuff), (int) FromCnt);
  605. }
  606. plzData->Stack[plzData->OutString++] =
  607. (BYTE) (plzData->LastChar =
  608. plzData->StringTable[code]);
  609. // output string
  610. while (plzData->OutString > 0 && cnt > 0) {
  611. *outbuff++ = plzData->Stack[--plzData->OutString];
  612. cnt--;
  613. }
  614. plzData->CodeTable[plzData->TableEntry] = plzData->OldCode; // Add string to table
  615. plzData->StringTable[plzData->TableEntry++] = (unsigned char) plzData->LastChar;
  616. if (plzData->TableEntry == plzData->CodeJump && plzData->CurBits < 12) {
  617. plzData->CodeJump += 1 << plzData->CurBits;
  618. plzData->CurBits++;
  619. }
  620. plzData->OldCode = incode;
  621. }
  622. } // End while
  623. cnt = (UINT)(plzData->CodeInput - FromBuff);
  624. return (cnt);
  625. }
  626. STATIC LZDATA* LZInitialize(int CharSize)
  627. {
  628. if (CharSize < 2)
  629. CharSize = 2;
  630. LZDATA* plzData = (LZDATA*) lcCalloc(sizeof(LZDATA));
  631. plzData->CharSize = CharSize;
  632. plzData->CodeSize = 12;
  633. plzData->ClearCode = (1 << CharSize);
  634. plzData->CodeTable = (int*) lcCalloc(sizeof(int) * HASH_SIZE);
  635. plzData->StringTable = (PBYTE) lcCalloc(HASH_SIZE);
  636. plzData->Stack = (PBYTE) lcCalloc(1 << 12);
  637. ExpandReset(plzData);
  638. return plzData;
  639. }
  640. STATIC void LZCleanUp(LZDATA* plzData)
  641. {
  642. if (plzData == NULL)
  643. return;
  644. if (plzData->CodeTable)
  645. lcFree(plzData->CodeTable);
  646. if (plzData->StringTable)
  647. lcFree(plzData->StringTable);
  648. if (plzData->HashTable)
  649. lcFree(plzData->HashTable);
  650. if (plzData->Stack)
  651. lcFree(plzData->Stack);
  652. lcFree(plzData);
  653. }
  654. INLINE int ColorsFromBitDepth(int bitsperpixel)
  655. {
  656. switch (bitsperpixel) {
  657. case 1:
  658. return 2;
  659. case 4:
  660. return 16;
  661. case 8:
  662. return 256;
  663. break;
  664. default:
  665. return 0;
  666. }
  667. }
  668. INLINE int ScanLineWidth(int width, int bitcount)
  669. {
  670. switch (bitcount) {
  671. case 1: // REVIEW: is this true?
  672. return ((width + 31) & ~31) * bitcount / 8;
  673. case 4:
  674. return ((width * 4 + 31) / 32 * 4);
  675. case 8:
  676. break;
  677. default:
  678. IASSERT(!"Invalid bitcount value in ScanLineWidth");
  679. break;
  680. }
  681. if (width & 0x03)
  682. width += (4 - width % 4);
  683. return width;
  684. }