Tizen 2.1 base
[platform/upstream/hplip.git] / prnt / hpijs / compression.cpp
1 /*****************************************************************************\
2   compression.cpp : Implimentation for the Compressor class
3
4   Copyright (c) 1996 - 2001, Hewlett-Packard Co.
5   All rights reserved.
6
7   Redistribution and use in source and binary forms, with or without
8   modification, are permitted provided that the following conditions
9   are met:
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.
18
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 \*****************************************************************************/
30
31
32 #include "header.h"
33
34 APDK_BEGIN_NAMESPACE
35
36 Compressor::Compressor(SystemServices* pSys, unsigned int RasterSize, BOOL useseed)
37     : pSS(pSys), SeedRow(NULL), UseSeedRow(useseed), inputsize(RasterSize), seeded(FALSE)
38 {
39     constructor_error=NO_ERROR;
40     iRastersReady=0;
41
42         originalKData=pSS->AllocMem(RasterSize);
43         CNEWCHECK(originalKData);
44
45     if (!UseSeedRow)
46         return;
47
48     SeedRow=pSS->AllocMem(RasterSize);
49     CNEWCHECK(SeedRow);
50 }
51
52 Compressor::~Compressor()
53 {
54         if (compressBuf) 
55                 pSS->FreeMem (compressBuf);
56     if (SeedRow)
57         pSS->FreeMem (SeedRow);
58         if (originalKData)
59                 pSS->FreeMem (originalKData);
60 }
61
62 unsigned int Compressor::GetOutputWidth(COLORTYPE color)
63 // since we return 1-for-1, just return result first call
64 {
65         if (myplane == color)
66         {
67                 return compressedsize;
68         }
69         else
70         {
71                 return raster.rastersize[color];
72         }
73 }
74
75
76 BYTE* Compressor::NextOutputRaster(COLORTYPE color)
77 // since we return 1-for-1, just return result first call
78 {
79     if (iRastersReady==0)
80         return (BYTE*)NULL;
81         if (color == COLORTYPE_COLOR)
82         {
83                 iRastersReady=0;
84         }
85         if (myplane == color)
86         {
87                 if (raster.rasterdata[color] == NULL)
88                         if (compressedsize != 0 && myplane == COLORTYPE_BLACK)
89                                 return compressBuf;
90                         else
91                                 return NULL;
92                 else
93                         return compressBuf;
94         }
95         else
96         {
97                 return raster.rasterdata[color];
98         }
99 }
100
101 Mode9::Mode9 (SystemServices* pSys,unsigned int RasterSize, BOOL bVIPPrinter)
102     : Compressor(pSys,RasterSize, TRUE)
103 {
104     if (constructor_error != NO_ERROR)  // if error in base constructor
105         return;
106
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;
111
112         memset(compressBuf, 0, RasterSize * 2);
113     memset(SeedRow,0,RasterSize);
114
115         ResetSeedRow = FALSE;
116     m_bVIPPrinter = bVIPPrinter;
117 }
118
119 Mode9::~Mode9()
120 { }
121
122 ////////////////////////////////////////////////////////////////////////////
123
124 typedef union {
125     unsigned char comchar;  /* command byte as char */
126     struct
127     {
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 */
132 #else
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 */
136 #endif
137     } bitf0;
138     struct
139     {
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 */
144 #else
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 */
148 #endif
149     } bitf1;
150 } Mode9_comtype;
151
152 #ifndef MIN
153 #define MIN(a,b)    (((a)>=(b))?(b):(a))
154 #endif
155
156 #define kPCLMode9           9
157
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. */
162
163 #define MAX_OFFSET1         2
164 #define OFFSET_START1       0
165 #define MAX_COUNT1          30
166 #define COUNT_START1        2
167
168 //*********************************************************
169 // This is based on code that came from Kevin Hudson.
170
171 void Mode9::Flush()
172 {
173     if (!seeded)
174         return;
175
176         compressedsize=0;
177
178     iRastersReady=0;
179     seeded=FALSE;
180 }
181
182 BOOL Mode9::Process(RASTERDATA* input)
183 // compresses input data,
184 // result in Mode9::compressbuf,
185 // updates compressedsize
186 {
187     if (input==NULL || 
188                 (input->rasterdata[COLORTYPE_COLOR]==NULL && input->rasterdata[COLORTYPE_BLACK]==NULL))    // flushing pipeline
189     {
190         Flush();
191         return FALSE;
192     }
193         else seeded = TRUE;
194
195         if (!ResetSeedRow && input->rasterdata[myplane] == 0)
196         {
197                 compressedsize=0;
198                 iRastersReady=1;
199                 return TRUE;
200         }
201
202         memset(compressBuf, 0, inputsize * 2);
203
204     unsigned int originalsize=input->rastersize[myplane];
205         unsigned int size=input->rastersize[myplane];
206         unsigned int layer;
207
208         //  Convert 8 bit per pixel data into 1 bit per pixel data
209         if (myplane == COLORTYPE_BLACK)
210         {
211                 if (input->rasterdata[myplane] == 0)
212                 {
213                         memset(originalKData, 0, inputsize);
214                         size = originalsize = inputsize;
215                 }
216                 else
217                 {
218                         size = originalsize = (input->rastersize[myplane]+7)/8;
219                         memset(originalKData, 0, size);
220
221                         int curBit = 0x80, curByte = 0;
222                         for (int i=0; i<input->rastersize[myplane]; i++)
223                         {
224                                 if (input->rasterdata[myplane][i])
225                                 {
226                                         originalKData[curByte] |= curBit;
227                                 }
228                                 if (curBit == 0x01)
229                                 {
230                                         curByte++;
231                                         curBit = 0x80;
232                                 }
233                                 else
234                                 {
235                                         curBit = curBit >> 1;
236                                 }
237                         }
238                         ResetSeedRow = TRUE;
239                 }
240         }
241     if ((myphase) && (myphase->prev))       // if in pipeline, as opposed to autonomous call
242         {
243         layer = myphase->prev->Exec->iRastersDelivered;
244         }
245     else layer = 1;
246
247         if (myplane == COLORTYPE_BLACK)
248         {
249                 layer = 1;
250         }
251
252     layer--;    // using as offset
253     char *sptr = (char *)(&SeedRow[size*layer]);
254
255     BYTE *nptr;
256         if (myplane == COLORTYPE_BLACK)
257         {
258                 nptr = originalKData;
259         }
260         else
261         {
262                 nptr = input->rasterdata[myplane];
263         }
264     BYTE *tempPtr;
265     char last_byte;
266     unsigned int    offset,byte_count,rem_count;
267     Mode9_comtype       command;
268     char* dest=    (char*) compressBuf;
269     register char *dptr=dest;
270
271     while ( size > 0 )
272     {
273         offset = 0;
274
275 /*
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.
279  */
280
281         if (seeded && !m_bVIPPrinter)
282         {
283             /* find a difference between the seed row and this row. */
284             while ((*sptr++ == *nptr++) && (offset < size) )
285             {
286                 offset++;
287             }
288             sptr--;
289             nptr--;
290         }
291
292         if ( offset >= size )   /* too far to find diff, bail */
293           goto bail;
294
295         size -= offset;
296
297         if ((*nptr != nptr[1]) || (size < 2))   /************  if doing a mode 0 **********/
298         {
299             command.bitf0.type = 0;
300             last_byte = *nptr++;   /* keep track of the last_byte */
301             sptr++;        /* seed pointer must keep up with nptr */
302             byte_count = 1;
303
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
311                byte-count) */
312             while ((*sptr++ != *nptr) && (last_byte != *nptr) && (byte_count < size))
313             {
314                byte_count++;
315                last_byte = *nptr++;
316             }
317             sptr--;
318
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))
322             {
323                 nptr--;  /* Now sptr points to first byte in the new run of mode 1. */
324                 sptr--;
325                 byte_count--;
326             }
327
328             size -= byte_count;
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. */
332
333             if (offset > (MAX_OFFSET0+OFFSET_START0))
334                 command.bitf0.roff = MAX_OFFSET0+1;
335             else
336                 command.bitf0.roff = offset-OFFSET_START0;
337
338             if (byte_count > (MAX_COUNT0+COUNT_START0))
339                 command.bitf0.replace_count = MAX_COUNT0+1;
340             else
341                 command.bitf0.replace_count = byte_count-COUNT_START0;
342
343             *dptr++ = command.comchar;
344
345             if (offset > (MAX_OFFSET0+OFFSET_START0))
346             {
347                 offset -= (MAX_OFFSET0+OFFSET_START0+1);
348                 if (offset == 0)
349                 {
350                     *dptr++ = 0;
351                 }
352                 else
353                 {
354                      while( offset )
355                      {
356                        *dptr++ = MIN ( offset, 255 );
357
358                        if ( offset == 255 )
359                        *dptr++ = 0;
360
361                         offset -= MIN ( offset, 255 );
362                     }
363                 }
364             }
365
366             if (byte_count > (MAX_COUNT0+COUNT_START0))
367             {
368                 rem_count = byte_count - (MAX_COUNT0+COUNT_START0+1);
369                 if (rem_count == 0)
370                     *dptr++ = 0;
371                 else
372                 {
373                     while( rem_count )
374                     {
375                         *dptr++ = MIN ( rem_count, 255 );
376
377                         if ( rem_count == 255 )
378                         *dptr++ = 0;
379
380                          rem_count -= MIN ( rem_count, 255 );
381                     }
382                 }
383             }
384
385             /* Now output the run of bytes.  First set up a pointer to the first source byte. */
386
387             tempPtr = nptr - byte_count;
388             for(;byte_count;byte_count--)
389             {
390                 *dptr++ = *tempPtr++;
391             }
392
393         } else      /************ If doing a mode 1 *************/
394         {
395             /* mode 1, next two bytes are equal */
396             command.bitf1.type = 1;
397             nptr++;
398             last_byte = *nptr++;
399             byte_count = 2;
400
401             while ((last_byte == *nptr++) && (byte_count < size))
402             {
403                byte_count++;
404             }
405             nptr--;
406             sptr += byte_count;
407             size -= byte_count;
408
409             if (offset > (MAX_OFFSET1+OFFSET_START1))
410                 command.bitf1.roff = MAX_OFFSET1+1;
411             else
412                 command.bitf1.roff = offset-OFFSET_START1;
413
414             if (byte_count > (MAX_COUNT1+COUNT_START1))
415                 command.bitf1.replace_count = MAX_COUNT1+1;
416             else
417                 command.bitf1.replace_count =  byte_count-COUNT_START1;
418
419             *dptr++ = command.comchar;
420
421             if (offset > (MAX_OFFSET1+OFFSET_START1))
422             {
423                 offset -= (MAX_OFFSET1+OFFSET_START1+1);
424                 if (offset == 0)
425                 {
426                  *dptr++ = 0;
427                 }
428                 else
429                 {
430                      while( offset )
431                      {
432                         *dptr++ = MIN ( offset, 255 );
433
434                         if ( offset == 255 )
435                             *dptr++ = 0;
436
437                         offset -= MIN ( offset, 255 );
438                     }
439                 }
440             }  /* if (offset > MAX...  */
441
442             if (byte_count > (MAX_COUNT1+COUNT_START1))
443             {
444                 rem_count = byte_count - (MAX_COUNT1+COUNT_START1+1);
445                 if (rem_count == 0)
446                     *dptr++ = 0;
447                 else
448                 {
449                     while( rem_count )
450                     {
451                         *dptr++ = MIN ( rem_count, 255 );
452
453                         if ( rem_count == 255 )
454                             *dptr++ = 0;
455
456                         rem_count -= MIN ( rem_count, 255 );
457                     }
458                  }
459              }  /* if (byte_count > ... */
460
461              *dptr++ = last_byte;  /* Now output the repeated byte. */
462         }
463     }  /* while (size > 0) */
464
465 bail:
466     size = ( dptr - dest );
467     compressedsize = size;
468         if (myplane == COLORTYPE_BLACK)
469         {
470                 memcpy(&(SeedRow[layer*originalsize]), originalKData, originalsize);
471         }
472         else
473         {
474                 memcpy(&(SeedRow[layer*originalsize]), input->rasterdata[myplane], originalsize);
475         }
476     seeded = TRUE;
477     iRastersReady=1;
478
479         return TRUE;
480 }
481
482 /*
483  *  Only 8xx, 8x5, 9xx, ljmono and ljcolor use Mode2
484  */
485
486 #if defined(APDK_DJ8xx)|| defined(APDK_DJ9xx) || defined(APDK_LJMONO) || defined(APDK_LJCOLOR)
487
488
489 Mode2::Mode2 (SystemServices* pSys, unsigned int RasterSize)
490     : Compressor (pSys, RasterSize, FALSE)
491 {
492         compressBuf = (BYTE*)pSS->AllocMem(RasterSize );
493                 if (compressBuf == NULL)
494                         constructor_error=ALLOCMEM_ERROR;
495 }
496
497 Mode2::~Mode2()
498 { }
499
500 BOOL Mode2::Process (RASTERDATA* input)
501 // mode 2 compression code from Kevin Hudson
502 {
503     BYTE* pDst = compressBuf;
504     int ndstcount = 0;
505
506     if (input==NULL || 
507                 (myplane == COLORTYPE_COLOR && input->rasterdata[COLORTYPE_COLOR] == NULL) ||
508             (myplane == COLORTYPE_BLACK && input->rasterdata[COLORTYPE_BLACK] == NULL))    // flushing pipeline
509     {
510                 compressedsize=0;
511
512         iRastersReady=0;
513         return FALSE;
514     }
515
516         unsigned int size = input->rastersize[myplane];
517     for (unsigned int ni = 0; ni < size;)
518     {
519         if ( ni + 1 < size && input->rasterdata[myplane][ ni ] == input->rasterdata[myplane][ ni + 1 ] )
520         {
521             unsigned int nrepeatcount;
522             for ( ni += 2, nrepeatcount = 1; ni < size && nrepeatcount < 127; ++ni, ++nrepeatcount )
523             {
524                 if ( input->rasterdata[myplane][ ni ] != input->rasterdata[myplane][ ni - 1 ] )
525                 {
526                     break;
527                 }
528             }
529             int tmprepeat = 0 - nrepeatcount;
530             BYTE trunc = (BYTE) tmprepeat;
531             pDst[ ndstcount++ ] = trunc;
532             pDst[ ndstcount++ ] = input->rasterdata[myplane][ ni - 1 ];
533         }
534         else
535         {
536             int nliteralcount;
537             int nfirst = ni;
538             for ( ++ni, nliteralcount = 0; ni < size && nliteralcount < 127; ++ni, ++nliteralcount )
539             {
540                 if ( input->rasterdata[myplane][ ni ] == input->rasterdata[myplane][ ni - 1 ] )
541                 {
542                     --ni;
543                     --nliteralcount;
544                     break;
545                 }
546             }
547             pDst[ ndstcount++ ] = (BYTE) nliteralcount;
548             for ( int nj = 0; nj <= nliteralcount; ++nj )
549             {
550                 pDst[ ndstcount++ ] = input->rasterdata[myplane][ nfirst++ ];
551             }
552         }
553     }
554
555     size = ndstcount;
556     compressedsize = size;
557     iRastersReady = 1;
558     return TRUE;
559 }
560 #endif      // if 8xx, 9xx, ljmono, ljcolor
561
562 #ifdef APDK_LJCOLOR
563 /*
564  *  Mode 3 (Delta Row Compression)
565  *  Raghu Cauligi
566  */
567
568 Mode3::Mode3 (SystemServices* pSys, Printer *pPrinter, unsigned int RasterSize)
569      : Compressor (pSys, RasterSize, TRUE)
570 {
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;
577         
578     memset (SeedRow, 0x0, inputsize);
579     m_pPrinter = pPrinter;
580 }
581
582 Mode3::~Mode3 ()
583 {
584
585 }
586
587 void Mode3::Flush ()
588 {
589     if (!seeded)
590         return;
591         compressedsize=0;
592     iRastersReady  = 0;
593     seeded         = FALSE;
594     memset (SeedRow, 0x0, inputsize);
595     m_pPrinter->Send ((const BYTE *) "\033*b0Y", 5);
596
597 }
598
599 BOOL Mode3::Process (RASTERDATA *input)
600 {
601     if (input==NULL || 
602                 (myplane == COLORTYPE_COLOR && input->rasterdata[COLORTYPE_COLOR] == NULL) ||
603             (myplane == COLORTYPE_BLACK && input->rasterdata[COLORTYPE_BLACK] == NULL))    // flushing pipeline
604     {
605         Flush();
606         return FALSE;
607     }
608     else
609     {
610         seeded = TRUE;
611     }
612
613     unsigned    int     uOrgSize = input->rastersize[myplane];
614         unsigned    int     size = input->rastersize[myplane];
615     unsigned    int     uOffset;
616
617     BYTE        *pszSptr  = SeedRow;
618     BYTE        *pszInPtr = input->rasterdata[myplane];
619     BYTE        *pszCurPtr;
620     BYTE        ucByteCount;
621     BYTE        *pszOutPtr = compressBuf;
622
623     while (size > 0)
624     {
625         uOffset = 0;
626
627         if (seeded)
628         {
629             while ((*pszSptr == *pszInPtr) && (uOffset < size))
630             {
631                 pszSptr++;
632                 pszInPtr++;
633                 uOffset++;
634             }
635         }
636
637         if (uOffset >= size)
638         {
639           break;
640         }
641
642         size -= uOffset;
643
644         pszCurPtr = pszInPtr;
645         ucByteCount = 1;
646         pszSptr++;
647         pszInPtr++;
648         while ((*pszSptr != *pszInPtr) && ucByteCount < size && ucByteCount < 8)
649         {
650             pszSptr++;
651             pszInPtr++;
652             ucByteCount++;
653         }
654         ucByteCount--;
655         if (uOffset < 31)
656         {
657             *pszOutPtr++ = ((ucByteCount << 5) | uOffset);
658         }
659         else
660         {
661             uOffset -= 31;
662             *pszOutPtr++ = ((ucByteCount << 5) | 31);
663
664             while (uOffset >= 255)
665             {
666                 *pszOutPtr++ = 255;
667                 uOffset -= 255;
668             }
669             *pszOutPtr++ = uOffset;
670         }
671         ucByteCount++;
672         size -= (ucByteCount);
673         memcpy (pszOutPtr, pszCurPtr, ucByteCount);
674         pszOutPtr += ucByteCount;
675     }
676
677     compressedsize = pszOutPtr - compressBuf;
678     memcpy (SeedRow, input->rasterdata[myplane], uOrgSize);
679     seeded = TRUE;
680     iRastersReady = 1;
681     return TRUE;
682
683 // Mode 3
684 }
685
686 #endif  // APDK_LJCOLOR
687 APDK_END_NAMESPACE
688
689 ////////////////////////////////////////////////////////////////////
690