Tizen 2.1 base
[platform/upstream/hplip.git] / prnt / hpcups / Mode10.cpp
1 /*****************************************************************************\
2   Mode10.cpp : Implementation of Mode10 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 #include "Mode10.h"
32
33 Mode10::Mode10 (unsigned int PlaneSize) : Compressor (PlaneSize, true)
34 {
35     if (constructor_error != NO_ERROR)  // if error in base constructor
36     {
37         return;
38     }
39
40     union
41     {
42         short    s;
43         char     c[2];
44     } uEndian;
45     uEndian.s = 0x0A0B;
46     m_eEndian = LITTLEENDIAN;
47     if (uEndian.c[0] == 0x0A)
48         m_eEndian = BIGENDIAN;
49
50         // In the worst case, compression expands data by 50%
51         compressBuf = new BYTE[(PlaneSize + PlaneSize/2)];
52         if (compressBuf == NULL)
53                 constructor_error = ALLOCMEM_ERROR;
54
55     memset (SeedRow, 0xFF, PlaneSize);
56 } //Mode10
57
58 Mode10::~Mode10()
59 { }
60
61 void Mode10::Flush ()
62 {
63     if (!seeded)
64     {
65         return;
66     }
67         compressedsize = 0;
68     iRastersReady = 0;
69     seeded = false;
70     memset (SeedRow, 0xFF, inputsize);
71 } //Flush
72
73 inline uint32_t Mode10::get3Pixel (BYTE *pixAddress, int pixelOffset)
74 {
75     pixAddress += ((pixelOffset << 1) + pixelOffset);     //pixAddress += pixelOffset * 3;
76
77     BYTE r = *(pixAddress);
78     BYTE g = *(pixAddress + 1);
79     BYTE b = *(pixAddress + 2);
80
81     return (kWhite & ((r << 16) | (g << 8) | (b)));
82
83 } //get3Pixel
84
85 void Mode10::put3Pixel (BYTE *pixAddress, int pixelOffset, uint32_t pixel)
86 {
87     pixAddress += ((pixelOffset << 1) + pixelOffset);     //pixAddress += pixelOffset * 3;
88
89     unsigned int temp = (pixel & kWhite);
90
91     *(pixAddress)     = ((temp >> 16) & 0x000000FF);
92     *(pixAddress + 1) = ((temp >> 8) & 0x000000FF);
93     *(pixAddress + 2) = (temp & 0x000000FF);
94
95 } //put3Pixel
96
97
98 unsigned short Mode10::ShortDelta (uint32_t lastPixel, uint32_t lastUpperPixel)
99 {
100     int dr, dg, db;
101     int result;
102
103     dr = GetRed (lastPixel) - GetRed (lastUpperPixel);
104     dg = GetGreen (lastPixel) - GetGreen (lastUpperPixel);
105     db = GetBlue (lastPixel) - GetBlue (lastUpperPixel);
106
107     if ((dr <= 15) && (dr >= -16) && (dg <= 15) && (dg >= -16) && (db <= 30) && (db >= -32))
108     {   // Note db is divided by 2 to double it's range from -16..15 to -32..30
109         result = ((dr << 10) & 0x007C00) | (((dg << 5) & 0x0003E0) | ((db >> 1) & 0x01F) | 0x8000);   // set upper bit to signify short delta
110     }
111     else
112     {
113         result = 0;  // upper bit is zero to signify delta won't work
114     }
115
116     return (unsigned short) result;
117 }
118
119 bool Mode10::Process (RASTERDATA *input)
120 /****************************************************************************
121 Initially written by Elden Wood
122 August 1998
123
124 Similar to mode 9, though tailored for pixel data.
125 For more information see the Bert Compression Format document.
126
127 This function compresses a single row per call.
128 ****************************************************************************/
129 {
130     if (input == NULL || 
131        (input->rasterdata[COLORTYPE_COLOR] == NULL && input->rasterdata[COLORTYPE_BLACK] == NULL))    // flushing pipeline
132     {
133         Flush ();
134         return false;
135     }
136
137     if (myplane == COLORTYPE_BLACK || input->rasterdata[COLORTYPE_COLOR]==NULL)
138     {
139         iRastersReady = 1;
140         compressedsize = 0;
141         return true;
142     }
143     unsigned int originalsize = input->rastersize[myplane];
144     unsigned int size = input->rastersize[myplane];
145
146     unsigned char *seedRowPtr = (unsigned char *) SeedRow;
147
148     unsigned char *compressedDataPtr = compressBuf;
149     unsigned char *curRowPtr =  (unsigned char *) input->rasterdata[myplane];
150     unsigned int rowWidthInBytes = size;
151     ASSERT(curRowPtr);
152     ASSERT(seedRowPtr);
153     ASSERT(compressedDataPtr);
154     ASSERT(rowWidthInBytes >= BYTES_PER_PIXEL);
155     ASSERT((rowWidthInBytes % BYTES_PER_PIXEL) == 0);
156
157     unsigned char *compressedDataStart = compressedDataPtr;
158     unsigned int lastPixel = (rowWidthInBytes / BYTES_PER_PIXEL) - 1;
159
160     // Setup sentinal value to replace last pixel of curRow. Simplifies future end condition checking.
161     uint32_t realLastPixel = getPixel(curRowPtr, lastPixel);
162
163     uint32_t newLastPixel = realLastPixel;
164     while ((getPixel (curRowPtr, lastPixel - 1) == newLastPixel) ||
165            (getPixel (seedRowPtr, lastPixel) == newLastPixel))
166     {
167         putPixel (curRowPtr, lastPixel, newLastPixel += 0x100); // add one to green.
168     }
169     unsigned int curPixel = 0;
170     unsigned int seedRowPixelCopyCount;
171     unsigned int cachedColor = kWhite;
172
173     do // all pixels in row
174     {
175         unsigned char CMDByte = 0;
176         int replacementCount;
177
178         // Find seedRowPixelCopyCount for upcoming copy
179         seedRowPixelCopyCount = curPixel;
180         while (getPixel (seedRowPtr, curPixel) == getPixel (curRowPtr, curPixel))
181         {
182             curPixel++;
183         }
184
185         seedRowPixelCopyCount = curPixel - seedRowPixelCopyCount;
186         ASSERT (curPixel <= lastPixel);
187
188         int pixelSource = 0;
189
190         if (curPixel == lastPixel) // On last pixel of row. RLE could also leave us on the last pixel of the row from the previous iteration.
191         {
192             putPixel(curRowPtr, lastPixel, realLastPixel);
193
194             if (getPixel(seedRowPtr, curPixel) == realLastPixel)
195             {
196                 goto mode10rtn;
197             }
198             else // code last pix as a literal
199             {
200
201                 CMDByte = eLiteral;
202                 pixelSource = eeNewPixel;
203                 replacementCount = 1;
204                 curPixel++;
205             }
206         }
207         else // prior to last pixel of row
208         {
209             ASSERT(curPixel < lastPixel);
210
211             replacementCount = curPixel;
212             uint32_t RLERun = getPixel (curRowPtr, curPixel);
213
214             curPixel++; // Adjust for next pixel.
215             while (RLERun == getPixel (curRowPtr, curPixel)) // RLE
216             {
217                 curPixel++;
218             }
219             curPixel--; // snap back to current.
220             replacementCount = curPixel - replacementCount;
221             ASSERT(replacementCount >= 0);
222
223             if (replacementCount > 0) // Adjust for total occurance and move to next pixel to do.
224             {
225                 curPixel++;
226                 replacementCount++;
227
228                 if (cachedColor == RLERun)
229                 {
230                     pixelSource = eeCachedColor;
231                 }
232                 else if (getPixel (seedRowPtr, curPixel-replacementCount + 1) == RLERun)
233                 {
234                     pixelSource = eeNEPixel;
235                 }
236                 else if ((curPixel-replacementCount > 0) &&
237                          (getPixel (curRowPtr, curPixel-replacementCount - 1) == RLERun))
238                 {
239                     pixelSource = eeWPixel;
240                 }
241                 else
242                 {
243                     pixelSource = eeNewPixel;
244                     cachedColor = RLERun;
245                 }
246
247                 CMDByte = eRLE; // Set default for later.
248
249             }
250
251             if (curPixel == lastPixel)
252             {
253                 ASSERT(replacementCount > 0); // Already found some RLE pixels
254
255                 if (realLastPixel == RLERun) // Add to current RLE. Otherwise it'll be part of the literal from the seedrow section above on the next iteration.
256                 {
257                     putPixel (curRowPtr, lastPixel, realLastPixel);
258                     replacementCount++;
259                     curPixel++;
260                 }
261             }
262
263             if (0 == replacementCount) // no RLE so it's a literal by default.
264             {
265                 uint32_t tempPixel = getPixel (curRowPtr, curPixel);
266
267                 ASSERT(tempPixel != getPixel (curRowPtr, curPixel + 1)); // not RLE
268                 ASSERT(tempPixel != getPixel (seedRowPtr, curPixel)); // not seedrow copy
269
270                 CMDByte = eLiteral;
271
272                 if (cachedColor == tempPixel)
273                 {
274                     pixelSource = eeCachedColor;
275
276                 }
277                 else if (getPixel (seedRowPtr, curPixel + 1) == tempPixel)
278                 {
279                     pixelSource = eeNEPixel;
280
281                 }
282                 else if ((curPixel > 0) &&  (getPixel (curRowPtr, curPixel-1) == tempPixel))
283                 {
284                     pixelSource = eeWPixel;
285
286                 }
287                 else
288                 {
289
290                     pixelSource = eeNewPixel;
291                     cachedColor = tempPixel;
292                 }
293
294                 replacementCount = curPixel;
295                 uint32_t cachePixel;
296                 uint32_t nextPixel = getPixel (curRowPtr, curPixel+1);
297                 do
298                 {
299                     if (++curPixel == lastPixel)
300                     {
301                         putPixel (curRowPtr, lastPixel, realLastPixel);
302                         curPixel++;
303                         break;
304                     }
305                     cachePixel = nextPixel;
306                 }
307                 while ((cachePixel != (nextPixel = getPixel (curRowPtr, curPixel+1))) &&
308                        (cachePixel != getPixel (seedRowPtr, curPixel)));
309
310                 replacementCount = curPixel - replacementCount;
311
312                 ASSERT(replacementCount > 0);
313             }
314         }
315
316         //ASSERT(seedRowPixelCopyCount >= 0);
317
318         // Write out compressed data next.
319         if (eLiteral == CMDByte)
320         {
321             ASSERT(replacementCount >= 1);
322
323             replacementCount -= 1; // normalize it
324
325             CMDByte |= pixelSource; // Could put this directly into CMDByte above.
326             CMDByte |= MIN(3, seedRowPixelCopyCount) << 3;
327             CMDByte |= MIN(7, replacementCount);
328
329             *compressedDataPtr++ = CMDByte;
330
331             if (seedRowPixelCopyCount >= 3)
332             {
333                 outputVLIBytesConsecutively (seedRowPixelCopyCount - 3, compressedDataPtr);
334             }
335
336             replacementCount += 1; // denormalize it
337
338             int totalReplacementCount = replacementCount;
339             int upwardPixelCount = 1;
340
341             if (eeNewPixel != pixelSource)
342             {
343                 replacementCount -= 1; // Do not encode 1st pixel of run since it comes from an alternate location.
344                 upwardPixelCount = 2;
345             }
346
347             for ( ; upwardPixelCount <= totalReplacementCount; upwardPixelCount++)
348             {
349                 ASSERT(totalReplacementCount >= upwardPixelCount);
350
351                 unsigned short compressedPixel = ShortDelta (getPixel (curRowPtr, curPixel - replacementCount),
352                                                              getPixel (seedRowPtr, curPixel - replacementCount));
353                 if (compressedPixel)
354                 {
355                     *compressedDataPtr++ = compressedPixel >> 8;
356                     *compressedDataPtr++ = (unsigned char)compressedPixel;
357
358                 }
359                 else
360                 {
361                     uint32_t uncompressedPixel = getPixel (curRowPtr, curPixel - replacementCount);
362
363                     uncompressedPixel >>= 1; // Lose the lsb of blue and zero out the msb of the 3 bytes.
364
365                     *compressedDataPtr++ = (BYTE) (uncompressedPixel >> 16);
366                     *compressedDataPtr++ = (BYTE) (uncompressedPixel >> 8);
367                     *compressedDataPtr++ = (BYTE) (uncompressedPixel);
368
369                 }
370
371                 if (((upwardPixelCount-8) % 255) == 0)  // See if it's time to spill a single VLI byte.
372                 {
373                     *compressedDataPtr++ = MIN(255, totalReplacementCount - upwardPixelCount);
374                 }
375
376                 replacementCount--;
377             }
378         }
379         else // RLE
380         {
381             ASSERT(replacementCount >= 2);
382
383             replacementCount -= 2; // normalize it
384
385             CMDByte |= pixelSource; // Could put this directly into CMDByte above.
386             CMDByte |= MIN(3, seedRowPixelCopyCount) << 3;
387             CMDByte |= MIN(7, replacementCount);
388
389             *compressedDataPtr++ = CMDByte;
390
391             if (seedRowPixelCopyCount >= 3)
392             {
393                 outputVLIBytesConsecutively (seedRowPixelCopyCount - 3, compressedDataPtr);
394             }
395
396             replacementCount += 2; // denormalize it
397
398             if (eeNewPixel == pixelSource)
399             {
400                 unsigned short compressedPixel = ShortDelta(getPixel (curRowPtr, curPixel - replacementCount),
401                                                             getPixel (seedRowPtr, curPixel - replacementCount));
402                 if (compressedPixel)
403                 {
404                     *compressedDataPtr++ = compressedPixel >> 8;
405                     *compressedDataPtr++ = (unsigned char) compressedPixel;
406                 }
407                 else
408                 {
409                     uint32_t uncompressedPixel = getPixel (curRowPtr, curPixel - replacementCount);
410
411                     uncompressedPixel >>= 1;
412
413                     *compressedDataPtr++ = (BYTE) (uncompressedPixel >> 16);
414                     *compressedDataPtr++ = (BYTE) (uncompressedPixel >> 8);
415                     *compressedDataPtr++ = (BYTE) (uncompressedPixel);
416                 }
417             }
418
419             if (replacementCount - 2 >= 7) outputVLIBytesConsecutively (replacementCount - (7+2), compressedDataPtr);
420         }
421     } while (curPixel <= lastPixel);
422 mode10rtn:
423     size = static_cast<int>(compressedDataPtr - compressedDataStart); // return # of compressed bytes.
424     compressedsize = size;
425     memcpy (SeedRow, input->rasterdata[myplane], originalsize);
426     seeded = true;
427     iRastersReady = 1;
428     return true;
429 } //Process
430
431 bool Mode10::NextOutputRaster (RASTERDATA& next_raster)
432 {
433     if (iRastersReady == 0)
434     {
435         return false;
436     }
437
438     if (myplane == COLORTYPE_COLOR && compressedsize != 0)
439     {
440         next_raster.rastersize[COLORTYPE_COLOR] = compressedsize;
441         next_raster.rasterdata[COLORTYPE_COLOR] = compressBuf;
442     }
443     else
444     {
445         next_raster.rastersize[COLORTYPE_COLOR] = 0;
446         next_raster.rasterdata[COLORTYPE_COLOR] = raster.rasterdata[COLORTYPE_COLOR];
447     }
448
449     next_raster.rastersize[COLORTYPE_BLACK] = raster.rastersize[COLORTYPE_BLACK];
450     next_raster.rasterdata[COLORTYPE_BLACK] = raster.rasterdata[COLORTYPE_BLACK];
451
452     iRastersReady = 0;
453     return true;
454 }
455