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.
653 lines
19 KiB
653 lines
19 KiB
//-----------------------------------------------------------------------------
|
|
// Minidriver for ESC/P 2 devices
|
|
// Does ink reduction for Epson Stylus Color series of printers.
|
|
// normanh Sep '95
|
|
// marcm 20 Sep '95 (updated for Pro/Pro XL limits)
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "escp2ms.h"
|
|
|
|
|
|
CBFilterGraphics( lpdv, lpBuf, len )
|
|
void *lpdv;
|
|
BYTE *lpBuf;
|
|
int len;
|
|
{
|
|
|
|
MDEV *pMDev;
|
|
PBYTE lpSrc,lpTgt;
|
|
WORD i;
|
|
short sLastByte;
|
|
// added by DerryD, May 96
|
|
PMINI pMini;
|
|
// end
|
|
|
|
pMDev = ((MDEV *)(( M_UD_PDEV * )lpdv)->pMDev);
|
|
|
|
|
|
// This our first time in ??
|
|
// Make a request for a memory buffer
|
|
// rasdd will call us back with same buffer of grx data.
|
|
if ( ! pMDev->pMemBuf )
|
|
{
|
|
/* Allocate DWORD aligned memory size */
|
|
pMDev->iMemReq = ((TOT_MEM_REQ + 3) & ~3);
|
|
return -2;
|
|
}
|
|
|
|
// added by DerryD, May 96
|
|
|
|
pMini = (PMINI)(pMDev->pMemBuf );
|
|
|
|
// end
|
|
|
|
//Have we setup our local area on MDEV ??
|
|
//rasdd zero's our structure so can rely on fMdv being FALSE
|
|
if (!pMini->fMdv )
|
|
if ( !MiniEnable(pMDev) )
|
|
return -1;
|
|
|
|
//Jump out here for efficient non 720dpi printing (no ink duty)
|
|
if (pMDev->igRes.x != 720)
|
|
{
|
|
SingleScanOut(lpdv,lpBuf,(WORD)len,pMini->bPlaneSelect[pMini->bWPlane],pMini);
|
|
pMini->bWPlane++;
|
|
if (pMini->bWPlane == (BYTE)(pMDev->sDevPlanes))
|
|
pMini->bWPlane = 0;
|
|
return 1;
|
|
}
|
|
|
|
|
|
lpSrc= lpBuf;
|
|
lpTgt= pMini->lpKCMY[pMini->bWPlane];
|
|
|
|
|
|
sLastByte = pMini->iKCMYlens[pMini->bWPlane] > len ?
|
|
pMini->iKCMYlens[pMini->bWPlane] : len;
|
|
|
|
//We store each of the k,c,m,y planes as they arrive
|
|
for (i=0;i < sLastByte + 1; i++, lpSrc++,lpTgt++)
|
|
*lpTgt = (i < len) ? *lpSrc : 0;
|
|
|
|
//Store length of the scan, will need this later
|
|
pMini->iKCMYlens[pMini->bWPlane] = len;
|
|
|
|
// An attempt at optimisation. If only one plane is used in a scan
|
|
// our ink reduction code will be a lot faster
|
|
// check how may colors active for this scan
|
|
if (len)
|
|
pMini->bColors |= 1 << pMini->bWPlane;
|
|
|
|
pMini->bWPlane++ ; // our plane counter
|
|
//Have we received all planes?
|
|
if (pMini->bWPlane == pMDev->sDevPlanes)
|
|
{
|
|
short j;
|
|
|
|
for (j = 3; j >= 0; j--, pMini->bColors <<=1)
|
|
if (pMini->bColors == 0x08)
|
|
{
|
|
// Just one plane, faster output
|
|
SinglePlaneInkDuty(lpdv, pMDev, (BYTE)j ,len, pMini);
|
|
break;
|
|
}
|
|
|
|
if (j == -1) //nothing sent yet, we get to use the fun code.
|
|
MultiPlaneInkDuty(lpdv, pMDev, pMini);
|
|
|
|
pMini->bColors = 0;
|
|
pMini->bWPlane = 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
//sets up private minidriver structure
|
|
int MiniEnable(pMDev)
|
|
MDEV *pMDev;
|
|
{
|
|
|
|
BYTE bKCMYlimit;
|
|
BYTE bRGBlimit;
|
|
|
|
// added by DerryD, May 96
|
|
|
|
PMINI pMini;
|
|
|
|
pMini = (PMINI)(pMDev->pMemBuf );
|
|
|
|
// end , derryd
|
|
|
|
//Should get cleverer about calculating the amount of mem we require.
|
|
//Buffers for our lookup tables
|
|
pMini->pSinglePlaneLookup = (BYTE *)(pMDev->pMemBuf + MINIDATA_SIZE );
|
|
pMini->pRGBLookup = (BYTE *)(pMini->pSinglePlaneLookup + SINGLE_LOOKUP_SIZE);
|
|
pMini->pKCMYLookup =(BYTE *)(pMini->pRGBLookup + RGB_LOOKUP_SIZE);
|
|
|
|
//Buffer for our TIFF compression
|
|
pMini->pCompBuf = (BYTE *)(pMini->pKCMYLookup + KCMY_LOOKUP_SIZE);
|
|
|
|
//Buffer For planes of data
|
|
pMini->lpKCMY[0] = (BYTE *)(pMini->pCompBuf + COMP_BUF_SIZE);
|
|
pMini->lpKCMY[1] = (BYTE *)(pMini->lpKCMY[0] + MAXBLOCK);
|
|
pMini->lpKCMY[2] = (BYTE *)(pMini->lpKCMY[1] + MAXBLOCK);
|
|
pMini->lpKCMY[3] = (BYTE *)(pMini->lpKCMY[2] + MAXBLOCK);
|
|
|
|
pMini->bWPlane = 0;
|
|
pMini->bColors = 0;
|
|
pMini->fMdv = 1;
|
|
//Esc/p2 values for colour selection cmd
|
|
pMini->bPlaneSelect[0] = 0x80;
|
|
pMini->bPlaneSelect[1] = 0x82;
|
|
pMini->bPlaneSelect[2] = 0x81;
|
|
pMini->bPlaneSelect[3] = 0x84;
|
|
|
|
// Select the correct limits depending on the printer model
|
|
switch (pMDev->iModel)
|
|
{
|
|
case MODEL_STYLUS_PROXL:
|
|
case MODEL_STYLUS_PRO:
|
|
bKCMYlimit = 4; // Refer to EHQ tables below
|
|
bRGBlimit = 4;
|
|
break;
|
|
case MODEL_STYLUS_COLOR:
|
|
bKCMYlimit = 2; // Refer to EHQ tables below
|
|
bRGBlimit = 1;
|
|
break;
|
|
default:
|
|
bKCMYlimit = 6; // Should never be used...
|
|
bRGBlimit = 6;
|
|
break;
|
|
}
|
|
|
|
//setup single plane lookup table
|
|
{
|
|
BYTE * Filter;
|
|
BYTE bSrc, bSrcBit, bMask;
|
|
// bMinus1 and bMinus2 represent the contents of the previous bits
|
|
BYTE bMinus1,bMinus2,bMix;
|
|
WORD i,h,j; //loop counters
|
|
|
|
Filter =pMini->pSinglePlaneLookup;
|
|
for (h =0; h < 4; h++)
|
|
{
|
|
for (i =1; i < 256; i++)
|
|
{
|
|
bSrc = (BYTE)i;
|
|
bMinus1 = (h & 0x01) ? 2 : 0;
|
|
bMinus2 = (h & 0x02) ? 1 : 0;
|
|
|
|
//Process each bit, watching at the previous ones (Minus1 and Minus2)
|
|
for(j=0;j<8;j++)
|
|
{
|
|
bMask=0x80>>j;
|
|
bSrcBit= bSrc&bMask;
|
|
bMix = bMinus1 + bMinus2;
|
|
if(!bSrcBit) //Skip blank bit
|
|
{
|
|
bMinus2 = bMinus1>>1;
|
|
bMinus1 = 0;
|
|
continue;
|
|
}
|
|
if(bMix > bKCMYlimit) //Already enough ink?
|
|
{
|
|
bSrc = bSrc ^ bMask; //remove the bit
|
|
bMinus2 = bMinus1>>1;
|
|
bMinus1 = 0;
|
|
}
|
|
else
|
|
{
|
|
bMinus2 = bMinus1>>1;
|
|
bMinus1 = 2;
|
|
}
|
|
}//end j
|
|
Filter[ (h<<8) | i] = bSrc;
|
|
}//end i
|
|
}//end h
|
|
}// end SinglePlaneLookup
|
|
|
|
//MultiPlane lookup tables setup
|
|
{
|
|
BYTE * OKAY_RGB;
|
|
BYTE * OKAY_KCMY;
|
|
BYTE bWeight;
|
|
BYTE bBack2 ; //set of cmyk for 2 bits back
|
|
BYTE bBack1 ; //set of cmyk for 1 bit back
|
|
WORD i;
|
|
|
|
OKAY_RGB = pMini->pRGBLookup;
|
|
OKAY_KCMY = pMini->pKCMYLookup;
|
|
//we go thru every value of i, although not all are possible
|
|
//Assign weight values corresponding to those provided by Epson
|
|
// allow or dissallow depending on final weight
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
bBack2 = (BYTE)i >>4;
|
|
bBack1 = (BYTE)i & 0x0F;
|
|
bWeight = 0;
|
|
|
|
switch (bBack1)
|
|
{
|
|
case RED:
|
|
case GREEN:
|
|
case BLUE:
|
|
bWeight =4;
|
|
break;
|
|
case BLACK:
|
|
case CYAN:
|
|
case MAGENTA:
|
|
case YELLOW:
|
|
bWeight =2;
|
|
break;
|
|
}
|
|
switch (bBack2)
|
|
{
|
|
case RED:
|
|
case GREEN:
|
|
case BLUE:
|
|
bWeight +=2;
|
|
break;
|
|
case BLACK:
|
|
case CYAN:
|
|
case MAGENTA:
|
|
case YELLOW:
|
|
bWeight +=1;
|
|
break;
|
|
}
|
|
|
|
OKAY_RGB[i] = (bWeight < (bRGBlimit + 1)) ? TRUE : FALSE;
|
|
OKAY_KCMY[i] = (bWeight < (bKCMYlimit + 1)) ? TRUE : FALSE;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
int SinglePlaneInkDuty(lpdv,pMDev,bColor, len, pMini )
|
|
void * lpdv;
|
|
MDEV * pMDev;
|
|
BYTE bColor;
|
|
int len;
|
|
PMINI pMini;
|
|
{
|
|
LPBYTE lpSrc;
|
|
WORD i; //loop counter
|
|
WORD wPrev;
|
|
BYTE * Filter ; //lookup table for single plane filtering.
|
|
|
|
Filter = pMini->pSinglePlaneLookup;
|
|
lpSrc = pMini->lpKCMY[bColor];
|
|
wPrev = 0;
|
|
|
|
for(i=0;i<len;i++,lpSrc++)
|
|
{
|
|
if ( !*lpSrc)
|
|
{
|
|
wPrev =0;
|
|
continue;
|
|
}
|
|
wPrev |= *lpSrc;
|
|
*lpSrc = Filter[ wPrev ]; //Put my corrected byte back into my buffer
|
|
wPrev = (wPrev << 8 ) & 0x0300 ;// just keep final two bits for Minus1 & Minus2
|
|
}
|
|
//Send the scanline
|
|
return SingleScanOut(lpdv,pMini->lpKCMY[bColor], (WORD)len,
|
|
pMini->bPlaneSelect[bColor], pMini);
|
|
}
|
|
|
|
|
|
// Table below provided by M. Morisse / Epson Europe B.V. for Verde 720 dpi
|
|
// (To support Ink duty limit of 65% on Verde @ 720 dpi)
|
|
//
|
|
// With this method, best result are achieved with:
|
|
// X Resolution = 720 dpi
|
|
// Y Resolution = 720 dpi
|
|
// Halftoning = 6x6 Enhanced
|
|
// sSpotDiameter = 1/254 inch (Stylus COLOR)
|
|
// sSpotDiameter = 1/362 inch (Stylus Pro/Pro XL with MicroDot)
|
|
// Gamma = 1.0 (360 dpi) or 0.7 (720 dpi)
|
|
//-----------------------------------------------------------------------------
|
|
// Method 11: Datas are rasterized @ 720dpi than this BlockOut() will allow or
|
|
// not each pixel by looking first at the previous ones (Minus1 and Minus2).
|
|
//
|
|
// Each new pixel will be allowed according to the following table
|
|
// (n, n-1, n-2 can each be filled by 0, 1 or 2 CMYK pixels)
|
|
//
|
|
// Stylus COLOR in 720 dpi
|
|
// Previous NewPixel bMix Allow? Resulting Ink
|
|
// n-2 n-1 n
|
|
// --- --- -------- ---- ------ -------------
|
|
// 0 0 1 0 Y 33%
|
|
// 1 0 1 1 Y 66%
|
|
// 0 1 1 2 Y 66%
|
|
// 1 1 1 3 N 66%
|
|
// 2 0 1 2 Y 100% but with a middle blank
|
|
// 0 2 1 4 N 66%
|
|
// 2 2 (IMPOSSIBLE)
|
|
// 0 0 2 0 Y 66%
|
|
// 1 0 2 1 Y 100%, but with a middle blank
|
|
// 0 1 2 2 N 33%
|
|
// 1 1 2 3 N 66%
|
|
// 2 0 2 2 N 66%
|
|
// 0 2 2 4 N 66%
|
|
// 2 2 (IMPOSSIBLE)
|
|
// ==> CMYKlimit = 2, RGBlimit = 1
|
|
//
|
|
// Stylus Pro/Pro XL in 720 dpi with MicroDot
|
|
// Previous NewPixel bMix Allow? Resulting Ink
|
|
// n-2 n-1 n
|
|
// --- --- -------- ---- ------ -------------
|
|
// 0 0 1 0 Y 33%
|
|
// 1 0 1 1 Y 66%
|
|
// 0 1 1 2 Y 66%
|
|
// 1 1 1 3 Y 100%
|
|
// 2 0 1 2 Y 100%
|
|
// 0 2 1 4 Y 100%
|
|
// 2 2 1 6 N 133%
|
|
// 0 0 2 0 Y 66%
|
|
// 1 0 2 1 Y 100%
|
|
// 0 1 2 2 Y 100%
|
|
// 1 1 2 3 Y 133%
|
|
// 2 0 2 2 Y 133%
|
|
// 0 2 2 4 Y 133%
|
|
// 2 2 2 6 N 133%
|
|
// ==> CMYKlimit = 4, RGBlimit = 4
|
|
//
|
|
// To identify the different cases, in Minus1 and Minus2 are stored the
|
|
// contents of the 2 previous bits with the following weights:
|
|
// Nothing : 0
|
|
// K, C, M or Y only: 2
|
|
// R, G or B : 4
|
|
// and when we move from one bit to the next, bMinus2 becomes bMinus1 / 2
|
|
// bMix is the sum of bMinus1 and bMinus2
|
|
// The choice of leaving a bit or not will be taken depending on which colour
|
|
// we would like to use (CMYK or RGB) and the value of bMix
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
int MultiPlaneInkDuty(lpdv,pMDev, pMini)
|
|
void * lpdv;
|
|
MDEV * pMDev;
|
|
PMINI pMini; // added by DerryD, May 96
|
|
{
|
|
BYTE * lpK, *lpC, *lpM,*lpY;
|
|
WORD wMax = 0; //largest scan of all planes
|
|
WORD i; //loop counter
|
|
|
|
BYTE bMask;
|
|
BYTE bColorBit;
|
|
BYTE bPrev; // lower nibble represents previous set of kcmy bits,
|
|
// upper nibble the previous previous set
|
|
|
|
BYTE * OKAY_KCMY; // table of yes or no answers for bit combinations
|
|
BYTE * OKAY_RGB; // table of yes or no answers for bit combinations
|
|
|
|
OKAY_KCMY = pMini->pKCMYLookup;
|
|
OKAY_RGB = pMini->pRGBLookup;
|
|
|
|
for (i=0 ; i< pMDev->sDevPlanes ;i++)
|
|
wMax = (pMini->iKCMYlens[i] > wMax ) ? pMini->iKCMYlens[i] : wMax;
|
|
|
|
//OK now limit the Ink Duty...
|
|
lpK = pMini->lpKCMY[0];
|
|
lpC = pMini->lpKCMY[1];
|
|
lpM = pMini->lpKCMY[2];
|
|
lpY = pMini->lpKCMY[3];
|
|
|
|
|
|
//Process in BYTES
|
|
bPrev =0;
|
|
for(i=0;i<wMax;i++, lpK++,lpC++,lpM++,lpY++)
|
|
{
|
|
if(!*lpK && !*lpC && !*lpM && !*lpY) //Skip white dwords
|
|
{
|
|
bPrev =0;
|
|
continue;
|
|
}
|
|
|
|
//Process each bit, watching the previous ones - bPrev
|
|
for(bMask =0x80; bMask >=1;bMask >>= 1)
|
|
{
|
|
//determine colour of this bit.
|
|
bColorBit = (*lpK & bMask) ? BLACK : NOCOLOR;
|
|
bColorBit |= (*lpC & bMask) ? CYAN : NOCOLOR;
|
|
bColorBit |= (*lpM & bMask) ? MAGENTA : NOCOLOR;
|
|
bColorBit |= (*lpY & bMask) ? YELLOW : NOCOLOR;
|
|
|
|
switch (bColorBit)
|
|
{
|
|
|
|
case NOCOLOR:
|
|
break;
|
|
|
|
case RED:
|
|
if (!OKAY_RGB[bPrev]) //can't allow
|
|
{
|
|
*lpM ^= bMask; //mask out relavent bits
|
|
*lpY ^= bMask;
|
|
bColorBit = NOCOLOR; //and reset appropriately
|
|
}
|
|
break;
|
|
case GREEN:
|
|
if (!OKAY_RGB[bPrev])
|
|
{
|
|
*lpC ^= bMask;
|
|
*lpY ^= bMask;
|
|
bColorBit = NOCOLOR;
|
|
}
|
|
break;
|
|
case BLUE:
|
|
if (!OKAY_RGB[bPrev])
|
|
{
|
|
*lpC ^= bMask; //Remove the bits
|
|
*lpM ^= bMask;
|
|
bColorBit = NOCOLOR;
|
|
}
|
|
break;
|
|
case BLACK:
|
|
if (!OKAY_KCMY[bPrev])
|
|
{
|
|
*lpK ^= bMask; //Remove the bit
|
|
bColorBit = NOCOLOR;
|
|
}
|
|
break;
|
|
case CYAN:
|
|
if (!OKAY_KCMY[bPrev])
|
|
{
|
|
*lpC ^= bMask; //Remove the bit
|
|
bColorBit = NOCOLOR;
|
|
}
|
|
break;
|
|
case MAGENTA:
|
|
if (!OKAY_KCMY[bPrev])
|
|
{
|
|
*lpM ^= bMask; //Remove the bit
|
|
bColorBit = NOCOLOR;
|
|
}
|
|
break;
|
|
case YELLOW:
|
|
if (!OKAY_KCMY[bPrev])
|
|
{
|
|
*lpY ^= bMask; //Remove the bit
|
|
bColorBit = NOCOLOR;
|
|
}
|
|
break;
|
|
}
|
|
bPrev = (bPrev << 4) | bColorBit;
|
|
|
|
}//Next bit!
|
|
}//Next BYTE
|
|
|
|
//Send the planes now .
|
|
for (i=3; (short)i >= 0; i--)
|
|
if (pMini->iKCMYlens[i]) //Check for empty plane
|
|
SingleScanOut(lpdv,pMini->lpKCMY[i],(WORD)pMini->iKCMYlens[i],
|
|
pMini->bPlaneSelect[i], pMini);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
int SingleScanOut(lpdv,lpBuf,len, bPlane, pMini)
|
|
void * lpdv;
|
|
LPBYTE lpBuf;
|
|
WORD len;
|
|
BYTE bPlane;
|
|
PMINI pMini;
|
|
{
|
|
WORD wCompLen,ret;
|
|
WORD sCMD_Len;
|
|
MDEV *pMDev;
|
|
|
|
char CMDSendPlane[10];
|
|
BYTE * lpTgt = lpBuf +len -1;
|
|
|
|
//we've done work on these planes.
|
|
//May be trailing white space or blank planes
|
|
while (*lpTgt-- == 0 && len > 0)
|
|
len--;
|
|
if (len ==0) //nothing to send
|
|
return 0;
|
|
|
|
pMDev = ((MDEV *)(( M_UD_PDEV * )lpdv)->pMDev);
|
|
|
|
if (pMDev->sDevPlanes > 1)
|
|
ntmdInit.WriteSpoolBuf(lpdv, (BYTE *)(&bPlane), 1); //Select Colour
|
|
|
|
wCompLen = TIFF_Comp(pMini->pCompBuf,lpBuf, len);
|
|
sCMD_Len = sprintf(CMDSendPlane,"2%c%c",(BYTE)wCompLen,(BYTE)(wCompLen>>8));
|
|
ntmdInit.WriteSpoolBuf(lpdv, CMDSendPlane, sCMD_Len);
|
|
ret= ntmdInit.WriteSpoolBuf(lpdv, pMini->pCompBuf, wCompLen);
|
|
|
|
ntmdInit.WriteSpoolBuf(lpdv, "\xE2", 1);
|
|
return (ret);
|
|
}
|
|
|
|
/****************************** Function Header *****************************
|
|
* iCompTIFF
|
|
* Encodes the input data using TIFF v4. TIFF stands for Tagged Image
|
|
* File Format. It embeds control characters in the data stream.
|
|
* These determine whether the following data is plain raster data
|
|
* or a repetition count plus data byte. Thus, there is the choice
|
|
* of run length encoding if it makes sense, else just send the
|
|
* plain data. Consult an HP LaserJet Series III manual for details.
|
|
*
|
|
* CAVEATS:
|
|
* The output buffer is presumed large enough to hold the output.
|
|
* In the worst case (NO REPETITIONS IN DATA) there is an extra
|
|
* byte added every 128 bytes of input data. So, you should make
|
|
* the output buffer at least 1% larger than the input buffer.
|
|
*
|
|
* RETURNS:
|
|
* Number of bytes in output buffer.
|
|
*
|
|
* HISTORY:
|
|
* 10:29 on Thu 25 Jun 1992 -by- Lindsay Harris [lindsayh]
|
|
* First incarnation.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int
|
|
TIFF_Comp( pbOBuf, pbIBuf, cb )
|
|
BYTE *pbOBuf; /* Output buffer, PRESUMED BIG ENOUGH: see above */
|
|
BYTE *pbIBuf; /* Raster data to send */
|
|
int cb; /* Number of bytes in the above */
|
|
{
|
|
BYTE *pbOut; /* Output byte location */
|
|
BYTE *pbStart; /* Start of current input stream */
|
|
BYTE *pb; /* Miscellaneous usage */
|
|
BYTE *pbEnd; /* The last byte of input */
|
|
BYTE jLast; /* Last byte, for match purposes */
|
|
|
|
int cSize; /* Bytes in the current length */
|
|
int cSend; /* Number to send in this command */
|
|
|
|
|
|
pbOut = pbOBuf;
|
|
pbStart = pbIBuf;
|
|
pbEnd = pbIBuf + cb; /* The last byte */
|
|
|
|
jLast = *pbIBuf++;
|
|
|
|
while( pbIBuf < pbEnd )
|
|
{
|
|
if( jLast == *pbIBuf )
|
|
{
|
|
/* Find out how long this run is. Then decide on using it */
|
|
|
|
for( pb = pbIBuf; pb < pbEnd && *pb == jLast; ++pb )
|
|
;
|
|
|
|
/*
|
|
* Note that pbIBuf points at the SECOND byte of the pattern!
|
|
* AND also that pb points at the first byte AFTER the run.
|
|
*/
|
|
|
|
if( (pb - pbIBuf) >= (TIFF_MIN_RUN - 1) )
|
|
{
|
|
/*
|
|
* Worth recording as a run, so first set the literal
|
|
* data which may have already been scanned before recording
|
|
* this run.
|
|
*/
|
|
|
|
if( (cSize = pbIBuf - pbStart - 1) > 0 )
|
|
{
|
|
/* There is literal data, so record it now */
|
|
while( (cSend = min( cSize, TIFF_MAX_LITERAL )) > 0 )
|
|
{
|
|
*pbOut++ = cSend - 1;
|
|
CopyMemory( pbOut, pbStart, cSend );
|
|
pbOut += cSend;
|
|
pbStart += cSend;
|
|
cSize -= cSend;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Now for the repeat pattern. Same logic, but only
|
|
* one byte is needed per entry.
|
|
*/
|
|
|
|
cSize = pb - pbIBuf + 1;
|
|
|
|
while( (cSend = min( cSize, TIFF_MAX_RUN )) > 0 )
|
|
{
|
|
*pbOut++ = 1 - cSend; /* -ve indicates repeat */
|
|
*pbOut++ = jLast;
|
|
cSize -= cSend;
|
|
}
|
|
|
|
pbStart = pb; /* Ready for the next one! */
|
|
}
|
|
pbIBuf = pb; /* Start from this position! */
|
|
}
|
|
else
|
|
jLast = *pbIBuf++; /* Onto the next byte */
|
|
|
|
}
|
|
|
|
if( pbStart < pbIBuf )
|
|
{
|
|
/* Left some dangling. This can only be literal data. */
|
|
|
|
cSize = pbIBuf - pbStart;
|
|
|
|
while( (cSend = min( cSize, TIFF_MAX_LITERAL )) > 0 )
|
|
{
|
|
*pbOut++ = cSend - 1;
|
|
CopyMemory( pbOut, pbStart, cSend );
|
|
pbOut += cSend;
|
|
pbStart += cSend;
|
|
cSize -= cSend;
|
|
}
|
|
}
|
|
|
|
return pbOut - pbOBuf;
|
|
}
|
|
|
|
|