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.

1474 lines
31 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. faxtiff.c
  5. Abstract:
  6. Functions to compress the bitmap bits using CCITT Group3 2-dimensional coding
  7. and output the resulting data as TIFF-F file.
  8. Environment:
  9. Windows NT fax driver, kernel mode
  10. Revision History:
  11. 01/23/96 -davidx-
  12. Created it.
  13. mm/dd/yy -author-
  14. description
  15. NOTE:
  16. Please refer to faxtiff.h for a description of
  17. the structure of our TIFF output file.
  18. --*/
  19. #include "faxdrv.h"
  20. #include "faxtiff.h"
  21. #include "faxtable.h"
  22. BOOL
  23. WriteData(
  24. PDEVDATA pdev,
  25. PVOID pbuf,
  26. DWORD cbbuf
  27. )
  28. /*++
  29. Routine Description:
  30. Output a buffer of data to the spooler
  31. Arguments:
  32. pdev - Points to our DEVDATA structure
  33. pbuf - Points to data buffer
  34. cbbuf - Number of bytes in the buffer
  35. Return Value:
  36. TRUE if successful, FALSE otherwise.
  37. --*/
  38. {
  39. DWORD cbwritten;
  40. //
  41. // Stop if the document has been cancelled.
  42. //
  43. if (pdev->flags & PDEV_CANCELLED)
  44. return FALSE;
  45. //
  46. // Send output to spooler directly
  47. //
  48. if (! WritePrinter(pdev->hPrinter, pbuf, cbbuf, &cbwritten) || cbbuf != cbwritten) {
  49. Error(("WritePrinter failed\n"));
  50. pdev->flags |= PDEV_CANCELLED;
  51. return FALSE;
  52. }
  53. pdev->fileOffset += cbbuf;
  54. return TRUE;
  55. }
  56. PDWORD
  57. CalcXposeMatrix(
  58. VOID
  59. )
  60. /*++
  61. Routine Description:
  62. Generate the transpose matrix for rotating landscape bitmaps
  63. Arguments:
  64. NONE
  65. Return Value:
  66. Pointer to the generated transpose matrix
  67. NULL if there is an error
  68. --*/
  69. {
  70. static DWORD templateData[16] = {
  71. /* 0000 */ 0x00000000,
  72. /* 0001 */ 0x00000001,
  73. /* 0010 */ 0x00000100,
  74. /* 0011 */ 0x00000101,
  75. /* 0100 */ 0x00010000,
  76. /* 0101 */ 0x00010001,
  77. /* 0110 */ 0x00010100,
  78. /* 0111 */ 0x00010101,
  79. /* 1000 */ 0x01000000,
  80. /* 1001 */ 0x01000001,
  81. /* 1010 */ 0x01000100,
  82. /* 1011 */ 0x01000101,
  83. /* 1100 */ 0x01010000,
  84. /* 1101 */ 0x01010001,
  85. /* 1110 */ 0x01010100,
  86. /* 1111 */ 0x01010101
  87. };
  88. PDWORD pdwXpose, pTemp;
  89. INT index;
  90. //
  91. // First check if the transpose matrix has been generated already
  92. //
  93. if (pdwXpose = MemAlloc(sizeof(DWORD) * 2 * (1 << BYTEBITS))) {
  94. for (index=0, pTemp=pdwXpose; index < (1 << BYTEBITS); index++, pTemp++) {
  95. pTemp[0] = templateData[index >> 4];
  96. pTemp[1 << BYTEBITS] = templateData[index & 0xf];
  97. }
  98. }
  99. return pdwXpose;
  100. }
  101. BOOL
  102. OutputPageBitmap(
  103. PDEVDATA pdev,
  104. PBYTE pBitmapData
  105. )
  106. /*++
  107. Routine Description:
  108. Output a completed page bitmap to the spooler
  109. Arguments:
  110. pdev - Points to our DEVDATA structure
  111. pBitmapData - Points to bitmap data
  112. Return Value:
  113. TRUE if successful, FALSE if there is an error
  114. --*/
  115. {
  116. LONG bmpWidth, bmpHeight;
  117. BOOL result;
  118. DWORD compressedBytes;
  119. Verbose(("Sending page %d...\n", pdev->pageCount));
  120. Assert(pdev->pCompBits == NULL);
  121. //
  122. // For portrait output, encode the entire bitmap in one shot
  123. // For landscape output, we need to rotate the bitmap here:
  124. // Generate the transpose matrix and allocate a
  125. // temporary buffer large enough to hold 8 scanlines
  126. //
  127. if (IsLandscapeMode(pdev)) {
  128. bmpWidth = pdev->imageSize.cy;
  129. bmpHeight = pdev->imageSize.cx;
  130. } else {
  131. bmpWidth = pdev->imageSize.cx;
  132. bmpHeight = pdev->imageSize.cy;
  133. }
  134. //
  135. // Initialize fax encodier
  136. //
  137. if (! InitFaxEncoder(pdev, bmpWidth, bmpHeight))
  138. return FALSE;
  139. if (! IsLandscapeMode(pdev)) {
  140. LONG dwordCount;
  141. PDWORD pBits;
  142. //
  143. // Invert the entire page bitmap in memory
  144. //
  145. Assert(bmpWidth % DWORDBITS == 0);
  146. dwordCount = (bmpWidth * bmpHeight) / DWORDBITS;
  147. pBits = (PDWORD) pBitmapData;
  148. while (dwordCount--)
  149. *pBits++ ^= 0xffffffff;
  150. //
  151. // Compress the page bitmap
  152. //
  153. result = EncodeFaxData(pdev, pBitmapData, bmpWidth, bmpHeight);
  154. //
  155. // Restore the original page bitmap
  156. //
  157. dwordCount = (bmpWidth * bmpHeight) / DWORDBITS;
  158. pBits = (PDWORD) pBitmapData;
  159. while (dwordCount--)
  160. *pBits++ ^= 0xffffffff;
  161. if (! result) {
  162. FreeCompBitsBuffer(pdev);
  163. return FALSE;
  164. }
  165. } else {
  166. register PDWORD pdwXposeHigh, pdwXposeLow;
  167. register DWORD dwHigh, dwLow;
  168. PBYTE pBuffer, pbCol;
  169. LONG deltaNew;
  170. //
  171. // Calculate the transpose matrix for fast bitmap rotation
  172. //
  173. if (!(pdwXposeHigh = CalcXposeMatrix()) || !(pBuffer = MemAllocZ(bmpWidth))) {
  174. MemFree(pdwXposeHigh);
  175. FreeCompBitsBuffer(pdev);
  176. return FALSE;
  177. }
  178. pdwXposeLow = pdwXposeHigh + (1 << BYTEBITS);
  179. //
  180. // During each iteration thru the following loop, we will process
  181. // one byte column and generate 8 rotated scanlines.
  182. //
  183. Assert(bmpHeight % BYTEBITS == 0);
  184. Assert(bmpWidth % DWORDBITS == 0);
  185. deltaNew = bmpWidth / BYTEBITS;
  186. pbCol = pBitmapData + (bmpHeight / BYTEBITS - 1);
  187. do {
  188. PBYTE pbWrite = pBuffer;
  189. PBYTE pbTemp = pbCol;
  190. LONG loopCount = deltaNew;
  191. while (loopCount--) {
  192. //
  193. // Rotate the next 8 bytes in the current column
  194. // Unroll the loop here in hopes of faster execution
  195. //
  196. dwHigh = pdwXposeHigh[*pbTemp];
  197. dwLow = pdwXposeLow[*pbTemp];
  198. pbTemp += pdev->lineOffset;
  199. dwHigh = (dwHigh << 1) | pdwXposeHigh[*pbTemp];
  200. dwLow = (dwLow << 1) | pdwXposeLow[*pbTemp];
  201. pbTemp += pdev->lineOffset;
  202. dwHigh = (dwHigh << 1) | pdwXposeHigh[*pbTemp];
  203. dwLow = (dwLow << 1) | pdwXposeLow[*pbTemp];
  204. pbTemp += pdev->lineOffset;
  205. dwHigh = (dwHigh << 1) | pdwXposeHigh[*pbTemp];
  206. dwLow = (dwLow << 1) | pdwXposeLow[*pbTemp];
  207. pbTemp += pdev->lineOffset;
  208. dwHigh = (dwHigh << 1) | pdwXposeHigh[*pbTemp];
  209. dwLow = (dwLow << 1) | pdwXposeLow[*pbTemp];
  210. pbTemp += pdev->lineOffset;
  211. dwHigh = (dwHigh << 1) | pdwXposeHigh[*pbTemp];
  212. dwLow = (dwLow << 1) | pdwXposeLow[*pbTemp];
  213. pbTemp += pdev->lineOffset;
  214. dwHigh = (dwHigh << 1) | pdwXposeHigh[*pbTemp];
  215. dwLow = (dwLow << 1) | pdwXposeLow[*pbTemp];
  216. pbTemp += pdev->lineOffset;
  217. dwHigh = (dwHigh << 1) | pdwXposeHigh[*pbTemp];
  218. dwLow = (dwLow << 1) | pdwXposeLow[*pbTemp];
  219. pbTemp += pdev->lineOffset;
  220. //
  221. // Invert black and white pixel polarity
  222. //
  223. dwHigh ^= 0xffffffff;
  224. dwLow ^= 0xffffffff;
  225. //
  226. // Distribute the resulting byte to 8 separate scanlines
  227. //
  228. *pbWrite = (BYTE) dwLow;
  229. pbWrite += deltaNew;
  230. *pbWrite = (BYTE) (dwLow >> BYTEBITS);
  231. pbWrite += deltaNew;
  232. *pbWrite = (BYTE) (dwLow >> BYTEBITS*2);
  233. pbWrite += deltaNew;
  234. *pbWrite = (BYTE) (dwLow >> BYTEBITS*3);
  235. pbWrite += deltaNew;
  236. *pbWrite = (BYTE) dwHigh;
  237. pbWrite += deltaNew;
  238. *pbWrite = (BYTE) (dwHigh >> BYTEBITS);
  239. pbWrite += deltaNew;
  240. *pbWrite = (BYTE) (dwHigh >> BYTEBITS*2);
  241. pbWrite += deltaNew;
  242. *pbWrite = (BYTE) (dwHigh >> BYTEBITS*3);
  243. pbWrite -= (deltaNew * BYTEBITS - deltaNew - 1);
  244. }
  245. //
  246. // Encode the next band of scanlines
  247. //
  248. if (! EncodeFaxData(pdev, pBuffer, bmpWidth, BYTEBITS)) {
  249. MemFree(pdwXposeHigh);
  250. MemFree(pBuffer);
  251. FreeCompBitsBuffer(pdev);
  252. return FALSE;
  253. }
  254. } while (pbCol-- != pBitmapData);
  255. MemFree(pdwXposeHigh);
  256. MemFree(pBuffer);
  257. }
  258. //
  259. // Output EOB (two EOLs) after the last scanline
  260. // and make sure the compressed data is WORD aligned
  261. //
  262. OutputBits(pdev, EOL_LENGTH, EOL_CODE);
  263. OutputBits(pdev, EOL_LENGTH, EOL_CODE);
  264. FlushBits(pdev);
  265. if ((compressedBytes = (DWORD)(pdev->pCompBufPtr - pdev->pCompBits)) & 1) {
  266. *pdev->pCompBufPtr++ = 0;
  267. compressedBytes++;
  268. }
  269. //
  270. // Output the IFD for the previous page and generate the IFD for the current page
  271. // Output the compressed bitmap data
  272. //
  273. result = WriteTiffIFD(pdev, bmpWidth, bmpHeight, compressedBytes) &&
  274. WriteTiffBits(pdev, pdev->pCompBits, compressedBytes);
  275. FreeCompBitsBuffer(pdev);
  276. return result;
  277. }
  278. INT
  279. FindWhiteRun(
  280. PBYTE pbuf,
  281. INT startBit,
  282. INT stopBit
  283. )
  284. /*++
  285. Routine Description:
  286. Find the next span of white pixels on the specified line
  287. Arguments:
  288. pbuf - Points to uncompressed pixel data for the current line
  289. startBit - Starting bit index
  290. stopBit - Last bit index
  291. Return Value:
  292. Length of the next run of white pixels
  293. --*/
  294. {
  295. static const BYTE WhiteRuns[256] = {
  296. 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
  297. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  298. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  299. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  300. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  301. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  302. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  303. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  304. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  305. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  306. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  307. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  308. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  309. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  310. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  311. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  312. };
  313. INT run, bits, n;
  314. pbuf += (startBit >> 3);
  315. if ((bits = stopBit-startBit) <= 0)
  316. return 0;
  317. //
  318. // Take care of the case where starting bit index is not a multiple of 8
  319. //
  320. if (n = (startBit & 7)) {
  321. run = WhiteRuns[(*pbuf << n) & 0xff];
  322. if (run > BYTEBITS-n)
  323. run = BYTEBITS-n;
  324. if (n+run < BYTEBITS)
  325. return run;
  326. bits -= run;
  327. pbuf++;
  328. } else
  329. run = 0;
  330. //
  331. // Look for consecutive DWORD value = 0
  332. //
  333. if (bits >= DWORDBITS * 2) {
  334. PDWORD pdw;
  335. //
  336. // Align to a DWORD boundary first
  337. //
  338. while ((ULONG_PTR) pbuf & 3) {
  339. if (*pbuf != 0)
  340. return run + WhiteRuns[*pbuf];
  341. run += BYTEBITS;
  342. bits -= BYTEBITS;
  343. pbuf++;
  344. }
  345. pdw = (PDWORD) pbuf;
  346. while (bits >= DWORDBITS && *pdw == 0) {
  347. pdw++;
  348. run += DWORDBITS;
  349. bits -= DWORDBITS;
  350. }
  351. pbuf = (PBYTE) pdw;
  352. }
  353. //
  354. // Look for consecutive BYTE value = 0
  355. //
  356. while (bits >= BYTEBITS) {
  357. if (*pbuf != 0)
  358. return run + WhiteRuns[*pbuf];
  359. pbuf++;
  360. run += BYTEBITS;
  361. bits -= BYTEBITS;
  362. }
  363. //
  364. // Count the number of white pixels in the last byte
  365. //
  366. if (bits > 0)
  367. run += WhiteRuns[*pbuf];
  368. return run;
  369. }
  370. INT
  371. FindBlackRun(
  372. PBYTE pbuf,
  373. INT startBit,
  374. INT stopBit
  375. )
  376. /*++
  377. Routine Description:
  378. Find the next span of black pixels on the specified line
  379. Arguments:
  380. pbuf - Points to uncompressed pixel data for the current line
  381. startBit - Starting bit index
  382. stopBit - Last bit index
  383. Return Value:
  384. Length of the next run of black pixels
  385. --*/
  386. {
  387. static const BYTE BlackRuns[256] = {
  388. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  389. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  390. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  391. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  392. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  393. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  394. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  395. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  396. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  397. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  398. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  399. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  400. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  401. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  402. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  403. 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8
  404. };
  405. INT run, bits, n;
  406. pbuf += (startBit >> 3);
  407. if ((bits = stopBit-startBit) <= 0)
  408. return 0;
  409. //
  410. // Take care of the case where starting bit index is not a multiple of 8
  411. //
  412. if (n = (startBit & 7)) {
  413. run = BlackRuns[(*pbuf << n) & 0xff];
  414. if (run > BYTEBITS-n)
  415. run = BYTEBITS-n;
  416. if (n+run < BYTEBITS)
  417. return run;
  418. bits -= run;
  419. pbuf++;
  420. } else
  421. run = 0;
  422. //
  423. // Look for consecutive DWORD value = 0xffffffff
  424. //
  425. if (bits >= DWORDBITS * 2) {
  426. PDWORD pdw;
  427. //
  428. // Align to a DWORD boundary first
  429. //
  430. while ((ULONG_PTR) pbuf & 3) {
  431. if (*pbuf != 0xff)
  432. return run + BlackRuns[*pbuf];
  433. run += BYTEBITS;
  434. bits -= BYTEBITS;
  435. pbuf++;
  436. }
  437. pdw = (PDWORD) pbuf;
  438. while (bits >= DWORDBITS && *pdw == 0xffffffff) {
  439. pdw++;
  440. run += DWORDBITS;
  441. bits -= DWORDBITS;
  442. }
  443. pbuf = (PBYTE) pdw;
  444. }
  445. //
  446. // Look for consecutive BYTE value = 0xff
  447. //
  448. while (bits >= BYTEBITS) {
  449. if (*pbuf != 0xff)
  450. return run + BlackRuns[*pbuf];
  451. pbuf++;
  452. run += BYTEBITS;
  453. bits -= BYTEBITS;
  454. }
  455. //
  456. // Count the number of white pixels in the last byte
  457. //
  458. if (bits > 0)
  459. run += BlackRuns[*pbuf];
  460. return run;
  461. }
  462. VOID
  463. OutputRun(
  464. PDEVDATA pdev,
  465. INT run,
  466. PCODETABLE pCodeTable
  467. )
  468. /*++
  469. Routine Description:
  470. Output a single run (black or white) using the specified code table
  471. Arguments:
  472. pdev - Points to our DEVDATA structure
  473. run - Specifies the length of the run
  474. pCodeTable - Specifies the code table to use
  475. Return Value:
  476. NONE
  477. --*/
  478. {
  479. PCODETABLE pTableEntry;
  480. //
  481. // Use make-up code word for 2560 for any runs of at least 2624 pixels
  482. // This is currently not necessary for us since our scanlines always
  483. // have 1728 pixels.
  484. //
  485. while (run >= 2624) {
  486. pTableEntry = pCodeTable + (63 + (2560 >> 6));
  487. OutputBits(pdev, pTableEntry->length, pTableEntry->code);
  488. run -= 2560;
  489. }
  490. //
  491. // Use appropriate make-up code word if the run is longer than 63 pixels
  492. //
  493. if (run >= 64) {
  494. pTableEntry = pCodeTable + (63 + (run >> 6));
  495. OutputBits(pdev, pTableEntry->length, pTableEntry->code);
  496. run &= 0x3f;
  497. }
  498. //
  499. // Output terminating code word
  500. //
  501. OutputBits(pdev, pCodeTable[run].length, pCodeTable[run].code);
  502. }
  503. #ifdef USE1D
  504. VOID
  505. OutputEOL(
  506. PDEVDATA pdev
  507. )
  508. /*++
  509. Routine Description:
  510. Output EOL code at the beginning of each scanline
  511. Arguments:
  512. pdev - Points to our DEVDATA structure
  513. Return Value:
  514. NONE
  515. --*/
  516. {
  517. DWORD length, code;
  518. //
  519. // EOL code word always ends on a byte boundary
  520. //
  521. code = EOL_CODE;
  522. length = EOL_LENGTH + ((pdev->bitcnt - EOL_LENGTH) & 7);
  523. OutputBits(pdev, length, code);
  524. }
  525. BOOL
  526. EncodeFaxData(
  527. PDEVDATA pdev,
  528. PBYTE plinebuf,
  529. INT lineWidth,
  530. INT lineCount
  531. )
  532. /*++
  533. Routine Description:
  534. Compress the specified number of scanlines
  535. Arguments:
  536. pdev - Points to our DEVDATA structure
  537. plinebuf - Points to scanline data to be compressed
  538. lineWidth - Scanline width in pixels
  539. lineCount - Number of scanlines
  540. Return Value:
  541. TRUE if successful, FALSE if there is an error
  542. --*/
  543. {
  544. INT delta = lineWidth / BYTEBITS;
  545. INT bitIndex, run;
  546. while (lineCount--) {
  547. //
  548. // Make sure the compressed bitmap buffer doesn't overflow
  549. //
  550. if ((pdev->pCompBufPtr >= pdev->pCompBufMark) && !GrowCompBitsBuffer(pdev, delta))
  551. return FALSE;
  552. //
  553. // Output byte-aligned EOL code
  554. //
  555. OutputEOL(pdev);
  556. //
  557. // Use 1-dimensional encoding scheme
  558. //
  559. bitIndex = 0;
  560. while (TRUE) {
  561. //
  562. // Code white run
  563. //
  564. run = FindWhiteRun(plinebuf, bitIndex, lineWidth);
  565. OutputRun(pdev, run, WhiteRunCodes);
  566. if ((bitIndex += run) >= lineWidth)
  567. break;
  568. //
  569. // Code black run
  570. //
  571. run = FindBlackRun(plinebuf, bitIndex, lineWidth);
  572. OutputRun(pdev, run, BlackRunCodes);
  573. if ((bitIndex += run) >= lineWidth)
  574. break;
  575. }
  576. //
  577. // Move on to the next scanline
  578. //
  579. plinebuf += delta;
  580. }
  581. return TRUE;
  582. }
  583. #else //!USE1D
  584. BOOL
  585. EncodeFaxData(
  586. PDEVDATA pdev,
  587. PBYTE plinebuf,
  588. INT lineWidth,
  589. INT lineCount
  590. )
  591. /*++
  592. Routine Description:
  593. Compress the specified number of scanlines
  594. Arguments:
  595. pdev - Points to our DEVDATA structure
  596. plinebuf - Points to scanline data to be compressed
  597. lineWidth - Scanline width in pixels
  598. lineCount - Number of scanlines
  599. Return Value:
  600. TRUE if successful, FALSE if there is an error
  601. --*/
  602. {
  603. INT delta = lineWidth / BYTEBITS;
  604. INT a0, a1, a2, b1, b2, distance;
  605. PBYTE prefline = pdev->prefline;
  606. Assert(lineWidth % BYTEBITS == 0);
  607. while (lineCount--) {
  608. //
  609. // Make sure the compressed bitmap buffer doesn't overflow
  610. //
  611. if ((pdev->pCompBufPtr >= pdev->pCompBufMark) && !GrowCompBitsBuffer(pdev, delta))
  612. return FALSE;
  613. //
  614. // Use 2-dimensional encoding scheme
  615. //
  616. a0 = 0;
  617. a1 = GetBit(plinebuf, 0) ? 0 : NextChangingElement(plinebuf, 0, lineWidth, 0);
  618. b1 = GetBit(prefline, 0) ? 0 : NextChangingElement(prefline, 0, lineWidth, 0);
  619. while (TRUE) {
  620. b2 = (b1 >= lineWidth) ? lineWidth :
  621. NextChangingElement(prefline, b1, lineWidth, GetBit(prefline, b1));
  622. if (b2 < a1) {
  623. //
  624. // Pass mode
  625. //
  626. OutputBits(pdev, PASSCODE_LENGTH, PASSCODE);
  627. a0 = b2;
  628. } else if ((distance = a1 - b1) <= 3 && distance >= -3) {
  629. //
  630. // Vertical mode
  631. //
  632. OutputBits(pdev, VertCodes[distance+3].length, VertCodes[distance+3].code);
  633. a0 = a1;
  634. } else {
  635. //
  636. // Horizontal mode
  637. //
  638. a2 = (a1 >= lineWidth) ? lineWidth :
  639. NextChangingElement(plinebuf, a1, lineWidth, GetBit(plinebuf, a1));
  640. OutputBits(pdev, HORZCODE_LENGTH, HORZCODE);
  641. if (a1 != 0 && GetBit(plinebuf, a0)) {
  642. OutputRun(pdev, a1-a0, BlackRunCodes);
  643. OutputRun(pdev, a2-a1, WhiteRunCodes);
  644. } else {
  645. OutputRun(pdev, a1-a0, WhiteRunCodes);
  646. OutputRun(pdev, a2-a1, BlackRunCodes);
  647. }
  648. a0 = a2;
  649. }
  650. if (a0 >= lineWidth)
  651. break;
  652. a1 = NextChangingElement(plinebuf, a0, lineWidth, GetBit(plinebuf, a0));
  653. b1 = NextChangingElement(prefline, a0, lineWidth, !GetBit(plinebuf, a0));
  654. b1 = NextChangingElement(prefline, b1, lineWidth, GetBit(plinebuf, a0));
  655. }
  656. //
  657. // Move on to the next scanline
  658. //
  659. prefline = plinebuf;
  660. plinebuf += delta;
  661. }
  662. //
  663. // Remember the last line as a reference
  664. //
  665. CopyMemory(pdev->prefline, prefline, delta);
  666. return TRUE;
  667. }
  668. #endif //!USE1D
  669. //
  670. // IFD entries we generate for each page
  671. //
  672. WORD FaxIFDTags[NUM_IFD_ENTRIES] = {
  673. TIFFTAG_NEWSUBFILETYPE,
  674. TIFFTAG_IMAGEWIDTH,
  675. TIFFTAG_IMAGEHEIGHT,
  676. TIFFTAG_BITSPERSAMPLE,
  677. TIFFTAG_COMPRESSION,
  678. TIFFTAG_PHOTOMETRIC,
  679. TIFFTAG_FILLORDER,
  680. TIFFTAG_STRIPOFFSETS,
  681. TIFFTAG_SAMPLESPERPIXEL,
  682. TIFFTAG_ROWSPERSTRIP,
  683. TIFFTAG_STRIPBYTECOUNTS,
  684. TIFFTAG_XRESOLUTION,
  685. TIFFTAG_YRESOLUTION,
  686. #ifdef USE1D
  687. TIFFTAG_G3OPTIONS,
  688. #else
  689. TIFFTAG_G4OPTIONS,
  690. #endif
  691. TIFFTAG_RESUNIT,
  692. TIFFTAG_PAGENUMBER,
  693. TIFFTAG_SOFTWARE,
  694. TIFFTAG_CLEANFAXDATA,
  695. };
  696. #define SoftwareStr "Windows NT Fax Driver"
  697. static FAXIFD FaxIFDTemplate = {
  698. 0,
  699. NUM_IFD_ENTRIES,
  700. {
  701. { TIFFTAG_NEWSUBFILETYPE, TIFFTYPE_LONG, 1, SUBFILETYPE_PAGE },
  702. { TIFFTAG_IMAGEWIDTH, TIFFTYPE_LONG, 1, 0 },
  703. { TIFFTAG_IMAGEHEIGHT, TIFFTYPE_LONG, 1, 0 },
  704. { TIFFTAG_BITSPERSAMPLE, TIFFTYPE_SHORT, 1, 1 },
  705. #ifdef USE1D
  706. { TIFFTAG_COMPRESSION, TIFFTYPE_SHORT, 1, COMPRESSION_G3FAX },
  707. #else
  708. { TIFFTAG_COMPRESSION, TIFFTYPE_SHORT, 1, COMPRESSION_G4FAX },
  709. #endif
  710. { TIFFTAG_PHOTOMETRIC, TIFFTYPE_SHORT, 1, PHOTOMETRIC_WHITEIS0 },
  711. #ifdef USELSB
  712. { TIFFTAG_FILLORDER, TIFFTYPE_SHORT, 1, FILLORDER_LSB },
  713. #else
  714. { TIFFTAG_FILLORDER, TIFFTYPE_SHORT, 1, FILLORDER_MSB },
  715. #endif
  716. { TIFFTAG_STRIPOFFSETS, TIFFTYPE_LONG, 1, 0 },
  717. { TIFFTAG_SAMPLESPERPIXEL, TIFFTYPE_SHORT, 1, 1 },
  718. { TIFFTAG_ROWSPERSTRIP, TIFFTYPE_LONG, 1, 0 },
  719. { TIFFTAG_STRIPBYTECOUNTS, TIFFTYPE_LONG, 1, 0 },
  720. { TIFFTAG_XRESOLUTION, TIFFTYPE_RATIONAL, 1, 0 },
  721. { TIFFTAG_YRESOLUTION, TIFFTYPE_RATIONAL, 1, 0 },
  722. #ifdef USE1D
  723. { TIFFTAG_G3OPTIONS, TIFFTYPE_LONG, 1, G3_ALIGNEOL },
  724. #else
  725. { TIFFTAG_G4OPTIONS, TIFFTYPE_LONG, 1, 0 },
  726. #endif
  727. { TIFFTAG_RESUNIT, TIFFTYPE_SHORT, 1, RESUNIT_INCH },
  728. { TIFFTAG_PAGENUMBER, TIFFTYPE_SHORT, 2, 0 },
  729. { TIFFTAG_SOFTWARE, TIFFTYPE_ASCII, sizeof(SoftwareStr)+1, 0 },
  730. { TIFFTAG_CLEANFAXDATA, TIFFTYPE_SHORT, 1, 0 },
  731. },
  732. 0,
  733. DRIVER_SIGNATURE,
  734. TIFFF_RES_X,
  735. 1,
  736. TIFFF_RES_Y,
  737. 1,
  738. SoftwareStr
  739. };
  740. BOOL
  741. OutputDocTrailer(
  742. PDEVDATA pdev
  743. )
  744. /*++
  745. Routine Description:
  746. Output document trailer information to the spooler
  747. Arguments:
  748. pdev - Points to our DEVDATA structure
  749. Return Value:
  750. TRUE if successful, FALSE if there is an error
  751. --*/
  752. {
  753. PFAXIFD pFaxIFD = pdev->pFaxIFD;
  754. if (pFaxIFD == NULL || pdev->pageCount == 0)
  755. return TRUE;
  756. //
  757. // Output the IFD for the last page of the document
  758. //
  759. pFaxIFD->nextIFDOffset = pFaxIFD->filler = 0;
  760. return WriteData(pdev, pFaxIFD, sizeof(FAXIFD));
  761. }
  762. BOOL
  763. WriteTiffIFD(
  764. PDEVDATA pdev,
  765. LONG bmpWidth,
  766. LONG bmpHeight,
  767. DWORD compressedBytes
  768. )
  769. /*++
  770. Routine Description:
  771. Output the IFD for the previous page and generate the IFD for the current page
  772. Arguments:
  773. pdev - Points to our DEVDATA structure
  774. bmpWidth, bmpHeight - Width and height of the bitmap image
  775. compressedBytes - Size of compressed bitmap data
  776. Return Value:
  777. TRUE if successful, FALSE otherwise
  778. NOTE:
  779. Please refer to faxtiff.h for a description of
  780. the structure of our TIFF output file.
  781. --*/
  782. {
  783. PFAXIFD pFaxIFD = pdev->pFaxIFD;
  784. ULONG_PTR offset;
  785. BOOL result = TRUE;
  786. //
  787. // Create the IFD data structure if necessary
  788. //
  789. if (pFaxIFD == NULL) {
  790. if (! (pFaxIFD = MemAlloc(sizeof(FAXIFD))))
  791. return FALSE;
  792. pdev->pFaxIFD = pFaxIFD;
  793. memcpy(pFaxIFD, &FaxIFDTemplate, sizeof(FAXIFD));
  794. #if DBG
  795. for (offset=0; offset < NUM_IFD_ENTRIES; offset++) {
  796. Assert(pFaxIFD->ifd[offset].tag == FaxIFDTags[offset]);
  797. }
  798. #endif
  799. }
  800. if (pdev->pageCount <= 1) {
  801. //
  802. // If this is the very first page, there is no previous IFD.
  803. // Output the TIFF file header instead.
  804. //
  805. TIFFFILEHEADER *pTiffFileHeader;
  806. pdev->fileOffset = 0;
  807. if (pTiffFileHeader = MemAlloc(sizeof(TIFFFILEHEADER))) {
  808. pTiffFileHeader->magic1 = TIFF_MAGIC1;
  809. pTiffFileHeader->magic2 = TIFF_MAGIC2;
  810. pTiffFileHeader->signature = DRIVER_SIGNATURE;
  811. pTiffFileHeader->firstIFD = sizeof(TIFFFILEHEADER) +
  812. compressedBytes +
  813. offsetof(FAXIFD, wIFDEntries);
  814. result = WriteData(pdev, pTiffFileHeader, sizeof(TIFFFILEHEADER));
  815. MemFree(pTiffFileHeader);
  816. } else {
  817. Error(("Memory allocation failed\n"));
  818. result = FALSE;
  819. }
  820. } else {
  821. //
  822. // Not the first page of the document
  823. // Output the IFD for the previous page
  824. //
  825. pFaxIFD->nextIFDOffset = pdev->fileOffset + compressedBytes + sizeof(FAXIFD) +
  826. offsetof(FAXIFD, wIFDEntries);
  827. result = WriteData(pdev, pFaxIFD, sizeof(FAXIFD));
  828. }
  829. //
  830. // Generate the IFD for the current page
  831. //
  832. offset = pdev->fileOffset;
  833. pFaxIFD->ifd[IFD_PAGENUMBER].value = MAKELONG(pdev->pageCount-1, 0);
  834. pFaxIFD->ifd[IFD_IMAGEWIDTH].value = bmpWidth;
  835. pFaxIFD->ifd[IFD_IMAGEHEIGHT].value = bmpHeight;
  836. pFaxIFD->ifd[IFD_ROWSPERSTRIP].value = bmpHeight;
  837. pFaxIFD->ifd[IFD_STRIPBYTECOUNTS].value = compressedBytes;
  838. pFaxIFD->ifd[IFD_STRIPOFFSETS].value = (ULONG)offset;
  839. offset += compressedBytes;
  840. pFaxIFD->ifd[IFD_XRESOLUTION].value = (ULONG)offset + offsetof(FAXIFD, xresNum);
  841. pFaxIFD->ifd[IFD_YRESOLUTION].value = (ULONG)offset + offsetof(FAXIFD, yresNum);
  842. pFaxIFD->ifd[IFD_SOFTWARE].value = (ULONG)offset + offsetof(FAXIFD, software);
  843. pFaxIFD->yresNum = (pdev->dm.dmPublic.dmYResolution == FAXRES_VERTDRAFT) ?
  844. TIFFF_RES_Y_DRAFT :
  845. TIFFF_RES_Y;
  846. return result;
  847. }
  848. BOOL
  849. WriteTiffBits(
  850. PDEVDATA pdev,
  851. PBYTE pCompBits,
  852. DWORD compressedBytes
  853. )
  854. /*++
  855. Routine Description:
  856. Output the compressed bitmap data to the spooler
  857. Arguments:
  858. pdev - Points to our DEVDATA structure
  859. pCompBits - Points to a buffer containing compressed bitmap data
  860. compressedBytes - Size of compressed bitmap data
  861. Return Value:
  862. TRUE if successful, FALSE if there is an error
  863. --*/
  864. #define OUTPUT_BUFFER_SIZE 4096
  865. {
  866. PBYTE pBuffer;
  867. DWORD bytesToWrite;
  868. #ifndef USERMODE_DRIVER
  869. //
  870. // Since we allocated the compressed bitmap data buffer from
  871. // the user mode memory space, we couldn't passed it directly
  872. // to EngWritePrinter.
  873. //
  874. // Here we allocate a temporary buffer from kernel mode memory
  875. // space and output the compressed data one buffer at a time.
  876. //
  877. if (! (pBuffer = MemAlloc(OUTPUT_BUFFER_SIZE))) {
  878. Error(("Memory allocation failed\n"));
  879. return FALSE;
  880. }
  881. while (compressedBytes > 0) {
  882. bytesToWrite = min(compressedBytes, OUTPUT_BUFFER_SIZE);
  883. CopyMemory(pBuffer, pCompBits, bytesToWrite);
  884. if (! WriteData(pdev, pBuffer, bytesToWrite)) {
  885. MemFree(pBuffer);
  886. return FALSE;
  887. }
  888. pCompBits += bytesToWrite;
  889. compressedBytes -= bytesToWrite;
  890. }
  891. MemFree(pBuffer);
  892. return TRUE;
  893. #else
  894. //
  895. // just dump the data in OUTPUT_BUFFER_SIZE increments
  896. //
  897. pBuffer = pCompBits;
  898. while (compressedBytes > 0) {
  899. bytesToWrite = min(compressedBytes, OUTPUT_BUFFER_SIZE);
  900. if (! WriteData(pdev, pBuffer, bytesToWrite) ) {
  901. return FALSE;
  902. }
  903. pBuffer += bytesToWrite;
  904. compressedBytes -= bytesToWrite;
  905. }
  906. return TRUE;
  907. #endif
  908. }
  909. BOOL
  910. GrowCompBitsBuffer(
  911. PDEVDATA pdev,
  912. LONG scanlineSize
  913. )
  914. /*++
  915. Routine Description:
  916. Enlarge the buffer for holding the compressed bitmap data
  917. Arguments:
  918. pdev - Points to our DEVDATA structure
  919. scanlineSize - Number of uncompressed bytes per scanline
  920. Return Value:
  921. TRUE if successful, FALSE if memory allocation fails
  922. --*/
  923. {
  924. DWORD oldBufferSize;
  925. PBYTE pNewBuffer;
  926. //
  927. // Allocate a new buffer which is one increment larger than existing one
  928. //
  929. oldBufferSize = pdev->pCompBits ? pdev->compBufSize : 0;
  930. pdev->compBufSize = oldBufferSize + pdev->compBufInc;
  931. if (! (pNewBuffer = MemAlloc(pdev->compBufSize))) {
  932. Error(("MemAlloc failed\n"));
  933. FreeCompBitsBuffer(pdev);
  934. return FALSE;
  935. }
  936. if (pdev->pCompBits) {
  937. //
  938. // Growing an existing buffer
  939. //
  940. Warning(("Growing compressed bitmap buffer: %d -> %d\n", oldBufferSize, pdev->compBufSize));
  941. memcpy(pNewBuffer, pdev->pCompBits, oldBufferSize);
  942. pdev->pCompBufPtr = pNewBuffer + (pdev->pCompBufPtr - pdev->pCompBits);
  943. MemFree(pdev->pCompBits);
  944. pdev->pCompBits = pNewBuffer;
  945. } else {
  946. //
  947. // First time allocation
  948. //
  949. pdev->pCompBufPtr = pdev->pCompBits = pNewBuffer;
  950. }
  951. //
  952. // Set a high-water mark to about 4 scanlines before the end of the buffer
  953. //
  954. pdev->pCompBufMark = pdev->pCompBits + (pdev->compBufSize - 4*scanlineSize);
  955. return TRUE;
  956. }
  957. VOID
  958. FreeCompBitsBuffer(
  959. PDEVDATA pdev
  960. )
  961. /*++
  962. Routine Description:
  963. Free the buffer for holding the compressed bitmap data
  964. Arguments:
  965. pdev - Points to our DEVDATA structure
  966. Return Value:
  967. NONE
  968. --*/
  969. {
  970. if (pdev->pCompBits) {
  971. MemFree(pdev->prefline);
  972. MemFree(pdev->pCompBits);
  973. pdev->pCompBits = pdev->pCompBufPtr = NULL;
  974. pdev->compBufSize = 0;
  975. }
  976. }
  977. BOOL
  978. InitFaxEncoder(
  979. PDEVDATA pdev,
  980. LONG bmpWidth,
  981. LONG bmpHeight
  982. )
  983. /*++
  984. Routine Description:
  985. Initialize the fax encoder
  986. Arguments:
  987. pdev - Points to our DEVDATA structure
  988. bmpWidth, bmpHeight - Width and height of the bitmap
  989. Return Value:
  990. TRUE if successful, FALSE if there is an error
  991. --*/
  992. {
  993. //
  994. // Calculate the increment in which to enlarge the compressed bits buffer:
  995. // about 1/4 of the uncompressed bitmap buffer
  996. //
  997. bmpWidth /= BYTEBITS;
  998. pdev->compBufInc = bmpWidth * bmpHeight / 4;
  999. //
  1000. // Allocate the initial buffer
  1001. //
  1002. if (! (pdev->prefline = MemAllocZ(bmpWidth)) ||
  1003. ! GrowCompBitsBuffer(pdev, bmpWidth))
  1004. {
  1005. MemFree(pdev->prefline);
  1006. return FALSE;
  1007. }
  1008. //
  1009. // Perform other initialization of fax encoder
  1010. //
  1011. pdev->bitdata = 0;
  1012. pdev->bitcnt = DWORDBITS;
  1013. return TRUE;
  1014. }