Tizen 2.1 base
[platform/upstream/hplip.git] / prnt / hpijs / halftoner_open.cpp
1 /*****************************************************************************\
2   halftoner_open.cpp : Open Source Imaging Halftoning
3
4   Copyright (c) 1994 - 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 "header.h"
32 #include "halftoner.h"
33 #include "halftoner_open.h"
34
35 APDK_BEGIN_NAMESPACE
36
37 extern unsigned char BayerMatrix[];
38
39 Halftoner_Open::Halftoner_Open
40 (
41     SystemServices* pSys,
42     PrintMode* pPM,
43     unsigned int iInputWidth,
44     unsigned int iNumRows[],
45     unsigned int HiResFactor,
46     BOOL matrixbased
47 )
48     :  Halftoner(pSys,pPM,iInputWidth,iNumRows,HiResFactor,matrixbased)
49 {  }
50
51
52 Halftoner_Open::~Halftoner_Open()
53 { }
54
55
56 BOOL Halftoner_Open::Process
57 (
58     RASTERDATA* pbyInputKRGBRaster
59 )
60 {
61     unsigned int i;
62     int j, k;
63 \r
64     if ((pbyInputKRGBRaster == NULL) ||
65        (pbyInputKRGBRaster && pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR]==NULL && pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK]==NULL))
66     {
67         Restart();
68         return FALSE;   // no output
69     }
70     started=TRUE;
71
72     for (i=StartPlane; i < (ColorPlaneCount+StartPlane); i++)
73     {
74         for (j=0; j < NumRows[i]; j++)
75         {
76             for (k=0; k < ColorDepth[i]; k++)
77             {
78                 int PlaneSize= (OutputWidth[i] + 7) / 8;
79                 memset(ColorPlane[i][j][k], 0, PlaneSize);
80             }
81         }
82     }
83         if (pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR])
84         {
85                 // increment current raster
86                 ++nNextRaster;
87                 if ( -1 == nNextRaster )
88                         nNextRaster = 0;
89
90                 fRasterOdd        = ( 1 & nNextRaster ) ? 0 : 1;
91
92                 BYTE* input;
93                 unsigned int numpix;
94
95                 for (i=StartPlane; i <= EndPlane; i++)
96                 {
97                         if (OutputWidth[i] > AdjustedInputWidth)
98                         {
99                                 memset(tempBuffer, 0, OutputWidth[i]);  // clear it out because outwidth might be
100                                                                                                                 // > factor*inwidth due to roundoff
101                                 memcpy(tempBuffer,pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR],InputWidth);
102                                 int factor = NumRows[i] * ResBoost;
103                                 PixelMultiply(tempBuffer, InputWidth, factor);
104                                 input=tempBuffer;
105                                 numpix = OutputWidth[i];
106                         }
107                         else
108                         {
109                                 input=pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR];
110                                 numpix = AdjustedInputWidth;
111                         }
112
113                         fDitherParms[i].fNumPix = numpix;
114                         fDitherParms[i].fInput = input;
115                         fDitherParms[i].fErr = ErrBuff[i];
116                         fDitherParms[i].fErr++; // This is for serpentine
117                         fDitherParms[i].fSymmetricFlag = HPTRUE;   // Symmetric only
118                         if (i == K)
119                                 fDitherParms[i].fFEDResPtr = fBlackFEDResPtr;
120                         else
121                                 fDitherParms[i].fFEDResPtr = fColorFEDResPtr;
122                         fDitherParms[i].fRasterEvenOrOdd = fRasterOdd;
123                         fDitherParms[i].fHifipe = ColorDepth[i]>1;
124
125                         // for matrix //////////////
126                         if (usematrix)
127                         {
128                                 fDitherParms[i].fSqueezeOffset=0;
129                                 fDitherParms[i].fMatrixRowSize = BayerMatrix[1];
130                                 BYTE colorindex = i + 2;
131                                 if (i>=Y)
132                                         colorindex = 4;
133                                 BYTE ditheroffset = BayerMatrix[colorindex];
134                                 BYTE matrixrowsize = BayerMatrix[1];
135                                 fDitherParms[i].fDitherCellOffset = ditheroffset;
136                                 HPBytePtr matrixptr = (HPBytePtr)(
137                                         (((ditheroffset + nNextRaster) % matrixrowsize) * matrixrowsize)
138                                                 + 5 + BayerMatrix);
139
140                                 fDitherParms[i].fMatrixV1 = matrixptr;
141                         }
142
143                         ////////////////////////////////////
144
145                         for (j=0; j < NumRows[i]; j++)
146                         {
147                                 fDitherParms[i].fOutput1 = ColorPlane[i][j][0];
148                                 fDitherParms[i].fOutput2 = ColorPlane[i][j][1];
149
150                                 if (usematrix)
151                                 {
152                                         memset(fDitherParms[i].fOutput1, 0, OutputWidth[i]/8);
153                                         if (fDitherParms[i].fOutput2)
154                                                 memset(fDitherParms[i].fOutput2, 0, OutputWidth[i]/8);
155                                         HTMATRIXHI_KCMY((THTDitherParmsPtr) fDitherParms, i);
156                                 }
157                                 else HTEDiffOpen   ((THTDitherParmsPtr) fDitherParms, i);
158
159
160                                 // cleanup bits at end of row due to input-width not being divisible by 8
161                                 CleanOddBits(i,j);
162                         }
163
164                         pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR] += InputWidth;
165
166                 }
167         }
168
169         if (pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK])
170         {
171                 int factor = 1;
172                 if (OutputWidth[K] > AdjustedInputWidth)
173                 {
174                         memset(tempBuffer, 0, OutputWidth[K]);
175                         memcpy(tempBuffer,pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK],pbyInputKRGBRaster->rastersize[COLORTYPE_BLACK]);
176
177                         factor = NumRows[K] * ResBoost;
178                         PixelMultiply(tempBuffer, pbyInputKRGBRaster->rastersize[COLORTYPE_BLACK], factor);
179                 }
180
181                 //  Convert 8bit per pixel data into 1 bit per pixel data
182                 memset(originalKData, 0, (pbyInputKRGBRaster->rastersize[COLORTYPE_BLACK] * factor +7)/8);
183                 int curBit = 0x80, curByte = 0;
184                 for (int i=0; i<pbyInputKRGBRaster->rastersize[COLORTYPE_BLACK] * factor; i++)
185                 {
186                         if (OutputWidth[K] > AdjustedInputWidth)
187                         {
188                                 if (tempBuffer[i])
189                                 {
190                                         originalKData[curByte] |= curBit;
191                                 }
192                         }
193                         else
194                         {
195                                 if (pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK][i])
196                                 {
197                                         originalKData[curByte] |= curBit;
198                                 }
199                         }
200                         if (curBit == 0x01)
201                         {
202                                 curByte++;
203                                 curBit = 0x80;
204                         }
205                         else
206                         {
207                                 curBit = curBit >> 1;
208                         }
209                 }
210                 for (j=0; j < NumRows[K]; j++)
211                 {
212                         for (k = 0; k < (pbyInputKRGBRaster->rastersize[COLORTYPE_BLACK] * factor +7)/8; k++)
213                                 if (ColorPlane[K][j][0])
214                                         ColorPlane[K][j][0][k] |= originalKData[k];
215                                 if (ColorPlane[K][j][1])
216                                         ColorPlane[K][j][1][k] |= originalKData[k];
217                 }
218         }
219
220         iColor = StartPlane;
221         iRow = iPlane = 0;
222         iRastersReady = PlaneCount();
223         iRastersDelivered = 0;
224         return TRUE;   // one raster in, one raster out
225 } //Process
226
227
228 void Halftoner_Open::HTEDiffOpen
229 (
230     THTDitherParmsPtr ditherParmsPtr,
231     HPUInt16 count
232 )
233 {
234
235
236     ditherParms = ditherParmsPtr+count;
237     errPtr = ditherParms->fErr;
238     numLoop = ditherParms->fNumPix;
239     inputPtr = ditherParms->fInput;
240     fedResTbl = ditherParms->fFEDResPtr;
241     symmetricFlag = ditherParms->fSymmetricFlag;
242     doNext8Pixels = HPTRUE;
243     hifipe = ditherParms->fHifipe;
244     outputPtr1 = ditherParms->fOutput1;
245
246     outputPtr1 = ditherParms->fOutput1;
247
248     if (hifipe)
249     {
250         outputPtr1 = ditherParms->fOutput1;
251         outputPtr2 = ditherParms->fOutput2;
252         outputPtr3 = ditherParms->fOutput3;
253     }
254
255     diffusionErrorPtr = errPtr;
256
257     rasterByte1 = 0;
258     rasterByte2 = 0;
259     rasterByte3 = 0;
260
261     if( ditherParms->fRasterEvenOrOdd == 1 )
262     {
263         tmpShortStore = *diffusionErrorPtr;
264
265         *diffusionErrorPtr = 0;
266
267         for (pixelCount = numLoop + 8; (pixelCount -= 8) > 0; )
268         {
269             if (pixelCount > 16) // if next 16 pixels are white, skip 8
270             {
271                 doNext8Pixels = Forward16PixelsNonWhite(inputPtr);
272             }
273             else
274             {
275                 doNext8Pixels = HPTRUE;
276             }
277
278             if (doNext8Pixels)
279             {
280                 thValue = HPRand();
281                 FORWARD_FED( thValue, 0x80 );
282                 thValue = HPRand();
283                 FORWARD_FED( thValue, 0x40 );
284                 thValue = HPRand();
285                 FORWARD_FED( thValue, 0x20 );
286                 thValue = HPRand();
287                 FORWARD_FED( thValue, 0x10 );
288                 thValue = HPRand();
289                 FORWARD_FED( thValue, 0x08 );
290                 thValue = HPRand();
291                 FORWARD_FED( thValue, 0x04 );
292                 thValue = HPRand();
293                 FORWARD_FED( thValue, 0x02 );
294                 thValue = HPRand();
295                 FORWARD_FED( thValue, 0x01 );
296
297                 *outputPtr1++ = rasterByte1;
298                 rasterByte1 = 0;
299
300                 if (hifipe)
301                 {
302                     *outputPtr2++ = rasterByte2;
303                     rasterByte2 = 0;
304                 }
305             }
306             else  // Do white space skipping
307             {
308                 inputPtr += 8;
309                 *outputPtr1++ = 0;
310                 if (hifipe)
311                 {
312                     *outputPtr2++ = 0;
313                 }
314                 *diffusionErrorPtr++ = 0;
315                 *diffusionErrorPtr++ = 0;
316                 *diffusionErrorPtr++ = 0;
317                 *diffusionErrorPtr++ = 0;
318                 *diffusionErrorPtr++ = 0;
319                 *diffusionErrorPtr++ = 0;
320                 *diffusionErrorPtr++ = 0;
321                 *diffusionErrorPtr++ = 0;
322                 rasterByte1 = 0;
323                 rasterByte2 = 0;
324                 tmpShortStore = 0;
325             }
326         } // for pixelCount
327     }
328     else
329     {
330         rasterByte1 = 0;
331         rasterByte2 = 0;
332         inputPtr  += ( numLoop-1 );
333         outputPtr1 += ( numLoop/8 - 1 );
334         outputPtr2 += ( numLoop/8 - 1 );
335         diffusionErrorPtr += ( numLoop-1 );
336
337         tmpShortStore = *diffusionErrorPtr;
338
339         *diffusionErrorPtr = 0;
340
341         for (pixelCount = numLoop + 8; (pixelCount -= 8) > 0; )
342         {
343             if (pixelCount > 16) // if next 16 pixels are white, skip 8
344             {
345                 doNext8Pixels = Backward16PixelsNonWhite(inputPtr);
346             }
347             else
348             {
349                 doNext8Pixels = HPTRUE;
350             }
351
352             if (doNext8Pixels)
353             {
354                 thValue = HPRand();
355                 BACKWARD_FED( thValue, 0x01 );
356                 thValue = HPRand();
357                 BACKWARD_FED( thValue, 0x02 );
358                 thValue = HPRand();
359                 BACKWARD_FED( thValue, 0x04 );
360                 thValue = HPRand();
361                 BACKWARD_FED( thValue, 0x08 );
362                 thValue = HPRand();
363                 BACKWARD_FED( thValue, 0x10 );
364                 thValue = HPRand();
365                 BACKWARD_FED( thValue, 0x20 );
366                 thValue = HPRand();
367                 BACKWARD_FED( thValue, 0x40 );
368                 thValue = HPRand();
369                 BACKWARD_FED( thValue, 0x80 );
370
371                 *outputPtr1-- = rasterByte1;
372                 rasterByte1 = 0;
373
374                 if (hifipe)
375                 {
376                     *outputPtr2-- = rasterByte2;
377                     rasterByte2 = 0;
378                 }
379             }
380             else  // Do white space skipping
381             {
382                 inputPtr -= 8;
383                 *outputPtr1-- = 0;
384                 if (hifipe)
385                 {
386                     *outputPtr2-- = 0;
387                 }
388                 *diffusionErrorPtr-- = 0;
389                 *diffusionErrorPtr-- = 0;
390                 *diffusionErrorPtr-- = 0;
391                 *diffusionErrorPtr-- = 0;
392                 *diffusionErrorPtr-- = 0;
393                 *diffusionErrorPtr-- = 0;
394                 *diffusionErrorPtr-- = 0;
395                 *diffusionErrorPtr-- = 0;
396                 rasterByte1 = 0;
397                 rasterByte2 = 0;
398                 tmpShortStore = 0;
399             }
400         }
401     }
402 } //HTEDiffOpen
403
404 //////////////////////////////////////////////////////////
405 void Halftoner_Open::FORWARD_FED
406 (
407     HPInt16 thresholdValue,
408     unsigned int bitMask
409 )
410 {
411     tone = (*inputPtr++ );
412     fedResPtr = fedResTbl + (tone << 2);
413     level = *fedResPtr++;
414     if (tone != 0)
415     {
416     tone = ( tmpShortStore + (HPInt16)(*fedResPtr++) );
417     if (tone >= thresholdValue)
418         {
419         tone -= 255;
420         level++;
421         }
422         switch (level)
423         {
424             case 0:
425             break;
426             case 1:
427             rasterByte1 |= bitMask;
428             break;
429             case 2:
430             rasterByte2 |= bitMask;
431             break;
432             case 3:
433             rasterByte2 |= bitMask; rasterByte1 |= bitMask;
434             break;
435             case 4:
436             rasterByte3 |= bitMask;
437             break;
438             case 5:
439             rasterByte3 |= bitMask; rasterByte1 |= bitMask;
440             break;
441             case 6:
442             rasterByte3 |= bitMask; rasterByte2 |= bitMask;
443             break;
444             case 7:
445             rasterByte3 |= bitMask; rasterByte2 |= bitMask; rasterByte1 |= bitMask;
446             break;
447         }
448     }
449     else
450     {
451     tone = tmpShortStore;
452     }
453     *diffusionErrorPtr++ = tone >> 1;
454     tmpShortStore = *diffusionErrorPtr + (tone - (tone >> 1));
455 } //FORWARD_FED
456
457
458 void Halftoner_Open::BACKWARD_FED
459 (
460     HPInt16 thresholdValue,
461     unsigned int bitMask
462 )
463 {
464     tone = (*inputPtr-- );
465     fedResPtr = fedResTbl + (tone << 2);
466     level = *fedResPtr++;
467     if (tone != 0)
468     {
469     tone = ( tmpShortStore + (HPInt16)(*fedResPtr++) );
470     if (tone >= thresholdValue)
471         {
472         tone -= 255;
473         level++;
474         }
475         switch (level)
476         {
477             case 0:
478             break;
479             case 1:
480             rasterByte1 |= bitMask;
481             break;
482             case 2:
483             rasterByte2 |= bitMask;
484             break;
485             case 3:
486             rasterByte2 |= bitMask; rasterByte1 |= bitMask;
487             break;
488             case 4:
489             rasterByte3 |= bitMask;
490             break;
491             case 5:
492             rasterByte3 |= bitMask; rasterByte1 |= bitMask;
493             break;
494             case 6:
495             rasterByte3 |= bitMask; rasterByte2 |= bitMask;
496             break;
497             case 7:
498             rasterByte3 |= bitMask; rasterByte2 |= bitMask; rasterByte1 |= bitMask;
499             break;
500         }
501     }
502     else
503     {
504     tone = tmpShortStore;
505     }
506     *diffusionErrorPtr-- = tone >> 1;
507     tmpShortStore = *diffusionErrorPtr + (tone - (tone >> 1));
508
509 } //BACKWARD_FED
510
511 APDK_END_NAMESPACE