1
/*****************************************************************************\
2
Halftoner.cpp : Implimentation for the Halftoner class
4
Copyright (c) 1996 - 2009, 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
//============================================================================
62
#include "CommonDefinitions.h"
63
#include "Processor.h"
64
#include "Halftoner.h"
69
unsigned int iInputWidth,
73
) : ColorPlaneCount(pPM->dyeCount),
74
InputWidth(iInputWidth),
75
ResBoost(HiResFactor),
77
fBlackFEDResPtr(pPM->BlackFEDTable),
78
fColorFEDResPtr(pPM->ColorFEDTable),
85
usematrix(matrixbased)
91
StartPlane = K; // most common case
93
if (ColorPlaneCount == 3) // CMY pen
96
NumRows[K] = ColorDepth[K] = OutputWidth[K] = 0;
99
EndPlane=Y; // most common case
100
if (ColorPlaneCount == 6)
104
if (ColorPlaneCount == 1)
109
AdjustedInputWidth = InputWidth;
110
if (AdjustedInputWidth % 8)
112
AdjustedInputWidth += 8 - (AdjustedInputWidth % 8);
116
for (i = StartPlane; i < (ColorPlaneCount + StartPlane); i++)
118
ColorDepth[i]= pPM->ColorDepth[i];
119
NumRows[i]=iNumRows[i];
121
OutputWidth[i] = AdjustedInputWidth * NumRows[i] * ResBoost;
123
for (;i < (unsigned)MAXCOLORPLANES; i++)
125
NumRows[i] = ColorDepth[i] = OutputWidth[i] = 0;
128
oddbits = AdjustedInputWidth - InputWidth;
129
///////////////////////////////////////////////////////////////////////////
130
for (i=0; i <= Mlight; i++)
135
for (i = StartPlane; i <= EndPlane; i++)
137
ErrBuff[i] = (short *) new char[((OutputWidth[i] + 2) * sizeof(short))];
138
if (ErrBuff[i] == NULL)
144
if (OutputWidth[K] > AdjustedInputWidth)
145
// need to expand input data (easier than expanding bit-pixels after) on K row
147
tempBuffer = (BYTE*) new BYTE[(OutputWidth[K])];
148
if (tempBuffer == NULL)
154
tempBuffer2 = (BYTE*) new BYTE[(OutputWidth[K])];
155
if (tempBuffer2 == NULL)
162
Restart(); // this zeroes buffers and sets nextraster counter
164
// allocate output buffers
165
for (i = 0; i < (unsigned)MAXCOLORPLANES; i++)
167
for (j = 0; j < MAXCOLORROWS; j++)
169
for (k = 0; k < MAXCOLORDEPTH; k++)
171
ColorPlane[i][j][k] = NULL;
176
for (i=StartPlane; i < (ColorPlaneCount+StartPlane); i++)
178
for (j=0; j < NumRows[i]; j++)
180
for (k=0; k < ColorDepth[i]; k++)
182
PlaneSize= OutputWidth[i]/8 + // doublecheck ... should already be divisble by 8
183
((OutputWidth[i] % 8)!=0);
184
ColorPlane[i][j][k] = (BYTE*) new BYTE[(PlaneSize)];
185
if (ColorPlane[i][j] == NULL)
189
memset(ColorPlane[i][j][k], 0, PlaneSize);
194
PlaneSize = (OutputWidth[0] + 7) / 8;
197
originalKData = (BYTE*) new BYTE[(PlaneSize)];
198
if (originalKData == NULL)
202
memset(originalKData, 0, PlaneSize);
210
for (i=0; i < ColorPlaneCount; i++)
212
for (j=0; j < NumRows[i]; j++)
214
for (k=0; k < ColorDepth[i]; k++)
216
if (ColorPlane[i][j][k])
218
delete [] (ColorPlane[i][j][k]);
225
delete [] (originalKData);
231
Halftoner::~Halftoner()
235
for (int i=0; i < MAXCOLORPLANES; i++)
237
for (int j=0; j < NumRows[i]; j++)
239
for (int k=0; k < ColorDepth[i]; k++)
241
if (ColorPlane[i][j][k])
243
delete [] (ColorPlane[i][j][k]);
250
delete [] (originalKData);
255
void Halftoner::Restart()
259
for (unsigned int i = StartPlane; i <= EndPlane; i++)
261
memset(ErrBuff[i], 0, (OutputWidth[i]+2) * sizeof(short));
268
void Halftoner::Flush()
278
void Halftoner::FreeBuffers()
280
for (unsigned int i = StartPlane; i <= EndPlane; i++)
282
delete [] (ErrBuff[i]);
286
delete [] (tempBuffer);
290
delete [] (tempBuffer2);
295
// dumb horizontal doubling (tripling, etc.) for resolution-boost prior to halftoning
296
void Halftoner::PixelMultiply(unsigned char* buffer, unsigned int width, unsigned int factor)
303
for (int j = (int)(width-1); j >= 0; j--)
305
unsigned int iOffset = j * factor;
306
for (unsigned int k = 0; k < factor; k++)
308
buffer[iOffset + k] = buffer[j];
314
unsigned int Halftoner::getOutputWidth()
316
// return size of data in the plane being delivered (depends on iRastersDelivered)
317
// (will be used in connection with compression seedrow)
318
unsigned int colorplane, tmp;
319
// figure out which colorplane we're on
320
unsigned int rasterd = iRastersDelivered;
321
// we come after increment of iRastersDelivered
327
tmp = (unsigned int)(NumRows[0]*ColorDepth[0]);
332
// have to count up to possible 6th plane;
333
// but we'll save code by assuming sizes of C,M,Y (Cl,Ml) are all same
339
int temp = (OutputWidth[colorplane] + 7) / 8;
343
bool Halftoner::NextOutputRaster(RASTERDATA &next_raster)
345
if (iRastersReady == 0)
350
if (iColor == (ColorPlaneCount+StartPlane))
355
if (iPlane == ColorDepth[iColor])
359
return NextOutputRaster(next_raster);
362
if (iRow == NumRows[iColor])
366
return NextOutputRaster(next_raster);
371
next_raster.rasterdata[COLORTYPE_COLOR] = ColorPlane[iColor][iRow][iPlane++];
372
next_raster.rastersize[COLORTYPE_COLOR] = getOutputWidth();
373
next_raster.rasterdata[COLORTYPE_BLACK] = raster.rasterdata[COLORTYPE_BLACK];
374
next_raster.rastersize[COLORTYPE_BLACK] = 0;
379
bool Halftoner::LastPlane()
381
return ((iColor == (ColorPlaneCount+StartPlane-1)) &&
382
(iRow == (unsigned int)(NumRows[iColor] - 1)) &&
383
(iPlane == ColorDepth[iColor]) // was pre-incremented
388
bool Halftoner::FirstPlane()
390
return ((iColor == StartPlane) &&
392
(iPlane == 1) // was pre-incremented
396
unsigned int Halftoner::GetMaxOutputWidth()
397
// This is needed by Configure, since the output-width for Halftoner is variable
398
// depending on the colorplane
400
if (myplane == COLORTYPE_COLOR)
403
for (unsigned int i=StartPlane; i <= EndPlane; i++)
405
if (OutputWidth[i] > max)
407
max = OutputWidth[i];
410
return (max / 8) + ((max % 8)!=0);
416
} //GetMaxOutputWidth
419
unsigned int Halftoner::PlaneCount()
421
unsigned int count=0;
423
for (int i = 0; i < MAXCOLORPLANES; i++)
425
count += NumRows[i] * ColorDepth[i];
432
void Halftoner::CleanOddBits(unsigned int iColor, unsigned int iRow)
434
int index = (OutputWidth[iColor]/8)-1;
436
for (int i=0; i < ColorDepth[iColor]; i++)
438
BYTE lastbyte0 = ColorPlane[iColor][iRow][i][index];
439
lastbyte0 = lastbyte0 >> oddbits;
440
lastbyte0 = lastbyte0 << oddbits;
441
ColorPlane[iColor][iRow][i][index] = lastbyte0;
446
extern unsigned char BayerMatrix[];
448
bool Halftoner::Process
450
RASTERDATA* pbyInputKRGBRaster
455
if ((pbyInputKRGBRaster == NULL) ||
456
(pbyInputKRGBRaster && pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR]==NULL && pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK]==NULL))
459
return false; // no output
463
for (i=StartPlane; i < (ColorPlaneCount+StartPlane); i++)
465
for (j=0; j < NumRows[i]; j++)
467
for (k=0; k < ColorDepth[i]; k++)
469
int PlaneSize= (OutputWidth[i] + 7) / 8;
470
memset(ColorPlane[i][j][k], 0, PlaneSize);
474
if (pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR])
476
// increment current raster
478
if ( -1 == nNextRaster )
481
fRasterOdd = ( 1 & nNextRaster ) ? 0 : 1;
486
for (i=StartPlane; i <= EndPlane; i++)
488
if (OutputWidth[i] > AdjustedInputWidth)
490
memset(tempBuffer, 0, OutputWidth[i]); // clear it out because outwidth might be
491
// > factor*inwidth due to roundoff
492
memcpy(tempBuffer,pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR],InputWidth);
493
int factor = NumRows[i] * ResBoost;
494
PixelMultiply(tempBuffer, InputWidth, factor);
496
numpix = OutputWidth[i];
500
input=pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR];
501
numpix = AdjustedInputWidth;
504
fDitherParms[i].fNumPix = numpix;
505
fDitherParms[i].fInput = input;
506
fDitherParms[i].fErr = ErrBuff[i];
507
fDitherParms[i].fErr++; // This is for serpentine
508
fDitherParms[i].fSymmetricFlag = true; // Symmetric only
510
fDitherParms[i].fFEDResPtr = fBlackFEDResPtr;
512
fDitherParms[i].fFEDResPtr = fColorFEDResPtr;
513
fDitherParms[i].fRasterEvenOrOdd = fRasterOdd;
514
fDitherParms[i].fHifipe = ColorDepth[i]>1;
516
// for matrix //////////////
519
fDitherParms[i].fSqueezeOffset=0;
520
fDitherParms[i].fMatrixRowSize = BayerMatrix[1];
521
BYTE colorindex = i + 2;
524
BYTE ditheroffset = BayerMatrix[colorindex];
525
BYTE matrixrowsize = BayerMatrix[1];
526
fDitherParms[i].fDitherCellOffset = ditheroffset;
527
BYTE * matrixptr = (BYTE *)(
528
(((ditheroffset + nNextRaster) % matrixrowsize) * matrixrowsize)
531
fDitherParms[i].fMatrixV1 = matrixptr;
534
////////////////////////////////////
536
for (j=0; j < NumRows[i]; j++)
538
fDitherParms[i].fOutput1 = ColorPlane[i][j][0];
539
fDitherParms[i].fOutput2 = ColorPlane[i][j][1];
543
memset(fDitherParms[i].fOutput1, 0, OutputWidth[i]/8);
544
if (fDitherParms[i].fOutput2)
545
memset(fDitherParms[i].fOutput2, 0, OutputWidth[i]/8);
546
HTMATRIXHI_KCMY((THTDitherParmsPtr) fDitherParms, i);
548
else HTEDiffOpen ((THTDitherParmsPtr) fDitherParms, i);
551
// cleanup bits at end of row due to input-width not being divisible by 8
555
pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR] += InputWidth;
560
if (pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK])
563
if (OutputWidth[K] > AdjustedInputWidth)
565
memset(tempBuffer, 0, OutputWidth[K]);
566
memcpy(tempBuffer,pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK],pbyInputKRGBRaster->rastersize[COLORTYPE_BLACK]);
568
factor = NumRows[K] * ResBoost;
569
PixelMultiply(tempBuffer, pbyInputKRGBRaster->rastersize[COLORTYPE_BLACK], factor);
572
// Convert 8bit per pixel data into 1 bit per pixel data
573
memset(originalKData, 0, (pbyInputKRGBRaster->rastersize[COLORTYPE_BLACK] * factor +7)/8);
574
int curBit = 0x80, curByte = 0;
575
for (int i=0; i<pbyInputKRGBRaster->rastersize[COLORTYPE_BLACK] * factor; i++)
577
if (OutputWidth[K] > AdjustedInputWidth)
581
originalKData[curByte] |= curBit;
586
if (pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK][i])
588
originalKData[curByte] |= curBit;
598
curBit = curBit >> 1;
601
for (j=0; j < NumRows[K]; j++)
603
for (k = 0; k < (pbyInputKRGBRaster->rastersize[COLORTYPE_BLACK] * factor +7)/8; k++)
604
if (ColorPlane[K][j][0])
605
ColorPlane[K][j][0][k] |= originalKData[k];
606
if (ColorPlane[K][j][1])
607
ColorPlane[K][j][1][k] |= originalKData[k];
613
iRastersReady = PlaneCount();
614
iRastersDelivered = 0;
615
return true; // one raster in, one raster out
619
void Halftoner::HTEDiffOpen
621
THTDitherParmsPtr ditherParmsPtr,
627
ditherParms = ditherParmsPtr+count;
628
errPtr = ditherParms->fErr;
629
numLoop = ditherParms->fNumPix;
630
inputPtr = ditherParms->fInput;
631
fedResTbl = ditherParms->fFEDResPtr;
632
symmetricFlag = ditherParms->fSymmetricFlag;
633
doNext8Pixels = true;
634
hifipe = ditherParms->fHifipe;
635
outputPtr1 = ditherParms->fOutput1;
639
outputPtr1 = ditherParms->fOutput1;
640
outputPtr2 = ditherParms->fOutput2;
641
outputPtr3 = ditherParms->fOutput3;
644
diffusionErrorPtr = errPtr;
650
if( ditherParms->fRasterEvenOrOdd == 1 )
652
tmpShortStore = *diffusionErrorPtr;
654
*diffusionErrorPtr = 0;
656
for (pixelCount = numLoop + 8; (pixelCount -= 8) > 0; )
658
if (pixelCount > 16) // if next 16 pixels are white, skip 8
660
doNext8Pixels = Forward16PixelsNonWhite(inputPtr);
664
doNext8Pixels = true;
670
FORWARD_FED( thValue, 0x80 );
672
FORWARD_FED( thValue, 0x40 );
674
FORWARD_FED( thValue, 0x20 );
676
FORWARD_FED( thValue, 0x10 );
678
FORWARD_FED( thValue, 0x08 );
680
FORWARD_FED( thValue, 0x04 );
682
FORWARD_FED( thValue, 0x02 );
684
FORWARD_FED( thValue, 0x01 );
686
*outputPtr1++ = rasterByte1;
691
*outputPtr2++ = rasterByte2;
695
else // Do white space skipping
703
*diffusionErrorPtr++ = 0;
704
*diffusionErrorPtr++ = 0;
705
*diffusionErrorPtr++ = 0;
706
*diffusionErrorPtr++ = 0;
707
*diffusionErrorPtr++ = 0;
708
*diffusionErrorPtr++ = 0;
709
*diffusionErrorPtr++ = 0;
710
*diffusionErrorPtr++ = 0;
721
inputPtr += ( numLoop-1 );
722
outputPtr1 += ( numLoop/8 - 1 );
723
outputPtr2 += ( numLoop/8 - 1 );
724
diffusionErrorPtr += ( numLoop-1 );
726
tmpShortStore = *diffusionErrorPtr;
728
*diffusionErrorPtr = 0;
730
for (pixelCount = numLoop + 8; (pixelCount -= 8) > 0; )
732
if (pixelCount > 16) // if next 16 pixels are white, skip 8
734
doNext8Pixels = Backward16PixelsNonWhite(inputPtr);
738
doNext8Pixels = true;
744
BACKWARD_FED( thValue, 0x01 );
746
BACKWARD_FED( thValue, 0x02 );
748
BACKWARD_FED( thValue, 0x04 );
750
BACKWARD_FED( thValue, 0x08 );
752
BACKWARD_FED( thValue, 0x10 );
754
BACKWARD_FED( thValue, 0x20 );
756
BACKWARD_FED( thValue, 0x40 );
758
BACKWARD_FED( thValue, 0x80 );
760
*outputPtr1-- = rasterByte1;
765
*outputPtr2-- = rasterByte2;
769
else // Do white space skipping
777
*diffusionErrorPtr-- = 0;
778
*diffusionErrorPtr-- = 0;
779
*diffusionErrorPtr-- = 0;
780
*diffusionErrorPtr-- = 0;
781
*diffusionErrorPtr-- = 0;
782
*diffusionErrorPtr-- = 0;
783
*diffusionErrorPtr-- = 0;
784
*diffusionErrorPtr-- = 0;
793
//////////////////////////////////////////////////////////
794
void Halftoner::FORWARD_FED
796
short thresholdValue,
800
tone = (*inputPtr++ );
801
fedResPtr = fedResTbl + (tone << 2);
802
level = *fedResPtr++;
805
tone = ( tmpShortStore + (short)(*fedResPtr++) );
806
if (tone >= thresholdValue)
816
rasterByte1 |= bitMask;
819
rasterByte2 |= bitMask;
822
rasterByte2 |= bitMask; rasterByte1 |= bitMask;
825
rasterByte3 |= bitMask;
828
rasterByte3 |= bitMask; rasterByte1 |= bitMask;
831
rasterByte3 |= bitMask; rasterByte2 |= bitMask;
834
rasterByte3 |= bitMask; rasterByte2 |= bitMask; rasterByte1 |= bitMask;
840
tone = tmpShortStore;
842
*diffusionErrorPtr++ = tone >> 1;
843
tmpShortStore = *diffusionErrorPtr + (tone - (tone >> 1));
847
void Halftoner::BACKWARD_FED
849
short thresholdValue,
853
tone = (*inputPtr-- );
854
fedResPtr = fedResTbl + (tone << 2);
855
level = *fedResPtr++;
858
tone = ( tmpShortStore + (short)(*fedResPtr++) );
859
if (tone >= thresholdValue)
869
rasterByte1 |= bitMask;
872
rasterByte2 |= bitMask;
875
rasterByte2 |= bitMask; rasterByte1 |= bitMask;
878
rasterByte3 |= bitMask;
881
rasterByte3 |= bitMask; rasterByte1 |= bitMask;
884
rasterByte3 |= bitMask; rasterByte2 |= bitMask;
887
rasterByte3 |= bitMask; rasterByte2 |= bitMask; rasterByte1 |= bitMask;
893
tone = tmpShortStore;
895
*diffusionErrorPtr-- = tone >> 1;
896
tmpShortStore = *diffusionErrorPtr + (tone - (tone >> 1));
900
#define Dither4LevelHiFipe(matrix,bitMask)\
902
tone = (*inputPtr++ );\
903
fedResPtr = fedResTbl + (tone << 2);\
904
level = *fedResPtr++;\
905
if (*(fedResPtr) >= (BYTE)matrix )\
914
rasterByte1 |= bitMask;\
917
rasterByte2 |= bitMask;\
920
rasterByte2 |= bitMask; rasterByte1 |= bitMask;\
923
rasterByte3 |= bitMask;\
926
rasterByte3 |= bitMask; rasterByte1 |= bitMask;\
929
rasterByte3 |= bitMask; rasterByte2 |= bitMask;\
932
rasterByte3 |= bitMask; rasterByte2 |= bitMask; rasterByte1 |= bitMask;\
937
// Each dither matrix has a header of five bytes
938
// 1st byte (Size (in bytes) of row in the matrix) - 1
939
// 2nd byte Size (in bytes) of row in the matrix
940
// 3rd byte Black offset
941
// 4th byte Cyan offset
942
// 5th byte Magenta offset
944
// With matrix actually starting on the 6th Byte.
946
// Black, cyan, and magenta are all offset into different
947
// locations in the dither matrix. (Yellow uses the same offsets as
951
// Ditherparms should be set up as Fed with the following additions
952
// ditherParms->fSqueezeOffset = first dirty pixel, if white has been skipped at the beginning of the row
953
// ditherParmsPtr->fMatrixRowSize = Byte 2 of the Header
954
// ditherParmsPtr->fDitherCellOffset = Black, Cyan, or Magenta Offset respectively
956
// To select the right row of the matrix for each color
958
// ditherParms->fMatrixV1 = ((matrixStart + rasterIndex + DitherCellOffset) % (MatrixRowSize)) * (MatrixRowSize)
960
DRIVER_ERROR Halftoner::HTMATRIXHI_KCMY (THTDitherParmsPtr ditherParmsPtr,
961
unsigned short count)
963
THTDitherParmsPtr ditherParms = ditherParmsPtr+count;
965
BYTE rasterByte1,rasterByte2, rasterByte3;
969
unsigned short numLoop = ditherParms->fNumPix;
970
BYTE * inputPtr = ditherParms->fInput;
975
BYTE * fedResTbl = (BYTE * )ditherParms->fFEDResPtr;
978
BYTE * matrixV = ditherParms->fMatrixV1;
980
unsigned short index;
981
unsigned short matrixRowSize = ditherParms->fMatrixRowSize;
987
outputPtr1 = ditherParms->fOutput1;
988
outputPtr2 = ditherParms->fOutput2;
989
outputPtr3 = ditherParms->fOutput3;
991
if (!ditherParms->fSymmetricFlag)
992
return SYSTEM_ERROR; // matrixHI_KCMY asymetric not supported
994
index = (ditherParms->fDitherCellOffset + ditherParms->fSqueezeOffset) % (matrixRowSize);
995
matrixH = matrixV + index;
997
for (pixelCount = numLoop + 8; (pixelCount -= 8) > 0; )
999
// if we've reached end of matrix we need to reset
1000
// our row pointer to the start of the row
1001
if ( index == matrixRowSize )
1007
Dither4LevelHiFipe(*matrixH,0x80);
1009
Dither4LevelHiFipe(*matrixH,0x40);
1011
Dither4LevelHiFipe(*matrixH,0x20);
1013
Dither4LevelHiFipe(*matrixH,0x10);
1015
Dither4LevelHiFipe(*matrixH,0x08);
1017
Dither4LevelHiFipe(*matrixH,0x04);
1019
Dither4LevelHiFipe(*matrixH,0x02);
1021
Dither4LevelHiFipe(*matrixH,0x01);
1024
*outputPtr1++ |= rasterByte1;
1026
*outputPtr2++ |= rasterByte2;
1035
unsigned char BayerMatrix[] =
1037
0x07, 0x08, 0x00, 0x00, 0x00,
1038
0x2, 0x82, 0x22, 0xa2, 0xa, 0x8a, 0x2a, 0xaa,
1039
0xc2, 0x42, 0xe2, 0x62, 0xca, 0x4a, 0xea, 0x6a,
1040
0x32, 0xb2, 0x12, 0x92, 0x3a, 0xba, 0x1a, 0x9a,
1041
0xf2, 0x72, 0xd2, 0x52, 0xfa, 0x7a, 0xda, 0x5a,
1042
0xe, 0x8e, 0x2e, 0xae, 0x6, 0x86, 0x26, 0xa6,
1043
0xce, 0x4e, 0xee, 0x6e, 0xc6, 0x46, 0xe6, 0x66,
1044
0x3e, 0xbe, 0x1e, 0x9e, 0x36, 0xb6, 0x16, 0x96,
1045
0xfe, 0x7e, 0xde, 0x5e, 0xf6, 0x76, 0xd6, 0x56,