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
429 lines
14 KiB
/*++
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
This file contains the parts of the AWD library that are also TIFF-aware
|
|
(i.e., conversion routines).
|
|
|
|
Author:
|
|
Brian Dewey (t-briand) 1997-7-16
|
|
--*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ole2.h> // AWD is an OLE compound document.
|
|
#include <assert.h>
|
|
|
|
#include "awdlib.h" // Header file for this library.
|
|
#include "viewrend.h" // AWD rendering library.
|
|
#include "tifflibp.h" // Need this for the stolen compression routines.
|
|
|
|
// ------------------------------------------------------------
|
|
// Defines
|
|
#define FAX_IMAGE_WIDTH (1728)
|
|
|
|
// ------------------------------------------------------------
|
|
// Global variables
|
|
HANDLE hTiffDest; // Used in the internal OutputPage()
|
|
// and ConvertAWDToTiff().
|
|
|
|
// ------------------------------------------------------------
|
|
// Internal prototypes
|
|
BOOL
|
|
CompressBitmapStrip(
|
|
PBYTE pBrandBits,
|
|
LPDWORD pMmrBrandBits,
|
|
INT BrandHeight,
|
|
INT BrandWidth,
|
|
DWORD *DwordsOut,
|
|
DWORD *BitsOut
|
|
); // Routine stolen from tiff library.
|
|
// Used to be EncodeMmrBranding().
|
|
|
|
void
|
|
ConvertWidth(const LPBYTE lpSrc, DWORD dwSrcWidth,
|
|
LPBYTE lpDest, DWORD dwDestWidth,
|
|
DWORD dwHeight);
|
|
|
|
BOOL OutputPage(AWD_FILE *psStorages, const WCHAR *pwcsDocName);
|
|
|
|
// ------------------------------------------------------------
|
|
// Routines
|
|
|
|
// ConvertAWDToTiff
|
|
//
|
|
// This function does exactly what it says. Given the name of an AWD file, it
|
|
// attempts to convert it to a tiff file.
|
|
//
|
|
// Parameters:
|
|
// pwcsAwdFile name of the AWD file.
|
|
// pwcsTiffFile name of the TIFF file.
|
|
//
|
|
// Returns:
|
|
// TRUE on successful conversion, FALSE otherwise.
|
|
//
|
|
// Author:
|
|
// Brian Dewey (t-briand) 1997-7-14
|
|
BOOL
|
|
ConvertAWDToTiff(const WCHAR *pwcsAwdFile, WCHAR *pwcsTiffFile)
|
|
{
|
|
BOOL bRetVal; // Holds our return value.
|
|
AWD_FILE sAWDStorages; // Holds the main storages of the AWD file.
|
|
|
|
// Initialization.
|
|
HeapInitialize(NULL, NULL, NULL, NULL);
|
|
|
|
// Open the source.
|
|
if(!OpenAWDFile(pwcsAwdFile, &sAWDStorages)) {
|
|
return FALSE;
|
|
}
|
|
|
|
// Open the destination
|
|
hTiffDest = TiffCreate(pwcsTiffFile,
|
|
TIFF_COMPRESSION_MMR,
|
|
FAX_IMAGE_WIDTH,
|
|
2, // Fill order 2 == LSB2MSB (I think).
|
|
1); // HIRES
|
|
if(hTiffDest == NULL) {
|
|
CloseAWDFile(&sAWDStorages);
|
|
return FALSE;
|
|
}
|
|
bRetVal = EnumDocuments(&sAWDStorages, OutputPage);
|
|
CloseAWDFile(&sAWDStorages);
|
|
TiffClose(hTiffDest);
|
|
return bRetVal;
|
|
}
|
|
|
|
// CompressBitmapStrip
|
|
//
|
|
// Stolen from Tiff library, where it's called EncodeMmrBranding().
|
|
//
|
|
// Author: ???
|
|
BOOL
|
|
CompressBitmapStrip(
|
|
PBYTE pBrandBits,
|
|
LPDWORD pMmrBrandBits,
|
|
INT BrandHeight,
|
|
INT BrandWidth,
|
|
DWORD *DwordsOut,
|
|
DWORD *BitsOut
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Encode an MMR branding from uncompressed branding bits.
|
|
I don't have enough time to write an optimized
|
|
Uncompressed -> MMR convertor, so the compromise is
|
|
to use the existing Uncompressed Decoder (fast enough)
|
|
and use the optimized MMR Encoder.
|
|
Since we only convert few lines for Branding, it's OK.
|
|
|
|
--*/
|
|
|
|
{
|
|
INT a0, a1, a2, b1, b2, distance;
|
|
LPBYTE prefline;
|
|
BYTE pZeroline[1728/8];
|
|
INT delta = BrandWidth / BYTEBITS;
|
|
INT Lines = 0;
|
|
LPDWORD lpdwOut = pMmrBrandBits;
|
|
BYTE BitOut = 0;
|
|
|
|
|
|
|
|
#if TIFFDBG
|
|
_tprintf( TEXT("encoding line #%d\n"), TiffInstance->Lines );
|
|
#endif
|
|
|
|
|
|
// set first all white reference line
|
|
|
|
prefline = pZeroline;
|
|
|
|
ZeroMemory(pZeroline, BrandWidth/8);
|
|
|
|
// loop til all lines done
|
|
|
|
do {
|
|
|
|
a0 = 0;
|
|
a1 = GetBit( pBrandBits, 0) ? 0 : NextChangingElement(pBrandBits, 0, BrandWidth, 0 );
|
|
b1 = GetBit( prefline, 0) ? 0 : NextChangingElement(prefline, 0, BrandWidth, 0 );
|
|
|
|
while (TRUE) {
|
|
|
|
b2 = (b1 >= BrandWidth) ? BrandWidth :
|
|
NextChangingElement( prefline, b1, BrandWidth, GetBit(prefline, b1 ));
|
|
|
|
if (b2 < a1) {
|
|
|
|
//
|
|
// Pass mode
|
|
//
|
|
|
|
//OutputBits( TiffInstance, PASSCODE_LENGTH, PASSCODE );
|
|
(*lpdwOut) += ( ((DWORD) (PASSCODE_REVERSED)) << BitOut);
|
|
if ( (BitOut = BitOut + PASSCODE_LENGTH ) > 31 ) {
|
|
BitOut -= 32;
|
|
*(++lpdwOut) = ( (DWORD) (PASSCODE_REVERSED) ) >> (PASSCODE_LENGTH - BitOut);
|
|
}
|
|
|
|
|
|
#if TIFFDBG
|
|
PrintRunInfo( 1, 0, PASSCODE_LENGTH, PASSCODE );
|
|
_tprintf( TEXT("\t\ta0=%d, a1=%d, a2=%d, b1=%d, b2=%d\n"), a0, a1, a2, b1, b2 );
|
|
#endif
|
|
a0 = b2;
|
|
|
|
} else if ((distance = a1 - b1) <= 3 && distance >= -3) {
|
|
|
|
//
|
|
// Vertical mode
|
|
//
|
|
|
|
// OutputBits( TiffInstance, VertCodes[distance+3].length, VertCodes[distance+3].code );
|
|
(*lpdwOut) += ( ( (DWORD) VertCodesReversed[distance+3].code) << BitOut);
|
|
if ( (BitOut = BitOut + VertCodesReversed[distance+3].length ) > 31 ) {
|
|
BitOut -= 32;
|
|
*(++lpdwOut) = ( (DWORD) (VertCodesReversed[distance+3].code) ) >> (VertCodesReversed[distance+3].length - BitOut);
|
|
}
|
|
|
|
#if TIFFDBG
|
|
PrintRunInfo( 2, a1-a0, VertCodes[distance+3].length, VertCodes[distance+3].code );
|
|
_tprintf( TEXT("\t\ta0=%d, a1=%d, a2=%d, b1=%d, b2=%d\n"), a0, a1, a2, b1, b2 );
|
|
#endif
|
|
a0 = a1;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Horizontal mode
|
|
//
|
|
|
|
a2 = (a1 >= BrandWidth) ? BrandWidth :
|
|
NextChangingElement( pBrandBits, a1, BrandWidth, GetBit( pBrandBits, a1 ) );
|
|
|
|
// OutputBits( TiffInstance, HORZCODE_LENGTH, HORZCODE );
|
|
(*lpdwOut) += ( ((DWORD) (HORZCODE_REVERSED)) << BitOut);
|
|
if ( (BitOut = BitOut + HORZCODE_LENGTH ) > 31 ) {
|
|
BitOut -= 32;
|
|
*(++lpdwOut) = ( (DWORD) (HORZCODE_REVERSED) ) >> (HORZCODE_LENGTH - BitOut);
|
|
}
|
|
|
|
|
|
|
|
#if TIFFDBG
|
|
PrintRunInfo( 3, 0, HORZCODE_LENGTH, HORZCODE );
|
|
_tprintf( TEXT("\t\ta0=%d, a1=%d, a2=%d, b1=%d, b2=%d\n"), a0, a1, a2, b1, b2 );
|
|
#endif
|
|
|
|
if (a1 != 0 && GetBit( pBrandBits, a0 )) {
|
|
|
|
//OutputRun( TiffInstance, a1-a0, BlackRunCodes );
|
|
//OutputRun( TiffInstance, a2-a1, WhiteRunCodes );
|
|
OutputRunFastReversed(a1-a0, BLACK, &lpdwOut, &BitOut);
|
|
OutputRunFastReversed(a2-a1, WHITE, &lpdwOut, &BitOut);
|
|
|
|
} else {
|
|
|
|
//OutputRun( TiffInstance, a1-a0, WhiteRunCodes );
|
|
//OutputRun( TiffInstance, a2-a1, BlackRunCodes );
|
|
OutputRunFastReversed(a1-a0, WHITE, &lpdwOut, &BitOut);
|
|
OutputRunFastReversed(a2-a1, BLACK, &lpdwOut, &BitOut);
|
|
|
|
}
|
|
|
|
a0 = a2;
|
|
}
|
|
|
|
if (a0 >= BrandWidth) {
|
|
Lines++;
|
|
break;
|
|
}
|
|
|
|
a1 = NextChangingElement( pBrandBits, a0, BrandWidth, GetBit( pBrandBits, a0 ) );
|
|
b1 = NextChangingElement( prefline, a0, BrandWidth, !GetBit( pBrandBits, a0 ) );
|
|
b1 = NextChangingElement( prefline, b1, BrandWidth, GetBit( pBrandBits, a0 ) );
|
|
}
|
|
|
|
prefline = pBrandBits;
|
|
pBrandBits += (BrandWidth / 8);
|
|
|
|
} while (Lines < BrandHeight);
|
|
|
|
*DwordsOut = (DWORD)(lpdwOut - pMmrBrandBits);
|
|
*BitsOut = BitOut;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// ConvertWidth
|
|
//
|
|
// Changes the width of a bitmap. If the desired width is smaller than the current
|
|
// width, this is accomplished by truncating lines. If the desired width is greater
|
|
// than the current width, data will be copied up from the next line.
|
|
//
|
|
// Parameters:
|
|
// lpSrc Bitmap source.
|
|
// dwSrcWidth Its width.
|
|
// lpDest Pointer to destination.
|
|
// dwDestWidth Desired width of destination
|
|
// dwHeight Height of image (won't change).
|
|
//
|
|
// Returns:
|
|
// nothing.
|
|
//
|
|
// Author:
|
|
// Brian Dewey (t-briand) 1997-7-10
|
|
void
|
|
ConvertWidth(const LPBYTE lpSrc, DWORD dwSrcWidth,
|
|
LPBYTE lpDest, DWORD dwDestWidth,
|
|
DWORD dwHeight)
|
|
{
|
|
LPBYTE lpSrcCur, lpDestCur;
|
|
DWORD dwCurLine;
|
|
|
|
for(lpSrcCur = lpSrc, lpDestCur = lpDest, dwCurLine = 0;
|
|
dwCurLine < dwHeight;
|
|
lpSrcCur += dwSrcWidth, lpDestCur += dwDestWidth, dwCurLine++) {
|
|
memcpy(lpDestCur, lpSrcCur, dwDestWidth);
|
|
}
|
|
}
|
|
|
|
// OutputPage
|
|
//
|
|
// This is the core of the converter; it takes a single AWD page and writes it
|
|
// to the TIFF file.
|
|
//
|
|
// Parameters:
|
|
// psStorages Pointer to the AWD file from which we read.
|
|
// pwcsDocName Name of the page.
|
|
//
|
|
// Returns:
|
|
// TRUE on success, FALSE on failure.
|
|
//
|
|
// Author:
|
|
// Brian Dewey (t-briand) 1997-7-2
|
|
BOOL
|
|
OutputPage(AWD_FILE *psStorages, const WCHAR *pwcsDocName)
|
|
{
|
|
BITMAP bmBand; // A band of image data.
|
|
LPBYTE lpOutBuf; // Output bitmap (resized).
|
|
LPBYTE lpOutCur; // Used to write one line at a time.
|
|
LPDWORD lpdwOutCompressed; // Compressed output.
|
|
DWORD dwDwordsOut, // Number of DWORDS in compressed output...
|
|
dwBitsOut = 0; // Number of bits in compressed output.
|
|
DWORD dwBitsOutOld = 0; // BitsOut from the *previous* band compression.
|
|
LPVOID lpViewerContext; // The viewer context; used by viewrend library.
|
|
VIEWINFO sViewInfo; // Information about the image.
|
|
WORD awResolution[2], // Holds X & Y resolutions
|
|
wBandSize = 256; // Desired band size; will be reset by ViewerOpen.
|
|
IStream *psDocument; // Our document stream.
|
|
BOOL bRet = FALSE; // Return value; FALSE by default.
|
|
UINT iCurPage; // Current page.
|
|
const DWORD dwMagicHeight = 3000; // FIXBKD
|
|
|
|
if((psDocument = OpenAWDStream(psStorages->psDocuments, pwcsDocName)) == NULL) {
|
|
fwprintf(stderr, L"OutputPage:Unable to open stream '%s'.\n",
|
|
pwcsDocName);
|
|
return FALSE; // We failed.
|
|
}
|
|
// Now, open a viewer context and start reading bands of the image.
|
|
if((lpViewerContext = ViewerOpen(psDocument,
|
|
HRAW_DATA,
|
|
awResolution,
|
|
&wBandSize,
|
|
&sViewInfo)) == NULL) {
|
|
fprintf(stderr, "OutputPage:Unable to open viewer context.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
iCurPage = 0; // Initialize our counter.
|
|
|
|
bmBand.bmBits = malloc(wBandSize); // Allocate memory to hold the band.
|
|
if(!ViewerGetBand(lpViewerContext, &bmBand)) {
|
|
fprintf(stderr, "OutputPage:Unable to obtain image band.\n");
|
|
return FALSE;
|
|
}
|
|
// lpOutBuf = malloc(bmBand.bmHeight * (FAX_IMAGE_WIDTH / 8));
|
|
lpOutBuf = malloc(dwMagicHeight * (FAX_IMAGE_WIDTH / 8));
|
|
// Provided compression actually *compresses*, we should have more than
|
|
// enough memory allocated.
|
|
lpdwOutCompressed = malloc(dwMagicHeight * (FAX_IMAGE_WIDTH / 8));
|
|
|
|
if(!lpOutBuf || !lpdwOutCompressed) {
|
|
// check whether we are short in memory
|
|
TiffEndPage(hTiffDest);
|
|
if(lpOutBuf) free(lpOutBuf);
|
|
if(lpdwOutCompressed) free(lpdwOutCompressed);
|
|
return FALSE; // This will stop the conversion process.
|
|
}
|
|
|
|
memset(lpOutBuf, '\0', dwMagicHeight * (FAX_IMAGE_WIDTH / 8));
|
|
memset(lpdwOutCompressed, '\0', dwMagicHeight * (FAX_IMAGE_WIDTH / 8));
|
|
|
|
|
|
// Main loop
|
|
while(iCurPage < sViewInfo.cPage) {
|
|
lpOutCur = lpOutBuf;
|
|
while(bmBand.bmHeight) {
|
|
// Make sure our bitmap has FAX_IMAGE_WIDTH as its width.
|
|
ConvertWidth(bmBand.bmBits, bmBand.bmWidth / 8,
|
|
lpOutCur, FAX_IMAGE_WIDTH / 8,
|
|
bmBand.bmHeight);
|
|
lpOutCur += (bmBand.bmHeight * (FAX_IMAGE_WIDTH / 8));
|
|
|
|
if(!ViewerGetBand(lpViewerContext, &bmBand)) {
|
|
fprintf(stderr, "OutputPage:Unable to obtain image band.\n");
|
|
goto output_exit; // Will return FALSE by default.
|
|
}
|
|
} // while (wasn't that easy?)
|
|
|
|
memset(lpdwOutCompressed, '\0', dwMagicHeight * (FAX_IMAGE_WIDTH / 8));
|
|
CompressBitmapStrip(lpOutBuf,
|
|
lpdwOutCompressed,
|
|
(ULONG)((lpOutCur - lpOutBuf) / (FAX_IMAGE_WIDTH / 8)),
|
|
FAX_IMAGE_WIDTH,
|
|
&dwDwordsOut,
|
|
&dwBitsOut);
|
|
memset(lpOutBuf, '\0', dwMagicHeight * (FAX_IMAGE_WIDTH / 8));
|
|
fprintf(stderr, "OutputPage:Compressed image to %d dwords, %d bits.\n",
|
|
dwDwordsOut, dwBitsOut);
|
|
|
|
if(!TiffStartPage(hTiffDest)) {
|
|
fprintf(stderr, "OutputPage:Unable to open output page.\n");
|
|
return FALSE; // We can't begin a page for some reason.
|
|
if(lpOutBuf) free(lpOutBuf);
|
|
if(lpdwOutCompressed) free(lpdwOutCompressed);
|
|
}
|
|
TiffWriteRaw(hTiffDest, (LPBYTE)lpdwOutCompressed,
|
|
(dwDwordsOut + 1) * sizeof(DWORD));
|
|
((PTIFF_INSTANCE_DATA)hTiffDest)->Lines =
|
|
(ULONG)((lpOutCur - lpOutBuf) / (FAX_IMAGE_WIDTH / 8));
|
|
if(sViewInfo.yRes <= 100)
|
|
((PTIFF_INSTANCE_DATA)hTiffDest)->YResolution = 98;
|
|
else
|
|
((PTIFF_INSTANCE_DATA)hTiffDest)->YResolution = 196;
|
|
TiffEndPage(hTiffDest);
|
|
|
|
// Now, move to a new page of the data.
|
|
iCurPage++;
|
|
if(iCurPage < sViewInfo.cPage) {
|
|
ViewerSetPage(lpViewerContext, iCurPage);
|
|
if(!ViewerGetBand(lpViewerContext, &bmBand)) {
|
|
fprintf(stderr, "OutputPage:Unable to obtain image band.\n");
|
|
goto output_exit; // Will return FALSE by default.
|
|
}
|
|
}
|
|
}
|
|
|
|
// Free memory.
|
|
bRet = TRUE;
|
|
output_exit:
|
|
free(lpdwOutCompressed);
|
|
free(lpOutBuf);
|
|
free(bmBand.bmBits);
|
|
return bRet;
|
|
}
|
|
|