1 /*****************************************************************************\
2 compression.cpp : Implimentation for the Compressor class
4 Copyright (c) 1996 - 2001, Hewlett-Packard Co.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. Neither the name of Hewlett-Packard nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
20 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
22 NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24 TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 \*****************************************************************************/
36 Compressor::Compressor(SystemServices* pSys, unsigned int RasterSize, BOOL useseed)
37 : pSS(pSys), SeedRow(NULL), UseSeedRow(useseed), inputsize(RasterSize), seeded(FALSE)
39 constructor_error=NO_ERROR;
42 originalKData=pSS->AllocMem(RasterSize);
43 CNEWCHECK(originalKData);
48 SeedRow=pSS->AllocMem(RasterSize);
52 Compressor::~Compressor()
55 pSS->FreeMem (compressBuf);
57 pSS->FreeMem (SeedRow);
59 pSS->FreeMem (originalKData);
62 unsigned int Compressor::GetOutputWidth(COLORTYPE color)
63 // since we return 1-for-1, just return result first call
67 return compressedsize;
71 return raster.rastersize[color];
76 BYTE* Compressor::NextOutputRaster(COLORTYPE color)
77 // since we return 1-for-1, just return result first call
81 if (color == COLORTYPE_COLOR)
87 if (raster.rasterdata[color] == NULL)
88 if (compressedsize != 0 && myplane == COLORTYPE_BLACK)
97 return raster.rasterdata[color];
101 Mode9::Mode9 (SystemServices* pSys,unsigned int RasterSize, BOOL bVIPPrinter)
102 : Compressor(pSys,RasterSize, TRUE)
104 if (constructor_error != NO_ERROR) // if error in base constructor
107 // Allocate double the RasterSize to accommodate worst case
108 compressBuf = (BYTE*)pSS->AllocMem(RasterSize * 2);
109 if (compressBuf == NULL)
110 constructor_error=ALLOCMEM_ERROR;
112 memset(compressBuf, 0, RasterSize * 2);
113 memset(SeedRow,0,RasterSize);
115 ResetSeedRow = FALSE;
116 m_bVIPPrinter = bVIPPrinter;
122 ////////////////////////////////////////////////////////////////////////////
125 unsigned char comchar; /* command byte as char */
128 #if defined(APDK_LITTLE_ENDIAN) || defined(LITTLE_ENDIAN_HW)
129 unsigned replace_count:3; /* replace count 1-7, 8=8+next byte */
130 unsigned roff:4; /* relative offset 0-14, 15=15+next byte */
131 unsigned type:1; /* type of replacement: 0=mode0, 1=mode1 */
133 unsigned type:1; /* type of replacement: 0=mode0, 1=mode1 */
134 unsigned roff:4; /* relative offset 0-14, 15=15+next byte */
135 unsigned replace_count:3; /* replace count 1-7, 8=8+next byte */
140 #if defined(APDK_LITTLE_ENDIAN) || defined(LITTLE_ENDIAN_HW)
141 unsigned replace_count:5; /* replace count 2-32, 33=33+next byte */
142 unsigned roff:2; /* relative offset 0-2, 3=3+next byte */
143 unsigned type:1; /* type of replacement: 0=mode0, 1=mode1 */
145 unsigned type:1; /* type of replacement: 0=mode0, 1=mode1 */
146 unsigned roff:2; /* relative offset 0-2, 3=3+next byte */
147 unsigned replace_count:5; /* replace count 2-32, 33=33+next byte */
153 #define MIN(a,b) (((a)>=(b))?(b):(a))
158 #define MAX_OFFSET0 14 /* Largest unscaled value an offset can have before extra byte is needed. */
159 #define OFFSET_START0 0
160 #define MAX_COUNT0 6 /* Largest unscaled value a count can have before extra byte is needed */
161 #define COUNT_START0 1 /* What a count of zero has a value of. */
163 #define MAX_OFFSET1 2
164 #define OFFSET_START1 0
165 #define MAX_COUNT1 30
166 #define COUNT_START1 2
168 //*********************************************************
169 // This is based on code that came from Kevin Hudson.
182 BOOL Mode9::Process(RASTERDATA* input)
183 // compresses input data,
184 // result in Mode9::compressbuf,
185 // updates compressedsize
188 (input->rasterdata[COLORTYPE_COLOR]==NULL && input->rasterdata[COLORTYPE_BLACK]==NULL)) // flushing pipeline
195 if (!ResetSeedRow && input->rasterdata[myplane] == 0)
202 memset(compressBuf, 0, inputsize * 2);
204 unsigned int originalsize=input->rastersize[myplane];
205 unsigned int size=input->rastersize[myplane];
208 // Convert 8 bit per pixel data into 1 bit per pixel data
209 if (myplane == COLORTYPE_BLACK)
211 if (input->rasterdata[myplane] == 0)
213 memset(originalKData, 0, inputsize);
214 size = originalsize = inputsize;
218 size = originalsize = (input->rastersize[myplane]+7)/8;
219 memset(originalKData, 0, size);
221 int curBit = 0x80, curByte = 0;
222 for (int i=0; i<input->rastersize[myplane]; i++)
224 if (input->rasterdata[myplane][i])
226 originalKData[curByte] |= curBit;
235 curBit = curBit >> 1;
241 if ((myphase) && (myphase->prev)) // if in pipeline, as opposed to autonomous call
243 layer = myphase->prev->Exec->iRastersDelivered;
247 if (myplane == COLORTYPE_BLACK)
252 layer--; // using as offset
253 char *sptr = (char *)(&SeedRow[size*layer]);
256 if (myplane == COLORTYPE_BLACK)
258 nptr = originalKData;
262 nptr = input->rasterdata[myplane];
266 unsigned int offset,byte_count,rem_count;
267 Mode9_comtype command;
268 char* dest= (char*) compressBuf;
269 register char *dptr=dest;
276 * If we are here because we are doing KRGB processing, don't offset off of
277 * the seedrow because seedrow here and one setup with mode10 may be out of sync,
278 * causing artifacts in the output.
281 if (seeded && !m_bVIPPrinter)
283 /* find a difference between the seed row and this row. */
284 while ((*sptr++ == *nptr++) && (offset < size) )
292 if ( offset >= size ) /* too far to find diff, bail */
297 if ((*nptr != nptr[1]) || (size < 2)) /************ if doing a mode 0 **********/
299 command.bitf0.type = 0;
300 last_byte = *nptr++; /* keep track of the last_byte */
301 sptr++; /* seed pointer must keep up with nptr */
304 /* Now find all of the bytes in a row that don't match
305 either a run of mode3 or mode 1. A slight
306 optimization here would be to not jump out of this
307 run of mode 0 for a single mode 3 or two mode 1
308 bytes if we have to jump right back into mode 0,
309 especially if there are already 7 mode 0 bytes here
310 (we've already spent the extra byte for the
312 while ((*sptr++ != *nptr) && (last_byte != *nptr) && (byte_count < size))
319 /* Adjust the count if the last_byte == current_byte.
320 Save these bytes for the upcomming run of mode 1. */
321 if ((byte_count < size) && (last_byte == (char)*nptr))
323 nptr--; /* Now sptr points to first byte in the new run of mode 1. */
329 /* Now output full command. If offset is over 14 then
330 need optional offset bytes. If byte count is over 7
331 then need optional byte count. */
333 if (offset > (MAX_OFFSET0+OFFSET_START0))
334 command.bitf0.roff = MAX_OFFSET0+1;
336 command.bitf0.roff = offset-OFFSET_START0;
338 if (byte_count > (MAX_COUNT0+COUNT_START0))
339 command.bitf0.replace_count = MAX_COUNT0+1;
341 command.bitf0.replace_count = byte_count-COUNT_START0;
343 *dptr++ = command.comchar;
345 if (offset > (MAX_OFFSET0+OFFSET_START0))
347 offset -= (MAX_OFFSET0+OFFSET_START0+1);
356 *dptr++ = MIN ( offset, 255 );
361 offset -= MIN ( offset, 255 );
366 if (byte_count > (MAX_COUNT0+COUNT_START0))
368 rem_count = byte_count - (MAX_COUNT0+COUNT_START0+1);
375 *dptr++ = MIN ( rem_count, 255 );
377 if ( rem_count == 255 )
380 rem_count -= MIN ( rem_count, 255 );
385 /* Now output the run of bytes. First set up a pointer to the first source byte. */
387 tempPtr = nptr - byte_count;
388 for(;byte_count;byte_count--)
390 *dptr++ = *tempPtr++;
393 } else /************ If doing a mode 1 *************/
395 /* mode 1, next two bytes are equal */
396 command.bitf1.type = 1;
401 while ((last_byte == *nptr++) && (byte_count < size))
409 if (offset > (MAX_OFFSET1+OFFSET_START1))
410 command.bitf1.roff = MAX_OFFSET1+1;
412 command.bitf1.roff = offset-OFFSET_START1;
414 if (byte_count > (MAX_COUNT1+COUNT_START1))
415 command.bitf1.replace_count = MAX_COUNT1+1;
417 command.bitf1.replace_count = byte_count-COUNT_START1;
419 *dptr++ = command.comchar;
421 if (offset > (MAX_OFFSET1+OFFSET_START1))
423 offset -= (MAX_OFFSET1+OFFSET_START1+1);
432 *dptr++ = MIN ( offset, 255 );
437 offset -= MIN ( offset, 255 );
440 } /* if (offset > MAX... */
442 if (byte_count > (MAX_COUNT1+COUNT_START1))
444 rem_count = byte_count - (MAX_COUNT1+COUNT_START1+1);
451 *dptr++ = MIN ( rem_count, 255 );
453 if ( rem_count == 255 )
456 rem_count -= MIN ( rem_count, 255 );
459 } /* if (byte_count > ... */
461 *dptr++ = last_byte; /* Now output the repeated byte. */
463 } /* while (size > 0) */
466 size = ( dptr - dest );
467 compressedsize = size;
468 if (myplane == COLORTYPE_BLACK)
470 memcpy(&(SeedRow[layer*originalsize]), originalKData, originalsize);
474 memcpy(&(SeedRow[layer*originalsize]), input->rasterdata[myplane], originalsize);
483 * Only 8xx, 8x5, 9xx, ljmono and ljcolor use Mode2
486 #if defined(APDK_DJ8xx)|| defined(APDK_DJ9xx) || defined(APDK_LJMONO) || defined(APDK_LJCOLOR)
489 Mode2::Mode2 (SystemServices* pSys, unsigned int RasterSize)
490 : Compressor (pSys, RasterSize, FALSE)
492 compressBuf = (BYTE*)pSS->AllocMem(RasterSize );
493 if (compressBuf == NULL)
494 constructor_error=ALLOCMEM_ERROR;
500 BOOL Mode2::Process (RASTERDATA* input)
501 // mode 2 compression code from Kevin Hudson
503 BYTE* pDst = compressBuf;
507 (myplane == COLORTYPE_COLOR && input->rasterdata[COLORTYPE_COLOR] == NULL) ||
508 (myplane == COLORTYPE_BLACK && input->rasterdata[COLORTYPE_BLACK] == NULL)) // flushing pipeline
516 unsigned int size = input->rastersize[myplane];
517 for (unsigned int ni = 0; ni < size;)
519 if ( ni + 1 < size && input->rasterdata[myplane][ ni ] == input->rasterdata[myplane][ ni + 1 ] )
521 unsigned int nrepeatcount;
522 for ( ni += 2, nrepeatcount = 1; ni < size && nrepeatcount < 127; ++ni, ++nrepeatcount )
524 if ( input->rasterdata[myplane][ ni ] != input->rasterdata[myplane][ ni - 1 ] )
529 int tmprepeat = 0 - nrepeatcount;
530 BYTE trunc = (BYTE) tmprepeat;
531 pDst[ ndstcount++ ] = trunc;
532 pDst[ ndstcount++ ] = input->rasterdata[myplane][ ni - 1 ];
538 for ( ++ni, nliteralcount = 0; ni < size && nliteralcount < 127; ++ni, ++nliteralcount )
540 if ( input->rasterdata[myplane][ ni ] == input->rasterdata[myplane][ ni - 1 ] )
547 pDst[ ndstcount++ ] = (BYTE) nliteralcount;
548 for ( int nj = 0; nj <= nliteralcount; ++nj )
550 pDst[ ndstcount++ ] = input->rasterdata[myplane][ nfirst++ ];
556 compressedsize = size;
560 #endif // if 8xx, 9xx, ljmono, ljcolor
564 * Mode 3 (Delta Row Compression)
568 Mode3::Mode3 (SystemServices* pSys, Printer *pPrinter, unsigned int RasterSize)
569 : Compressor (pSys, RasterSize, TRUE)
571 // Worst case is when two rows are completely different
572 // In that case, one command byte is added for every 8 bytes
573 // In the worst case, compression expands data by 50%
574 compressBuf = (BYTE*)pSS->AllocMem(RasterSize + RasterSize/2);
575 if (compressBuf == NULL)
576 constructor_error=ALLOCMEM_ERROR;
578 memset (SeedRow, 0x0, inputsize);
579 m_pPrinter = pPrinter;
594 memset (SeedRow, 0x0, inputsize);
595 m_pPrinter->Send ((const BYTE *) "\033*b0Y", 5);
599 BOOL Mode3::Process (RASTERDATA *input)
602 (myplane == COLORTYPE_COLOR && input->rasterdata[COLORTYPE_COLOR] == NULL) ||
603 (myplane == COLORTYPE_BLACK && input->rasterdata[COLORTYPE_BLACK] == NULL)) // flushing pipeline
613 unsigned int uOrgSize = input->rastersize[myplane];
614 unsigned int size = input->rastersize[myplane];
615 unsigned int uOffset;
617 BYTE *pszSptr = SeedRow;
618 BYTE *pszInPtr = input->rasterdata[myplane];
621 BYTE *pszOutPtr = compressBuf;
629 while ((*pszSptr == *pszInPtr) && (uOffset < size))
644 pszCurPtr = pszInPtr;
648 while ((*pszSptr != *pszInPtr) && ucByteCount < size && ucByteCount < 8)
657 *pszOutPtr++ = ((ucByteCount << 5) | uOffset);
662 *pszOutPtr++ = ((ucByteCount << 5) | 31);
664 while (uOffset >= 255)
669 *pszOutPtr++ = uOffset;
672 size -= (ucByteCount);
673 memcpy (pszOutPtr, pszCurPtr, ucByteCount);
674 pszOutPtr += ucByteCount;
677 compressedsize = pszOutPtr - compressBuf;
678 memcpy (SeedRow, input->rasterdata[myplane], uOrgSize);
686 #endif // APDK_LJCOLOR
689 ////////////////////////////////////////////////////////////////////