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.
 
 
 
 
 
 

963 lines
23 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
decode.c
Abstract:
This file contains functions for decoding (de-compressing)
compressed 1 bit per pel data from a TIFF data
stream. The supported compression algorithms are
as follows:
o Uncompressed (raw)
o One dimensional - MH or Modified Huffman
o Two dimensional - MR or Modified Read
Environment:
WIN32 User Mode
Author:
Wesley Witt (wesw) 17-Feb-1996
--*/
#include "tifflibp.h"
#pragma hdrstop
BOOL
DecodeUnCompressedFaxData(
PTIFF_INSTANCE_DATA TiffInstance,
LPBYTE OutputBuffer,
BOOL SingleLineBuffer,
DWORD PadLength
)
/*++
Routine Description:
Decode a single page of uncompressed TIFF data.
Arguments:
TiffInstance - Pointer to the TIFF instance data
OutputBuffer - Output buffer where the uncompressed data
is written. This buffer must be allocated
by the caller and must be large enough for
a single page of data.
Return Value:
NONE
--*/
{
__try {
FillMemory( OutputBuffer, TiffInstance->ImageHeight * (TiffInstance->ImageWidth / 8), WHITE );
} __except (EXCEPTION_EXECUTE_HANDLER) {
return FALSE;
}
TiffInstance->Lines = TiffInstance->StripDataSize / (TiffInstance->ImageWidth / 8);
CopyMemory( OutputBuffer, TiffInstance->StripData, TiffInstance->StripDataSize );
return TRUE;
}
BOOL
DecodeMHFaxData(
PTIFF_INSTANCE_DATA TiffInstance,
LPBYTE OutputBuffer,
BOOL SingleLineBuffer,
DWORD PadLength
)
/*++
Routine Description:
Decode a single page of 1 dimensionaly compressed
TIFF data.
Arguments:
TiffInstance - Pointer to the TIFF instance data
OutputBuffer - Output buffer where the uncompressed data
is written. This buffer must be allocated
by the caller and must be large enough for
a single page of data.
Return Value:
NONE
--*/
{
DWORD i;
DWORD j;
BYTE octet;
PDECODE_TREE Tree;
INT code;
PBYTE plinebuf;
DWORD lineWidth;
DWORD Lines;
DWORD EolCount;
DWORD BadFaxLines;
BOOL LastLineBad;
//
// initialization
//
if (!SingleLineBuffer) {
__try {
FillMemory( OutputBuffer, TiffInstance->ImageHeight * (TiffInstance->ImageWidth / 8), WHITE );
} __except (EXCEPTION_EXECUTE_HANDLER) {
return FALSE;
}
}
Tree = WhiteDecodeTree;
code = 0;
Lines = 0;
EolCount = 1;
BadFaxLines = 0;
LastLineBad = FALSE;
TiffInstance->Color = 0;
TiffInstance->RunLength = 0;
TiffInstance->bitdata = 0;
TiffInstance->bitcnt = DWORDBITS;
TiffInstance->bitbuf = OutputBuffer;
TiffInstance->StartGood = 0;
TiffInstance->EndGood = 0;
plinebuf = TiffInstance->StripData;
lineWidth = TiffInstance->ImageWidth;
for (i=0; i<TiffInstance->StripDataSize; i++) {
if (plinebuf[i] == 0) {
break;
}
}
//
// loop thru each byte in the file
//
for (; i<TiffInstance->StripDataSize; i++) {
octet = plinebuf[i];
if (i == 2147) DebugBreak();
//
// loop thru each bit in the byte
//
for (j=0; j<8; j++,octet<<=1) {
if (code == DECODEEOL) {
if (!(octet&0x80)) {
//
// here we skip all bits until we hit a 1 bit
// this happens when the first octet in a line
// is all zeroes and we detect that we are
// searching for an EOL
//
continue;
}
if (TiffInstance->RunLength && TiffInstance->RunLength != lineWidth) {
if (TiffInstance->RunLength < lineWidth) {
TiffInstance->Color = 0;
OutputCodeBits( TiffInstance, lineWidth - TiffInstance->RunLength );
}
if (LastLineBad) {
BadFaxLines += 1;
} else {
if (BadFaxLines > TiffInstance->BadFaxLines) {
TiffInstance->BadFaxLines = BadFaxLines;
}
BadFaxLines = 1;
LastLineBad = TRUE;
}
} else {
LastLineBad = FALSE;
}
if (!TiffInstance->StartGood) {
TiffInstance->StartGood = i - 1;
}
//
// we hit the eol marker
//
Tree = WhiteDecodeTree;
TiffInstance->Color = 0;
code = 0;
if (SingleLineBuffer) {
TiffInstance->bitbuf = OutputBuffer;
}
if (TiffInstance->RunLength) {
FlushLine(TiffInstance,PadLength);
TiffInstance->RunLength = 0;
Lines += 1;
EolCount = 1;
} else {
//
// the eol count is maintained to that
// an rtc sequence is detected.
//
EolCount += 1;
if (EolCount == 6) {
//
// this is an rtc sequence, so any
// data that follows in the file
// is garbage.
//
goto good_exit;
}
}
continue;
}
code = ((octet&0x80)>>7) ? Tree[code].Right : Tree[code].Left;
if (code == BADRUN) {
return FALSE;
}
if (code < 1) {
code = (-code);
OutputCodeBits( TiffInstance, code );
if (code < 64) {
//
// terminating code
//
TiffInstance->Color = !TiffInstance->Color;
Tree = TiffInstance->Color ? BlackDecodeTree : WhiteDecodeTree;
}
code = 0;
}
}
}
good_exit:
TiffInstance->EndGood = i;
if (BadFaxLines > TiffInstance->BadFaxLines) {
TiffInstance->BadFaxLines = BadFaxLines;
}
FlushBits( TiffInstance );
TiffInstance->Lines = Lines;
return TRUE;
}
BOOL
DecodeMRFaxData(
PTIFF_INSTANCE_DATA TiffInstance,
LPBYTE OutputBuffer,
BOOL SingleLineBuffer,
DWORD PadLength
)
/*++
Routine Description:
Decode a single page of 2 dimensionaly compressed
TIFF data.
Arguments:
TiffInstance - Pointer to the TIFF instance data
OutputBuffer - Output buffer where the uncompressed data
is written. This buffer must be allocated
by the caller and must be large enough for
a single page of data.
Return Value:
NONE
--*/
{
DWORD i;
DWORD j;
BYTE octet;
PDECODE_TREE Tree;
INT code;
LPBYTE prefline;
LPBYTE pcurrline;
DWORD HorzRuns;
BOOL OneDimensional;
DWORD a0;
DWORD a1;
DWORD b1;
DWORD b2;
PBYTE plinebuf;
DWORD lineWidth;
DWORD Lines;
DWORD EolCount;
DWORD BadFaxLines;
BOOL LastLineBad;
//
// initialization
//
if (!SingleLineBuffer) {
__try {
FillMemory( OutputBuffer, TiffInstance->ImageHeight * (TiffInstance->ImageWidth / 8), WHITE );
} __except (EXCEPTION_EXECUTE_HANDLER) {
return FALSE;
}
}
Tree = WhiteDecodeTree;
code = 0;
HorzRuns = 0;
EolCount = 1;
BadFaxLines = 0;
LastLineBad = FALSE;
TiffInstance->Color = 0;
TiffInstance->RunLength = 0;
TiffInstance->bitdata = 0;
TiffInstance->bitcnt = DWORDBITS;
TiffInstance->bitbuf = OutputBuffer;
OneDimensional = TRUE;
plinebuf = TiffInstance->StripData;
lineWidth = TiffInstance->ImageWidth;
pcurrline = OutputBuffer;
prefline = OutputBuffer;
a0 = 0;
a1 = 0;
b1 = 0;
b2 = 0;
Lines = 0;
//
// loop thru each byte in the file
//
for (j=0; j<TiffInstance->StripDataSize; j++) {
octet = *plinebuf++;
//
// loop thru each bit in the byte
//
for (i=0; i<8; i++,octet<<=1) {
if (code == DECODEEOL2) {
//
// we hit the final eol marker
//
if (TiffInstance->RunLength && TiffInstance->RunLength != lineWidth) {
if (TiffInstance->RunLength < lineWidth) {
TiffInstance->Color = 0;
OutputCodeBits( TiffInstance, lineWidth - TiffInstance->RunLength );
}
if (LastLineBad) {
BadFaxLines += 1;
} else {
if (BadFaxLines > TiffInstance->BadFaxLines) {
TiffInstance->BadFaxLines = BadFaxLines;
}
BadFaxLines = 1;
LastLineBad = TRUE;
}
} else {
LastLineBad = FALSE;
}
if (!TiffInstance->StartGood) {
TiffInstance->StartGood = i - 1;
}
//
// set the decoding tree
//
OneDimensional = (octet & 0x80) == 0x80;
Tree = OneDimensional ? WhiteDecodeTree : TwoDecodeTree;
//
// reset the control variables
//
TiffInstance->Color = 0;
code = 0;
a0 = 0;
a1 = 0;
b1 = 0;
b2 = 0;
//
// if there is a non-zero runlength then
// spaw the reference & current line pointers
// and count this line. the runlength can be
// zero when there is just an empty eol in
// the stream.
//
if (SingleLineBuffer) {
TiffInstance->bitbuf = OutputBuffer;
}
if (TiffInstance->RunLength) {
TiffInstance->RunLength = 0;
Lines += 1;
prefline = pcurrline;
pcurrline = TiffInstance->bitbuf;
} else {
//
// the eol count is maintained to that
// an rtc sequence is detected.
//
EolCount += 1;
if (EolCount == 6) {
//
// this is an rtc sequence, so any
// data that follows in the file
// is garbage.
//
goto good_exit;
}
}
continue;
}
if (code == DECODEEOL) {
if (!(octet&0x80)) {
//
// here we skip all bits until we hit a 1 bit
// this happens when the first octet in a line
// is all zeroes and we detect that we are
// searching for an EOL
//
continue;
}
//
// this forces the code to pickup the next
// bit in the stream, which tells whether
// the next line is encoded in MH or MR compression
//
code = DECODEEOL2;
continue;
}
if (code == BADRUN) {
code = 0;
continue;
}
code = ((octet&0x80)>>7) ? Tree[code].Right : Tree[code].Left;
b1 = NextChangingElement( prefline, a0, lineWidth, !TiffInstance->Color );
b1 = NextChangingElement( prefline, b1, lineWidth, TiffInstance->Color );
b2 = NextChangingElement( prefline, b1, lineWidth, GetBit(prefline, b1 ) );
if (OneDimensional) {
if (code < 1) {
code = (-code);
OutputCodeBits( TiffInstance, code );
//
// the affect of this is to accumulate the runlengths
// into a0, causing a0 to be placed on a2 when horizontal
// mode is completed/
//
a0 += code;
if (code < 64) {
//
// terminating code
//
TiffInstance->Color = !TiffInstance->Color;
Tree = TiffInstance->Color ? BlackDecodeTree : WhiteDecodeTree;
if (HorzRuns) {
HorzRuns -= 1;
if (!HorzRuns) {
Tree = TwoDecodeTree;
OneDimensional = FALSE;
}
}
}
code = 0;
}
continue;
}
if (code == HORZMODE) {
//
// horizontal mode occurs when b1-a1 greater than 3
//
code= 0;
HorzRuns = 2;
OneDimensional = TRUE;
Tree = TiffInstance->Color ? BlackDecodeTree : WhiteDecodeTree;
} else if (code == PASSMODE) {
//
// pass mode occurs when the position of b2 lies
// to the left of a1, but a1 cannot be equal to b2.
//
code = b2 - a0;
OutputCodeBits( TiffInstance, code );
code = 0;
a0 = b2;
} else if (code >= VTMODE3N && code <= VTMODE3P) {
//
// vertical mode occurs when b1-a1 <= 3
//
a1 = b1 - (VTMODE0 - code);
code = a1 - a0;
OutputCodeBits( TiffInstance, code );
code = 0;
a0 = a1;
TiffInstance->Color = !TiffInstance->Color;
}
}
}
good_exit:
TiffInstance->EndGood = i;
if (BadFaxLines > TiffInstance->BadFaxLines) {
TiffInstance->BadFaxLines = BadFaxLines;
}
FlushBits( TiffInstance );
TiffInstance->Lines = Lines;
return TRUE;
}
BOOL
DecodeMMRFaxData(
PTIFF_INSTANCE_DATA TiffInstance,
LPBYTE OutputBuffer,
BOOL SingleLineBuffer,
DWORD PadLength
)
/*++
Routine Description:
Decode a single page of 2 dimensionaly compressed
TIFF data.
Arguments:
TiffInstance - Pointer to the TIFF instance data
OutputBuffer - Output buffer where the uncompressed data
is written. This buffer must be allocated
by the caller and must be large enough for
a single page of data.
Return Value:
NONE
--*/
{
DWORD i;
DWORD j;
BYTE octet;
PDECODE_TREE Tree;
INT code;
LPBYTE prefline;
LPBYTE pcurrline;
DWORD HorzRuns;
BOOL OneDimensional;
DWORD a0;
DWORD a1;
DWORD b1;
DWORD b2;
PBYTE plinebuf;
DWORD lineWidth;
DWORD Lines;
DWORD EolCount;
//
// initialization
//
if (!SingleLineBuffer) {
__try {
FillMemory( OutputBuffer, TiffInstance->ImageHeight * (TiffInstance->ImageWidth / 8), WHITE );
} __except (EXCEPTION_EXECUTE_HANDLER) {
return FALSE;
}
}
Tree = TwoDecodeTree;
code = 0;
HorzRuns = 0;
EolCount = 0;
TiffInstance->Color = 0;
TiffInstance->RunLength = 0;
TiffInstance->bitdata = 0;
TiffInstance->bitcnt = DWORDBITS;
TiffInstance->bitbuf = OutputBuffer;
OneDimensional = FALSE;
plinebuf = TiffInstance->StripData;
lineWidth = TiffInstance->ImageWidth;
pcurrline = OutputBuffer;
prefline = OutputBuffer;
a0 = 0;
a1 = 0;
b1 = 0;
b2 = 0;
Lines = 0;
//
// loop thru each byte in the file
//
for (j=0; j<TiffInstance->StripDataSize; j++) {
octet = *plinebuf++;
//
// loop thru each bit in the byte
//
for (i=0; i<8; i++,octet<<=1) {
if (Lines + 1 == TiffInstance->ImageHeight && TiffInstance->RunLength == lineWidth)
{
goto good_exit;
}
//
// if the OneDimensional flag is set and the RunLength == lineWidth
// then it means that the last run length was horizontal mode
// and it was not a terminating code. in this case we must go
// process the remaining termination code before ending the line.
//
// if the OneDimensional flag is NOT set and the RunLength == lineWidth
// then we are at the end of a line. for mmr compression there are
// no eols, so this is the pseudo eol.
//
if ((TiffInstance->RunLength == lineWidth) && (!OneDimensional)) {
//
// set the decoding tree
//
Tree = TwoDecodeTree;
//
// reset the control variables
//
TiffInstance->Color = 0;
code = 0;
a0 = 0;
a1 = 0;
b1 = 0;
b2 = 0;
Tree = TwoDecodeTree;
OneDimensional = FALSE;
//
// if there is a non-zero runlength then
// spaw the reference & current line pointers
// and count this line. the runlength can be
// zero when there is just an empty eol in
// the stream.
//
if (SingleLineBuffer) {
TiffInstance->bitbuf = OutputBuffer;
}
TiffInstance->RunLength = 0;
Lines += 1;
prefline = pcurrline;
pcurrline = TiffInstance->bitbuf;
b1 = GetBit(prefline, 0) ? 0 : NextChangingElement(prefline, 0, lineWidth, 0);
} else if (code == DECODEEOL2) {
//
// the eol count is maintained to that
// an rtc sequence is detected.
//
EolCount += 1;
if (EolCount == 2) {
//
// this is an rtc sequence, so any
// data that follows in the file
// is garbage.
//
goto good_exit;
}
continue;
} else if (code == DECODEEOL) {
if (!(octet&0x80)) {
//
// here we skip all bits until we hit a 1 bit
// this happens when the first octet in a line
// is all zeroes and we detect that we are
// searching for an EOL
//
continue;
}
//
// this forces the code to pickup the next
// bit in the stream, which tells whether
// the next line is encoded in MH or MR compression
//
code = DECODEEOL2;
continue;
} else if (code == BADRUN) {
code = 0;
continue;
} else {
b1 = NextChangingElement( prefline, a0, lineWidth, !TiffInstance->Color );
b1 = NextChangingElement( prefline, b1, lineWidth, TiffInstance->Color );
}
b2 = NextChangingElement( prefline, b1, lineWidth, GetBit(prefline, b1 ) );
code = ((octet&0x80)>>7) ? Tree[code].Right : Tree[code].Left;
if (OneDimensional) {
if (code < 1) {
code = (-code);
OutputCodeBits( TiffInstance, code );
//
// the affect of this is to accumulate the runlengths
// into a0, causing a0 to be placed on a2 when horizontal
// mode is completed/
//
a0 += code;
if (code < 64) {
//
// terminating code
//
TiffInstance->Color = !TiffInstance->Color;
Tree = TiffInstance->Color ? BlackDecodeTree : WhiteDecodeTree;
if (HorzRuns) {
HorzRuns -= 1;
if (!HorzRuns) {
Tree = TwoDecodeTree;
OneDimensional = FALSE;
}
}
}
code = 0;
}
continue;
}
if (code == HORZMODE) {
//
// horizontal mode occurs when b1-a1 greater than 3
//
code= 0;
HorzRuns = 2;
OneDimensional = TRUE;
Tree = TiffInstance->Color ? BlackDecodeTree : WhiteDecodeTree;
} else if (code == PASSMODE) {
//
// pass mode occurs when the position of b2 lies
// to the left of a1, but a1 cannot be equal to b2.
//
code = b2 - a0;
OutputCodeBits( TiffInstance, code );
code = 0;
a0 = b2;
} else if (code >= VTMODE3N && code <= VTMODE3P) {
//
// vertical mode occurs when b1-a1 <= 3
//
a1 = b1 - (VTMODE0 - code);
code = a1 - a0;
OutputCodeBits( TiffInstance, code );
code = 0;
a0 = a1;
TiffInstance->Color = !TiffInstance->Color;
}
}
}
good_exit:
FlushBits( TiffInstance );
TiffInstance->Lines = Lines;
return TRUE;
}