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.

429 lines
14 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. This file contains the parts of the AWD library that are also TIFF-aware
  4. (i.e., conversion routines).
  5. Author:
  6. Brian Dewey (t-briand) 1997-7-16
  7. --*/
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <ole2.h> // AWD is an OLE compound document.
  11. #include <assert.h>
  12. #include "awdlib.h" // Header file for this library.
  13. #include "viewrend.h" // AWD rendering library.
  14. #include "tifflibp.h" // Need this for the stolen compression routines.
  15. // ------------------------------------------------------------
  16. // Defines
  17. #define FAX_IMAGE_WIDTH (1728)
  18. // ------------------------------------------------------------
  19. // Global variables
  20. HANDLE hTiffDest; // Used in the internal OutputPage()
  21. // and ConvertAWDToTiff().
  22. // ------------------------------------------------------------
  23. // Internal prototypes
  24. BOOL
  25. CompressBitmapStrip(
  26. PBYTE pBrandBits,
  27. LPDWORD pMmrBrandBits,
  28. INT BrandHeight,
  29. INT BrandWidth,
  30. DWORD *DwordsOut,
  31. DWORD *BitsOut
  32. ); // Routine stolen from tiff library.
  33. // Used to be EncodeMmrBranding().
  34. void
  35. ConvertWidth(const LPBYTE lpSrc, DWORD dwSrcWidth,
  36. LPBYTE lpDest, DWORD dwDestWidth,
  37. DWORD dwHeight);
  38. BOOL OutputPage(AWD_FILE *psStorages, const WCHAR *pwcsDocName);
  39. // ------------------------------------------------------------
  40. // Routines
  41. // ConvertAWDToTiff
  42. //
  43. // This function does exactly what it says. Given the name of an AWD file, it
  44. // attempts to convert it to a tiff file.
  45. //
  46. // Parameters:
  47. // pwcsAwdFile name of the AWD file.
  48. // pwcsTiffFile name of the TIFF file.
  49. //
  50. // Returns:
  51. // TRUE on successful conversion, FALSE otherwise.
  52. //
  53. // Author:
  54. // Brian Dewey (t-briand) 1997-7-14
  55. BOOL
  56. ConvertAWDToTiff(const WCHAR *pwcsAwdFile, WCHAR *pwcsTiffFile)
  57. {
  58. BOOL bRetVal; // Holds our return value.
  59. AWD_FILE sAWDStorages; // Holds the main storages of the AWD file.
  60. // Initialization.
  61. HeapInitialize(NULL, NULL, NULL, NULL);
  62. // Open the source.
  63. if(!OpenAWDFile(pwcsAwdFile, &sAWDStorages)) {
  64. return FALSE;
  65. }
  66. // Open the destination
  67. hTiffDest = TiffCreate(pwcsTiffFile,
  68. TIFF_COMPRESSION_MMR,
  69. FAX_IMAGE_WIDTH,
  70. 2, // Fill order 2 == LSB2MSB (I think).
  71. 1); // HIRES
  72. if(hTiffDest == NULL) {
  73. CloseAWDFile(&sAWDStorages);
  74. return FALSE;
  75. }
  76. bRetVal = EnumDocuments(&sAWDStorages, OutputPage);
  77. CloseAWDFile(&sAWDStorages);
  78. TiffClose(hTiffDest);
  79. return bRetVal;
  80. }
  81. // CompressBitmapStrip
  82. //
  83. // Stolen from Tiff library, where it's called EncodeMmrBranding().
  84. //
  85. // Author: ???
  86. BOOL
  87. CompressBitmapStrip(
  88. PBYTE pBrandBits,
  89. LPDWORD pMmrBrandBits,
  90. INT BrandHeight,
  91. INT BrandWidth,
  92. DWORD *DwordsOut,
  93. DWORD *BitsOut
  94. )
  95. /*++
  96. Routine Description:
  97. Encode an MMR branding from uncompressed branding bits.
  98. I don't have enough time to write an optimized
  99. Uncompressed -> MMR convertor, so the compromise is
  100. to use the existing Uncompressed Decoder (fast enough)
  101. and use the optimized MMR Encoder.
  102. Since we only convert few lines for Branding, it's OK.
  103. --*/
  104. {
  105. INT a0, a1, a2, b1, b2, distance;
  106. LPBYTE prefline;
  107. BYTE pZeroline[1728/8];
  108. INT delta = BrandWidth / BYTEBITS;
  109. INT Lines = 0;
  110. LPDWORD lpdwOut = pMmrBrandBits;
  111. BYTE BitOut = 0;
  112. #if TIFFDBG
  113. _tprintf( TEXT("encoding line #%d\n"), TiffInstance->Lines );
  114. #endif
  115. // set first all white reference line
  116. prefline = pZeroline;
  117. ZeroMemory(pZeroline, BrandWidth/8);
  118. // loop til all lines done
  119. do {
  120. a0 = 0;
  121. a1 = GetBit( pBrandBits, 0) ? 0 : NextChangingElement(pBrandBits, 0, BrandWidth, 0 );
  122. b1 = GetBit( prefline, 0) ? 0 : NextChangingElement(prefline, 0, BrandWidth, 0 );
  123. while (TRUE) {
  124. b2 = (b1 >= BrandWidth) ? BrandWidth :
  125. NextChangingElement( prefline, b1, BrandWidth, GetBit(prefline, b1 ));
  126. if (b2 < a1) {
  127. //
  128. // Pass mode
  129. //
  130. //OutputBits( TiffInstance, PASSCODE_LENGTH, PASSCODE );
  131. (*lpdwOut) += ( ((DWORD) (PASSCODE_REVERSED)) << BitOut);
  132. if ( (BitOut = BitOut + PASSCODE_LENGTH ) > 31 ) {
  133. BitOut -= 32;
  134. *(++lpdwOut) = ( (DWORD) (PASSCODE_REVERSED) ) >> (PASSCODE_LENGTH - BitOut);
  135. }
  136. #if TIFFDBG
  137. PrintRunInfo( 1, 0, PASSCODE_LENGTH, PASSCODE );
  138. _tprintf( TEXT("\t\ta0=%d, a1=%d, a2=%d, b1=%d, b2=%d\n"), a0, a1, a2, b1, b2 );
  139. #endif
  140. a0 = b2;
  141. } else if ((distance = a1 - b1) <= 3 && distance >= -3) {
  142. //
  143. // Vertical mode
  144. //
  145. // OutputBits( TiffInstance, VertCodes[distance+3].length, VertCodes[distance+3].code );
  146. (*lpdwOut) += ( ( (DWORD) VertCodesReversed[distance+3].code) << BitOut);
  147. if ( (BitOut = BitOut + VertCodesReversed[distance+3].length ) > 31 ) {
  148. BitOut -= 32;
  149. *(++lpdwOut) = ( (DWORD) (VertCodesReversed[distance+3].code) ) >> (VertCodesReversed[distance+3].length - BitOut);
  150. }
  151. #if TIFFDBG
  152. PrintRunInfo( 2, a1-a0, VertCodes[distance+3].length, VertCodes[distance+3].code );
  153. _tprintf( TEXT("\t\ta0=%d, a1=%d, a2=%d, b1=%d, b2=%d\n"), a0, a1, a2, b1, b2 );
  154. #endif
  155. a0 = a1;
  156. } else {
  157. //
  158. // Horizontal mode
  159. //
  160. a2 = (a1 >= BrandWidth) ? BrandWidth :
  161. NextChangingElement( pBrandBits, a1, BrandWidth, GetBit( pBrandBits, a1 ) );
  162. // OutputBits( TiffInstance, HORZCODE_LENGTH, HORZCODE );
  163. (*lpdwOut) += ( ((DWORD) (HORZCODE_REVERSED)) << BitOut);
  164. if ( (BitOut = BitOut + HORZCODE_LENGTH ) > 31 ) {
  165. BitOut -= 32;
  166. *(++lpdwOut) = ( (DWORD) (HORZCODE_REVERSED) ) >> (HORZCODE_LENGTH - BitOut);
  167. }
  168. #if TIFFDBG
  169. PrintRunInfo( 3, 0, HORZCODE_LENGTH, HORZCODE );
  170. _tprintf( TEXT("\t\ta0=%d, a1=%d, a2=%d, b1=%d, b2=%d\n"), a0, a1, a2, b1, b2 );
  171. #endif
  172. if (a1 != 0 && GetBit( pBrandBits, a0 )) {
  173. //OutputRun( TiffInstance, a1-a0, BlackRunCodes );
  174. //OutputRun( TiffInstance, a2-a1, WhiteRunCodes );
  175. OutputRunFastReversed(a1-a0, BLACK, &lpdwOut, &BitOut);
  176. OutputRunFastReversed(a2-a1, WHITE, &lpdwOut, &BitOut);
  177. } else {
  178. //OutputRun( TiffInstance, a1-a0, WhiteRunCodes );
  179. //OutputRun( TiffInstance, a2-a1, BlackRunCodes );
  180. OutputRunFastReversed(a1-a0, WHITE, &lpdwOut, &BitOut);
  181. OutputRunFastReversed(a2-a1, BLACK, &lpdwOut, &BitOut);
  182. }
  183. a0 = a2;
  184. }
  185. if (a0 >= BrandWidth) {
  186. Lines++;
  187. break;
  188. }
  189. a1 = NextChangingElement( pBrandBits, a0, BrandWidth, GetBit( pBrandBits, a0 ) );
  190. b1 = NextChangingElement( prefline, a0, BrandWidth, !GetBit( pBrandBits, a0 ) );
  191. b1 = NextChangingElement( prefline, b1, BrandWidth, GetBit( pBrandBits, a0 ) );
  192. }
  193. prefline = pBrandBits;
  194. pBrandBits += (BrandWidth / 8);
  195. } while (Lines < BrandHeight);
  196. *DwordsOut = (DWORD)(lpdwOut - pMmrBrandBits);
  197. *BitsOut = BitOut;
  198. return TRUE;
  199. }
  200. // ConvertWidth
  201. //
  202. // Changes the width of a bitmap. If the desired width is smaller than the current
  203. // width, this is accomplished by truncating lines. If the desired width is greater
  204. // than the current width, data will be copied up from the next line.
  205. //
  206. // Parameters:
  207. // lpSrc Bitmap source.
  208. // dwSrcWidth Its width.
  209. // lpDest Pointer to destination.
  210. // dwDestWidth Desired width of destination
  211. // dwHeight Height of image (won't change).
  212. //
  213. // Returns:
  214. // nothing.
  215. //
  216. // Author:
  217. // Brian Dewey (t-briand) 1997-7-10
  218. void
  219. ConvertWidth(const LPBYTE lpSrc, DWORD dwSrcWidth,
  220. LPBYTE lpDest, DWORD dwDestWidth,
  221. DWORD dwHeight)
  222. {
  223. LPBYTE lpSrcCur, lpDestCur;
  224. DWORD dwCurLine;
  225. for(lpSrcCur = lpSrc, lpDestCur = lpDest, dwCurLine = 0;
  226. dwCurLine < dwHeight;
  227. lpSrcCur += dwSrcWidth, lpDestCur += dwDestWidth, dwCurLine++) {
  228. memcpy(lpDestCur, lpSrcCur, dwDestWidth);
  229. }
  230. }
  231. // OutputPage
  232. //
  233. // This is the core of the converter; it takes a single AWD page and writes it
  234. // to the TIFF file.
  235. //
  236. // Parameters:
  237. // psStorages Pointer to the AWD file from which we read.
  238. // pwcsDocName Name of the page.
  239. //
  240. // Returns:
  241. // TRUE on success, FALSE on failure.
  242. //
  243. // Author:
  244. // Brian Dewey (t-briand) 1997-7-2
  245. BOOL
  246. OutputPage(AWD_FILE *psStorages, const WCHAR *pwcsDocName)
  247. {
  248. BITMAP bmBand; // A band of image data.
  249. LPBYTE lpOutBuf; // Output bitmap (resized).
  250. LPBYTE lpOutCur; // Used to write one line at a time.
  251. LPDWORD lpdwOutCompressed; // Compressed output.
  252. DWORD dwDwordsOut, // Number of DWORDS in compressed output...
  253. dwBitsOut = 0; // Number of bits in compressed output.
  254. DWORD dwBitsOutOld = 0; // BitsOut from the *previous* band compression.
  255. LPVOID lpViewerContext; // The viewer context; used by viewrend library.
  256. VIEWINFO sViewInfo; // Information about the image.
  257. WORD awResolution[2], // Holds X & Y resolutions
  258. wBandSize = 256; // Desired band size; will be reset by ViewerOpen.
  259. IStream *psDocument; // Our document stream.
  260. BOOL bRet = FALSE; // Return value; FALSE by default.
  261. UINT iCurPage; // Current page.
  262. const DWORD dwMagicHeight = 3000; // FIXBKD
  263. if((psDocument = OpenAWDStream(psStorages->psDocuments, pwcsDocName)) == NULL) {
  264. fwprintf(stderr, L"OutputPage:Unable to open stream '%s'.\n",
  265. pwcsDocName);
  266. return FALSE; // We failed.
  267. }
  268. // Now, open a viewer context and start reading bands of the image.
  269. if((lpViewerContext = ViewerOpen(psDocument,
  270. HRAW_DATA,
  271. awResolution,
  272. &wBandSize,
  273. &sViewInfo)) == NULL) {
  274. fprintf(stderr, "OutputPage:Unable to open viewer context.\n");
  275. return FALSE;
  276. }
  277. iCurPage = 0; // Initialize our counter.
  278. bmBand.bmBits = malloc(wBandSize); // Allocate memory to hold the band.
  279. if(!ViewerGetBand(lpViewerContext, &bmBand)) {
  280. fprintf(stderr, "OutputPage:Unable to obtain image band.\n");
  281. return FALSE;
  282. }
  283. // lpOutBuf = malloc(bmBand.bmHeight * (FAX_IMAGE_WIDTH / 8));
  284. lpOutBuf = malloc(dwMagicHeight * (FAX_IMAGE_WIDTH / 8));
  285. // Provided compression actually *compresses*, we should have more than
  286. // enough memory allocated.
  287. lpdwOutCompressed = malloc(dwMagicHeight * (FAX_IMAGE_WIDTH / 8));
  288. if(!lpOutBuf || !lpdwOutCompressed) {
  289. // check whether we are short in memory
  290. TiffEndPage(hTiffDest);
  291. if(lpOutBuf) free(lpOutBuf);
  292. if(lpdwOutCompressed) free(lpdwOutCompressed);
  293. return FALSE; // This will stop the conversion process.
  294. }
  295. memset(lpOutBuf, '\0', dwMagicHeight * (FAX_IMAGE_WIDTH / 8));
  296. memset(lpdwOutCompressed, '\0', dwMagicHeight * (FAX_IMAGE_WIDTH / 8));
  297. // Main loop
  298. while(iCurPage < sViewInfo.cPage) {
  299. lpOutCur = lpOutBuf;
  300. while(bmBand.bmHeight) {
  301. // Make sure our bitmap has FAX_IMAGE_WIDTH as its width.
  302. ConvertWidth(bmBand.bmBits, bmBand.bmWidth / 8,
  303. lpOutCur, FAX_IMAGE_WIDTH / 8,
  304. bmBand.bmHeight);
  305. lpOutCur += (bmBand.bmHeight * (FAX_IMAGE_WIDTH / 8));
  306. if(!ViewerGetBand(lpViewerContext, &bmBand)) {
  307. fprintf(stderr, "OutputPage:Unable to obtain image band.\n");
  308. goto output_exit; // Will return FALSE by default.
  309. }
  310. } // while (wasn't that easy?)
  311. memset(lpdwOutCompressed, '\0', dwMagicHeight * (FAX_IMAGE_WIDTH / 8));
  312. CompressBitmapStrip(lpOutBuf,
  313. lpdwOutCompressed,
  314. (ULONG)((lpOutCur - lpOutBuf) / (FAX_IMAGE_WIDTH / 8)),
  315. FAX_IMAGE_WIDTH,
  316. &dwDwordsOut,
  317. &dwBitsOut);
  318. memset(lpOutBuf, '\0', dwMagicHeight * (FAX_IMAGE_WIDTH / 8));
  319. fprintf(stderr, "OutputPage:Compressed image to %d dwords, %d bits.\n",
  320. dwDwordsOut, dwBitsOut);
  321. if(!TiffStartPage(hTiffDest)) {
  322. fprintf(stderr, "OutputPage:Unable to open output page.\n");
  323. return FALSE; // We can't begin a page for some reason.
  324. if(lpOutBuf) free(lpOutBuf);
  325. if(lpdwOutCompressed) free(lpdwOutCompressed);
  326. }
  327. TiffWriteRaw(hTiffDest, (LPBYTE)lpdwOutCompressed,
  328. (dwDwordsOut + 1) * sizeof(DWORD));
  329. ((PTIFF_INSTANCE_DATA)hTiffDest)->Lines =
  330. (ULONG)((lpOutCur - lpOutBuf) / (FAX_IMAGE_WIDTH / 8));
  331. if(sViewInfo.yRes <= 100)
  332. ((PTIFF_INSTANCE_DATA)hTiffDest)->YResolution = 98;
  333. else
  334. ((PTIFF_INSTANCE_DATA)hTiffDest)->YResolution = 196;
  335. TiffEndPage(hTiffDest);
  336. // Now, move to a new page of the data.
  337. iCurPage++;
  338. if(iCurPage < sViewInfo.cPage) {
  339. ViewerSetPage(lpViewerContext, iCurPage);
  340. if(!ViewerGetBand(lpViewerContext, &bmBand)) {
  341. fprintf(stderr, "OutputPage:Unable to obtain image band.\n");
  342. goto output_exit; // Will return FALSE by default.
  343. }
  344. }
  345. }
  346. // Free memory.
  347. bRet = TRUE;
  348. output_exit:
  349. free(lpdwOutCompressed);
  350. free(lpOutBuf);
  351. free(bmBand.bmBits);
  352. return bRet;
  353. }