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.

595 lines
18 KiB

  1. /*++
  2. Copyright (c) 1996 - 1999 Microsoft Corporation
  3. Module Name:
  4. compress.c
  5. Abstract:
  6. Implementation of compression formats for sending data to devices.
  7. Environment:
  8. Windows NT Unidrv driver
  9. Revision History:
  10. 12/15/96 -alvins-
  11. Created
  12. --*/
  13. #include "raster.h"
  14. #include "compress.h" /* Function prototypes */
  15. //*************************************************************
  16. int
  17. iCompTIFF(
  18. BYTE *pbOBuf,
  19. BYTE *pbIBuf,
  20. int iBCnt
  21. )
  22. /*++
  23. Routine Description:
  24. This function is called to compress a scan line of data using
  25. TIFF v4 compression.
  26. Arguments:
  27. pbOBuf Pointer to output buffer PRESUMED LARGE ENOUGH
  28. pbIBuf Pointer to data buffer to compress
  29. iBCnt Number of bytes to compress
  30. Return Value:
  31. Number of compressed bytes
  32. Note:
  33. The output buffer is presumed large enough to hold the output.
  34. In the worst case (NO REPETITIONS IN DATA) there is an extra
  35. byte added every 128 bytes of input data. So, you should make
  36. the output buffer at least 1% larger than the input buffer.
  37. --*/
  38. {
  39. BYTE *pbOut; /* Output byte location */
  40. BYTE *pbStart; /* Start of current input stream */
  41. BYTE *pb; /* Miscellaneous usage */
  42. BYTE *pbEnd; /* The last byte of input */
  43. BYTE jLast; /* Last byte, for match purposes */
  44. BYTE bLast;
  45. int iSize; /* Bytes in the current length */
  46. int iSend; /* Number to send in this command */
  47. pbOut = pbOBuf;
  48. pbStart = pbIBuf;
  49. pbEnd = pbIBuf + iBCnt; /* The last byte */
  50. #if (TIFF_MIN_RUN >= 4)
  51. // this is a faster algorithm for calculating TIFF compression
  52. // that assumes a minimum RUN of at least 4 bytes. If the
  53. // third and fourth byte don't equal then the first/second bytes are
  54. // irrelevant. This means we can determine non-run data three times
  55. // as fast since we only check every third byte pair.
  56. if (iBCnt > TIFF_MIN_RUN)
  57. {
  58. // make sure the last two bytes aren't equal so we don't have to check
  59. // for the buffer end when looking for runs
  60. bLast = pbEnd[-1];
  61. pbEnd[-1] = ~pbEnd[-2];
  62. while( (pbIBuf += 3) < pbEnd )
  63. {
  64. if (*pbIBuf == pbIBuf[-1])
  65. {
  66. // save the run start pointer, pb, and check whether the first
  67. // bytes are also part of the run
  68. //
  69. pb = pbIBuf-1;
  70. if (*pbIBuf == pbIBuf[-2])
  71. {
  72. pb--;
  73. if (*pbIBuf == pbIBuf[-3])
  74. pb--;
  75. }
  76. // Find out how long this run is
  77. jLast = *pb;
  78. do {
  79. pbIBuf++;
  80. } while (*pbIBuf == jLast);
  81. // test whether last byte is also part of the run
  82. //
  83. if (jLast == bLast && pbIBuf == (pbEnd-1))
  84. pbIBuf++;
  85. // Determine if the run is longer that the required
  86. // minimum run size.
  87. //
  88. if ((iSend = (int)(pbIBuf - pb)) >= (TIFF_MIN_RUN))
  89. {
  90. /*
  91. * Worth recording as a run, so first set the literal
  92. * data which may have already been scanned before recording
  93. * this run.
  94. */
  95. if( (iSize = (int)(pb - pbStart)) > 0 )
  96. {
  97. /* There is literal data, so record it now */
  98. while (iSize > TIFF_MAX_LITERAL)
  99. {
  100. iSize -= TIFF_MAX_LITERAL;
  101. *pbOut++ = TIFF_MAX_LITERAL-1;
  102. CopyMemory(pbOut, pbStart, TIFF_MAX_LITERAL);
  103. pbStart += TIFF_MAX_LITERAL;
  104. pbOut += TIFF_MAX_LITERAL;
  105. }
  106. *pbOut++ = iSize - 1;
  107. CopyMemory(pbOut, pbStart, iSize);
  108. pbOut += iSize;
  109. }
  110. /*
  111. * Now for the repeat pattern. Same logic, but only
  112. * one byte is needed per entry.
  113. */
  114. iSize = iSend;
  115. while (iSize > TIFF_MAX_RUN)
  116. {
  117. *((char *)pbOut)++ = 1 - TIFF_MAX_RUN;
  118. *pbOut++ = jLast;
  119. iSize -= TIFF_MAX_RUN;
  120. }
  121. *pbOut++ = 1 - iSize;
  122. *pbOut++ = jLast;
  123. pbStart = pbIBuf; /* Ready for the next one! */
  124. }
  125. }
  126. }
  127. pbEnd[-1] = bLast;
  128. }
  129. #else
  130. jLast = *pbIBuf++;
  131. while( pbIBuf < pbEnd )
  132. {
  133. if( jLast == *pbIBuf )
  134. {
  135. /* Find out how long this run is. Then decide on using it */
  136. pb = pbIBuf;
  137. do {
  138. pbIBuf++;
  139. } while (pbIBuf < pbEnd && *pbIBuf == jLast);
  140. /*
  141. * Note that pb points at the SECOND byte of the pattern!
  142. * AND also that pbIBuf points at the first byte AFTER the run.
  143. */
  144. if ((iSend = pbIBuf - pb) >= (TIFF_MIN_RUN - 1))
  145. {
  146. /*
  147. * Worth recording as a run, so first set the literal
  148. * data which may have already been scanned before recording
  149. * this run.
  150. */
  151. if( (iSize = pb - pbStart - 1) > 0 )
  152. {
  153. /* There is literal data, so record it now */
  154. while (iSize > TIFF_MAX_LITERAL)
  155. {
  156. iSize -= TIFF_MAX_LITERAL;
  157. *pbOut++ = TIFF_MAX_LITERAL-1;
  158. CopyMemory(pbOut, pbStart, TIFF_MAX_LITERAL);
  159. pbStart += TIFF_MAX_LITERAL;
  160. pbOut += TIFF_MAX_LITERAL;
  161. }
  162. *pbOut++ = iSize - 1;
  163. CopyMemory(pbOut, pbStart, iSize);
  164. pbOut += iSize;
  165. }
  166. /*
  167. * Now for the repeat pattern. Same logic, but only
  168. * one byte is needed per entry.
  169. */
  170. iSize = iSend + 1;
  171. while (iSize > TIFF_MAX_RUN)
  172. {
  173. *((char *)pbOut)++ = 1 - TIFF_MAX_RUN;
  174. *pbOut++ = jLast;
  175. iSize -= TIFF_MAX_RUN;
  176. }
  177. *pbOut++ = 1 - iSize;
  178. *pbOut++ = jLast;
  179. pbStart = pbIBuf; /* Ready for the next one! */
  180. }
  181. if (pbIBuf == pbEnd)
  182. break;
  183. }
  184. jLast = *pbIBuf++; /* Onto the next byte */
  185. }
  186. #endif
  187. if ((iSize = (int)(pbEnd - pbStart)) > 0)
  188. {
  189. /* Left some dangling. This can only be literal data. */
  190. while( (iSend = min( iSize, TIFF_MAX_LITERAL )) > 0 )
  191. {
  192. *pbOut++ = iSend - 1;
  193. CopyMemory( pbOut, pbStart, iSend );
  194. pbOut += iSend;
  195. pbStart += iSend;
  196. iSize -= iSend;
  197. }
  198. }
  199. return (int)(pbOut - pbOBuf);
  200. }
  201. //**********************************************************
  202. int
  203. iCompFERLE(
  204. BYTE *pbOBuf,
  205. BYTE *pbIBuf,
  206. int iBCnt,
  207. int iMaxCnt
  208. )
  209. /*++
  210. Routine Description:
  211. This function is called to compress a scan line of data using
  212. Far East Run length encoding.
  213. Arguments:
  214. pbOBuf Pointer to output buffer PRESUMED LARGE ENOUGH
  215. pbIBuf Pointer to data buffer to compress
  216. iBCnt Number of bytes to compress
  217. iMaxCnt Maximum number of bytes to create on output
  218. Return Value:
  219. Number of compressed bytes or -1 if too large for buffer
  220. --*/
  221. {
  222. BYTE *pbO; /* Record output location */
  223. BYTE *pbI; /* Scanning for runs */
  224. BYTE *pbIEnd; /* First byte past end of input data */
  225. BYTE *pbStart; /* Start of current data stream */
  226. BYTE *pbTmp;
  227. BYTE jLast; /* Previous byte */
  228. int iSize; /* Number of bytes in the run */
  229. if (iBCnt == 0)
  230. return 0;
  231. pbO = pbOBuf; /* Working copy */
  232. pbIEnd = pbIBuf + iBCnt; /* Gone too far if we reach here */
  233. /*
  234. * Calculate the maximum amount of data we will generate
  235. */
  236. pbStart = pbIBuf;
  237. while (++pbIBuf < pbIEnd)
  238. {
  239. if (*pbIBuf == pbIBuf[-1])
  240. {
  241. // valid run but we will first output any literal data
  242. if ((iSize = (int)(pbIBuf - pbStart) - 1) > 0)
  243. {
  244. if ((iMaxCnt -= iSize) < 0) // test for output overflow
  245. return -1;
  246. CopyMemory(pbO,pbStart,iSize);
  247. pbO += iSize;
  248. }
  249. // determine the run length
  250. jLast = *pbIBuf;
  251. pbI = pbIBuf;
  252. pbTmp = pbIBuf + FERLE_MAX_RUN - 1;
  253. if (pbTmp > pbIEnd)
  254. pbTmp = pbIEnd;
  255. do {
  256. pbIBuf++;
  257. } while (pbIBuf < pbTmp && *pbIBuf == jLast);
  258. iSize = (int)(pbIBuf - pbI) + 1; /* Number of times */
  259. // output the RLE strings
  260. if ((iMaxCnt -= 3) < 0) // test for output overflow
  261. return -1;
  262. *pbO++ = jLast; // copy data byte twice
  263. *pbO++ = jLast;
  264. *pbO++ = (BYTE)iSize;
  265. // test if we are done
  266. if( pbIBuf == pbIEnd )
  267. return (int)(pbO - pbOBuf);
  268. // setup for continuation of loop
  269. pbStart = pbIBuf;
  270. }
  271. }
  272. /*
  273. * Since the data did not end in a run we must output the last
  274. * literal data if we haven't overflowed the buffer.
  275. */
  276. iSize = (int)(pbIBuf - pbStart);
  277. if (iMaxCnt < iSize)
  278. return -1;
  279. CopyMemory(pbO,pbStart,iSize);
  280. pbO += iSize;
  281. return (int)(pbO - pbOBuf);
  282. }
  283. //****************************************************
  284. int
  285. iCompDeltaRow(
  286. BYTE *pbOBuf,
  287. BYTE *pbIBuf,
  288. BYTE *pbPBuf,
  289. int iBCnt,
  290. int iLimit
  291. )
  292. /*++
  293. Routine Description:
  294. This function is called to compress a scan line of data using
  295. delta row compression.
  296. Arguments:
  297. pbOBuf Pointer to output buffer
  298. pbIBuf Pointer to data buffer to compress
  299. pbPBuf Pointer to previous row data buffer
  300. iBCnt Number of bytes in the above
  301. iLimit Don't exceed this number of compressed bytes
  302. Return Value:
  303. Number of compressed bytes or -1 if too large for buffer
  304. Note:
  305. A return value of 0 is valid since it implies the two lines
  306. are identical.
  307. --*/
  308. {
  309. #ifdef _X86_
  310. BYTE *pbO; /* Record output location */
  311. BYTE *pbOEnd; /* As far as we will go in the output buffer */
  312. BYTE *pbIEnd;
  313. BYTE *pbStart;
  314. BYTE *pb;
  315. int iDelta;
  316. int iOffset; // index of current data stream
  317. int iSize; /* Number of bytes in the run */
  318. /*
  319. * Limit the amount of data we will generate. For performance
  320. * reasons we will ignore the effects of an offset value
  321. * greater than 30 since it implies we were able to already skip
  322. * that many bytes. However, for safety sake we will reduce the
  323. * max allowable size by 2 bytes.
  324. */
  325. pbO = pbOBuf; /* Working copy */
  326. pbOEnd = pbOBuf + iLimit - 2;
  327. iDelta = pbPBuf - pbIBuf;
  328. pbIEnd = pbIBuf + iBCnt;
  329. pbStart = pbIBuf;
  330. //
  331. // this is the main loop for compressing the data
  332. //
  333. while (pbIBuf < pbIEnd)
  334. {
  335. // fast skip for matching dwords
  336. //
  337. if (!((ULONG_PTR)pbIBuf & 3))
  338. {
  339. while (pbIBuf <= (pbIEnd-4) && *(DWORD *)pbIBuf == *(DWORD *)&pbIBuf[iDelta])
  340. pbIBuf += 4;
  341. if (pbIBuf >= pbIEnd)
  342. break;
  343. }
  344. // test for non-matching bytes and output the necessary compression string
  345. //
  346. if (*pbIBuf != pbIBuf[iDelta])
  347. {
  348. // determine the run length
  349. pb = pbIBuf;
  350. do {
  351. pb++;
  352. } while (pb < pbIEnd && *pb != pb[iDelta]);
  353. iSize = (int)(pb - pbIBuf);
  354. // Lets make sure we have room in the buffer before
  355. // we continue this, this compression algorithm adds
  356. // 1 byte for every 8 bytes of data worst case.
  357. //
  358. if (((iSize * 9 + 7) >> 3) > (pbOEnd - pbO)) // gives tighter code
  359. return -1;
  360. iOffset = (int)(pbIBuf - pbStart);
  361. if (iOffset > 30)
  362. {
  363. if (iSize < 8)
  364. *pbO++ = ((iSize-1) << 5) + 31;
  365. else
  366. *pbO++ = (7 << 5) + 31;
  367. iOffset -= 31;
  368. while (iOffset >= 255)
  369. {
  370. iOffset -= 255;
  371. *pbO++ = 255;
  372. }
  373. *pbO++ = (BYTE)iOffset;
  374. if (iSize > 8)
  375. goto FastEightByteRun;
  376. }
  377. else if (iSize > 8)
  378. {
  379. *pbO++ = (7 << 5) + iOffset;
  380. FastEightByteRun:
  381. while (1)
  382. {
  383. CopyMemory(pbO,pbIBuf,8);
  384. pbIBuf += 8;
  385. pbO += 8;
  386. if ((iSize -= 8) <= 8)
  387. break;
  388. *pbO++ = (7 << 5);
  389. }
  390. *pbO++ = (iSize-1) << 5;
  391. }
  392. else
  393. *pbO++ = ((iSize-1) << 5) + iOffset;
  394. CopyMemory (pbO,pbIBuf,iSize);
  395. pbIBuf += iSize;
  396. pbO += iSize;
  397. pbStart = pbIBuf;
  398. }
  399. pbIBuf++;
  400. }
  401. return (int)(pbO - pbOBuf);
  402. #else
  403. BYTE *pbO; /* Record output location */
  404. BYTE *pbOEnd; /* As far as we will go in the output buffer */
  405. BYTE *pbIEnd;
  406. BYTE *pbStart;
  407. BYTE *pb;
  408. int iOffset; // index of current data stream
  409. int iSize; /* Number of bytes in the run */
  410. /*
  411. * Limit the amount of data we will generate. For performance
  412. * reasons we will ignore the effects of an offset value
  413. * greater than 30 since it implies we were able to already skip
  414. * that many bytes. However, for safety sake we will reduce the
  415. * max allowable size by 2 bytes.
  416. */
  417. pbO = pbOBuf; /* Working copy */
  418. pbOEnd = pbOBuf + iLimit - 2;
  419. pbIEnd = pbIBuf + iBCnt;
  420. pbStart = pbIBuf;
  421. //
  422. // this is the main loop for compressing the data
  423. //
  424. while (pbIBuf < pbIEnd)
  425. {
  426. // fast skip for matching dwords
  427. //
  428. if (!((ULONG_PTR)pbIBuf & 3))
  429. {
  430. while (pbIBuf <= (pbIEnd-4) && *(DWORD *)pbIBuf == *(DWORD *)pbPBuf)
  431. {
  432. pbIBuf += 4;
  433. pbPBuf += 4;
  434. }
  435. if (pbIBuf >= pbIEnd)
  436. break;
  437. }
  438. // test for non-matching bytes and output the necessary compression string
  439. //
  440. if (*pbIBuf != *pbPBuf)
  441. {
  442. // determine the run length
  443. pb = pbIBuf;
  444. do {
  445. pb++;
  446. pbPBuf++;
  447. } while (pb < pbIEnd && *pb != *pbPBuf);
  448. iSize = (int)(pb - pbIBuf);
  449. // Lets make sure we have room in the buffer before
  450. // we continue this, this compression algorithm adds
  451. // 1 byte for every 8 bytes of data worst case.
  452. //
  453. if (((iSize * 9 + 7) >> 3) > (int)(pbOEnd - pbO))
  454. return -1;
  455. // special case the initial offset value since it
  456. // occurs only once and may require extra bytes
  457. //
  458. if ((iOffset = (int)(pbIBuf - pbStart)))
  459. {
  460. int iSend = min (iSize,8);
  461. if (iOffset > 30)
  462. {
  463. *pbO++ = ((iSend-1) << 5) + 31;
  464. iOffset -= 31;
  465. while (iOffset >= 255)
  466. {
  467. *pbO++ = 255;
  468. iOffset -= 255;
  469. }
  470. *pbO++ = (BYTE)iOffset;
  471. }
  472. else
  473. {
  474. *pbO++ = ((iSend-1) << 5) + iOffset;
  475. }
  476. // output the initial changed bytes
  477. CopyMemory(pbO,pbIBuf,iSend);
  478. pbIBuf += iSend;
  479. pbO += iSend;
  480. iSize -= iSend;
  481. }
  482. // now output any remaining changed data
  483. //
  484. while (iSize)
  485. {
  486. if (iSize >= 8)
  487. {
  488. *pbO++ = (8 - 1) << 5;
  489. CopyMemory(pbO,pbIBuf,8);
  490. pbIBuf += 8;
  491. pbO += 8;
  492. iSize -= 8;
  493. }
  494. else
  495. {
  496. *pbO++ = (iSize-1) << 5;
  497. CopyMemory(pbO,pbIBuf,iSize);
  498. pbIBuf += iSize;
  499. pbO += iSize;
  500. break;
  501. }
  502. }
  503. pbStart = pbIBuf;
  504. }
  505. pbIBuf++;
  506. pbPBuf++;
  507. }
  508. return (int)(pbO - pbOBuf);
  509. #endif
  510. }