Leaked source code of windows server 2003
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.

2304 lines
68 KiB

  1. /*----------------------------------------------------------------------+
  2. | decmprss.c - Microsoft Video 1 Compressor - decompress code |
  3. | |
  4. | |
  5. | Copyright (c) 1990-1994 Microsoft Corporation. |
  6. | Portions Copyright Media Vision Inc. |
  7. | All Rights Reserved. |
  8. | |
  9. | You have a non-exclusive, worldwide, royalty-free, and perpetual |
  10. | license to use this source code in developing hardware, software |
  11. | (limited to drivers and other software required for hardware |
  12. | functionality), and firmware for video display and/or processing |
  13. | boards. Microsoft makes no warranties, express or implied, with |
  14. | respect to the Video 1 codec, including without limitation warranties |
  15. | of merchantability or fitness for a particular purpose. Microsoft |
  16. | shall not be liable for any damages whatsoever, including without |
  17. | limitation consequential damages arising from your use of the Video 1 |
  18. | codec. |
  19. | |
  20. | |
  21. +----------------------------------------------------------------------*/
  22. #ifdef _WIN32
  23. //#ifdef DEBUG DEBUG is not defined on NT until win32.h is included...
  24. // Always define here so that the ntrtl headers get included
  25. #ifndef CHICAGO
  26. #if DBG
  27. // We only want this stuff in the debug build
  28. #define MEASURE_PERFORMANCE
  29. #endif
  30. #endif
  31. //#endif
  32. #endif
  33. #ifdef MEASURE_PERFORMANCE // Displays frame decompress times on the debugger
  34. #include <nt.h>
  35. #include <ntrtl.h>
  36. #include <nturtl.h>
  37. #endif
  38. #include <windows.h>
  39. #include <win32.h>
  40. #include "msvidc.h"
  41. #ifdef DEBUG
  42. #undef INLINE // Make debugging easier - less code movement
  43. #define INLINE
  44. #else
  45. #undef MEASURE_PERFORMANCE // Turn it off for non debug builds
  46. #endif
  47. #ifdef MEASURE_PERFORMANCE
  48. STATICDT LARGE_INTEGER PC1; /* current counter value */
  49. STATICDT LARGE_INTEGER PC2; /* current counter value */
  50. STATICDT LARGE_INTEGER PC3; /* current counter value */
  51. STATICFN VOID StartCounting(VOID)
  52. {
  53. QueryPerformanceCounter(&PC1);
  54. return;
  55. }
  56. STATICFN VOID EndCounting(LPSTR szId)
  57. {
  58. QueryPerformanceCounter(&PC2);
  59. PC3.QuadPart = PC2.QuadPart - PC1.QuadPart;
  60. DPF(("%s: %d ticks", szId, PC3.LowPart));
  61. return;
  62. }
  63. #else
  64. #define StartCounting()
  65. #define EndCounting(x)
  66. #endif
  67. /*
  68. * dither table pointers declared and initialised in msvidc.c
  69. */
  70. extern LPVOID lpDitherTable;
  71. /*
  72. * these two pointers point into the lpDitherTable
  73. */
  74. LPBYTE lpLookup;
  75. LPWORD lpScale;
  76. /*
  77. ** Lookup table for expanding 4 bits into 4 bytes
  78. */
  79. CONST DWORD ExpansionTable[16] = {
  80. 0x00000000,
  81. 0x000000FF,
  82. 0x0000FF00,
  83. 0x0000FFFF,
  84. 0x00FF0000,
  85. 0x00FF00FF,
  86. 0x00FFFF00,
  87. 0x00FFFFFF,
  88. 0xFF000000,
  89. 0xFF0000FF,
  90. 0xFF00FF00,
  91. 0xFF00FFFF,
  92. 0xFFFF0000,
  93. 0xFFFF00FF,
  94. 0xFFFFFF00,
  95. 0xFFFFFFFF
  96. };
  97. /*
  98. * Lookup table to turn a bitmask to a byte mask
  99. */
  100. DWORD Bits2Bytes[13] = {0, 0xffff, 0xffff0000, 0xffffffff,
  101. 0xffff, 0, 0, 0,
  102. 0xffff0000, 0, 0, 0,
  103. 0xffffffff};
  104. //#include <limits.h>
  105. //#include <mmsystem.h>
  106. //#include <aviffmt.h>
  107. #define RGB555toRGBTRIPLE( rgbT, rgb ) rgbT.rgbtRed=(BYTE)((rgb & 0x7c00) >> 7); \
  108. rgbT.rgbtGreen=(BYTE)((rgb & 0x3e0) >>2); \
  109. rgbT.rgbtBlue=(BYTE)((rgb & 0x1f) << 3)
  110. static WORD edgeBitMask[HEIGHT_CBLOCK*WIDTH_CBLOCK] = {
  111. 0x0001,0x0002,0x0010,0x0020,
  112. 0x0004,0x0008,0x0040,0x0080,
  113. 0x0100,0x0200,0x1000,0x2000,
  114. 0x0400,0x0800,0x4000,0x8000
  115. };
  116. /* make a DWORD that has four copies of the byte x */
  117. #define MAKE4(x) ( (x << 24) | (x << 16) | (x << 8) | x)
  118. /* make a DWORD that has two copies of the byte x (low word) and two of y */
  119. #define MAKE22(x, y) ( (y << 24) | (y << 16) | (x << 8) | (x))
  120. /**************************************************************************
  121. compute a pointer into a DIB handling correctly "upside" down DIBs
  122. ***************************************************************************/
  123. STATICFN LPVOID DibXY(LPBITMAPINFOHEADER lpbi, LPBYTE lpBits, LONG x, LONG y, INT FAR *pWidthBytes)
  124. {
  125. int WidthBytes;
  126. if (x > 0)
  127. ((BYTE FAR *)lpBits) += ((int)x * (int)lpbi->biBitCount) >> 3;
  128. WidthBytes = (((((int)lpbi->biWidth * (int)lpbi->biBitCount) >> 3) + 3)&~3);
  129. if (lpbi->biHeight < 0)
  130. {
  131. WidthBytes = -WidthBytes;
  132. ((BYTE _huge *)lpBits) += lpbi->biSizeImage + WidthBytes;
  133. }
  134. if (y > 0)
  135. ((BYTE _huge *)lpBits) += ((long)y * WidthBytes);
  136. if (pWidthBytes)
  137. *pWidthBytes = WidthBytes;
  138. return lpBits;
  139. }
  140. /*
  141. * 16-bit decompression to 24-bit RGB--------------------------------------
  142. */
  143. /*************************************************
  144. purp: decompress a 4 by 4 compression block to RGBDWORD
  145. entry: uncmp == address of the destination uncompressed image
  146. cmp == address of the compressed image
  147. exit: returns updated address of the compressed image
  148. and 16 pixels are generated
  149. *************************************************/
  150. // note that the skip count is now stored in the parent stack frame
  151. // and passed as a pointer pSkipCount. This ensures that we are multithread
  152. // safe.
  153. STATICFN HPWORD INLINE DecompressCBlockToRGBTRIPLE(
  154. HPRGBTRIPLE uncmp,
  155. HPWORD cmp,
  156. INT bytesPerRow,
  157. LONG FAR * pSkipCount
  158. )
  159. {
  160. UINT by;
  161. UINT bx;
  162. UINT y;
  163. UINT x;
  164. WORD mask;
  165. WORD color0;
  166. WORD color1;
  167. WORD bitMask;
  168. RGBTRIPLE rgbTriple0;
  169. RGBTRIPLE rgbTriple1;
  170. HPRGBTRIPLE row;
  171. HPRGBTRIPLE blockRow;
  172. HPRGBTRIPLE blockColumn;
  173. WORD *pEdgeBitMask;
  174. // check for outstanding skips
  175. if (*pSkipCount > 0)
  176. {
  177. // NOT YET IMPLEMENTED Assert(!"Skip count should be handled by caller");
  178. (*pSkipCount) --;
  179. return cmp;
  180. }
  181. // get mask and init bit mask
  182. mask = *cmp++;
  183. // check for a skip or a solid color
  184. if (mask & 0x8000)
  185. {
  186. if ((mask & ~SKIP_MASK) == SKIP_MAGIC)
  187. {
  188. *pSkipCount = (mask & SKIP_MASK);
  189. #ifdef _WIN32
  190. Assert(*pSkipCount != 0); // break (on debug builds) if SkipCount == 0
  191. #endif
  192. (*pSkipCount)--;
  193. return cmp;
  194. }
  195. else
  196. {
  197. // solid color
  198. RGB555toRGBTRIPLE( rgbTriple1, mask );
  199. for( row = uncmp,y=0; y < HEIGHT_CBLOCK; y++, row = NEXT_RGBT_PIXEL_ROW( row, bytesPerRow ) )
  200. for( x=0; x < WIDTH_CBLOCK; x++ )
  201. row[x] = rgbTriple1;
  202. return cmp;
  203. }
  204. }
  205. bitMask = 1;
  206. pEdgeBitMask = edgeBitMask;
  207. if( (*cmp & 0x8000) != 0 )
  208. { // this is an edge with 4 color pairs in four small blocks
  209. blockRow = uncmp;
  210. for( by=0; by < 2; by++, blockRow = NEXT_BLOCK_ROW( blockRow, bytesPerRow, EDGE_HEIGHT_CBLOCK ) )
  211. {
  212. blockColumn = blockRow;
  213. for( bx=0; bx < 2; bx++, blockColumn += EDGE_WIDTH_CBLOCK )
  214. {
  215. color1 = *cmp++;
  216. RGB555toRGBTRIPLE( rgbTriple1, color1 );
  217. color0 = *cmp++;
  218. RGB555toRGBTRIPLE( rgbTriple0, color0 );
  219. row = blockColumn;
  220. for( y=0; y < EDGE_HEIGHT_CBLOCK; y++, row = NEXT_RGBT_PIXEL_ROW( row, bytesPerRow ) )
  221. {
  222. for( x=0; x < EDGE_WIDTH_CBLOCK; x++ )
  223. {
  224. if( (mask & *pEdgeBitMask++ ) != 0 )
  225. row[x] = rgbTriple1;
  226. else
  227. row[x] = rgbTriple0;
  228. bitMask <<= 1;
  229. }
  230. }
  231. }
  232. }
  233. }
  234. else
  235. { // not an edge with only 1 colour pair and one large block
  236. color1 = *cmp++;
  237. RGB555toRGBTRIPLE( rgbTriple1, color1 );
  238. color0 = *cmp++;
  239. RGB555toRGBTRIPLE( rgbTriple0, color0 );
  240. row = uncmp;
  241. for( y=0; y < HEIGHT_CBLOCK; y++, row = NEXT_RGBT_PIXEL_ROW( row, bytesPerRow ) )
  242. {
  243. for( x=0; x < WIDTH_CBLOCK; x++ )
  244. {
  245. if( (mask & bitMask ) != 0 )
  246. row[x] = rgbTriple1;
  247. else
  248. row[x] = rgbTriple0;
  249. bitMask <<= 1;
  250. }
  251. }
  252. }
  253. return( cmp );
  254. }
  255. /*************************************************
  256. purp: decompress the image to RGBTRIPLE
  257. entry: lpinst = pointer to instance data
  258. hpCompressed = pointer to compressed data
  259. exit: returns number of bytes in the uncompressed image
  260. lpinst->hDib = handle to the uncompressed image
  261. *************************************************/
  262. DWORD FAR PASCAL DecompressFrame24(LPBITMAPINFOHEADER lpbiIn, LPVOID lpIn,
  263. LPBITMAPINFOHEADER lpbiOut, LPVOID lpOut, LONG x, LONG y)
  264. {
  265. HPWORD cmp = (HPWORD)lpIn;
  266. int bix;
  267. int biy;
  268. HPRGBTRIPLE blockRow;
  269. HPRGBTRIPLE blockColumn;
  270. int bytesPerRow;
  271. DWORD actualSize;
  272. LONG SkipCount = 0;
  273. DPF(("DecompressFrame24:\n"));
  274. bix = (UINT)((UINT)lpbiIn->biWidth / WIDTH_CBLOCK);
  275. biy = (UINT)((UINT)lpbiIn->biHeight / HEIGHT_CBLOCK);
  276. StartCounting();
  277. blockRow = DibXY(lpbiOut, lpOut, x, y, &bytesPerRow);
  278. for( y=0; y < biy; y++, blockRow = NEXT_BLOCK_ROW( blockRow, bytesPerRow, HEIGHT_CBLOCK ) )
  279. {
  280. blockColumn = blockRow;
  281. for( x=0; x < bix; x++, blockColumn += WIDTH_CBLOCK )
  282. {
  283. cmp = DecompressCBlockToRGBTRIPLE( blockColumn, cmp, bytesPerRow, &SkipCount);
  284. }
  285. }
  286. actualSize = bytesPerRow*biy*HEIGHT_CBLOCK;
  287. EndCounting("Decompress frame24 took");
  288. return( actualSize );
  289. }
  290. /*************************************************
  291. *************************************************/
  292. /*
  293. * -------- 8-bit decompression ----------------------------------------
  294. *
  295. *
  296. * The input stream consists of four cases, handled like this:
  297. *
  298. * SKIP lower 10 bits have skip count
  299. * Return the skip count to the caller (must be multi-thread safe).
  300. * Caller will advance the source pointer past the correct number of
  301. * of skipped cells.
  302. *
  303. * SOLID lower 8 bits is solid colour for entire cell
  304. * Write the colour to each pixel, four pixels (one DWORD) at
  305. * a time.
  306. *
  307. * Mask + 2 colours
  308. * 1s in the mask represent the first colour, 0s the second colour.
  309. * Pixels are represented thus:
  310. *
  311. * C D E F
  312. * 8 9 A B
  313. * 4 5 6 7
  314. * 0 1 2 3
  315. *
  316. * To write four pixels at once, we rely on the fact that:
  317. * (a ^ b) ^ a == b
  318. * and also that a ^ 0 == a.
  319. * We create a DWORD (Czero) containing four copies of the colour 0, and
  320. * another DWORD (Cxor) containing four copies of (colour 0 ^ colour 1).
  321. * Then we convert each bit in the mask (1 or 0) into a byte (0xff or 0),
  322. * and combining four mask bytes into a DWORD. Then we can select
  323. * four pixels at once (AND the mask with Czero and then XOR with Cxor).
  324. *
  325. * Mask + 8 colours.
  326. * 1s and 0s represent two colours as before, but the cell is divided
  327. * into 4 subcells with two colours per subcell. The first pair of
  328. * colours are for subcell 0145, then 2367, 89cd and abef.
  329. *
  330. * We use the same algorithm as for the mask+2 case except that when
  331. * making the mask, we need colours from the second pair in the top
  332. * two bytes of Czero and Cxor, and that we need to change colours
  333. * again after two rows.
  334. *
  335. * -----------------------------------------------------------------------
  336. */
  337. /*
  338. * DecompressCBlockTo8
  339. *
  340. *
  341. * decompress one cell to 16 8-bit pixels.
  342. *
  343. * parameters:
  344. * uncmp- pointer to de-compressed buffer for this block.
  345. * cmp - pointer to compressed data for this block
  346. * bytes.. - size of one row of de-compressed data
  347. * pSkipCount - place to return the skipcount if non-zero.
  348. *
  349. * returns:
  350. * pointer to the next block of compressed data to use.
  351. */
  352. STATICFN HPWORD INLINE DecompressCBlockTo8(
  353. HPBYTE uncmp,
  354. HPWORD cmp,
  355. INT bytesPerRow,
  356. LONG FAR * pSkipCount
  357. )
  358. {
  359. UINT y;
  360. WORD mask;
  361. BYTE b0,b1;
  362. HPBYTE row;
  363. BYTE b2, b3;
  364. DWORD Czero, Cxor;
  365. DWORD dwBytes;
  366. // skip counts should be handled by caller
  367. #ifdef _WIN32
  368. Assert(*pSkipCount == 0);
  369. #endif
  370. /* first word is the escape word or bit mask */
  371. mask = *cmp++;
  372. /*
  373. * is this an escape ?
  374. */
  375. if (mask & 0x8000)
  376. {
  377. /* yes - this is either a SKIP code, a solid colour, or an edge
  378. * cell (mask + 8 colours).
  379. */
  380. if ((mask & ~SKIP_MASK) == SKIP_MAGIC)
  381. {
  382. *pSkipCount = (mask & SKIP_MASK);
  383. #ifdef _WIN32
  384. Assert(*pSkipCount != 0); // break (on debug builds) if SkipCount == 0
  385. #endif
  386. (*pSkipCount)--; // the current cell
  387. return cmp;
  388. }
  389. else if ((mask & ~SKIP_MASK) == SOLID_MAGIC)
  390. {
  391. // solid color
  392. DWORD dw;
  393. //b0 = LOBYTE(mask);
  394. //dw = b0 | b0<<8 | b0<<16 | b0<<24;
  395. dw = LOBYTE(mask);
  396. dw = MAKE4(dw);
  397. #ifdef _WIN32
  398. Assert(HEIGHT_CBLOCK == 4); // If this ever changes...
  399. Assert(WIDTH_CBLOCK == 4);
  400. #endif
  401. for(y = 0, row = uncmp; y < HEIGHT_CBLOCK;y++, row+= bytesPerRow) {
  402. // We know we will iterate 4 times (WIDTH_CBLOCK) storing
  403. // 4 bytes of colour b0 in 4 adjacent rows
  404. *(DWORD UNALIGNED HUGE *)row = dw;
  405. }
  406. return cmp;
  407. }
  408. else // this is an edge with 4 color pairs in four small blocks
  409. {
  410. /* read 4 colours, and make AND and XOR masks */
  411. b0 = *((LPBYTE)cmp)++;
  412. b1 = *((LPBYTE)cmp)++;
  413. b2 = *((LPBYTE)cmp)++;
  414. b3 = *((LPBYTE)cmp)++;
  415. Czero = MAKE22(b1, b3);
  416. Cxor = Czero ^ MAKE22(b0, b2);
  417. row = uncmp;
  418. /* first two rows - top two subcells */
  419. for (y = 0; y < 2; y++) {
  420. /* turn bitmask into byte mask */
  421. dwBytes = ExpansionTable[mask & 0x0f];
  422. /* select colours and write to dest */
  423. *( (DWORD UNALIGNED HUGE *)row) = (dwBytes & Cxor) ^ Czero;
  424. row += bytesPerRow;
  425. mask >>= 4;
  426. }
  427. /* second two rows - bottom two subcells */
  428. /* read last four colours and make masks */
  429. b0 = *((LPBYTE)cmp)++;
  430. b1 = *((LPBYTE)cmp)++;
  431. b2 = *((LPBYTE)cmp)++;
  432. b3 = *((LPBYTE)cmp)++;
  433. Czero = MAKE22(b1, b3);
  434. Cxor = Czero ^ MAKE22(b0, b2);
  435. for (y = 0; y < 2; y++) {
  436. /* turn bitmask into byte mask */
  437. dwBytes = ExpansionTable[mask & 0x0f];
  438. /* select both colours and write to dest */
  439. *( (DWORD UNALIGNED HUGE *)row) = (dwBytes & Cxor) ^ Czero;
  440. row += bytesPerRow;
  441. mask >>= 4;
  442. }
  443. }
  444. }
  445. else // not an edge with only 1 colour pair and one large block
  446. {
  447. /* use and, xor to map several colours at once.
  448. * relies on (Czero ^ Cone) ^ Czero == Cone and Czero ^ 0 == Czero.
  449. */
  450. /* read colours */
  451. b1 = *((LPBYTE)cmp)++;
  452. b0 = *((LPBYTE)cmp)++;
  453. row = uncmp;
  454. /* make two DWORDs, one with four copies of colour 0, and one
  455. * with four copies of (b0 ^ b1).
  456. */
  457. Czero = MAKE4(b0);
  458. Cxor = Czero ^ MAKE4(b1);
  459. for (y = 0; y < 4; y++) {
  460. /* turn bitmask into byte mask */
  461. dwBytes = ExpansionTable[mask & 0x0f];
  462. /* select both colours and write to dest */
  463. *( (DWORD UNALIGNED HUGE *)row) = (dwBytes & Cxor) ^ Czero;
  464. row += bytesPerRow;
  465. mask >>= 4;
  466. }
  467. }
  468. return( cmp );
  469. }
  470. /*************************************************
  471. *************************************************/
  472. /*
  473. * decompress a CRAM-8 DIB to an 8-bit DIB
  474. *
  475. * Loop calling DecompressCBlockTo8 for each cell in the input
  476. * stream. This writes a block of 16 pixels and returns us the
  477. * pointer for the next block.
  478. */
  479. DWORD FAR PASCAL DecompressFrame8(LPBITMAPINFOHEADER lpbiIn, LPVOID lpIn,
  480. LPBITMAPINFOHEADER lpbiOut, LPVOID lpOut, LONG x, LONG y)
  481. {
  482. HPWORD cmp = (HPWORD)lpIn;
  483. int bix;
  484. int biy;
  485. HPBYTE blockRow;
  486. HPBYTE blockColumn;
  487. LONG SkipCount8 = 0; // multithread-safe - cannot be static
  488. int bytesPerRow;
  489. DPF(("DecompressFrame8:\n"));
  490. bix = (int)((UINT)lpbiIn->biWidth / WIDTH_CBLOCK);
  491. biy = (int)((UINT)lpbiIn->biHeight / HEIGHT_CBLOCK);
  492. StartCounting();
  493. blockRow = DibXY(lpbiOut, lpOut, x, y, &bytesPerRow);
  494. for( y=biy; y--; blockRow += bytesPerRow * HEIGHT_CBLOCK )
  495. {
  496. blockColumn = blockRow;
  497. for( x=bix; x--; blockColumn += WIDTH_CBLOCK )
  498. {
  499. cmp = DecompressCBlockTo8(blockColumn, cmp, bytesPerRow, &SkipCount8);
  500. // See if the SkipCount has been set. If so we want to move to
  501. // the next location rather than calling DecompressCBlock every
  502. // time around the loop. Keep the test simple to minimise the
  503. // overhead on every iteration that the Skipcount is 0.
  504. if (SkipCount8) {
  505. if ((x -= SkipCount8) <0) { // extends past this row
  506. LONG SkipRows;
  507. // More than just the remainder of this row to skip
  508. SkipCount8 =-x; // These bits are on the next row(s)
  509. // SkipCount8 will be >0 otherwise we would have gone
  510. // down the else leg.
  511. // Calculate how many complete and partial rows to skip.
  512. // We know we have skipped at least one row. The plan
  513. // is to restart the X loop at some point along the row.
  514. // If the skipcount takes us exactly to the end of a row
  515. // we drop out of the x loop, and let the outer y loop do
  516. // the decrement. This takes care of the case when the
  517. // skipcount takes us to the very end of the image.
  518. SkipRows = 1 + (SkipCount8-1)/bix;
  519. // Decrement the row count and set new blockrow start
  520. #ifdef _WIN32
  521. if (y<SkipRows) {
  522. Assert(y >= SkipRows);
  523. SkipRows = y;
  524. }
  525. #endif
  526. // Unless we have finished we need to reset blockRow
  527. y -= SkipRows;
  528. // y might be 0, but we must still complete the last row
  529. blockRow += bytesPerRow*HEIGHT_CBLOCK*SkipRows;
  530. // Calculate the offset into the next row we will process
  531. x = SkipCount8%bix; // This may be 0
  532. if (x) {
  533. // Set block column by the amount along the row
  534. // this iteration is starting, making allowance for
  535. // the "for x..." loop iterating blockColumn once.
  536. blockColumn = blockRow + ((x-1)*WIDTH_CBLOCK);
  537. x=bix-x; // Get the counter correct
  538. }
  539. SkipCount8 = 0; // Skip count now exhausted (so am I)
  540. } else {
  541. // SkipCount has been exhausted by this row
  542. // Either the row has completed, or there is more data
  543. // on this row. Check...
  544. if (x) {
  545. // More of this row left
  546. // Worry about moving blockColumn on the right amount
  547. blockColumn += WIDTH_CBLOCK*SkipCount8;
  548. } // else x==0 and we will drop out of the "for x..." loop
  549. // blockColumn will be reset when we reenter the x loop
  550. SkipCount8=0;
  551. }
  552. }
  553. }
  554. }
  555. EndCounting("Decompress 8bit took");
  556. return 0;
  557. }
  558. #ifdef _WIN32
  559. /* ---- 8-bit X2 decompress - in asm for Win16 ---------------------------*/
  560. /*
  561. * decompress one block, stretching by 2.
  562. *
  563. * parameters:
  564. * uncmp- pointer to de-compressed buffer for this block.
  565. * cmp - pointer to compressed data for this block
  566. * bytes.. - size of one row of de-compressed data
  567. *
  568. * returns:
  569. * pointer to the next block of compressed data.
  570. *
  571. * Given same incoming data, write a block of four pixels for every
  572. * pixel in original compressed image. Uses same techniques as
  573. * unstretched routine, masking and writing four pixels (one dword)
  574. * at a time.
  575. *
  576. * Stretching by 2 is done by simple pixel duplication.
  577. * Experiments were done (x86) to only store every other line, then to use
  578. * memcpy to fill in the gaps. This is slower than writing two identical
  579. * lines as you proceed.
  580. *
  581. * Skip counts are returned (via pSkipCount) to the caller, who will handle
  582. * advancing the source pointer accordingly.
  583. *
  584. */
  585. STATICFN HPWORD INLINE DecompressCBlockTo8X2(
  586. HPBYTE uncmp,
  587. HPWORD cmp,
  588. INT bytesPerRow,
  589. LONG FAR * pSkipCount)
  590. {
  591. UINT y;
  592. UINT dx, dy;
  593. WORD mask;
  594. BYTE b0,b1;
  595. HPBYTE row;
  596. DWORD Czero, Cxor, dwBytes;
  597. DWORD Ctwo, Cxor2;
  598. // skip counts should be handled by caller
  599. #ifdef _WIN32
  600. Assert (*pSkipCount == 0);
  601. #endif
  602. // get mask and init bit mask
  603. mask = *cmp++;
  604. // check for a skip or a solid color
  605. if (mask & 0x8000)
  606. {
  607. if ((mask & ~SKIP_MASK) == SKIP_MAGIC)
  608. {
  609. *pSkipCount = (mask & SKIP_MASK);
  610. #ifdef _WIN32
  611. Assert(*pSkipCount != 0); // break (on debug builds) if SkipCount == 0
  612. #endif
  613. (*pSkipCount)--;
  614. return cmp;
  615. }
  616. else if ((mask & ~SKIP_MASK) == SOLID_MAGIC)
  617. {
  618. // solid color
  619. DWORD dw;
  620. //b0 = LOBYTE(mask);
  621. //dw = b0 | b0<<8 | b0<<16 | b0<<24;
  622. dw = LOBYTE(mask);
  623. dw = MAKE4(dw);
  624. #ifdef _WIN32
  625. Assert(HEIGHT_CBLOCK == 4); // If this ever changes...
  626. Assert(WIDTH_CBLOCK == 4);
  627. #endif
  628. dx = WIDTH_CBLOCK * 2;
  629. dy = HEIGHT_CBLOCK * 2;
  630. for(row = uncmp; dy--; row+= bytesPerRow) {
  631. // We know we will iterate 8 times (dx) value storing
  632. // 4 bytes of colour b0 in eight adjacent rows
  633. *(DWORD UNALIGNED HUGE *)row = dw;
  634. *((DWORD UNALIGNED HUGE *)row+1) = dw;
  635. }
  636. return cmp;
  637. }
  638. else // this is an edge with 4 color pairs in four small blocks
  639. {
  640. /* read 2 colours, and make AND and XOR masks for first subcell*/
  641. b0 = *((LPBYTE)cmp)++;
  642. b1 = *((LPBYTE)cmp)++;
  643. Czero = MAKE4(b1);
  644. Cxor = Czero ^ MAKE4(b0);
  645. /* colour masks for second subcell */
  646. b0 = *((LPBYTE)cmp)++;
  647. b1 = *((LPBYTE)cmp)++;
  648. Ctwo = MAKE4(b1);
  649. Cxor2 = Ctwo ^ MAKE4(b0);
  650. row = uncmp;
  651. /* first two rows - top two subcells */
  652. for (y = 0; y < 2; y++) {
  653. /* --- first subcell (two pixels) ---- */
  654. /* turn bitmask into byte mask */
  655. #if 0
  656. dwBytes = ((mask & 1) ? 0xffff: 0) |
  657. ((mask & 2) ? 0xffff0000 : 0);
  658. #else
  659. dwBytes = Bits2Bytes[mask&3];
  660. #endif
  661. /* select both colours and write to dest */
  662. dwBytes = (dwBytes & Cxor) ^ Czero;
  663. *( (DWORD UNALIGNED HUGE *)row) = dwBytes;
  664. *( (DWORD UNALIGNED HUGE *)(row + bytesPerRow)) = dwBytes;
  665. /* ---- second subcell (two pixels) --- */
  666. /* turn bitmask into byte mask */
  667. #if 0
  668. dwBytes = ((mask & 4) ? 0xffff: 0) |
  669. ((mask & 8) ? 0xffff0000 : 0);
  670. #else
  671. dwBytes = Bits2Bytes[mask&0xc];
  672. #endif
  673. /* select both colours and write to dest */
  674. dwBytes = (dwBytes & Cxor2) ^ Ctwo;
  675. *( (DWORD UNALIGNED HUGE *)(row + sizeof(DWORD))) = dwBytes;
  676. *( (DWORD UNALIGNED HUGE *)(row + sizeof(DWORD) + bytesPerRow)) = dwBytes;
  677. row += bytesPerRow * 2;
  678. mask >>= 4;
  679. }
  680. /* second two rows - bottom two subcells */
  681. /* read 2 colours, and make AND and XOR masks for first subcell*/
  682. b0 = *((LPBYTE)cmp)++;
  683. b1 = *((LPBYTE)cmp)++;
  684. Czero = MAKE4(b1);
  685. Cxor = Czero ^ MAKE4(b0);
  686. /* colour masks for second subcell */
  687. b0 = *((LPBYTE)cmp)++;
  688. b1 = *((LPBYTE)cmp)++;
  689. Ctwo = MAKE4(b1);
  690. Cxor2 = Ctwo ^ MAKE4(b0);
  691. for (y = 0; y < 2; y++) {
  692. /* --- first subcell (two pixels) ---- */
  693. /* turn bitmask into byte mask */
  694. #if 0
  695. dwBytes = ((mask & 1) ? 0xffff: 0) |
  696. ((mask & 2) ? 0xffff0000 : 0);
  697. #else
  698. dwBytes = Bits2Bytes[mask&3];
  699. #endif
  700. /* select both colours and write to dest */
  701. dwBytes = (dwBytes & Cxor) ^ Czero;
  702. *( (DWORD UNALIGNED HUGE *)row) = dwBytes;
  703. *( (DWORD UNALIGNED HUGE *)(row + bytesPerRow)) = dwBytes;
  704. /* ---- second subcell (two pixels) --- */
  705. /* turn bitmask into byte mask */
  706. #if 0
  707. dwBytes = ((mask & 4) ? 0xffff: 0) |
  708. ((mask & 8) ? 0xffff0000 : 0);
  709. #else
  710. dwBytes = Bits2Bytes[mask&0xc];
  711. #endif
  712. /* select both colours and write to dest */
  713. dwBytes = (dwBytes & Cxor2) ^ Ctwo;
  714. *( (DWORD UNALIGNED HUGE *)(row + sizeof(DWORD))) = dwBytes;
  715. *( (DWORD UNALIGNED HUGE *)(row + sizeof(DWORD) + bytesPerRow)) = dwBytes;
  716. row += bytesPerRow * 2;
  717. mask >>= 4;
  718. }
  719. }
  720. }
  721. else // not an edge with only 1 color pair and one large block
  722. {
  723. /* use and, xor to map several colours at once.
  724. * relies on (Czero ^ Cone) ^ Czero == Cone and Czero ^ 0 == Czero.
  725. */
  726. /* read colours */
  727. b1 = *((LPBYTE)cmp)++;
  728. b0 = *((LPBYTE)cmp)++;
  729. row = uncmp;
  730. /* make two DWORDs, one with four copies of colour 0, and one
  731. * with four copies of (b0 ^ b1).
  732. */
  733. Czero = MAKE4(b0);
  734. Cxor = Czero ^ MAKE4(b1);
  735. for (y = 0; y < 4; y++) {
  736. /* --- first two pixels in row ---- */
  737. /* turn bitmask into byte mask */
  738. #if 0
  739. dwBytes = ((mask & 1) ? 0xffff: 0) |
  740. ((mask & 2) ? 0xffff0000 : 0);
  741. #else
  742. dwBytes = Bits2Bytes[mask&3];
  743. #endif
  744. /* select both colours and write to dest */
  745. dwBytes = (dwBytes & Cxor) ^ Czero;
  746. *( (DWORD UNALIGNED HUGE *)row) = dwBytes;
  747. *( (DWORD UNALIGNED HUGE *)(row + bytesPerRow)) = dwBytes;
  748. /* ---- second two pixels in row ---- */
  749. /* turn bitmask into byte mask */
  750. #if 0
  751. dwBytes = ((mask & 4) ? 0xffff: 0) |
  752. ((mask & 8) ? 0xffff0000 : 0);
  753. #else
  754. dwBytes = Bits2Bytes[mask&0xc];
  755. #endif
  756. /* select both colours and write to dest */
  757. dwBytes = (dwBytes & Cxor) ^ Czero;
  758. *( (DWORD UNALIGNED HUGE *)(row + sizeof(DWORD))) = dwBytes;
  759. *( (DWORD UNALIGNED HUGE *)(row + sizeof(DWORD) + bytesPerRow)) = dwBytes;
  760. row += bytesPerRow * 2;
  761. mask >>= 4;
  762. }
  763. }
  764. return( cmp );
  765. }
  766. /*
  767. * decompress one frame, stretching by 2.
  768. *
  769. * parameters:
  770. * lpbiIn pointer to compressed buffer for this frame
  771. * lpIn pointer to compressed data for this block
  772. * lpbiOut pointer to decompressed bitmap header
  773. * lpOut pointer to where to store the decompressed data
  774. *
  775. * returns:
  776. * 0 on success
  777. *
  778. * Uses DecompressCBlockTo8X2 (see above) to do the decompression.
  779. * This also returns (via a pointer to SkipCount8X2) the count of cells
  780. * to skip. We can then move the source and target pointers on
  781. * until the SkipCount is exhausted.
  782. */
  783. DWORD FAR PASCAL DecompressFrame8X2C(LPBITMAPINFOHEADER lpbiIn, LPVOID lpIn,
  784. LPBITMAPINFOHEADER lpbiOut, LPVOID lpOut, LONG x, LONG y)
  785. {
  786. HPWORD cmp = (HPWORD)lpIn;
  787. int bix;
  788. int biy;
  789. HPBYTE blockRow;
  790. HPBYTE blockColumn;
  791. LONG SkipCount8X2 = 0;
  792. int bytesPerRow;
  793. DPF(("DecompressFrame8X2C:\n"));
  794. bix = (int)(lpbiIn->biWidth) / (WIDTH_CBLOCK);
  795. biy = (int)(lpbiIn->biHeight) / (HEIGHT_CBLOCK);
  796. StartCounting();
  797. blockRow = DibXY(lpbiOut, lpOut, x, y, &bytesPerRow);
  798. for( y=biy; y--; blockRow += bytesPerRow * HEIGHT_CBLOCK*2 )
  799. {
  800. blockColumn = blockRow;
  801. for( x=bix; x--; blockColumn += WIDTH_CBLOCK*2 )
  802. {
  803. cmp = DecompressCBlockTo8X2(blockColumn, cmp, bytesPerRow, &SkipCount8X2);
  804. // See if the SkipCount has been set. If so we want to move to
  805. // the next location rather than calling DecompressCBlock every
  806. // time around the loop. Keep the test simple to minimise the
  807. // overhead on every iteration that the Skipcount is 0.
  808. if (SkipCount8X2) {
  809. if ((x -= SkipCount8X2) <0) { // extends past this row
  810. LONG SkipRows;
  811. // More than just the remainder of this row to skip
  812. SkipCount8X2 =-x; // These bits are on the next row(s)
  813. // SkipCount8X2 will be >0 otherwise we would have gone
  814. // down the else leg.
  815. // Calculate how many complete and partial rows to skip.
  816. // We know we have skipped at least one row. The plan
  817. // is to restart the X loop at some point along the row.
  818. // If the skipcount takes us exactly to the end of a row
  819. // we drop out of the x loop, and let the outer y loop do
  820. // the decrement. This takes care of the case when the
  821. // skipcount takes us to the very end of the image.
  822. SkipRows = 1 + (SkipCount8X2-1)/bix;
  823. // Decrement the row count and set new blockrow start
  824. #ifdef _WIN32
  825. if (y<SkipRows) {
  826. Assert(y >= SkipRows);
  827. SkipRows = y;
  828. }
  829. #endif
  830. // Unless we have finished we need to reset blockRow
  831. y -= SkipRows;
  832. // y might be 0, but we must still complete the last row
  833. blockRow += bytesPerRow*HEIGHT_CBLOCK*2*SkipRows;
  834. // Calculate the offset into the next row we will process
  835. x = SkipCount8X2%bix; // This may be 0
  836. if (x) {
  837. // Set block column by the amount along the row
  838. // this iteration is starting, making allowance for
  839. // the "for x..." loop iterating blockColumn once.
  840. blockColumn = blockRow + ((x-1)*WIDTH_CBLOCK*2);
  841. x=bix-x; // Get the counter correct
  842. }
  843. SkipCount8X2 = 0; // Skip count now exhausted (so am I)
  844. } else {
  845. // SkipCount has been exhausted by this row
  846. // Either the row has completed, or there is more data
  847. // on this row. Check...
  848. if (x) {
  849. // More of this row left
  850. // Worry about moving blockColumn on the right amount
  851. blockColumn += WIDTH_CBLOCK*2*SkipCount8X2;
  852. } // else x==0 and we will drop out of the "for x..." loop
  853. // blockColumn will be reset when we reenter the x loop
  854. SkipCount8X2=0;
  855. }
  856. }
  857. }
  858. }
  859. EndCounting("Decompress and stretch 8x2 took");
  860. return 0;
  861. }
  862. /*
  863. * -------- 16-bit decompression ----------------------------------------
  864. *
  865. *
  866. * CRAM-16 has 16-bit mask or escape code, together with 16-bit (RGB555)
  867. * colour words. We decode to 16 bits, to 24-bits (above), and to 8 bits
  868. * stretched 1:1 and 1:2 (this case DecompressFrame16To8X2C does
  869. * decompression, dithering and stretching in one pass.
  870. *
  871. * The input stream consists of four cases:
  872. *
  873. * SOLID top bit set, lower 15 bits is solid colour for entire cell
  874. * If the red element (bits 9-14) = '00001', then this is not a solid
  875. * colour but a skip count.
  876. * Write the colour to each pixel, two pixels (one DWORD) at
  877. * a time.
  878. *
  879. * SKIP top 6 bits = 100001xxxxxxxxxx, lower 10 bits have skip count
  880. * Store the skip count via a pointer to a variable passed by the.
  881. * parent - this way the skip count is maintained across calls
  882. *
  883. * Mask + 2 colours (top bit 0, bit 15 of first colour word also 0)
  884. * 1s in the mask represent the first colour, 0s the second colour.
  885. * Pixels are represented thus:
  886. *
  887. * C D E F
  888. * 8 9 A B
  889. * 4 5 6 7
  890. * 0 1 2 3
  891. *
  892. *
  893. * Mask + 8 colours. (top bit 0, bit 15 of first colour word == 1)
  894. *
  895. * 1s and 0s represent two colours as before, but the cell is divided
  896. * into 4 subcells with two colours per subcell. The first pair of
  897. * colours are for subcell 0145, then 2367, 89cd and abef.
  898. *
  899. *
  900. * Dithering:
  901. *
  902. * we use the table method from drawdib\dith775.c, and we import the
  903. * same tables and palette by including their header file. We have a fixed
  904. * palette in which we have 7 levels of red, 7 levels of green and 5 levels of
  905. * blue (= 245 combinations) in a 256-colour palette. We use tables
  906. * to quantize the colour elements to 7 levels, combine them into an 8-bit
  907. * value and then lookup in a table that maps this combination to the actual
  908. * palette. Before quantizing, we add on small corrections (less than one
  909. * level) based on the x,y position of the pixel to balance the
  910. * colour over a 4x4 pixel area: this makes the decompression slightly more
  911. * awkward since we dither differently for any x, y position within the cell.
  912. *
  913. * -----------------------------------------------------------------------
  914. */
  915. /* ---- 16-bit decompress to 16 bits ----------------------------------*/
  916. /*
  917. * decompress one 16bpp block to RGB555.
  918. *
  919. * parameters:
  920. * uncmp- pointer to de-compressed buffer for this block.
  921. * cmp - pointer to compressed data for this block
  922. * bytes.. - size of one row of de-compressed data
  923. * pSkipCount - outstanding count of cells to skip - set here and just stored
  924. * in parent stack frame for multi-thread-safe continuity.
  925. *
  926. * returns:
  927. * pointer to the next block of compressed data.
  928. *
  929. */
  930. STATICFN HPWORD INLINE
  931. DecompressCBlock16To555(
  932. HPBYTE uncmp,
  933. HPWORD cmp,
  934. INT bytesPerRow,
  935. LONG FAR *pSkipCount
  936. )
  937. {
  938. UINT y;
  939. WORD mask;
  940. WORD col0, col1;
  941. HPBYTE row;
  942. DWORD Czero, Cxor, Ctwo, Cxor2, dwBytes;
  943. // check for outstanding skips
  944. if (*pSkipCount > 0)
  945. {
  946. (*pSkipCount)--;
  947. return cmp;
  948. }
  949. // get mask and init bit mask
  950. mask = *cmp++;
  951. // check for a skip or a solid color
  952. if (mask & 0x8000)
  953. {
  954. if ((mask & ~SKIP_MASK) == SKIP_MAGIC)
  955. {
  956. *pSkipCount = (mask & SKIP_MASK);
  957. #ifdef _WIN32
  958. Assert(*pSkipCount != 0); // break (on debug builds) if SkipCount == 0
  959. #endif
  960. (*pSkipCount)--;
  961. return cmp;
  962. }
  963. else /* must be solid colour */
  964. {
  965. /* write four rows of 4 2-byte pixels of col0 */
  966. /* solid colour is lower 15 bits of mask */
  967. col0 = mask & 0x7fff;
  968. Czero = col0 | (col0 << 16);
  969. for(row = uncmp, y = 0; y < HEIGHT_CBLOCK; y++, row+= bytesPerRow) {
  970. *(DWORD UNALIGNED HUGE *)row = Czero;
  971. *((DWORD UNALIGNED HUGE *)row+1) = Czero;
  972. }
  973. return cmp;
  974. }
  975. }
  976. /* in 16-bit CRAM, both 4-pair and 1-pair cells have bit 15 of mask set
  977. * to zero. We distinguish between them based on bit 15 of the first
  978. * colour. if this is set, this is the 4-pair edge case cell.
  979. */
  980. if (*cmp & 0x8000) {
  981. // this is an edge with 4 colour pairs in four small blocks
  982. /* read 2 colours, and make AND and XOR masks for first subcell*/
  983. col0 = *cmp++;
  984. col1 = *cmp++;
  985. Czero = col1 | (col1 << 16);
  986. Cxor = Czero ^ (col0 | (col0 << 16));
  987. /* colour masks for second subcell */
  988. col0 = *cmp++;
  989. col1 = *cmp++;
  990. Ctwo = col1 | (col1 << 16);
  991. Cxor2 = Ctwo ^ (col0 | (col0 << 16));
  992. row = uncmp;
  993. /* first two rows - top two subcells */
  994. for (y = 0; y < 2; y++) {
  995. /* --- first subcell (two pixels) ---- */
  996. /* turn bitmask into byte mask */
  997. #if 0
  998. dwBytes = ((mask & 1) ? 0xffff: 0) |
  999. ((mask & 2) ? 0xffff0000 : 0);
  1000. #else
  1001. dwBytes = Bits2Bytes[mask&3];
  1002. #endif
  1003. /* select both colours and write to dest */
  1004. dwBytes = (dwBytes & Cxor) ^ Czero;
  1005. *( (DWORD UNALIGNED HUGE *)row) = dwBytes;
  1006. /* ---- second subcell (two pixels) --- */
  1007. /* turn bitmask into byte mask */
  1008. #if 0
  1009. dwBytes = ((mask & 4) ? 0xffff: 0) |
  1010. ((mask & 8) ? 0xffff0000 : 0);
  1011. #else
  1012. dwBytes = Bits2Bytes[mask&0xc];
  1013. #endif
  1014. /* select both colours and write to dest */
  1015. dwBytes = (dwBytes & Cxor2) ^ Ctwo;
  1016. *( (DWORD UNALIGNED HUGE *)(row + sizeof(DWORD))) = dwBytes;
  1017. row += bytesPerRow;
  1018. mask >>= 4;
  1019. }
  1020. /* second two rows - bottom two subcells */
  1021. /* read 2 colours, and make AND and XOR masks for first subcell*/
  1022. col0 = *cmp++;
  1023. col1 = *cmp++;
  1024. Czero = col1 | (col1 << 16);
  1025. Cxor = Czero ^ (col0 | (col0 << 16));
  1026. /* colour masks for second subcell */
  1027. col0 = *cmp++;
  1028. col1 = *cmp++;
  1029. Ctwo = col1 | (col1 << 16);
  1030. Cxor2 = Ctwo ^ (col0 | (col0 << 16));
  1031. for (y = 0; y < 2; y++) {
  1032. /* --- first subcell (two pixels) ---- */
  1033. /* turn bitmask into byte mask */
  1034. #if 0
  1035. dwBytes = ((mask & 1) ? 0xffff: 0) |
  1036. ((mask & 2) ? 0xffff0000 : 0);
  1037. #else
  1038. dwBytes = Bits2Bytes[mask&3];
  1039. #endif
  1040. /* select both colours and write to dest */
  1041. dwBytes = (dwBytes & Cxor) ^ Czero;
  1042. *( (DWORD UNALIGNED HUGE *)row) = dwBytes;
  1043. /* ---- second subcell (two pixels) --- */
  1044. /* turn bitmask into byte mask */
  1045. #if 0
  1046. dwBytes = ((mask & 4) ? 0xffff: 0) |
  1047. ((mask & 8) ? 0xffff0000 : 0);
  1048. #else
  1049. dwBytes = Bits2Bytes[mask&0xc];
  1050. #endif
  1051. /* select both colours and write to dest */
  1052. dwBytes = (dwBytes & Cxor2) ^ Ctwo;
  1053. *( (DWORD UNALIGNED HUGE *)(row + sizeof(DWORD))) = dwBytes;
  1054. row += bytesPerRow;
  1055. mask >>= 4;
  1056. }
  1057. } else {
  1058. // not an edge with only 1 colour pair and one large block
  1059. /* read colours */
  1060. col0 = *cmp++;
  1061. col1 = *cmp++;
  1062. Czero = col1 | (col1 << 16);
  1063. Cxor = Czero ^ (col0 | (col0 << 16));
  1064. row = uncmp;
  1065. for (y = 0; y < 4; y++) {
  1066. /* --- first two pixels in row ---- */
  1067. /* turn bitmask into byte mask */
  1068. #if 0
  1069. dwBytes = ((mask & 1) ? 0xffff: 0) |
  1070. ((mask & 2) ? 0xffff0000 : 0);
  1071. #else
  1072. dwBytes = Bits2Bytes[mask&3];
  1073. #endif
  1074. /* select both colours and write to dest */
  1075. dwBytes = (dwBytes & Cxor) ^ Czero;
  1076. *( (DWORD UNALIGNED HUGE *)row) = dwBytes;
  1077. /* ---- second two pixels in row ---- */
  1078. /* turn bitmask into byte mask */
  1079. #if 0
  1080. dwBytes = ((mask & 4) ? 0xffff: 0) |
  1081. ((mask & 8) ? 0xffff0000 : 0);
  1082. #else
  1083. dwBytes = Bits2Bytes[mask&0xc];
  1084. #endif
  1085. /* select both colours and write to dest */
  1086. dwBytes = (dwBytes & Cxor) ^ Czero;
  1087. *( (DWORD UNALIGNED HUGE *)(row + sizeof(DWORD))) = dwBytes;
  1088. row += bytesPerRow;
  1089. mask >>= 4;
  1090. }
  1091. }
  1092. return( cmp );
  1093. }
  1094. DWORD FAR PASCAL DecompressFrame16To555C(LPBITMAPINFOHEADER lpbiIn, LPVOID lpIn,
  1095. LPBITMAPINFOHEADER lpbiOut, LPVOID lpOut, LONG x, LONG y)
  1096. {
  1097. HPWORD cmp = (HPWORD)lpIn;
  1098. INT bix;
  1099. INT biy;
  1100. HPBYTE blockRow;
  1101. HPBYTE blockColumn;
  1102. LONG SkipCount = 0;
  1103. INT bytesPerRow;
  1104. DPF(("DecompressFrame16To555C:\n"));
  1105. bix = (UINT)(lpbiIn->biWidth) / (WIDTH_CBLOCK); // No negative values in
  1106. biy = (UINT)(lpbiIn->biHeight) / (HEIGHT_CBLOCK); // width or height fields
  1107. StartCounting();
  1108. blockRow = DibXY(lpbiOut, lpOut, x, y, &bytesPerRow);
  1109. for( y=0; y < biy; y++, blockRow += bytesPerRow * HEIGHT_CBLOCK )
  1110. {
  1111. blockColumn = blockRow;
  1112. for( x=0; x < bix; x++, blockColumn += (WIDTH_CBLOCK * sizeof(WORD)))
  1113. {
  1114. cmp = DecompressCBlock16To555(blockColumn, cmp, bytesPerRow, &SkipCount);
  1115. }
  1116. }
  1117. EndCounting("Decompress Frame16To555C took");
  1118. return 0;
  1119. }
  1120. // 16-bit 565 decompression
  1121. // macro to convert a 15-bit 555 colour to a 16-bit 565 colour
  1122. #define RGB555_TO_RGB565(c) (c = ( ((c & 0x7fe0) << 1) | (c & 0x1f)))
  1123. /*
  1124. * decompress one 16bpp block to RGB565.
  1125. *
  1126. * same as RGB555 but we need a colour translation between 555->565
  1127. *
  1128. * parameters:
  1129. * uncmp- pointer to de-compressed buffer for this block.
  1130. * cmp - pointer to compressed data for this block
  1131. * bytes.. - size of one row of de-compressed data
  1132. * pSkipCount - outstanding count of cells to skip - set here and just stored
  1133. * in parent stack frame for multi-thread-safe continuity.
  1134. *
  1135. * returns:
  1136. * pointer to the next block of compressed data.
  1137. *
  1138. */
  1139. STATICFN HPWORD INLINE
  1140. DecompressCBlock16To565(
  1141. HPBYTE uncmp,
  1142. HPWORD cmp,
  1143. INT bytesPerRow,
  1144. LONG FAR * pSkipCount
  1145. )
  1146. {
  1147. UINT y;
  1148. WORD mask;
  1149. WORD col0, col1;
  1150. HPBYTE row;
  1151. DWORD Czero, Cxor, Ctwo, Cxor2, dwBytes;
  1152. // check for outstanding skips
  1153. if (*pSkipCount > 0)
  1154. {
  1155. (*pSkipCount)--;
  1156. return cmp;
  1157. }
  1158. // get mask and init bit mask
  1159. mask = *cmp++;
  1160. // check for a skip or a solid color
  1161. if (mask & 0x8000)
  1162. {
  1163. if ((mask & ~SKIP_MASK) == SKIP_MAGIC)
  1164. {
  1165. *pSkipCount = (mask & SKIP_MASK);
  1166. #ifdef _WIN32
  1167. Assert(*pSkipCount != 0); // break (on debug builds) if SkipCount == 0
  1168. #endif
  1169. (*pSkipCount)--;
  1170. return cmp;
  1171. }
  1172. else /* must be solid colour */
  1173. {
  1174. /* write four rows of 4 2-byte pixels of col0 */
  1175. /* solid colour is lower 15 bits of mask */
  1176. col0 = mask & 0x7fff;
  1177. RGB555_TO_RGB565(col0);
  1178. Czero = col0 | (col0 << 16);
  1179. for(row = uncmp, y = 0; y < HEIGHT_CBLOCK; y++, row+= bytesPerRow) {
  1180. *(DWORD UNALIGNED HUGE *)row = Czero;
  1181. *((DWORD UNALIGNED HUGE *)row+1) = Czero;
  1182. }
  1183. return cmp;
  1184. }
  1185. }
  1186. /* in 16-bit CRAM, both 4-pair and 1-pair cells have bit 15 of mask set
  1187. * to zero. We distinguish between them based on bit 15 of the first
  1188. * colour. if this is set, this is the 4-pair edge case cell.
  1189. */
  1190. if (*cmp & 0x8000) {
  1191. // this is an edge with 4 colour pairs in four small blocks
  1192. /* read 2 colours, and make AND and XOR masks for first subcell*/
  1193. col0 = *cmp++;
  1194. RGB555_TO_RGB565(col0);
  1195. col1 = *cmp++;
  1196. RGB555_TO_RGB565(col1);
  1197. Czero = col1 | (col1 << 16);
  1198. Cxor = Czero ^ (col0 | (col0 << 16));
  1199. /* colour masks for second subcell */
  1200. col0 = *cmp++;
  1201. RGB555_TO_RGB565(col0);
  1202. col1 = *cmp++;
  1203. RGB555_TO_RGB565(col1);
  1204. Ctwo = col1 | (col1 << 16);
  1205. Cxor2 = Ctwo ^ (col0 | (col0 << 16));
  1206. row = uncmp;
  1207. /* first two rows - top two subcells */
  1208. for (y = 0; y < 2; y++) {
  1209. /* --- first subcell (two pixels) ---- */
  1210. /* turn bitmask into byte mask */
  1211. #if 0
  1212. dwBytes = ((mask & 1) ? 0xffff: 0) |
  1213. ((mask & 2) ? 0xffff0000 : 0);
  1214. #else
  1215. dwBytes = Bits2Bytes[mask&3];
  1216. #endif
  1217. /* select both colours and write to dest */
  1218. dwBytes = (dwBytes & Cxor) ^ Czero;
  1219. *( (DWORD UNALIGNED HUGE *)row) = dwBytes;
  1220. /* ---- second subcell (two pixels) --- */
  1221. /* turn bitmask into byte mask */
  1222. #if 0
  1223. dwBytes = ((mask & 4) ? 0xffff: 0) |
  1224. ((mask & 8) ? 0xffff0000 : 0);
  1225. #else
  1226. dwBytes = Bits2Bytes[mask&0xc];
  1227. #endif
  1228. /* select both colours and write to dest */
  1229. dwBytes = (dwBytes & Cxor2) ^ Ctwo;
  1230. *( (DWORD UNALIGNED HUGE *)(row + sizeof(DWORD))) = dwBytes;
  1231. row += bytesPerRow;
  1232. mask >>= 4;
  1233. }
  1234. /* second two rows - bottom two subcells */
  1235. /* read 2 colours, and make AND and XOR masks for first subcell*/
  1236. col0 = *cmp++;
  1237. RGB555_TO_RGB565(col0);
  1238. col1 = *cmp++;
  1239. RGB555_TO_RGB565(col1);
  1240. Czero = col1 | (col1 << 16);
  1241. Cxor = Czero ^ (col0 | (col0 << 16));
  1242. /* colour masks for second subcell */
  1243. col0 = *cmp++;
  1244. RGB555_TO_RGB565(col0);
  1245. col1 = *cmp++;
  1246. RGB555_TO_RGB565(col1);
  1247. Ctwo = col1 | (col1 << 16);
  1248. Cxor2 = Ctwo ^ (col0 | (col0 << 16));
  1249. for (y = 0; y < 2; y++) {
  1250. /* --- first subcell (two pixels) ---- */
  1251. /* turn bitmask into byte mask */
  1252. #if 0
  1253. dwBytes = ((mask & 1) ? 0xffff: 0) |
  1254. ((mask & 2) ? 0xffff0000 : 0);
  1255. #else
  1256. dwBytes = Bits2Bytes[mask&3];
  1257. #endif
  1258. /* select both colours and write to dest */
  1259. dwBytes = (dwBytes & Cxor) ^ Czero;
  1260. *( (DWORD UNALIGNED HUGE *)row) = dwBytes;
  1261. /* ---- second subcell (two pixels) --- */
  1262. /* turn bitmask into byte mask */
  1263. #if 0
  1264. dwBytes = ((mask & 4) ? 0xffff: 0) |
  1265. ((mask & 8) ? 0xffff0000 : 0);
  1266. #else
  1267. dwBytes = Bits2Bytes[mask&0xc];
  1268. #endif
  1269. /* select both colours and write to dest */
  1270. dwBytes = (dwBytes & Cxor2) ^ Ctwo;
  1271. *( (DWORD UNALIGNED HUGE *)(row + sizeof(DWORD))) = dwBytes;
  1272. row += bytesPerRow;
  1273. mask >>= 4;
  1274. }
  1275. } else {
  1276. // not an edge with only 1 colour pair and one large block
  1277. /* read colours */
  1278. col0 = *cmp++;
  1279. RGB555_TO_RGB565(col0);
  1280. col1 = *cmp++;
  1281. RGB555_TO_RGB565(col1);
  1282. Czero = col1 | (col1 << 16);
  1283. Cxor = Czero ^ (col0 | (col0 << 16));
  1284. row = uncmp;
  1285. for (y = 0; y < 4; y++) {
  1286. /* --- first two pixels in row ---- */
  1287. /* turn bitmask into byte mask */
  1288. #if 0
  1289. dwBytes = ((mask & 1) ? 0xffff: 0) |
  1290. ((mask & 2) ? 0xffff0000 : 0);
  1291. #else
  1292. dwBytes = Bits2Bytes[mask&3];
  1293. #endif
  1294. /* select both colours and write to dest */
  1295. dwBytes = (dwBytes & Cxor) ^ Czero;
  1296. *( (DWORD UNALIGNED HUGE *)row) = dwBytes;
  1297. /* ---- second two pixels in row ---- */
  1298. /* turn bitmask into byte mask */
  1299. #if 0
  1300. dwBytes = ((mask & 4) ? 0xffff: 0) |
  1301. ((mask & 8) ? 0xffff0000 : 0);
  1302. #else
  1303. dwBytes = Bits2Bytes[mask&0xc];
  1304. #endif
  1305. /* select both colours and write to dest */
  1306. dwBytes = (dwBytes & Cxor) ^ Czero;
  1307. *( (DWORD UNALIGNED HUGE *)(row + sizeof(DWORD))) = dwBytes;
  1308. row += bytesPerRow;
  1309. mask >>= 4;
  1310. }
  1311. }
  1312. return( cmp );
  1313. }
  1314. DWORD FAR PASCAL DecompressFrame16To565C(LPBITMAPINFOHEADER lpbiIn, LPVOID lpIn,
  1315. LPBITMAPINFOHEADER lpbiOut, LPVOID lpOut, LONG x, LONG y)
  1316. {
  1317. HPWORD cmp = (HPWORD)lpIn;
  1318. INT bix;
  1319. INT biy;
  1320. HPBYTE blockRow;
  1321. HPBYTE blockColumn;
  1322. LONG SkipCount = 0;
  1323. INT bytesPerRow;
  1324. DPF(("DecompressFrame16To565C:\n"));
  1325. bix = (UINT)(lpbiIn->biWidth) / (WIDTH_CBLOCK); // No negative values in
  1326. biy = (UINT)(lpbiIn->biHeight) / (HEIGHT_CBLOCK); // width or height fields
  1327. StartCounting();
  1328. blockRow = DibXY(lpbiOut, lpOut, x, y, &bytesPerRow);
  1329. for( y=0; y < biy; y++, blockRow += bytesPerRow * HEIGHT_CBLOCK )
  1330. {
  1331. blockColumn = blockRow;
  1332. for( x=0; x < bix; x++, blockColumn += (WIDTH_CBLOCK * sizeof(WORD)))
  1333. {
  1334. cmp = DecompressCBlock16To565(blockColumn, cmp, bytesPerRow, &SkipCount);
  1335. }
  1336. }
  1337. EndCounting("Decompress Frame16To565C took");
  1338. return 0;
  1339. }
  1340. /* ---- 16-bit decompress & dither to 8 bit - in asm for Win16 ---------------------------*/
  1341. /*
  1342. * dither using SCALE method. see dcram168.asm or drawdib\dith775a.asm
  1343. *
  1344. * 8-bit colour = lookup[ scale[ rgb555] + err]
  1345. *
  1346. * where error is one of the values in the 4x4 array below to balance
  1347. * the colour.
  1348. */
  1349. /*
  1350. * dither error array - values to add to rgb value after scaling before
  1351. * converting to 8 bits. Balances colour over a 4x4 matrix
  1352. */
  1353. int ditherr[4][4] = {
  1354. {0, 3283, 4924, 8207},
  1355. {6565, 6566, 1641, 1642},
  1356. {3283, 0, 8207, 4924},
  1357. {6566, 4925, 3282, 1641}
  1358. };
  1359. /* scale the rgb555 first by lookup in lpScale[rgb555] */
  1360. #define DITHER16TO8(col, x, y) lpLookup[col + ditherr[(y)&3][(x)&3]]
  1361. /*
  1362. * decompress one 16bpp block, and dither to 8 bpp using table dither method.
  1363. *
  1364. * parameters:
  1365. * uncmp- pointer to de-compressed buffer for this block.
  1366. * cmp - pointer to compressed data for this block
  1367. * bytes.. - size of one row of de-compressed data
  1368. * pSkipCount - skipcount stored in parent stack frame
  1369. *
  1370. * returns:
  1371. * pointer to the next block of compressed data.
  1372. *
  1373. */
  1374. STATICFN HPWORD INLINE
  1375. DecompressCBlock16To8(
  1376. HPBYTE uncmp,
  1377. HPWORD cmp,
  1378. INT bytesPerRow,
  1379. LONG * pSkipCount
  1380. )
  1381. {
  1382. UINT y;
  1383. WORD mask;
  1384. WORD col0, col1, col2, col3;
  1385. HPBYTE row;
  1386. DWORD Czero, Cone, Cxor, dwBytes;
  1387. // check for outstanding skips
  1388. if (*pSkipCount > 0)
  1389. {
  1390. Assert(!"Skip count should be handled by caller");
  1391. (*pSkipCount)--;
  1392. return cmp;
  1393. }
  1394. // get mask and init bit mask
  1395. mask = *cmp++;
  1396. // check for a skip or a solid color
  1397. if (mask & 0x8000)
  1398. {
  1399. if ((mask & ~SKIP_MASK) == SKIP_MAGIC)
  1400. {
  1401. *pSkipCount = (mask & SKIP_MASK);
  1402. #ifdef _WIN32
  1403. Assert(*pSkipCount != 0); // break (on debug builds) if SkipCount == 0
  1404. #endif
  1405. (*pSkipCount)--;
  1406. return cmp;
  1407. }
  1408. else /* must be solid colour */
  1409. {
  1410. /* solid colour is lower 15 bits of mask */
  1411. col0 = lpScale[mask & 0x7fff];
  1412. for(row = uncmp, y = 0; y < HEIGHT_CBLOCK; y++, row+= bytesPerRow) {
  1413. /* convert colour once for each row */
  1414. Czero = (DITHER16TO8(col0, 0, y) ) |
  1415. (DITHER16TO8(col0, 1, y) << 8 ) |
  1416. (DITHER16TO8(col0, 2, y) << 16 ) |
  1417. (DITHER16TO8(col0, 3, y) << 24 );
  1418. *(DWORD UNALIGNED HUGE *)row = Czero;
  1419. }
  1420. return cmp;
  1421. }
  1422. }
  1423. /* in 16-bit CRAM, both 4-pair and 1-pair cells have bit 15 of mask set
  1424. * to zero. We distinguish between them based on bit 15 of the first
  1425. * colour. if this is set, this is the 4-pair edge case cell.
  1426. */
  1427. if (*cmp & 0x8000) {
  1428. // this is an edge with 4 color pairs in four small blocks
  1429. col0 = lpScale[(*cmp++) & 0x7fff];
  1430. col1 = lpScale[(*cmp++) & 0x7fff];
  1431. col2 = lpScale[(*cmp++) & 0x7fff];
  1432. col3 = lpScale[(*cmp++) & 0x7fff];
  1433. row = uncmp;
  1434. /* first two rows - top two subcells */
  1435. for (y = 0; y < 2; y++) {
  1436. /* dithering requires that we make different
  1437. * colour masks depending on x and y position - and
  1438. * therefore re-do it each row
  1439. */
  1440. Czero = (DITHER16TO8(col1, 0, y) ) |
  1441. (DITHER16TO8(col1, 1, y) << 8 ) |
  1442. (DITHER16TO8(col3, 2, y) << 16 ) |
  1443. (DITHER16TO8(col3, 3, y) << 24 );
  1444. Cone = (DITHER16TO8(col0, 0, y) ) |
  1445. (DITHER16TO8(col0, 1, y) << 8 ) |
  1446. (DITHER16TO8(col2, 2, y) << 16 ) |
  1447. (DITHER16TO8(col2, 3, y) << 24 );
  1448. Cxor = Czero ^ Cone;
  1449. /* turn bitmask into byte mask */
  1450. dwBytes = ExpansionTable[mask & 0x0f];
  1451. /* select colours and write to dest */
  1452. *( (DWORD UNALIGNED HUGE *)row) = (dwBytes & Cxor) ^ Czero;
  1453. row += bytesPerRow;
  1454. mask >>= 4;
  1455. }
  1456. /* second two rows - bottom two subcells */
  1457. /* read last four colours */
  1458. col0 = lpScale[(*cmp++) & 0x7fff];
  1459. col1 = lpScale[(*cmp++) & 0x7fff];
  1460. col2 = lpScale[(*cmp++) & 0x7fff];
  1461. col3 = lpScale[(*cmp++) & 0x7fff];
  1462. for (; y < 4; y++) {
  1463. /* dithering requires that we make different
  1464. * colour masks depending on x and y position - and
  1465. * therefore re-do it each row
  1466. */
  1467. Czero = (DITHER16TO8(col1, 0, y) ) |
  1468. (DITHER16TO8(col1, 1, y) << 8 ) |
  1469. (DITHER16TO8(col3, 2, y) << 16 ) |
  1470. (DITHER16TO8(col3, 3, y) << 24 );
  1471. Cone = (DITHER16TO8(col0, 0, y) ) |
  1472. (DITHER16TO8(col0, 1, y) << 8 ) |
  1473. (DITHER16TO8(col2, 2, y) << 16 ) |
  1474. (DITHER16TO8(col2, 3, y) << 24 );
  1475. Cxor = Czero ^ Cone;
  1476. /* turn bitmask into byte mask */
  1477. dwBytes = ExpansionTable[mask & 0x0f];
  1478. /* select both colours and write to dest */
  1479. *( (DWORD UNALIGNED HUGE *)row) = (dwBytes & Cxor) ^ Czero;
  1480. row += bytesPerRow;
  1481. mask >>= 4;
  1482. }
  1483. } else {
  1484. // not an edge with only 1 colour pair and one large block
  1485. /* read colours */
  1486. col0 = lpScale[(*cmp++) & 0x7fff];
  1487. col1 = lpScale[(*cmp++) & 0x7fff];
  1488. row = uncmp;
  1489. for (y = 0; y < 4; y++) {
  1490. Czero = (DITHER16TO8(col1, 0, y) ) |
  1491. (DITHER16TO8(col1, 1, y) << 8 ) |
  1492. (DITHER16TO8(col1, 2, y) << 16 ) |
  1493. (DITHER16TO8(col1, 3, y) << 24 );
  1494. Cone = (DITHER16TO8(col0, 0, y) ) |
  1495. (DITHER16TO8(col0, 1, y) << 8 ) |
  1496. (DITHER16TO8(col0, 2, y) << 16 ) |
  1497. (DITHER16TO8(col0, 3, y) << 24 );
  1498. Cxor = Czero ^ Cone;
  1499. /* turn bitmask into byte mask */
  1500. dwBytes = ExpansionTable[mask & 0x0f];
  1501. /* select both colours and write to dest */
  1502. *( (DWORD UNALIGNED HUGE *)row) = (dwBytes & Cxor) ^ Czero;
  1503. row += bytesPerRow;
  1504. mask >>= 4;
  1505. }
  1506. }
  1507. return( cmp );
  1508. }
  1509. DWORD FAR PASCAL DecompressFrame16To8C(LPBITMAPINFOHEADER lpbiIn, LPVOID lpIn,
  1510. LPBITMAPINFOHEADER lpbiOut, LPVOID lpOut, LONG x, LONG y)
  1511. {
  1512. HPWORD cmp = (HPWORD)lpIn;
  1513. INT bix;
  1514. INT biy;
  1515. HPBYTE blockRow;
  1516. HPBYTE blockColumn;
  1517. LONG SkipCount = 0;
  1518. INT bytesPerRow;
  1519. DPF(("DecompressFrame16To8C:\n"));
  1520. /* init dither table pointers. lpDitherTable is inited in msvidc. */
  1521. lpScale = lpDitherTable;
  1522. lpLookup = (LPBYTE) &lpScale[32768];
  1523. bix = (UINT)(lpbiIn->biWidth) / (WIDTH_CBLOCK); // No negative values in
  1524. biy = (UINT)(lpbiIn->biHeight) / (HEIGHT_CBLOCK); // width or height fields
  1525. StartCounting();
  1526. blockRow = DibXY(lpbiOut, lpOut, x, y, &bytesPerRow);
  1527. for( y=biy; y--; blockRow += bytesPerRow * HEIGHT_CBLOCK )
  1528. {
  1529. blockColumn = blockRow;
  1530. for( x=bix; x--; blockColumn += WIDTH_CBLOCK)
  1531. {
  1532. cmp = DecompressCBlock16To8(blockColumn, cmp, bytesPerRow, &SkipCount);
  1533. // See if the SkipCount has been set. If so we want to move to
  1534. // the next location rather than calling DecompressCBlock every
  1535. // time around the loop. Keep the test simple to minimise the
  1536. // overhead on every iteration that the Skipcount is 0.
  1537. if (SkipCount) {
  1538. if ((x -= SkipCount) <0) { // extends past this row
  1539. LONG SkipRows;
  1540. // More than just the remainder of this row to skip
  1541. SkipCount =-x; // These bits are on the next row(s)
  1542. // SkipCount will be >0 otherwise we would have gone
  1543. // down the else leg.
  1544. // Calculate how many complete and partial rows to skip.
  1545. // We know we have skipped at least one row. The plan
  1546. // is to restart the X loop at some point along the row.
  1547. // If the skipcount takes us exactly to the end of a row
  1548. // we drop out of the x loop, and let the outer y loop do
  1549. // the decrement. This takes care of the case when the
  1550. // skipcount takes us to the very end of the image.
  1551. SkipRows = 1 + (SkipCount-1)/bix;
  1552. // Decrement the row count and set new blockrow start
  1553. #ifdef _WIN32
  1554. if (y<SkipRows) {
  1555. Assert(y >= SkipRows);
  1556. SkipRows = y;
  1557. }
  1558. #endif
  1559. // Unless we have finished we need to reset blockRow
  1560. y -= SkipRows;
  1561. // y might be 0, but we must still complete the last row
  1562. blockRow += bytesPerRow*HEIGHT_CBLOCK*SkipRows;
  1563. // Calculate the offset into the next row we will process
  1564. x = SkipCount%bix; // This may be 0
  1565. if (x) {
  1566. // Set block column by the amount along the row
  1567. // this iteration is starting, making allowance for
  1568. // the "for x..." loop iterating blockColumn once.
  1569. blockColumn = blockRow + ((x-1)*WIDTH_CBLOCK);
  1570. x=bix-x; // Get the counter correct
  1571. }
  1572. SkipCount = 0; // Skip count now exhausted (so am I)
  1573. } else {
  1574. // SkipCount has been exhausted by this row
  1575. // Either the row has completed, or there is more data
  1576. // on this row. Check...
  1577. if (x) {
  1578. // More of this row left
  1579. // Worry about moving blockColumn on the right amount
  1580. blockColumn += WIDTH_CBLOCK*SkipCount;
  1581. } // else x==0 and we will drop out of the "for x..." loop
  1582. // blockColumn will be reset when we reenter the x loop
  1583. SkipCount=0;
  1584. }
  1585. }
  1586. }
  1587. }
  1588. EndCounting("Decompress Frame16To8C took");
  1589. return 0;
  1590. }
  1591. /* -- 16-bit decompress to 8-bit X2 -----------------------------------*/
  1592. /*
  1593. * given a 16-bit CRAM input stream, decompress and dither to 8
  1594. * bits and stretch by 2 in both dimensions (ie draw each pixel 4 times).
  1595. */
  1596. /*
  1597. * decompress one 16bpp block, and dither to 8 bpp using table dither method.
  1598. * write each pixel 4 times to stretch X 2.
  1599. *
  1600. * parameters:
  1601. * uncmp- pointer to de-compressed buffer for this block.
  1602. * cmp - pointer to compressed data for this block
  1603. * bytes.. - size of one row of de-compressed data
  1604. * pSkipCount - skip count held in parent stack frame
  1605. *
  1606. * returns:
  1607. * pointer to the next block of compressed data.
  1608. *
  1609. */
  1610. STATICFN HPWORD INLINE
  1611. DecompressCBlock16To8X2(
  1612. HPBYTE uncmp,
  1613. HPWORD cmp,
  1614. INT bytesPerRow,
  1615. LONG * pSkipCount
  1616. )
  1617. {
  1618. UINT x, y;
  1619. WORD mask;
  1620. WORD col0, col1, col2, col3;
  1621. HPBYTE row, col;
  1622. DWORD Czero;
  1623. // check for outstanding skips
  1624. if (*pSkipCount > 0)
  1625. {
  1626. Assert(!"Skip count should be handled by caller");
  1627. (*pSkipCount)--;
  1628. return cmp;
  1629. }
  1630. // get mask and init bit mask
  1631. mask = *cmp++;
  1632. // check for a skip or a solid color
  1633. if (mask & 0x8000)
  1634. {
  1635. if ((mask & ~SKIP_MASK) == SKIP_MAGIC)
  1636. {
  1637. *pSkipCount = (mask & SKIP_MASK);
  1638. #ifdef _WIN32
  1639. Assert(*pSkipCount != 0); // break (on debug builds) if SkipCount == 0
  1640. #endif
  1641. (*pSkipCount)--;
  1642. return cmp;
  1643. }
  1644. else /* must be solid colour */
  1645. {
  1646. /* solid colour is lower 15 bits of mask */
  1647. col0 = lpScale[mask & 0x7fff];
  1648. for(row = uncmp, y = 0; y < HEIGHT_CBLOCK*2; y++, row+= bytesPerRow) {
  1649. /* convert colour once for each row */
  1650. Czero = (DITHER16TO8(col0, 0, (y&3)) ) |
  1651. (DITHER16TO8(col0, 1, (y&3)) << 8 ) |
  1652. (DITHER16TO8(col0, 2, (y&3)) << 16 ) |
  1653. (DITHER16TO8(col0, 3, (y&3)) << 24 );
  1654. *(DWORD UNALIGNED HUGE *)row = Czero;
  1655. *((DWORD UNALIGNED HUGE *)row + 1) = Czero;
  1656. }
  1657. return cmp;
  1658. }
  1659. }
  1660. /* in 16-bit CRAM, both 4-pair and 1-pair cells have bit 15 of mask set
  1661. * to zero. We distinguish between them based on bit 15 of the first
  1662. * colour. if this is set, this is the 4-pair edge case cell.
  1663. */
  1664. if (*cmp & 0x8000) {
  1665. // this is an edge with 4 colour pairs in four small blocks
  1666. row = uncmp;
  1667. /* first two rows - top two subcells */
  1668. for (y = 0; y < HEIGHT_CBLOCK*2; y += 2) {
  1669. /* read colours at start, and again half-way through */
  1670. if ((y == 0) || (y == HEIGHT_CBLOCK)) {
  1671. col0 = lpScale[(*cmp++) & 0x7fff];
  1672. col1 = lpScale[(*cmp++) & 0x7fff];
  1673. col2 = lpScale[(*cmp++) & 0x7fff];
  1674. col3 = lpScale[(*cmp++) & 0x7fff];
  1675. }
  1676. col = row;
  1677. /* first two pixels (first subcell) */
  1678. for (x = 0; x < WIDTH_CBLOCK; x += 2) {
  1679. if (mask & 1) {
  1680. *col = DITHER16TO8(col0, (x & 3), (y&3));
  1681. *(col + bytesPerRow) =
  1682. DITHER16TO8(col0, (x&3), ((y+1) & 3));
  1683. col++;
  1684. *col = DITHER16TO8(col0, ((x+1)&3), ((y)&3));
  1685. *(col + bytesPerRow) =
  1686. DITHER16TO8(col0, ((x+1)&3), ((y+1)&3));
  1687. } else {
  1688. *col = DITHER16TO8(col1, (x & 3), (y&3));
  1689. *(col + bytesPerRow) =
  1690. DITHER16TO8(col1, (x&3), ((y+1) & 3));
  1691. col++;
  1692. *col = DITHER16TO8(col1, ((x+1)&3), ((y)&3));
  1693. *(col + bytesPerRow) =
  1694. DITHER16TO8(col1, ((x+1)&3), ((y+1)&3));
  1695. }
  1696. col++;
  1697. mask >>= 1;
  1698. }
  1699. /* second two pixels (second subcell) */
  1700. for (; x < WIDTH_CBLOCK*2; x += 2) {
  1701. if (mask & 1) {
  1702. *col = DITHER16TO8(col2, (x & 3), (y&3));
  1703. *(col + bytesPerRow) =
  1704. DITHER16TO8(col2, (x&3), ((y+1) & 3));
  1705. col++;
  1706. *col = DITHER16TO8(col2, ((x+1)&3), ((y)&3));
  1707. *(col + bytesPerRow) =
  1708. DITHER16TO8(col2, ((x+1)&3), ((y+1)&3));
  1709. } else {
  1710. *col = DITHER16TO8(col3, (x & 3), (y&3));
  1711. *(col + bytesPerRow) =
  1712. DITHER16TO8(col3, (x&3), ((y+1) & 3));
  1713. col++;
  1714. *col = DITHER16TO8(col3, ((x+1)&3), ((y)&3));
  1715. *(col + bytesPerRow) =
  1716. DITHER16TO8(col3, ((x+1)&3), ((y+1)&3));
  1717. }
  1718. col++;
  1719. mask >>= 1;
  1720. }
  1721. row += bytesPerRow * 2;
  1722. }
  1723. } else {
  1724. // not an edge with only 1 colour pair and one large block
  1725. /* read colours */
  1726. col0 = lpScale[(*cmp++) & 0x7fff];
  1727. col1 = lpScale[(*cmp++) & 0x7fff];
  1728. row = uncmp;
  1729. for (y = 0; y < HEIGHT_CBLOCK*2; y += 2) {
  1730. col = row;
  1731. for (x = 0; x < WIDTH_CBLOCK*2; x += 2) {
  1732. if (mask & 1) {
  1733. *col = DITHER16TO8(col0, (x & 3), (y&3));
  1734. *(col + bytesPerRow) =
  1735. DITHER16TO8(col0, (x&3), ((y+1) & 3));
  1736. col++;
  1737. *col = DITHER16TO8(col0, ((x+1)&3), ((y)&3));
  1738. *(col + bytesPerRow) =
  1739. DITHER16TO8(col0, ((x+1)&3), ((y+1)&3));
  1740. } else {
  1741. *col = DITHER16TO8(col1, (x & 3), (y&3));
  1742. *(col + bytesPerRow) =
  1743. DITHER16TO8(col1, (x&3), ((y+1) & 3));
  1744. col++;
  1745. *col = DITHER16TO8(col1, ((x+1)&3), ((y)&3));
  1746. *(col + bytesPerRow) =
  1747. DITHER16TO8(col1, ((x+1)&3), ((y+1)&3));
  1748. }
  1749. col++;
  1750. mask >>= 1;
  1751. }
  1752. row += bytesPerRow * 2;
  1753. }
  1754. }
  1755. return( cmp );
  1756. }
  1757. DWORD FAR PASCAL DecompressFrame16To8X2C(LPBITMAPINFOHEADER lpbiIn, LPVOID lpIn,
  1758. LPBITMAPINFOHEADER lpbiOut, LPVOID lpOut, LONG x, LONG y)
  1759. {
  1760. HPWORD cmp = (HPWORD)lpIn;
  1761. INT bix;
  1762. INT biy;
  1763. HPBYTE blockRow;
  1764. HPBYTE blockColumn;
  1765. LONG SkipCount = 0;
  1766. INT bytesPerRow;
  1767. DPF(("DecompressFrame16To8X2C:\n"));
  1768. /* init dither table pointers. lpDitherTable is inited in msvidc. */
  1769. lpScale = lpDitherTable;
  1770. lpLookup = (LPBYTE) &lpScale[32768];
  1771. StartCounting();
  1772. bix = (UINT)(lpbiIn->biWidth) / (WIDTH_CBLOCK); // No negative values in
  1773. biy = (UINT)(lpbiIn->biHeight) / (HEIGHT_CBLOCK); // width or height fields
  1774. blockRow = DibXY(lpbiOut, lpOut, x, y, &bytesPerRow);
  1775. for( y=biy; y--; blockRow += bytesPerRow * HEIGHT_CBLOCK *2 )
  1776. {
  1777. blockColumn = blockRow;
  1778. for( x=bix; x--; blockColumn += WIDTH_CBLOCK*2)
  1779. {
  1780. cmp = DecompressCBlock16To8X2(blockColumn, cmp, bytesPerRow, &SkipCount);
  1781. // See if the SkipCount has been set. If so we want to move to
  1782. // the next location rather than calling DecompressCBlock every
  1783. // time around the loop. Keep the test simple to minimise the
  1784. // overhead on every iteration that the Skipcount is 0.
  1785. if (SkipCount) {
  1786. if ((x -= SkipCount) <0) { // extends past this row
  1787. LONG SkipRows;
  1788. // More than just the remainder of this row to skip
  1789. SkipCount =-x; // These bits are on the next row(s)
  1790. // SkipCount will be >0 otherwise we would have gone
  1791. // down the else leg.
  1792. // Calculate how many complete and partial rows to skip.
  1793. // We know we have skipped at least one row. The plan
  1794. // is to restart the X loop at some point along the row.
  1795. // If the skipcount takes us exactly to the end of a row
  1796. // we drop out of the x loop, and let the outer y loop do
  1797. // the decrement. This takes care of the case when the
  1798. // skipcount takes us to the very end of the image.
  1799. SkipRows = 1 + (SkipCount-1)/bix;
  1800. // Decrement the row count and set new blockrow start
  1801. #ifdef _WIN32
  1802. if (y<SkipRows) {
  1803. Assert(y >= SkipRows);
  1804. SkipRows = y;
  1805. }
  1806. #endif
  1807. // Unless we have finished we need to reset blockRow
  1808. y -= SkipRows;
  1809. // y might be 0, but we must still complete the last row
  1810. blockRow += bytesPerRow*HEIGHT_CBLOCK*2*SkipRows;
  1811. // Calculate the offset into the next row we will process
  1812. x = SkipCount%bix; // This may be 0
  1813. if (x) {
  1814. // Set block column by the amount along the row
  1815. // this iteration is starting, making allowance for
  1816. // the "for x..." loop iterating blockColumn once.
  1817. blockColumn = blockRow + ((x-1)*WIDTH_CBLOCK*2);
  1818. x=bix-x; // Get the counter correct
  1819. }
  1820. SkipCount = 0; // Skip count now exhausted (so am I)
  1821. } else {
  1822. // SkipCount has been exhausted by this row
  1823. // Either the row has completed, or there is more data
  1824. // on this row. Check...
  1825. if (x) {
  1826. // More of this row left
  1827. // Worry about moving blockColumn on the right amount
  1828. blockColumn += WIDTH_CBLOCK*2*SkipCount;
  1829. } // else x==0 and we will drop out of the "for x..." loop
  1830. // blockColumn will be reset when we reenter the x loop
  1831. SkipCount=0;
  1832. }
  1833. }
  1834. }
  1835. }
  1836. EndCounting("Decompress Frame16To8x2C took");
  1837. return 0;
  1838. }
  1839. #endif