1 /*****************************************************************************\
2 halftoner.cpp : Implimentation for the Halftoner 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 \*****************************************************************************/
32 //===========================================================================
34 // Filename : halftoner.cpp
36 // Module : Open Source Imaging
38 // Description : This file contains the constructor and destructor for
39 // the Halftoner class, which performs color-matching and
42 // Detailed Description:
44 // The only member functions needed are Process(inputRaster)
45 // and Restart (used to skip white space and for new page).
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)
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 //============================================================================
64 #include "halftoner.h"
72 unsigned int iInputWidth,
73 unsigned int iNumRows[],
74 unsigned int HiResFactor,
76 ) : ColorPlaneCount(pPM->dyeCount),
77 InputWidth(iInputWidth),
78 ResBoost(HiResFactor),
81 fBlackFEDResPtr(pPM->BlackFEDTable),
82 fColorFEDResPtr(pPM->ColorFEDTable),
89 usematrix(matrixbased)
93 constructor_error = NO_ERROR;
95 StartPlane = K; // most common case
97 if (ColorPlaneCount == 3) // CMY pen
100 NumRows[K] = ColorDepth[K] = OutputWidth[K] = 0;
103 EndPlane=Y; // most common case
104 if (ColorPlaneCount == 6)
108 if (ColorPlaneCount == 1)
113 AdjustedInputWidth = InputWidth;
114 if (AdjustedInputWidth % 8)
116 AdjustedInputWidth += 8 - (AdjustedInputWidth % 8);
120 for (i = StartPlane; i < (ColorPlaneCount + StartPlane); i++)
122 ColorDepth[i]= pPM->ColorDepth[i];
123 NumRows[i]=iNumRows[i];
125 OutputWidth[i] = AdjustedInputWidth * NumRows[i] * ResBoost;
128 for (;i < (unsigned)MAXCOLORPLANES; i++)
130 NumRows[i] = ColorDepth[i] = OutputWidth[i] = 0;
133 oddbits = AdjustedInputWidth - InputWidth;
134 ///////////////////////////////////////////////////////////////////////////
135 for (i=0; i <= Mlight; i++)
140 for (i=StartPlane; i <= EndPlane; i++)
142 ErrBuff[i] = (short*)pSS->AllocMem((OutputWidth[i] + 2) * sizeof(short));
143 if (ErrBuff[i] == NULL)
149 if (OutputWidth[K] > AdjustedInputWidth)
150 // need to expand input data (easier than expanding bit-pixels after) on K row
152 tempBuffer = (BYTE*) pSS->AllocMem(OutputWidth[K]);
153 if (tempBuffer == NULL)
159 tempBuffer2 = (BYTE*) pSS->AllocMem(OutputWidth[K]);
160 if (tempBuffer2 == NULL)
169 Restart(); // this zeroes buffers and sets nextraster counter
171 // allocate output buffers
172 for (i = 0; i < (unsigned)MAXCOLORPLANES; i++)
174 for (j = 0; j < MAXCOLORROWS; j++)
176 for (k = 0; k < MAXCOLORDEPTH; k++)
178 ColorPlane[i][j][k] = NULL;
183 for (i=StartPlane; i < (ColorPlaneCount+StartPlane); i++)
185 for (j=0; j < NumRows[i]; j++)
187 for (k=0; k < ColorDepth[i]; k++)
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)
196 memset(ColorPlane[i][j][k], 0, PlaneSize);
201 PlaneSize = (OutputWidth[0] + 7) / 8;
204 originalKData = (BYTE*) pSS->AllocMem(PlaneSize);
205 if (originalKData == NULL)
209 memset(originalKData, 0, PlaneSize);
214 constructor_error=ALLOCMEM_ERROR;
218 for (i=0; i < ColorPlaneCount; i++)
220 for (j=0; j < NumRows[i]; j++)
222 for (k=0; k < ColorDepth[i]; k++)
224 if (ColorPlane[i][j][k])
226 pSS->FreeMemory(ColorPlane[i][j][k]);
233 pSS->FreeMemory(originalKData);
239 Halftoner::~Halftoner()
241 DBG1("destroying Halftoner \n");
245 for (int i=0; i < MAXCOLORPLANES; i++)
247 for (int j=0; j < NumRows[i]; j++)
249 for (int k=0; k < ColorDepth[i]; k++)
251 if (ColorPlane[i][j][k])
253 pSS->FreeMemory(ColorPlane[i][j][k]);
260 pSS->FreeMemory(originalKData);
265 void Halftoner::Restart()
269 for (unsigned int i = StartPlane; i <= EndPlane; i++)
271 memset(ErrBuff[i], 0, (OutputWidth[i]+2) * sizeof(short));
278 void Halftoner::Flush()
288 void Halftoner::FreeBuffers()
290 for (unsigned int i = StartPlane; i <= EndPlane; i++)
292 pSS->FreeMemory(ErrBuff[i]);
296 pSS->FreeMemory(tempBuffer);
300 pSS->FreeMemory(tempBuffer2);
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)
313 for (int j = (int)(width-1); j >= 0; j--)
315 unsigned int iOffset = j * factor;
316 for (unsigned int k = 0; k < factor; k++)
318 buffer[iOffset + k] = buffer[j];
325 BYTE* Halftoner::NextOutputRaster(COLORTYPE rastercolor)
327 if (rastercolor == COLORTYPE_COLOR)
329 if (iRastersReady == 0)
334 if (iColor == (ColorPlaneCount+StartPlane))
339 if (iPlane == ColorDepth[iColor])
343 return NextOutputRaster(rastercolor);
346 if (iRow == NumRows[iColor])
350 return NextOutputRaster(rastercolor);
355 return ColorPlane[iColor][iRow][iPlane++];
364 BOOL Halftoner::LastPlane()
366 return ((iColor == (ColorPlaneCount+StartPlane-1)) &&
367 (iRow == (unsigned int)(NumRows[iColor] - 1)) &&
368 (iPlane == ColorDepth[iColor]) // was pre-incremented
373 BOOL Halftoner::FirstPlane()
375 return ((iColor == StartPlane) &&
377 (iPlane == 1) // was pre-incremented
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)
386 if (rastercolor == COLORTYPE_COLOR)
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
397 tmp = (unsigned int)(NumRows[0]*ColorDepth[0]);
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
409 int temp = (OutputWidth[colorplane] + 7) / 8;
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
423 if (rastercolor == COLORTYPE_COLOR)
426 for (unsigned int i=StartPlane; i <= EndPlane; i++)
428 if (OutputWidth[i] > max)
430 max = OutputWidth[i];
433 return (max / 8) + ((max % 8)!=0);
439 } //GetMaxOutputWidth
442 unsigned int Halftoner::PlaneCount()
444 unsigned int count=0;
446 for (int i = 0; i < MAXCOLORPLANES; i++)
448 count += NumRows[i] * ColorDepth[i];
455 void Halftoner::CleanOddBits(unsigned int iColor, unsigned int iRow)
457 int index = (OutputWidth[iColor]/8)-1;
459 for (int i=0; i < ColorDepth[iColor]; i++)
461 BYTE lastbyte0 = ColorPlane[iColor][iRow][i][index];
462 lastbyte0 = lastbyte0 >> oddbits;
463 lastbyte0 = lastbyte0 << oddbits;
464 ColorPlane[iColor][iRow][i][index] = lastbyte0;