1 /*****************************************************************************\
2 halftoner_open.cpp : Open Source Imaging Halftoning
4 Copyright (c) 1994 - 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 #include "halftoner.h"
33 #include "halftoner_open.h"
37 extern unsigned char BayerMatrix[];
39 Halftoner_Open::Halftoner_Open
43 unsigned int iInputWidth,
44 unsigned int iNumRows[],
45 unsigned int HiResFactor,
48 : Halftoner(pSys,pPM,iInputWidth,iNumRows,HiResFactor,matrixbased)
52 Halftoner_Open::~Halftoner_Open()
56 BOOL Halftoner_Open::Process
58 RASTERDATA* pbyInputKRGBRaster
64 if ((pbyInputKRGBRaster == NULL) ||
65 (pbyInputKRGBRaster && pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR]==NULL && pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK]==NULL))
68 return FALSE; // no output
72 for (i=StartPlane; i < (ColorPlaneCount+StartPlane); i++)
74 for (j=0; j < NumRows[i]; j++)
76 for (k=0; k < ColorDepth[i]; k++)
78 int PlaneSize= (OutputWidth[i] + 7) / 8;
79 memset(ColorPlane[i][j][k], 0, PlaneSize);
83 if (pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR])
85 // increment current raster
87 if ( -1 == nNextRaster )
90 fRasterOdd = ( 1 & nNextRaster ) ? 0 : 1;
95 for (i=StartPlane; i <= EndPlane; i++)
97 if (OutputWidth[i] > AdjustedInputWidth)
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);
105 numpix = OutputWidth[i];
109 input=pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR];
110 numpix = AdjustedInputWidth;
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
119 fDitherParms[i].fFEDResPtr = fBlackFEDResPtr;
121 fDitherParms[i].fFEDResPtr = fColorFEDResPtr;
122 fDitherParms[i].fRasterEvenOrOdd = fRasterOdd;
123 fDitherParms[i].fHifipe = ColorDepth[i]>1;
125 // for matrix //////////////
128 fDitherParms[i].fSqueezeOffset=0;
129 fDitherParms[i].fMatrixRowSize = BayerMatrix[1];
130 BYTE colorindex = i + 2;
133 BYTE ditheroffset = BayerMatrix[colorindex];
134 BYTE matrixrowsize = BayerMatrix[1];
135 fDitherParms[i].fDitherCellOffset = ditheroffset;
136 HPBytePtr matrixptr = (HPBytePtr)(
137 (((ditheroffset + nNextRaster) % matrixrowsize) * matrixrowsize)
140 fDitherParms[i].fMatrixV1 = matrixptr;
143 ////////////////////////////////////
145 for (j=0; j < NumRows[i]; j++)
147 fDitherParms[i].fOutput1 = ColorPlane[i][j][0];
148 fDitherParms[i].fOutput2 = ColorPlane[i][j][1];
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);
157 else HTEDiffOpen ((THTDitherParmsPtr) fDitherParms, i);
160 // cleanup bits at end of row due to input-width not being divisible by 8
164 pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR] += InputWidth;
169 if (pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK])
172 if (OutputWidth[K] > AdjustedInputWidth)
174 memset(tempBuffer, 0, OutputWidth[K]);
175 memcpy(tempBuffer,pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK],pbyInputKRGBRaster->rastersize[COLORTYPE_BLACK]);
177 factor = NumRows[K] * ResBoost;
178 PixelMultiply(tempBuffer, pbyInputKRGBRaster->rastersize[COLORTYPE_BLACK], factor);
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++)
186 if (OutputWidth[K] > AdjustedInputWidth)
190 originalKData[curByte] |= curBit;
195 if (pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK][i])
197 originalKData[curByte] |= curBit;
207 curBit = curBit >> 1;
210 for (j=0; j < NumRows[K]; j++)
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];
222 iRastersReady = PlaneCount();
223 iRastersDelivered = 0;
224 return TRUE; // one raster in, one raster out
228 void Halftoner_Open::HTEDiffOpen
230 THTDitherParmsPtr ditherParmsPtr,
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;
246 outputPtr1 = ditherParms->fOutput1;
250 outputPtr1 = ditherParms->fOutput1;
251 outputPtr2 = ditherParms->fOutput2;
252 outputPtr3 = ditherParms->fOutput3;
255 diffusionErrorPtr = errPtr;
261 if( ditherParms->fRasterEvenOrOdd == 1 )
263 tmpShortStore = *diffusionErrorPtr;
265 *diffusionErrorPtr = 0;
267 for (pixelCount = numLoop + 8; (pixelCount -= 8) > 0; )
269 if (pixelCount > 16) // if next 16 pixels are white, skip 8
271 doNext8Pixels = Forward16PixelsNonWhite(inputPtr);
275 doNext8Pixels = HPTRUE;
281 FORWARD_FED( thValue, 0x80 );
283 FORWARD_FED( thValue, 0x40 );
285 FORWARD_FED( thValue, 0x20 );
287 FORWARD_FED( thValue, 0x10 );
289 FORWARD_FED( thValue, 0x08 );
291 FORWARD_FED( thValue, 0x04 );
293 FORWARD_FED( thValue, 0x02 );
295 FORWARD_FED( thValue, 0x01 );
297 *outputPtr1++ = rasterByte1;
302 *outputPtr2++ = rasterByte2;
306 else // Do white space skipping
314 *diffusionErrorPtr++ = 0;
315 *diffusionErrorPtr++ = 0;
316 *diffusionErrorPtr++ = 0;
317 *diffusionErrorPtr++ = 0;
318 *diffusionErrorPtr++ = 0;
319 *diffusionErrorPtr++ = 0;
320 *diffusionErrorPtr++ = 0;
321 *diffusionErrorPtr++ = 0;
332 inputPtr += ( numLoop-1 );
333 outputPtr1 += ( numLoop/8 - 1 );
334 outputPtr2 += ( numLoop/8 - 1 );
335 diffusionErrorPtr += ( numLoop-1 );
337 tmpShortStore = *diffusionErrorPtr;
339 *diffusionErrorPtr = 0;
341 for (pixelCount = numLoop + 8; (pixelCount -= 8) > 0; )
343 if (pixelCount > 16) // if next 16 pixels are white, skip 8
345 doNext8Pixels = Backward16PixelsNonWhite(inputPtr);
349 doNext8Pixels = HPTRUE;
355 BACKWARD_FED( thValue, 0x01 );
357 BACKWARD_FED( thValue, 0x02 );
359 BACKWARD_FED( thValue, 0x04 );
361 BACKWARD_FED( thValue, 0x08 );
363 BACKWARD_FED( thValue, 0x10 );
365 BACKWARD_FED( thValue, 0x20 );
367 BACKWARD_FED( thValue, 0x40 );
369 BACKWARD_FED( thValue, 0x80 );
371 *outputPtr1-- = rasterByte1;
376 *outputPtr2-- = rasterByte2;
380 else // Do white space skipping
388 *diffusionErrorPtr-- = 0;
389 *diffusionErrorPtr-- = 0;
390 *diffusionErrorPtr-- = 0;
391 *diffusionErrorPtr-- = 0;
392 *diffusionErrorPtr-- = 0;
393 *diffusionErrorPtr-- = 0;
394 *diffusionErrorPtr-- = 0;
395 *diffusionErrorPtr-- = 0;
404 //////////////////////////////////////////////////////////
405 void Halftoner_Open::FORWARD_FED
407 HPInt16 thresholdValue,
411 tone = (*inputPtr++ );
412 fedResPtr = fedResTbl + (tone << 2);
413 level = *fedResPtr++;
416 tone = ( tmpShortStore + (HPInt16)(*fedResPtr++) );
417 if (tone >= thresholdValue)
427 rasterByte1 |= bitMask;
430 rasterByte2 |= bitMask;
433 rasterByte2 |= bitMask; rasterByte1 |= bitMask;
436 rasterByte3 |= bitMask;
439 rasterByte3 |= bitMask; rasterByte1 |= bitMask;
442 rasterByte3 |= bitMask; rasterByte2 |= bitMask;
445 rasterByte3 |= bitMask; rasterByte2 |= bitMask; rasterByte1 |= bitMask;
451 tone = tmpShortStore;
453 *diffusionErrorPtr++ = tone >> 1;
454 tmpShortStore = *diffusionErrorPtr + (tone - (tone >> 1));
458 void Halftoner_Open::BACKWARD_FED
460 HPInt16 thresholdValue,
464 tone = (*inputPtr-- );
465 fedResPtr = fedResTbl + (tone << 2);
466 level = *fedResPtr++;
469 tone = ( tmpShortStore + (HPInt16)(*fedResPtr++) );
470 if (tone >= thresholdValue)
480 rasterByte1 |= bitMask;
483 rasterByte2 |= bitMask;
486 rasterByte2 |= bitMask; rasterByte1 |= bitMask;
489 rasterByte3 |= bitMask;
492 rasterByte3 |= bitMask; rasterByte1 |= bitMask;
495 rasterByte3 |= bitMask; rasterByte2 |= bitMask;
498 rasterByte3 |= bitMask; rasterByte2 |= bitMask; rasterByte1 |= bitMask;
504 tone = tmpShortStore;
506 *diffusionErrorPtr-- = tone >> 1;
507 tmpShortStore = *diffusionErrorPtr + (tone - (tone >> 1));