mirror of https://github.com/lianthony/NT4.0
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.
1225 lines
28 KiB
1225 lines
28 KiB
/*++
|
|
|
|
Copyright (c) 1990-1993 Microsoft Corporation
|
|
|
|
|
|
Module Name:
|
|
|
|
compress.c
|
|
|
|
|
|
Abstract:
|
|
|
|
This module contains all data compression functions
|
|
|
|
|
|
Author:
|
|
|
|
18-Feb-1994 Fri 09:50:08 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
[Environment:]
|
|
|
|
GDI Device Driver - Plotter.
|
|
|
|
|
|
[Notes:]
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#define DBG_PLOTFILENAME DbgCompress
|
|
|
|
#define DBG_TIFF 0x00000001
|
|
#define DBG_DELTA 0x00000002
|
|
#define DBG_COMPRESS 0x00000004
|
|
#define DBG_OUTRTLSCAN 0x00000008
|
|
#define DBG_FLUSHADAPTBUF 0x00000010
|
|
#define DBG_ENTERRTLSCANS 0x00000020
|
|
#define DBG_DELTA_OFFSET0 0x00000040
|
|
#define DBG_NO_DELTA 0x40000000
|
|
#define DBG_NO_TIFF 0x80000000
|
|
|
|
DEFINE_DBGVAR(0);
|
|
|
|
|
|
#define TIFF_MIN_REPEATS 3
|
|
#define TIFF_MAX_REPEATS 128
|
|
#define TIFF_MAX_LITERAL 128
|
|
#define DELTA_MAX_ONE_REPLACE 8
|
|
#define DELTA_MAX_1ST_OFFSET 31
|
|
#define MIN_BLOCK_MODE_SIZE 8
|
|
|
|
//
|
|
// The MAX_ADAPT_SIZE is used to leave room for SET_ADAPT_CONTROL
|
|
//
|
|
|
|
#if (OUTPUT_BUFFER_SIZE >= (1024 * 32))
|
|
#define MAX_ADAPT_SIZE ((1024 * 32) - 16)
|
|
#else
|
|
#define MAX_ADAPT_SIZE (OUTPUT_BUFFER_SIZE - 16)
|
|
#endif
|
|
|
|
|
|
#define ADAPT_METHOD_ZERO 4
|
|
#define ADAPT_METHOD_DUP 5
|
|
|
|
#define SIZE_ADAPT_CONTROL 3
|
|
|
|
#define SET_ADAPT_CONTROL(pPDev, m, c) \
|
|
{ \
|
|
BYTE bAdaptCtrl[4]; \
|
|
\
|
|
bAdaptCtrl[0] = (BYTE)(m); \
|
|
bAdaptCtrl[1] = (BYTE)(((c) >> 8) & 0xFF); \
|
|
bAdaptCtrl[2] = (BYTE)(((c) ) & 0xFF); \
|
|
OutputBytes(pPDev, bAdaptCtrl, 3); \
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
FlushAdaptBuf(
|
|
PPDEV pPDev,
|
|
PRTLSCANS pRTLScans,
|
|
BOOL FlushEmptyDup
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function flush out the adaptive mode buffer
|
|
|
|
Arguments:
|
|
|
|
pPDev - Pointer to our PDEV
|
|
|
|
pRTLScans - Pointer to the RTLSCANS data structure
|
|
|
|
FlushEmptyDup - TRUE if cEmptyDup need to be flush out also
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE if OK,
|
|
|
|
Author:
|
|
|
|
09-Mar-1994 Wed 20:32:31 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD Count;
|
|
WORD cEmptyDup;
|
|
BOOL Ok = TRUE;
|
|
|
|
|
|
Count = pPDev->cbBufferBytes;
|
|
|
|
if (cEmptyDup = (FlushEmptyDup) ? pRTLScans->cEmptyDup : 0) {
|
|
|
|
Count += SIZE_ADAPT_CONTROL;
|
|
}
|
|
|
|
if (Count) {
|
|
|
|
DWORD cbBufferBytes;
|
|
BYTE TmpBuf[32];
|
|
|
|
|
|
PLOTDBG(DBG_FLUSHADAPTBUF, ("FlushAdaptBuf: Flush total %ld byte block",
|
|
Count));
|
|
|
|
//====================================================================
|
|
// SAVE the OutputBuffer for this temporary header
|
|
//====================================================================
|
|
|
|
CopyMemory(TmpBuf, pPDev->pOutBuffer, sizeof(TmpBuf));
|
|
|
|
cbBufferBytes = pPDev->cbBufferBytes;
|
|
pPDev->cbBufferBytes = 0;
|
|
|
|
//
|
|
// Now output the header
|
|
//
|
|
|
|
OutputBytes(pPDev, "\033*b", 3);
|
|
|
|
if (!pRTLScans->cAdaptBlk) {
|
|
|
|
pRTLScans->cAdaptBlk++;
|
|
OutputBytes(pPDev, "5m", 2);
|
|
}
|
|
|
|
OutputFormatStr(pPDev, "#dW", Count);
|
|
|
|
//====================================================================
|
|
// FLUSH OUTPUT BUFFER AND RESTORE BACK the OutputBuffer for this
|
|
// temporary header
|
|
//====================================================================
|
|
|
|
PLOTDBG(DBG_FLUSHADAPTBUF, ("FlushAdaptBuf: Flush TmpBuf[%ld] bytes of HEADER",
|
|
pPDev->cbBufferBytes));
|
|
|
|
FlushOutBuffer(pPDev);
|
|
|
|
CopyMemory(pPDev->pOutBuffer, TmpBuf, sizeof(TmpBuf));
|
|
pPDev->cbBufferBytes = cbBufferBytes;
|
|
|
|
if (cEmptyDup) {
|
|
|
|
PLOTDBG(DBG_FLUSHADAPTBUF, ("FlushAdaptBuf: Add %ld EmptyDup [%ld]",
|
|
(DWORD)cEmptyDup, (DWORD)pRTLScans->AdaptMethod));
|
|
|
|
SET_ADAPT_CONTROL(pPDev, pRTLScans->AdaptMethod, cEmptyDup);
|
|
|
|
pRTLScans->cEmptyDup = 0;
|
|
}
|
|
|
|
Ok = FlushOutBuffer(pPDev);
|
|
|
|
//
|
|
// After the block been sent the seed row is back to zero
|
|
//
|
|
|
|
ZeroMemory(pRTLScans->pbSeedRows[0],
|
|
(DWORD)pRTLScans->cxBytes * (DWORD)pRTLScans->Planes);
|
|
}
|
|
|
|
return(Ok);
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
ExitRTLScans(
|
|
PPDEV pPDev,
|
|
PRTLSCANS pRTLScans
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function initialize the RTLSCANS structure and decideds what compress
|
|
mode will be the best
|
|
|
|
Arguments:
|
|
|
|
pPDev - Pointer to our PDEV
|
|
|
|
pRTLScans - Pointer to the RTLSCANS data structure to be initialized
|
|
|
|
cxSize - Width of pixel per scans
|
|
|
|
Return Value:
|
|
|
|
TRUE if sucessful, FALSE if failed
|
|
|
|
Author:
|
|
|
|
22-Feb-1994 Tue 12:14:17 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
if (pRTLScans->CompressMode == COMPRESS_MODE_ADAPT) {
|
|
|
|
FlushAdaptBuf(pPDev, pRTLScans, TRUE);
|
|
}
|
|
|
|
if (pRTLScans->pbCompress) {
|
|
|
|
LocalFree(pRTLScans->pbCompress);
|
|
}
|
|
|
|
ZeroMemory(pRTLScans, sizeof(RTLSCANS));
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
EnterRTLScans(
|
|
PPDEV pPDev,
|
|
PRTLSCANS pRTLScans,
|
|
DWORD cx,
|
|
DWORD cy,
|
|
BOOL MonoBmp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function initialize the RTLSCANS structure and decideds what compress
|
|
mode will be the best
|
|
|
|
Arguments:
|
|
|
|
pPDev - Pointer to our PDEV
|
|
|
|
pRTLScans - Pointer to the RTLSCANS data structure to be initialized
|
|
|
|
cxSize - Width of pixel per scans
|
|
|
|
Return Value:
|
|
|
|
TRUE if sucessful, FALSE if failed
|
|
|
|
Author:
|
|
|
|
22-Feb-1994 Tue 12:14:17 created -by- Daniel Chou (danielc)
|
|
|
|
11-Mar-1994 Fri 19:23:34 updated -by- Daniel Chou (danielc)
|
|
Only flush the output buffer if we are really in ADAPTIVE mode
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
RTLSCANS RTLScans;
|
|
DWORD AllocSize;
|
|
DWORD MinBlkSize;
|
|
|
|
|
|
RTLScans.Flags = (RTLScans.cScans = cy) ? RTLSF_MORE_SCAN : 0;
|
|
RTLScans.pbCompress =
|
|
RTLScans.pbSeedRows[0] =
|
|
RTLScans.pbSeedRows[1] =
|
|
RTLScans.pbSeedRows[2] = NULL;
|
|
RTLScans.cEmptyDup = 0;
|
|
RTLScans.AdaptMethod = 0xFF;
|
|
RTLScans.cAdaptBlk = 0;
|
|
RTLScans.cxBytes = (DWORD)((cx + 7) >> 3);
|
|
RTLScans.CompressMode = COMPRESS_MODE_ROW;
|
|
RTLScans.MaxAdaptBufSize = MAX_ADAPT_SIZE;
|
|
|
|
if (!(RTLScans.Mask = (BYTE)(~(0xFF >> (cx & 0x07))))) {
|
|
|
|
//
|
|
// Exact at byte boundary
|
|
//
|
|
|
|
RTLScans.Mask = 0xFF;
|
|
}
|
|
|
|
MinBlkSize = 8;
|
|
|
|
if (MonoBmp) {
|
|
|
|
RTLScans.Planes = 1;
|
|
AllocSize = (DWORD)(RTLScans.cxBytes << 1);
|
|
|
|
if (RTLMONOENCODE_5(pPDev)) {
|
|
|
|
PLOTDBG(DBG_ENTERRTLSCANS, ("EnterRTLScans: Using Adaptive Mode Compression"));
|
|
|
|
RTLScans.CompressMode = COMPRESS_MODE_ADAPT;
|
|
MinBlkSize = 4;
|
|
}
|
|
|
|
} else {
|
|
|
|
RTLScans.Planes = 3;
|
|
AllocSize = (DWORD)(RTLScans.cxBytes << 2);
|
|
}
|
|
|
|
if ((RTLScans.cxBytes <= MinBlkSize) ||
|
|
(!(RTLScans.pbCompress = (LPBYTE)LocalAlloc(LPTR, AllocSize)))) {
|
|
|
|
BYTE Buf[4];
|
|
|
|
RTLScans.CompressMode = COMPRESS_MODE_BLOCK;
|
|
|
|
OutputFormatStr(pPDev,
|
|
"\033*b4m#dW",
|
|
4 + (RTLScans.cxBytes * RTLScans.Planes * cy));
|
|
|
|
Buf[0] = (BYTE)((cx >> 24) & 0xFF);
|
|
Buf[1] = (BYTE)((cx >> 16) & 0xFF);
|
|
Buf[2] = (BYTE)((cx >> 8) & 0xFF);
|
|
Buf[3] = (BYTE)((cx ) & 0xFF);
|
|
|
|
OutputBytes(pPDev, Buf, 4);
|
|
|
|
} else if (RTLScans.CompressMode == COMPRESS_MODE_ADAPT) {
|
|
|
|
//
|
|
// We must first flush current output buffer to let room for the
|
|
// Adapt method
|
|
//
|
|
|
|
FlushOutBuffer(pPDev);
|
|
}
|
|
|
|
if (RTLScans.pbCompress) {
|
|
|
|
RTLScans.pbSeedRows[0] = RTLScans.pbCompress + RTLScans.cxBytes;
|
|
|
|
if (!MonoBmp) {
|
|
|
|
RTLScans.pbSeedRows[1] = RTLScans.pbSeedRows[0] + RTLScans.cxBytes;
|
|
RTLScans.pbSeedRows[2] = RTLScans.pbSeedRows[1] + RTLScans.cxBytes;
|
|
}
|
|
}
|
|
|
|
*pRTLScans = RTLScans;
|
|
}
|
|
|
|
|
|
|
|
LONG
|
|
CompressToDelta(
|
|
LPBYTE pbSrc,
|
|
LPBYTE pbSeedRow,
|
|
LPBYTE pbDst,
|
|
LONG Size
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function compress the input data to delta type from the seed row
|
|
|
|
|
|
Arguments:
|
|
|
|
pbSrc - Pointer to the source to be compressed
|
|
|
|
pbSeedRow - Pointer to the previous seed row
|
|
|
|
pbDst - Pointer to the compress buffer
|
|
|
|
Size - Size of three pointers
|
|
|
|
|
|
Return Value:
|
|
|
|
LONG - the compress buffer size
|
|
|
|
>0 - Size of the buffer
|
|
=0 - The data is same as previouse line
|
|
<0 - Size is larger than the Size passed
|
|
|
|
Author:
|
|
|
|
22-Feb-1994 Tue 14:41:18 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
LPBYTE pbDstBeg;
|
|
LPBYTE pbDstEnd;
|
|
LPBYTE pbTmp;
|
|
LONG cSrcBytes;
|
|
LONG Offset;
|
|
UINT cReplace;
|
|
BOOL DoReplace;
|
|
|
|
|
|
#if DBG
|
|
if (DBG_PLOTFILENAME & DBG_NO_DELTA) {
|
|
|
|
return(-Size);
|
|
}
|
|
#endif
|
|
|
|
cSrcBytes = Size;
|
|
pbDstBeg = pbDst;
|
|
pbDstEnd = pbDst + Size;
|
|
cReplace = 0;
|
|
pbTmp = pbSrc;
|
|
|
|
|
|
while (cSrcBytes--) {
|
|
|
|
//
|
|
// We need to do byte replacement now
|
|
//
|
|
|
|
if (*pbSrc != *pbSeedRow) {
|
|
|
|
if (++cReplace == 1) {
|
|
|
|
//
|
|
// The pbTmp is the next byte to the last replacement byte and
|
|
// after we find the first different, it become the first byte
|
|
// of source to be copied as different data.
|
|
//
|
|
|
|
Offset = pbSrc - pbTmp;
|
|
pbTmp = pbSrc;
|
|
}
|
|
|
|
DoReplace = (BOOL)((cReplace >= DELTA_MAX_ONE_REPLACE) ||
|
|
(!cSrcBytes));
|
|
|
|
} else {
|
|
|
|
DoReplace = (BOOL)cReplace;
|
|
}
|
|
|
|
if (DoReplace) {
|
|
|
|
//
|
|
// Minimum we need one Command Byte and Replace Count Byte
|
|
//
|
|
|
|
if ((LONG)(pbDstEnd - pbDst) <= (LONG)cReplace) {
|
|
|
|
PLOTDBG(DBG_DELTA, ("CompressToDelta: 1ST_OFF: Dest Size is larger, give up"));
|
|
|
|
return(-Size);
|
|
}
|
|
|
|
PLOTDBG(DBG_DELTA, ("CompressToDelta: Replace=%ld, Offset=%ld",
|
|
(DWORD)cReplace, (DWORD)Offset));
|
|
|
|
|
|
//
|
|
// Set commmand byte to replacement count
|
|
//
|
|
|
|
*pbDst = (BYTE)((cReplace - 1) << 5);
|
|
|
|
//
|
|
// Add in the offset to the same destination byte
|
|
//
|
|
|
|
if (Offset < DELTA_MAX_1ST_OFFSET) {
|
|
|
|
*pbDst++ |= (BYTE)Offset;
|
|
|
|
} else {
|
|
|
|
//
|
|
// We need to send more than one offset, REMEMBER: We must
|
|
// send extra 0 if the ofset is eqaul to 31 or 255
|
|
//
|
|
|
|
*pbDst++ |= (BYTE)DELTA_MAX_1ST_OFFSET;
|
|
Offset -= DELTA_MAX_1ST_OFFSET;
|
|
|
|
do {
|
|
|
|
if (!Offset) {
|
|
|
|
PLOTDBG(DBG_DELTA_OFFSET0,
|
|
("CompressToDelta: Extra 0 offset SENT"));
|
|
}
|
|
|
|
if (pbDst >= pbDstEnd) {
|
|
|
|
PLOTDBG(DBG_DELTA, ("CompressToDelta: Dest Size is larger, give up"));
|
|
|
|
return(-Size);
|
|
}
|
|
|
|
*pbDst++ = (BYTE)((Offset >= 255) ? 255 : Offset);
|
|
|
|
} while ((Offset -= 255) >= 0);
|
|
}
|
|
|
|
//
|
|
// Now copy down the replacement bytes, if we mess up then this
|
|
// pb1stDiff will be NULL
|
|
//
|
|
|
|
CopyMemory(pbDst, pbTmp, cReplace);
|
|
|
|
pbDst += cReplace;
|
|
pbTmp += cReplace;
|
|
cReplace = 0;
|
|
}
|
|
|
|
//
|
|
// Advanced source/seed row pointers
|
|
//
|
|
|
|
++pbSrc;
|
|
++pbSeedRow;
|
|
}
|
|
|
|
PLOTDBG(DBG_DELTA, ("CompressToDelta: Compress from %ld to %ld, save=%ld",
|
|
Size, (DWORD)(pbDst - pbDstBeg),
|
|
Size - (DWORD)(pbDst - pbDstBeg)));
|
|
|
|
|
|
return((LONG)(pbDst - pbDstBeg));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LONG
|
|
CompressToTIFF(
|
|
LPBYTE pbSrc,
|
|
LPBYTE pbDst,
|
|
LONG Size
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function take the source data and compress them into the TIFF packbits
|
|
format at pbDst.
|
|
|
|
The TIFF packbits compression always consists a CONTROL byte and follow
|
|
by the byte data, the CONTROL byte has following range
|
|
|
|
-1 to -127 - The data byte follow the control byte is repeated this many
|
|
time. Repeat Count = -(Control Byte) + 1
|
|
|
|
0 to 127 - There are 1 to 128 literal data byte follow the control byte,
|
|
literal data count = (Control Byte) + 1
|
|
|
|
-128 - NOP
|
|
|
|
Arguments:
|
|
|
|
pbSrc - The source data to be compressed
|
|
|
|
pbDst - The compressed TIFF packbits format data
|
|
|
|
Size - Count of the data in the source and destination
|
|
|
|
Return Value:
|
|
|
|
>0 - Compress sucessful and return value is the total bytes in pbDst
|
|
=0 - All bytes are zero nothing to be compressed.
|
|
<0 - Compress data is larger than the source, compression failed and
|
|
pbDst has no valid data.
|
|
|
|
Author:
|
|
|
|
18-Feb-1994 Fri 09:54:47 created -by- Daniel Chou (danielc)
|
|
|
|
24-Feb-1994 Thu 10:43:01 updated -by- Daniel Chou (danielc)
|
|
Changed the logic so when multiple MAX repeats count is sent and last
|
|
repeat chunck is less than TIFF_MIN_REPEATS then we will treat that as
|
|
literal to save more spaces
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
LPBYTE pbSrcBeg;
|
|
LPBYTE pbSrcEnd;
|
|
LPBYTE pbDstBeg;
|
|
LPBYTE pbDstEnd;
|
|
LPBYTE pbLastRepeat;
|
|
LPBYTE pbTmp;
|
|
LONG RepeatCount;
|
|
LONG LiteralCount;
|
|
LONG CurSize;
|
|
BYTE LastSrc;
|
|
|
|
#if DBG
|
|
if (DBG_PLOTFILENAME & DBG_NO_TIFF) {
|
|
|
|
return(-Size);
|
|
}
|
|
#endif
|
|
|
|
|
|
pbSrcBeg = pbSrc;
|
|
pbSrcEnd = pbSrc + Size;
|
|
pbDstBeg = pbDst;
|
|
pbDstEnd = pbDst + Size;
|
|
pbLastRepeat = pbSrc;
|
|
|
|
while (pbSrcBeg < pbSrcEnd) {
|
|
|
|
pbTmp = pbSrcBeg;
|
|
LastSrc = *pbTmp++;
|
|
|
|
while ((pbTmp < pbSrcEnd) &&
|
|
(*pbTmp == LastSrc)) {
|
|
|
|
++pbTmp;
|
|
}
|
|
|
|
if (((RepeatCount = (LONG)(pbTmp - pbSrcBeg)) >= TIFF_MIN_REPEATS) ||
|
|
(pbTmp >= pbSrcEnd)) {
|
|
|
|
//
|
|
// Checking if we are repeat ZEROs to the end of the line, if so
|
|
// then make if auto zero fill and exit
|
|
//
|
|
|
|
LiteralCount = (LONG)(pbSrcBeg - pbLastRepeat);
|
|
|
|
if ((pbTmp >= pbSrcEnd) &&
|
|
(RepeatCount) &&
|
|
(LastSrc == 0)) {
|
|
|
|
if (RepeatCount == Size) {
|
|
|
|
PLOTDBG(DBG_TIFF,
|
|
("CompressToTIFF: All data = 0, size=%ld", Size));
|
|
|
|
return(0);
|
|
}
|
|
|
|
PLOTDBG(DBG_TIFF,
|
|
("CompressToTIFF: Last Chunck of Repeats (%ld) is Zeros, Skip it",
|
|
RepeatCount));
|
|
|
|
RepeatCount = 0;
|
|
|
|
} else if (RepeatCount < TIFF_MIN_REPEATS) {
|
|
|
|
//
|
|
// If repeats is not good enough to make it into repeat control
|
|
// then add it to the literal count
|
|
//
|
|
|
|
LiteralCount += RepeatCount;
|
|
RepeatCount = 0;
|
|
}
|
|
|
|
PLOTDBG(DBG_TIFF, ("CompressToTIFF: Literal=%ld, Repeats=%ld",
|
|
LiteralCount, RepeatCount));
|
|
|
|
//
|
|
// Setting literal count
|
|
//
|
|
|
|
while (LiteralCount) {
|
|
|
|
if ((CurSize = LiteralCount) > TIFF_MAX_LITERAL) {
|
|
|
|
CurSize = TIFF_MAX_LITERAL;
|
|
}
|
|
|
|
if ((pbDstEnd - pbDst) <= CurSize) {
|
|
|
|
PLOTDBG(DBG_TIFF,
|
|
("CompressToTIFF: [LITERAL] Dest Size is larger, give up"));
|
|
return(-Size);
|
|
}
|
|
|
|
//
|
|
// Set literal control bytes from 0-127
|
|
//
|
|
|
|
*pbDst++ = (BYTE)(CurSize - 1);
|
|
|
|
CopyMemory(pbDst, pbLastRepeat, CurSize);
|
|
|
|
pbDst += CurSize;
|
|
pbLastRepeat += CurSize;
|
|
LiteralCount -= CurSize;
|
|
}
|
|
|
|
//
|
|
// Setting repeat count if any
|
|
//
|
|
|
|
while (RepeatCount) {
|
|
|
|
if ((CurSize = RepeatCount) > TIFF_MAX_REPEATS) {
|
|
|
|
CurSize = TIFF_MAX_REPEATS;
|
|
}
|
|
|
|
if ((pbDstEnd - pbDst) < 2) {
|
|
|
|
PLOTDBG(DBG_TIFF,
|
|
("CompressToTIFF: [REPEATS] Dest Size is larger, give up"));
|
|
return(-Size);
|
|
}
|
|
|
|
//
|
|
// Set Repeat Control bytes from -1 to -127
|
|
//
|
|
|
|
*pbDst++ = (BYTE)(1 - CurSize);
|
|
*pbDst++ = (BYTE)LastSrc;
|
|
|
|
//
|
|
// If we have more than TIFF_MAX_REPEATS then we want to make
|
|
// sure we used most efficient method to send. If we have
|
|
// remaining repeated bytes less than TIFF_MIN_REPEATS then
|
|
// we want to skip that and use literal for the next run
|
|
//
|
|
|
|
if ((RepeatCount -= CurSize) < TIFF_MIN_REPEATS) {
|
|
|
|
PLOTDBG(DBG_TIFF,
|
|
("CompressToTIFF: Replaced Last REPEATS (%ld) for LITERAL",
|
|
RepeatCount));
|
|
|
|
pbTmp -= RepeatCount;
|
|
RepeatCount = 0;
|
|
}
|
|
}
|
|
|
|
pbLastRepeat = pbTmp;
|
|
}
|
|
|
|
pbSrcBeg = pbTmp;
|
|
}
|
|
|
|
PLOTDBG(DBG_TIFF, ("CompressToTIFF: Compress from %ld to %ld, save=%ld",
|
|
Size, (DWORD)(pbDst - pbDstBeg),
|
|
Size - (DWORD)(pbDst - pbDstBeg)));
|
|
|
|
return((LONG)(pbDst - pbDstBeg));
|
|
}
|
|
|
|
|
|
|
|
|
|
LONG
|
|
RTLCompression(
|
|
LPBYTE pbSrc,
|
|
LPBYTE pbSeedRow,
|
|
LPBYTE pbDst,
|
|
LONG Size,
|
|
LPBYTE pCompressMode
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function decides which RTL compress method is the best and then
|
|
compress to that method
|
|
|
|
Arguments:
|
|
|
|
pbSrc - pointer to the source scan
|
|
|
|
pbSeedRow - Pointer to the seed row for the current source scan
|
|
|
|
pbDst - Pointer to the compressed result will be stored
|
|
|
|
Size - size in bytes for pbSrc/pbSeedRow/pbDst
|
|
|
|
pCompressMode - Pointer to current compression mode, it will ALWAYS
|
|
updated to a new compress mode when it returned
|
|
|
|
|
|
Return Value:
|
|
|
|
>0 - Use *pCompressMode returned and output that many bytes
|
|
=0 - Use *pCompressMode returned and output ZERO byte
|
|
<0 - Use *pCompressMode returned and output original source and size
|
|
|
|
Author:
|
|
|
|
25-Feb-1994 Fri 12:49:29 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
LONG cDelta;
|
|
LONG cTiff;
|
|
LONG RetSize;
|
|
BYTE CompressMode;
|
|
|
|
|
|
if ((cDelta = CompressToDelta(pbSrc, pbSeedRow, pbDst, Size)) == 0) {
|
|
|
|
//
|
|
// Exact duplicate the preious row and seed row remained same
|
|
//
|
|
|
|
PLOTDBG(DBG_COMPRESS, ("RTLCompression: Duplicate the ROW"));
|
|
|
|
*pCompressMode = (BYTE)COMPRESS_MODE_DELTA;
|
|
return(0);
|
|
}
|
|
|
|
if ((cTiff = CompressToTIFF(pbSrc, pbDst, Size)) == 0) {
|
|
|
|
//
|
|
// Since a '*0W' for the delta means repeat last row so we must change
|
|
// to other mode, but we just want reset seed rows to all zeros
|
|
//
|
|
|
|
PLOTDBG(DBG_COMPRESS, ("RTLCompression: Row is all ZEROs"));
|
|
|
|
if (*pCompressMode == (BYTE)COMPRESS_MODE_DELTA) {
|
|
|
|
*pCompressMode = (BYTE)COMPRESS_MODE_ROW;
|
|
}
|
|
|
|
ZeroMemory(pbSeedRow, Size);
|
|
return(0);
|
|
}
|
|
|
|
if (cTiff < 0) {
|
|
|
|
if (cDelta < 0) {
|
|
|
|
PLOTDBG(DBG_COMPRESS, ("RTLCompression: Using COMPRESS_MODE_ROW"));
|
|
|
|
CompressMode = (BYTE)COMPRESS_MODE_ROW;
|
|
RetSize = -Size;
|
|
|
|
} else {
|
|
|
|
CompressMode = (BYTE)COMPRESS_MODE_DELTA;
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// At here cTiff is greater than zero
|
|
//
|
|
|
|
CompressMode = (BYTE)(((cDelta < 0) || (cTiff <= cDelta)) ?
|
|
COMPRESS_MODE_TIFF : COMPRESS_MODE_DELTA);
|
|
}
|
|
|
|
if ((*pCompressMode = CompressMode) == COMPRESS_MODE_DELTA) {
|
|
|
|
//
|
|
// We must redo the DELTA again, since pbDst already destroy by the
|
|
// TIFF compression
|
|
//
|
|
|
|
PLOTDBG(DBG_COMPRESS, ("RTLCompression: Using COMPRESS_MODE_DELTA"));
|
|
|
|
RetSize = CompressToDelta(pbSrc, pbSeedRow, pbDst, Size);
|
|
|
|
} else if (CompressMode == COMPRESS_MODE_TIFF) {
|
|
|
|
PLOTDBG(DBG_COMPRESS, ("RTLCompression: Using COMPRESS_MODE_TIFF"));
|
|
|
|
RetSize = cTiff;
|
|
}
|
|
|
|
//
|
|
// We need to have curreent source (Original SIZE) as new seed rows
|
|
//
|
|
|
|
CopyMemory(pbSeedRow, pbSrc, Size);
|
|
|
|
return(RetSize);
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
AdaptCompression(
|
|
PPDEV pPDev,
|
|
PRTLSCANS pRTLScans,
|
|
LPBYTE pbSrc,
|
|
LPBYTE pbSeedRow,
|
|
LPBYTE pbDst,
|
|
LONG Size
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function decides which RTL compress method is the best and then
|
|
compress to that method
|
|
|
|
Arguments:
|
|
|
|
pbSrc - pointer to the source scan
|
|
|
|
pbSeedRow - Pointer to the seed row for the current source scan
|
|
|
|
pbDst - Pointer to the compressed result will be stored
|
|
|
|
Size - size in bytes for pbSrc/pbSeedRow/pbDst
|
|
|
|
|
|
Return Value:
|
|
|
|
>0 - Use *pCompressMode returned and output that many bytes
|
|
=0 - Use *pCompressMode returned and output ZERO byte
|
|
<0 - Use *pCompressMode returned and output original source and size
|
|
|
|
Author:
|
|
|
|
25-Feb-1994 Fri 12:49:29 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
LPBYTE pbOrgDst;
|
|
LONG Count;
|
|
BOOL Ok;
|
|
BYTE AdaptMethod;
|
|
|
|
|
|
pbOrgDst = pbDst;
|
|
|
|
if (Count = RTLCompression(pbSrc, pbSeedRow, pbDst, Size, &AdaptMethod)) {
|
|
|
|
if (Count < 0) {
|
|
|
|
pbDst = pbSrc;
|
|
Count = -Count;
|
|
}
|
|
|
|
} else {
|
|
|
|
AdaptMethod = (AdaptMethod == COMPRESS_MODE_DELTA) ? ADAPT_METHOD_DUP :
|
|
ADAPT_METHOD_ZERO;
|
|
}
|
|
|
|
if ((Ok = (BOOL)(pRTLScans->cEmptyDup == 0xFFFF)) ||
|
|
((pPDev->cbBufferBytes + Count) > MAX_ADAPT_SIZE)) {
|
|
|
|
if (!(Ok = FlushAdaptBuf(pPDev, pRTLScans, Ok))) {
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Because the Seed ROW back to zero, we must re-do again
|
|
//
|
|
|
|
if (Count = RTLCompression(pbSrc,
|
|
pbSeedRow,
|
|
pbOrgDst,
|
|
Size,
|
|
&AdaptMethod)) {
|
|
|
|
if (Count < 0) {
|
|
|
|
pbDst = pbSrc;
|
|
Count = -Count;
|
|
}
|
|
|
|
} else {
|
|
|
|
AdaptMethod = (AdaptMethod == COMPRESS_MODE_DELTA) ?
|
|
ADAPT_METHOD_DUP : ADAPT_METHOD_ZERO;
|
|
}
|
|
|
|
} else {
|
|
|
|
Ok = TRUE;
|
|
}
|
|
|
|
if (AdaptMethod != pRTLScans->AdaptMethod) {
|
|
|
|
if (pRTLScans->cEmptyDup) {
|
|
|
|
SET_ADAPT_CONTROL(pPDev,
|
|
pRTLScans->AdaptMethod,
|
|
pRTLScans->cEmptyDup);
|
|
|
|
pRTLScans->cEmptyDup = 0;
|
|
}
|
|
|
|
pRTLScans->AdaptMethod = AdaptMethod;
|
|
}
|
|
|
|
if (Count) {
|
|
|
|
SET_ADAPT_CONTROL(pPDev, pRTLScans->AdaptMethod, Count);
|
|
OutputBytes(pPDev, pbDst, Count);
|
|
|
|
} else {
|
|
|
|
++(pRTLScans->cEmptyDup);
|
|
}
|
|
|
|
return(Ok);
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
OutputRTLScans(
|
|
PPDEV pPDev,
|
|
LPBYTE pbPlane1,
|
|
LPBYTE pbPlane2,
|
|
LPBYTE pbPlane3,
|
|
PRTLSCANS pRTLScans
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will output one scan line of RTL data and compressed if
|
|
necessary
|
|
|
|
Arguments:
|
|
|
|
pPDev - Pointer to our PDEV
|
|
|
|
pbPlane1 - First plane scan data
|
|
|
|
pbPlane2 - 2nd plane scan data
|
|
|
|
pbPlane3 - 3rd plane scan data
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN
|
|
|
|
|
|
Author:
|
|
|
|
18-Feb-1994 Fri 15:52:42 created -by- Daniel Chou (danielc)
|
|
|
|
21-Feb-1994 Mon 13:20:00 updated -by- Daniel Chou (danielc)
|
|
Make if output faster in scan line output
|
|
|
|
16-Mar-1994 Wed 15:38:23 updated -by- Daniel Chou (danielc)
|
|
Update so the source mask is restored after mask
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
LPBYTE pbCurScan;
|
|
LPBYTE pbCompress;
|
|
LPBYTE pbScans[3];
|
|
RTLSCANS RTLScans;
|
|
LONG Count;
|
|
UINT i;
|
|
BYTE EndGrafCH;
|
|
static BYTE BegGrafCmd[] = { 0x1B, '*', 'b' };
|
|
|
|
|
|
if (PLOT_CANCEL_JOB(pPDev)) {
|
|
|
|
PLOTWARN(("OutputRTLScans: JOB CANCELD. exit NOW"));
|
|
|
|
pRTLScans->Flags &= ~RTLSF_MORE_SCAN;
|
|
return(TRUE);
|
|
}
|
|
|
|
//
|
|
// If we are at last scan line then turn the flag off so that we can exit
|
|
//
|
|
|
|
if (!(--pRTLScans->cScans)) {
|
|
|
|
pRTLScans->Flags &= ~RTLSF_MORE_SCAN;
|
|
}
|
|
|
|
RTLScans = *pRTLScans;
|
|
Count = (LONG)(RTLScans.cxBytes - 1);
|
|
*(pbPlane1 + Count) &= RTLScans.Mask;
|
|
|
|
if ((i = (UINT)RTLScans.Planes) > 1) {
|
|
|
|
*(pbPlane2 + Count) &= RTLScans.Mask;
|
|
*(pbPlane3 + Count) &= RTLScans.Mask;
|
|
pbScans[2] = pbPlane1;
|
|
pbScans[1] = pbPlane2;
|
|
pbScans[0] = pbPlane3;
|
|
|
|
} else {
|
|
|
|
pbScans[0] = pbPlane1;
|
|
}
|
|
|
|
while (i--) {
|
|
|
|
EndGrafCH = (i) ? 'V' : 'W';
|
|
pbCurScan = pbScans[i];
|
|
|
|
if (RTLScans.CompressMode == COMPRESS_MODE_BLOCK) {
|
|
|
|
OutputBytes(pPDev, pbCurScan, RTLScans.cxBytes);
|
|
|
|
} else if (RTLScans.CompressMode == COMPRESS_MODE_ADAPT) {
|
|
|
|
AdaptCompression(pPDev,
|
|
pRTLScans,
|
|
pbCurScan,
|
|
RTLScans.pbSeedRows[i],
|
|
RTLScans.pbCompress,
|
|
RTLScans.cxBytes);
|
|
|
|
} else {
|
|
|
|
if ((Count = RTLCompression(pbCurScan,
|
|
RTLScans.pbSeedRows[i],
|
|
pbCompress = RTLScans.pbCompress,
|
|
RTLScans.cxBytes,
|
|
&(pRTLScans->CompressMode))) < 0) {
|
|
|
|
pbCompress = pbCurScan;
|
|
Count = RTLScans.cxBytes;
|
|
}
|
|
|
|
//
|
|
// Now output graphic header
|
|
//
|
|
|
|
OutputBytes(pPDev, BegGrafCmd, sizeof(BegGrafCmd));
|
|
|
|
//
|
|
// If we change compress mode then do it now and record the change
|
|
//
|
|
|
|
if (pRTLScans->CompressMode != RTLScans.CompressMode) {
|
|
|
|
PLOTDBG(DBG_OUTRTLSCAN, ("OutputRTLScan: Switch CompressMode from %ld to %ld",
|
|
(DWORD)RTLScans.CompressMode,
|
|
(DWORD)pRTLScans->CompressMode));
|
|
|
|
RTLScans.CompressMode = pRTLScans->CompressMode;
|
|
|
|
OutputFormatStr(pPDev, "#dm", (LONG)RTLScans.CompressMode);
|
|
}
|
|
|
|
OutputLONGParams(pPDev, &Count, 1, 'd');
|
|
OutputBytes(pPDev, &EndGrafCH, 1);
|
|
|
|
if (Count) {
|
|
|
|
OutputBytes(pPDev, pbCompress, Count);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|