1 /*****************************************************************************\
2 Mode9.cpp : implementaiton of Mode9 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 \*****************************************************************************/
33 Mode9::Mode9 (unsigned int RasterSize, bool bPackedBits)
34 : Compressor(RasterSize, true)
36 if (constructor_error != NO_ERROR) // if error in base constructor
39 // Allocate double the RasterSize to accommodate worst case
40 compressBuf = (BYTE*) new BYTE[RasterSize * 2];
41 if (compressBuf == NULL)
42 constructor_error=ALLOCMEM_ERROR;
44 memset(compressBuf, 0, RasterSize * 2);
45 memset(SeedRow,0,RasterSize);
48 m_bPackedBits = bPackedBits;
54 ////////////////////////////////////////////////////////////////////////////
57 unsigned char comchar; /* command byte as char */
60 #if defined(APDK_LITTLE_ENDIAN) || defined(LITTLE_ENDIAN_HW)
61 unsigned replace_count:3; /* replace count 1-7, 8=8+next byte */
62 unsigned roff:4; /* relative offset 0-14, 15=15+next byte */
63 unsigned type:1; /* type of replacement: 0=mode0, 1=mode1 */
65 unsigned type:1; /* type of replacement: 0=mode0, 1=mode1 */
66 unsigned roff:4; /* relative offset 0-14, 15=15+next byte */
67 unsigned replace_count:3; /* replace count 1-7, 8=8+next byte */
72 #if defined(APDK_LITTLE_ENDIAN) || defined(LITTLE_ENDIAN_HW)
73 unsigned replace_count:5; /* replace count 2-32, 33=33+next byte */
74 unsigned roff:2; /* relative offset 0-2, 3=3+next byte */
75 unsigned type:1; /* type of replacement: 0=mode0, 1=mode1 */
77 unsigned type:1; /* type of replacement: 0=mode0, 1=mode1 */
78 unsigned roff:2; /* relative offset 0-2, 3=3+next byte */
79 unsigned replace_count:5; /* replace count 2-32, 33=33+next byte */
85 #define MIN(a,b) (((a)>=(b))?(b):(a))
90 #define MAX_OFFSET0 14 /* Largest unscaled value an offset can have before extra byte is needed. */
91 #define OFFSET_START0 0
92 #define MAX_COUNT0 6 /* Largest unscaled value a count can have before extra byte is needed */
93 #define COUNT_START0 1 /* What a count of zero has a value of. */
96 #define OFFSET_START1 0
98 #define COUNT_START1 2
100 //*********************************************************
101 // This is based on code that came from Kevin Hudson.
111 memset (SeedRow, 0, inputsize);
114 bool Mode9::Process(RASTERDATA* input)
115 // compresses input data,
116 // result in Mode9::compressbuf,
117 // updates compressedsize
120 (input->rasterdata[COLORTYPE_COLOR]==NULL && input->rasterdata[COLORTYPE_BLACK]==NULL)) // flushing pipeline
128 if (!ResetSeedRow && input->rasterdata[myplane] == 0)
135 memset(compressBuf, 0, inputsize * 2);
137 unsigned int originalsize=input->rastersize[myplane];
138 unsigned int size=input->rastersize[myplane];
141 // Convert 8 bit per pixel data into 1 bit per pixel data
142 if (myplane == COLORTYPE_BLACK)
144 if (input->rasterdata[myplane] == 0)
146 memset(originalKData, 0, inputsize+1);
147 size = originalsize = inputsize;
151 size = originalsize = (input->rastersize[myplane]+7)/8;
152 memset(originalKData, 0, size);
154 memcpy(originalKData, input->rasterdata[myplane], size);
157 int curBit = 0x80, curByte = 0;
158 for (int i=0; i<input->rastersize[myplane]; i++)
160 if (input->rasterdata[myplane][i])
162 originalKData[curByte] |= curBit;
171 curBit = curBit >> 1;
178 if ((myphase) && (myphase->prev)) // if in pipeline, as opposed to autonomous call
180 layer = myphase->prev->Exec->iRastersDelivered;
184 if (myplane == COLORTYPE_BLACK)
189 layer--; // using as offset
190 char *sptr = (char *)(&SeedRow[size*layer]);
193 if (myplane == COLORTYPE_BLACK)
195 nptr = originalKData;
199 nptr = input->rasterdata[myplane];
203 unsigned int offset,byte_count,rem_count;
204 Mode9_comtype command;
205 char* dest= (char*) compressBuf;
206 register char *dptr=dest;
214 /* find a difference between the seed row and this row. */
215 while ((offset < size) && (*sptr++ == *nptr++))
223 if ( offset >= size ) /* too far to find diff, bail */
228 if ((*nptr != nptr[1]) || (size < 2)) /************ if doing a mode 0 **********/
230 command.bitf0.type = 0;
231 last_byte = *nptr++; /* keep track of the last_byte */
232 sptr++; /* seed pointer must keep up with nptr */
235 /* Now find all of the bytes in a row that don't match
236 either a run of mode3 or mode 1. A slight
237 optimization here would be to not jump out of this
238 run of mode 0 for a single mode 3 or two mode 1
239 bytes if we have to jump right back into mode 0,
240 especially if there are already 7 mode 0 bytes here
241 (we've already spent the extra byte for the
243 while ((*sptr++ != *nptr) && (last_byte != *nptr) && (byte_count < size))
250 /* Adjust the count if the last_byte == current_byte.
251 Save these bytes for the upcomming run of mode 1. */
252 if ((byte_count < size) && (last_byte == (char)*nptr))
254 nptr--; /* Now sptr points to first byte in the new run of mode 1. */
260 /* Now output full command. If offset is over 14 then
261 need optional offset bytes. If byte count is over 7
262 then need optional byte count. */
264 if (offset > (MAX_OFFSET0+OFFSET_START0))
265 command.bitf0.roff = MAX_OFFSET0+1;
267 command.bitf0.roff = offset-OFFSET_START0;
269 if (byte_count > (MAX_COUNT0+COUNT_START0))
270 command.bitf0.replace_count = MAX_COUNT0+1;
272 command.bitf0.replace_count = byte_count-COUNT_START0;
274 *dptr++ = command.comchar;
276 if (offset > (MAX_OFFSET0+OFFSET_START0))
278 offset -= (MAX_OFFSET0+OFFSET_START0+1);
287 *dptr++ = MIN ( offset, 255 );
292 offset -= MIN ( offset, 255 );
297 if (byte_count > (MAX_COUNT0+COUNT_START0))
299 rem_count = byte_count - (MAX_COUNT0+COUNT_START0+1);
306 *dptr++ = MIN ( rem_count, 255 );
308 if ( rem_count == 255 )
311 rem_count -= MIN ( rem_count, 255 );
316 /* Now output the run of bytes. First set up a pointer to the first source byte. */
318 tempPtr = nptr - byte_count;
319 for(;byte_count;byte_count--)
321 *dptr++ = *tempPtr++;
324 } else /************ If doing a mode 1 *************/
326 /* mode 1, next two bytes are equal */
327 command.bitf1.type = 1;
332 while ((last_byte == *nptr++) && (byte_count < size))
340 if (offset > (MAX_OFFSET1+OFFSET_START1))
341 command.bitf1.roff = MAX_OFFSET1+1;
343 command.bitf1.roff = offset-OFFSET_START1;
345 if (byte_count > (MAX_COUNT1+COUNT_START1))
346 command.bitf1.replace_count = MAX_COUNT1+1;
348 command.bitf1.replace_count = byte_count-COUNT_START1;
350 *dptr++ = command.comchar;
352 if (offset > (MAX_OFFSET1+OFFSET_START1))
354 offset -= (MAX_OFFSET1+OFFSET_START1+1);
363 *dptr++ = MIN ( offset, 255 );
368 offset -= MIN ( offset, 255 );
371 } /* if (offset > MAX... */
373 if (byte_count > (MAX_COUNT1+COUNT_START1))
375 rem_count = byte_count - (MAX_COUNT1+COUNT_START1+1);
382 *dptr++ = MIN ( rem_count, 255 );
384 if ( rem_count == 255 )
387 rem_count -= MIN ( rem_count, 255 );
390 } /* if (byte_count > ... */
392 *dptr++ = last_byte; /* Now output the repeated byte. */
394 } /* while (size > 0) */
397 size = static_cast<int>((dptr - dest));
398 compressedsize = size;
399 if (myplane == COLORTYPE_BLACK)
401 memcpy(&(SeedRow[layer*originalsize]), originalKData, originalsize);
405 memcpy(&(SeedRow[layer*originalsize]), input->rasterdata[myplane], originalsize);
413 bool Mode9::NextOutputRaster(RASTERDATA& next_raster)
414 // since we return 1-for-1, just return result first call
416 if (iRastersReady==0){
420 if (myplane == COLORTYPE_BLACK)
422 if (compressedsize != 0)
424 next_raster.rastersize[COLORTYPE_BLACK] = compressedsize;
425 next_raster.rasterdata[COLORTYPE_BLACK] = compressBuf;
429 next_raster.rastersize[COLORTYPE_BLACK] = 0;
430 next_raster.rasterdata[COLORTYPE_BLACK] = raster.rasterdata[COLORTYPE_BLACK];
432 next_raster.rastersize[COLORTYPE_COLOR] = raster.rastersize[COLORTYPE_COLOR];
433 next_raster.rasterdata[COLORTYPE_COLOR] = raster.rasterdata[COLORTYPE_COLOR];
437 if (myplane == COLORTYPE_COLOR)
439 if (compressedsize != 0)
441 next_raster.rastersize[COLORTYPE_COLOR] = compressedsize;
442 next_raster.rasterdata[COLORTYPE_COLOR] = compressBuf;
446 next_raster.rastersize[COLORTYPE_COLOR] = 0;
447 next_raster.rasterdata[COLORTYPE_COLOR] = raster.rasterdata[COLORTYPE_COLOR];
449 next_raster.rastersize[COLORTYPE_BLACK] = raster.rastersize[COLORTYPE_BLACK];
450 next_raster.rasterdata[COLORTYPE_BLACK] = raster.rasterdata[COLORTYPE_BLACK];