Tizen 2.0 Release
[platform/upstream/hplip.git] / prnt / hpijs / halftoner.cpp
1 /*****************************************************************************\
2   halftoner.cpp : Implimentation for the Halftoner 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 //===========================================================================
33 //
34 //  Filename     :  halftoner.cpp
35 //
36 //  Module       :  Open Source Imaging
37 //
38 //  Description  :  This file contains the constructor and destructor for
39 //                  the Halftoner class, which performs color-matching and
40 //                  halftoning.
41 //
42 // Detailed Description:
43 //
44 // The only member functions needed are Process(inputRaster)
45 // and Restart (used to skip white space and for new page).
46 //
47 // Configurability required in Slimhost driver is reflected in the
48 // parameters to the constructor:
49 // 1. SystemServices encapsulates memory management for platform-independence
50 // 2. PrintMode contains info on resolution and other properties
51 // 3. iInputWidth tells how many pixels input per plane
52 // 4. iNumRows is 1 except for mixed-resolution cases
53 // 5. HiResFactor is for boosting base resolution, e.g. 2 if 600 dpi grid
54 //      (base res assumed to be 300)
55 //
56 // These structures, together with the variable StartPlane (designating
57 // K or C in the fixed ordering KCMY), are accessed by the Translator
58 // component of the driver, in order to properly package the data in
59 // the printer command language.
60 //============================================================================
61
62 #include "header.h"
63 #include "hptypes.h"
64 #include "halftoner.h"
65
66 APDK_BEGIN_NAMESPACE
67
68 Halftoner::Halftoner
69 (
70     SystemServices* pSys,
71     PrintMode* pPM,
72     unsigned int iInputWidth,
73     unsigned int iNumRows[],
74     unsigned int HiResFactor,
75     BOOL matrixbased
76 ) : ColorPlaneCount(pPM->dyeCount),
77     InputWidth(iInputWidth),
78     ResBoost(HiResFactor),
79     pSS(pSys),
80     nNextRaster(0),
81     fBlackFEDResPtr(pPM->BlackFEDTable),
82     fColorFEDResPtr(pPM->ColorFEDTable),
83     iColor(0),
84     iRow(0),
85     iPlane(0),
86     tempBuffer(NULL),
87     tempBuffer2(NULL),
88     hold_random(0),
89     usematrix(matrixbased)
90 {
91     unsigned int i;
92     int j,k,PlaneSize;
93     constructor_error = NO_ERROR;
94
95     StartPlane = K;       // most common case
96
97     if (ColorPlaneCount == 3)     // CMY pen
98       {
99         StartPlane=C;
100         NumRows[K] = ColorDepth[K] = OutputWidth[K] = 0;
101       }
102
103     EndPlane=Y;         // most common case
104     if (ColorPlaneCount == 6)
105     {
106         EndPlane = Mlight;
107     }
108     if (ColorPlaneCount == 1)
109     {
110         EndPlane = K;
111     }
112
113     AdjustedInputWidth = InputWidth;
114     if (AdjustedInputWidth % 8)
115     {
116         AdjustedInputWidth += 8 - (AdjustedInputWidth % 8);
117     }
118
119     // init arrays
120     for (i = StartPlane; i < (ColorPlaneCount + StartPlane); i++)
121     {
122         ColorDepth[i]= pPM->ColorDepth[i];
123         NumRows[i]=iNumRows[i];
124
125         OutputWidth[i] = AdjustedInputWidth * NumRows[i] * ResBoost;
126
127     }
128     for (;i < (unsigned)MAXCOLORPLANES; i++)
129     {
130         NumRows[i] = ColorDepth[i] = OutputWidth[i] = 0;
131     }
132
133     oddbits = AdjustedInputWidth - InputWidth;
134     ///////////////////////////////////////////////////////////////////////////
135     for (i=0; i <= Mlight; i++)
136     {
137         ErrBuff[i]=NULL;
138     }
139
140     for (i=StartPlane; i <= EndPlane; i++)
141     {
142         ErrBuff[i] = (short*)pSS->AllocMem((OutputWidth[i] + 2) * sizeof(short));
143         if (ErrBuff[i] == NULL)
144         {
145             goto MemoryError;
146         }
147     }
148
149     if (OutputWidth[K] > AdjustedInputWidth)
150     // need to expand input data (easier than expanding bit-pixels after) on K row
151     {
152         tempBuffer = (BYTE*) pSS->AllocMem(OutputWidth[K]);
153         if (tempBuffer == NULL)
154         {
155             goto MemoryError;
156         }
157         if (EndPlane > Y)
158         {
159             tempBuffer2 = (BYTE*) pSS->AllocMem(OutputWidth[K]);
160             if (tempBuffer2 == NULL)
161             {
162                 goto MemoryError;
163             }
164         }
165
166     }
167
168
169     Restart();  // this zeroes buffers and sets nextraster counter
170
171     // allocate output buffers
172     for (i = 0; i < (unsigned)MAXCOLORPLANES; i++)
173     {
174         for (j = 0; j < MAXCOLORROWS; j++)
175         {
176             for (k = 0; k < MAXCOLORDEPTH; k++)
177             {
178                 ColorPlane[i][j][k] = NULL;
179             }
180         }
181     }
182
183     for (i=StartPlane; i < (ColorPlaneCount+StartPlane); i++)
184     {
185         for (j=0; j < NumRows[i]; j++)
186         {
187             for (k=0; k < ColorDepth[i]; k++)
188             {
189                 PlaneSize= OutputWidth[i]/8 + // doublecheck ... should already be divisble by 8
190                             ((OutputWidth[i] % 8)!=0);
191                 ColorPlane[i][j][k] = (BYTE*) pSS->AllocMem(PlaneSize);
192                 if (ColorPlane[i][j] == NULL)
193                 {
194                     goto MemoryError;
195                 }
196                 memset(ColorPlane[i][j][k], 0, PlaneSize);
197             }
198         }
199     }
200
201     PlaneSize = (OutputWidth[0] + 7) / 8;
202     if (PlaneSize > 0)
203     {
204         originalKData = (BYTE*) pSS->AllocMem(PlaneSize);
205         if (originalKData == NULL)
206         {
207             goto MemoryError;
208         }
209         memset(originalKData, 0, PlaneSize);
210     }
211     return;
212
213 MemoryError:
214     constructor_error=ALLOCMEM_ERROR;
215
216     FreeBuffers();
217
218     for (i=0; i < ColorPlaneCount; i++)
219     {
220         for (j=0; j < NumRows[i]; j++)
221         {
222             for (k=0; k < ColorDepth[i]; k++)
223             {
224                 if (ColorPlane[i][j][k])
225                 {
226                     pSS->FreeMemory(ColorPlane[i][j][k]);
227                 }
228             }
229         }
230     }
231         if (originalKData)
232         {
233                 pSS->FreeMemory(originalKData);
234         }
235
236 } //Halftoner
237
238
239 Halftoner::~Halftoner()
240 {
241     DBG1("destroying Halftoner \n");
242
243     FreeBuffers();
244
245     for (int i=0; i < MAXCOLORPLANES; i++)
246     {
247         for (int j=0; j < NumRows[i]; j++)
248         {
249             for (int k=0; k < ColorDepth[i]; k++)
250             {
251                 if (ColorPlane[i][j][k])
252                 {
253                     pSS->FreeMemory(ColorPlane[i][j][k]);
254                 }
255             }
256         }
257     }
258         if (originalKData)
259         {
260                 pSS->FreeMemory(originalKData);
261         }
262 } //~Halftoner
263
264
265 void Halftoner::Restart()
266 {
267     nNextRaster = 0;
268
269     for (unsigned int i = StartPlane; i <= EndPlane; i++)
270       {
271         memset(ErrBuff[i], 0, (OutputWidth[i]+2) * sizeof(short));
272       }
273
274     started = FALSE;
275 } //Restart
276
277
278 void Halftoner::Flush()
279 {
280     if (!started)
281     {
282         return;
283     }
284     Restart();
285 } //Flush
286
287
288 void Halftoner::FreeBuffers()
289 {
290     for (unsigned int i = StartPlane; i <= EndPlane; i++)
291       {
292         pSS->FreeMemory(ErrBuff[i]);
293       }
294     if (tempBuffer)
295     {
296         pSS->FreeMemory(tempBuffer);
297     }
298     if (tempBuffer2)
299     {
300         pSS->FreeMemory(tempBuffer2);
301     }
302 } //FreeBuffers
303
304
305 // dumb horizontal doubling (tripling, etc.) for resolution-boost prior to halftoning
306 void Halftoner::PixelMultiply(unsigned char* buffer, unsigned int width, unsigned int factor)
307 {
308     if (factor == 1)
309     {
310         return;
311     }
312
313     for (int j = (int)(width-1); j >= 0; j--)
314     {
315         unsigned int iOffset = j * factor;
316         for (unsigned int k = 0; k < factor; k++)
317         {
318             buffer[iOffset + k] = buffer[j];
319         }
320     }
321
322 } //PixelMultiply
323
324
325 BYTE* Halftoner::NextOutputRaster(COLORTYPE  rastercolor)
326 {
327         if (rastercolor == COLORTYPE_COLOR)
328         {
329                 if (iRastersReady == 0)
330                 {
331                         return NULL;
332                 }
333
334                 if (iColor == (ColorPlaneCount+StartPlane))
335                 {
336                         return NULL;
337                 }
338
339                 if (iPlane == ColorDepth[iColor])
340                 {
341                         iPlane = 0;
342                         iRow++;
343                         return NextOutputRaster(rastercolor);
344                 }
345
346                 if (iRow == NumRows[iColor])
347                 {
348                         iRow = 0;
349                         iColor++;
350                         return NextOutputRaster(rastercolor);
351                 }
352
353                 iRastersDelivered++;
354                 iRastersReady--;
355                 return ColorPlane[iColor][iRow][iPlane++];
356         }
357         else
358         {
359                 return NULL;
360         }
361 } //NextOutputRaster
362
363
364 BOOL Halftoner::LastPlane()
365 {
366       return ((iColor == (ColorPlaneCount+StartPlane-1)) &&
367               (iRow == (unsigned int)(NumRows[iColor] - 1)) &&
368               (iPlane == ColorDepth[iColor])        // was pre-incremented
369               );
370 } //LastPlane
371
372
373 BOOL Halftoner::FirstPlane()
374 {
375       return ((iColor == StartPlane) &&
376               (iRow == 0) &&
377               (iPlane == 1)        // was pre-incremented
378               );
379 } //FirstPlane
380
381
382 unsigned int Halftoner::GetOutputWidth(COLORTYPE  rastercolor)
383 // return size of data in the plane being delivered (depends on iRastersDelivered)
384 // (will be used in connection with compression seedrow)
385 {
386         if (rastercolor == COLORTYPE_COLOR)
387         {
388                 unsigned int colorplane, tmp;
389                 // figure out which colorplane we're on
390                 unsigned int rasterd = iRastersDelivered;
391                 // we come after increment of iRastersDelivered
392                 if (rasterd>0)
393                 {
394                         rasterd--;
395                 }
396
397                 tmp = (unsigned int)(NumRows[0]*ColorDepth[0]);
398                 if (rasterd < tmp)
399                 {
400                         colorplane = 0;
401                 }
402                 // have to count up to possible 6th plane;
403                 // but we'll save code by assuming sizes of C,M,Y (Cl,Ml) are all same
404                 else
405                 {
406                         colorplane = 1;
407                 }
408
409                 int temp = (OutputWidth[colorplane] + 7) / 8;
410                 return temp;
411         }
412         else
413         {
414                 return 0;
415         }
416 } //GetOutputWidth
417
418
419 unsigned int Halftoner::GetMaxOutputWidth(COLORTYPE  rastercolor)
420 // This is needed by Configure, since the output-width for Halftoner is variable
421 // depending on the colorplane
422 {
423         if (rastercolor == COLORTYPE_COLOR)
424         {
425                 unsigned int max=0;
426                 for (unsigned int i=StartPlane; i <= EndPlane; i++)
427                 {
428                         if (OutputWidth[i] > max)
429                         {
430                                 max = OutputWidth[i];
431                         }
432                 }
433                 return (max / 8) + ((max % 8)!=0);
434         }
435         else
436         {
437                 return 0;
438         }
439 } //GetMaxOutputWidth
440
441
442 unsigned int Halftoner::PlaneCount()
443 {
444  unsigned int count=0;
445
446      for (int i = 0; i < MAXCOLORPLANES; i++)
447      {
448          count += NumRows[i] * ColorDepth[i];
449      }
450
451   return count;
452 } //PlaneCount
453
454
455 void Halftoner::CleanOddBits(unsigned int iColor, unsigned int iRow)
456 {
457     int index = (OutputWidth[iColor]/8)-1;
458
459     for (int i=0; i < ColorDepth[iColor]; i++)
460     {
461         BYTE lastbyte0 = ColorPlane[iColor][iRow][i][index];
462         lastbyte0 = lastbyte0 >> oddbits;
463         lastbyte0 = lastbyte0 << oddbits;
464         ColorPlane[iColor][iRow][i][index] = lastbyte0;
465     }
466 } //CleanOddBits
467
468 APDK_END_NAMESPACE
469