~ubuntu-branches/ubuntu/raring/hplip/raring

« back to all changes in this revision

Viewing changes to prnt/hpcups/Halftoner.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mark Purcell
  • Date: 2009-12-14 20:08:44 UTC
  • mfrom: (2.1.118 lucid)
  • Revision ID: james.westby@ubuntu.com-20091214200844-z8qhqwgppbu3t7ze
Tags: 3.9.10-4
KBSD patch from KiBi (Closes: #560796)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************\
 
2
  Halftoner.cpp : Implimentation for the Halftoner class
 
3
 
 
4
  Copyright (c) 1996 - 2009, 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 "CommonDefinitions.h"
 
63
#include "Processor.h"
 
64
#include "Halftoner.h"
 
65
 
 
66
Halftoner::Halftoner
 
67
(
 
68
    PrintMode* pPM,
 
69
    unsigned int iInputWidth,
 
70
    int iNumRows[],
 
71
    int HiResFactor,
 
72
    bool matrixbased
 
73
) : ColorPlaneCount(pPM->dyeCount),
 
74
    InputWidth(iInputWidth),
 
75
    ResBoost(HiResFactor),
 
76
    nNextRaster(0),
 
77
    fBlackFEDResPtr(pPM->BlackFEDTable),
 
78
    fColorFEDResPtr(pPM->ColorFEDTable),
 
79
    iColor(0),
 
80
    iRow(0),
 
81
    iPlane(0),
 
82
    tempBuffer(NULL),
 
83
    tempBuffer2(NULL),
 
84
    hold_random(0),
 
85
    usematrix(matrixbased)
 
86
{
 
87
    unsigned int i;
 
88
    int j,k,PlaneSize;
 
89
    originalKData = NULL;
 
90
 
 
91
    StartPlane = K;       // most common case
 
92
 
 
93
    if (ColorPlaneCount == 3)     // CMY pen
 
94
    {
 
95
        StartPlane=C;
 
96
        NumRows[K] = ColorDepth[K] = OutputWidth[K] = 0;
 
97
    }
 
98
 
 
99
    EndPlane=Y;         // most common case
 
100
    if (ColorPlaneCount == 6)
 
101
    {
 
102
        EndPlane = Mlight;
 
103
    }
 
104
    if (ColorPlaneCount == 1)
 
105
    {
 
106
        EndPlane = K;
 
107
    }
 
108
 
 
109
    AdjustedInputWidth = InputWidth;
 
110
    if (AdjustedInputWidth % 8)
 
111
    {
 
112
        AdjustedInputWidth += 8 - (AdjustedInputWidth % 8);
 
113
    }
 
114
 
 
115
    // init arrays
 
116
    for (i = StartPlane; i < (ColorPlaneCount + StartPlane); i++)
 
117
    {
 
118
        ColorDepth[i]= pPM->ColorDepth[i];
 
119
        NumRows[i]=iNumRows[i];
 
120
 
 
121
        OutputWidth[i] = AdjustedInputWidth * NumRows[i] * ResBoost;
 
122
    }
 
123
    for (;i < (unsigned)MAXCOLORPLANES; i++)
 
124
    {
 
125
        NumRows[i] = ColorDepth[i] = OutputWidth[i] = 0;
 
126
    }
 
127
 
 
128
    oddbits = AdjustedInputWidth - InputWidth;
 
129
    ///////////////////////////////////////////////////////////////////////////
 
130
    for (i=0; i <= Mlight; i++)
 
131
    {
 
132
        ErrBuff[i]=NULL;
 
133
    }
 
134
 
 
135
    for (i = StartPlane; i <= EndPlane; i++)
 
136
    {
 
137
        ErrBuff[i] = (short *) new char[((OutputWidth[i] + 2) * sizeof(short))];
 
138
        if (ErrBuff[i] == NULL)
 
139
        {
 
140
            goto MemoryError;
 
141
        }
 
142
    }
 
143
 
 
144
    if (OutputWidth[K] > AdjustedInputWidth)
 
145
    // need to expand input data (easier than expanding bit-pixels after) on K row
 
146
    {
 
147
        tempBuffer = (BYTE*) new BYTE[(OutputWidth[K])];
 
148
        if (tempBuffer == NULL)
 
149
        {
 
150
            goto MemoryError;
 
151
        }
 
152
        if (EndPlane > Y)
 
153
        {
 
154
            tempBuffer2 = (BYTE*) new BYTE[(OutputWidth[K])];
 
155
            if (tempBuffer2 == NULL)
 
156
            {
 
157
                goto MemoryError;
 
158
            }
 
159
        }
 
160
    }
 
161
 
 
162
    Restart();  // this zeroes buffers and sets nextraster counter
 
163
 
 
164
    // allocate output buffers
 
165
    for (i = 0; i < (unsigned)MAXCOLORPLANES; i++)
 
166
    {
 
167
        for (j = 0; j < MAXCOLORROWS; j++)
 
168
        {
 
169
            for (k = 0; k < MAXCOLORDEPTH; k++)
 
170
            {
 
171
                ColorPlane[i][j][k] = NULL;
 
172
            }
 
173
        }
 
174
    }
 
175
 
 
176
    for (i=StartPlane; i < (ColorPlaneCount+StartPlane); i++)
 
177
    {
 
178
        for (j=0; j < NumRows[i]; j++)
 
179
        {
 
180
            for (k=0; k < ColorDepth[i]; k++)
 
181
            {
 
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)
 
186
                {
 
187
                    goto MemoryError;
 
188
                }
 
189
                memset(ColorPlane[i][j][k], 0, PlaneSize);
 
190
            }
 
191
        }
 
192
    }
 
193
 
 
194
    PlaneSize = (OutputWidth[0] + 7) / 8;
 
195
    if (PlaneSize > 0)
 
196
    {
 
197
        originalKData = (BYTE*) new BYTE[(PlaneSize)];
 
198
        if (originalKData == NULL)
 
199
        {
 
200
            goto MemoryError;
 
201
        }
 
202
        memset(originalKData, 0, PlaneSize);
 
203
    }
 
204
    return;
 
205
 
 
206
MemoryError:
 
207
 
 
208
    FreeBuffers();
 
209
 
 
210
    for (i=0; i < ColorPlaneCount; i++)
 
211
    {
 
212
        for (j=0; j < NumRows[i]; j++)
 
213
        {
 
214
            for (k=0; k < ColorDepth[i]; k++)
 
215
            {
 
216
                if (ColorPlane[i][j][k])
 
217
                {
 
218
                    delete [] (ColorPlane[i][j][k]);
 
219
                }
 
220
            }
 
221
        }
 
222
    }
 
223
    if (originalKData)
 
224
    {
 
225
        delete [] (originalKData);
 
226
    }
 
227
 
 
228
} //Halftoner
 
229
 
 
230
 
 
231
Halftoner::~Halftoner()
 
232
{
 
233
    FreeBuffers();
 
234
 
 
235
    for (int i=0; i < MAXCOLORPLANES; i++)
 
236
    {
 
237
        for (int j=0; j < NumRows[i]; j++)
 
238
        {
 
239
            for (int k=0; k < ColorDepth[i]; k++)
 
240
            {
 
241
                if (ColorPlane[i][j][k])
 
242
                {
 
243
                    delete [] (ColorPlane[i][j][k]);
 
244
                }
 
245
            }
 
246
        }
 
247
    }
 
248
    if (originalKData)
 
249
    {
 
250
        delete [] (originalKData);
 
251
    }
 
252
} //~Halftoner
 
253
 
 
254
 
 
255
void Halftoner::Restart()
 
256
{
 
257
    nNextRaster = 0;
 
258
 
 
259
    for (unsigned int i = StartPlane; i <= EndPlane; i++)
 
260
      {
 
261
        memset(ErrBuff[i], 0, (OutputWidth[i]+2) * sizeof(short));
 
262
      }
 
263
 
 
264
    started = false;
 
265
} //Restart
 
266
 
 
267
 
 
268
void Halftoner::Flush()
 
269
{
 
270
    if (!started)
 
271
    {
 
272
        return;
 
273
    }
 
274
    Restart();
 
275
} //Flush
 
276
 
 
277
 
 
278
void Halftoner::FreeBuffers()
 
279
{
 
280
    for (unsigned int i = StartPlane; i <= EndPlane; i++)
 
281
    {
 
282
        delete [] (ErrBuff[i]);
 
283
    }
 
284
    if (tempBuffer)
 
285
    {
 
286
        delete [] (tempBuffer);
 
287
    }
 
288
    if (tempBuffer2)
 
289
    {
 
290
        delete [] (tempBuffer2);
 
291
    }
 
292
} //FreeBuffers
 
293
 
 
294
 
 
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)
 
297
{
 
298
    if (factor == 1)
 
299
    {
 
300
        return;
 
301
    }
 
302
 
 
303
    for (int j = (int)(width-1); j >= 0; j--)
 
304
    {
 
305
        unsigned int iOffset = j * factor;
 
306
        for (unsigned int k = 0; k < factor; k++)
 
307
        {
 
308
            buffer[iOffset + k] = buffer[j];
 
309
        }
 
310
    }
 
311
 
 
312
} //PixelMultiply
 
313
 
 
314
unsigned int Halftoner::getOutputWidth()
 
315
{
 
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
 
322
    if (rasterd > 0)
 
323
    {
 
324
        rasterd--;
 
325
    }
 
326
 
 
327
    tmp = (unsigned int)(NumRows[0]*ColorDepth[0]);
 
328
    if (rasterd < tmp)
 
329
    {
 
330
        colorplane = 0;
 
331
    }
 
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
 
334
    else
 
335
    {
 
336
        colorplane = 1;
 
337
    }
 
338
 
 
339
    int temp = (OutputWidth[colorplane] + 7) / 8;
 
340
    return temp;
 
341
} // getOutputWidth
 
342
 
 
343
bool Halftoner::NextOutputRaster(RASTERDATA &next_raster)
 
344
{
 
345
    if (iRastersReady == 0)
 
346
    {
 
347
        return false;
 
348
    }
 
349
 
 
350
    if (iColor == (ColorPlaneCount+StartPlane))
 
351
    {
 
352
        return false;
 
353
    }
 
354
 
 
355
    if (iPlane == ColorDepth[iColor])
 
356
    {
 
357
        iPlane = 0;
 
358
        iRow++;
 
359
        return NextOutputRaster(next_raster);
 
360
    }
 
361
 
 
362
    if (iRow == NumRows[iColor])
 
363
    {
 
364
        iRow = 0;
 
365
        iColor++;
 
366
        return NextOutputRaster(next_raster);
 
367
    }
 
368
 
 
369
    iRastersDelivered++;
 
370
    iRastersReady--;
 
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;
 
375
    return true;
 
376
} //NextOutputRaster
 
377
 
 
378
 
 
379
bool Halftoner::LastPlane()
 
380
{
 
381
      return ((iColor == (ColorPlaneCount+StartPlane-1)) &&
 
382
              (iRow == (unsigned int)(NumRows[iColor] - 1)) &&
 
383
              (iPlane == ColorDepth[iColor])        // was pre-incremented
 
384
              );
 
385
} //LastPlane
 
386
 
 
387
 
 
388
bool Halftoner::FirstPlane()
 
389
{
 
390
      return ((iColor == StartPlane) &&
 
391
              (iRow == 0) &&
 
392
              (iPlane == 1)        // was pre-incremented
 
393
              );
 
394
} //FirstPlane
 
395
 
 
396
unsigned int Halftoner::GetMaxOutputWidth()
 
397
// This is needed by Configure, since the output-width for Halftoner is variable
 
398
// depending on the colorplane
 
399
{
 
400
    if (myplane == COLORTYPE_COLOR)
 
401
    {
 
402
        unsigned int max=0;
 
403
        for (unsigned int i=StartPlane; i <= EndPlane; i++)
 
404
        {
 
405
            if (OutputWidth[i] > max)
 
406
            {
 
407
                max = OutputWidth[i];
 
408
            }
 
409
        }
 
410
        return (max / 8) + ((max % 8)!=0);
 
411
    }
 
412
    else
 
413
    {
 
414
        return 0;
 
415
    }
 
416
} //GetMaxOutputWidth
 
417
 
 
418
 
 
419
unsigned int Halftoner::PlaneCount()
 
420
{
 
421
 unsigned int count=0;
 
422
 
 
423
     for (int i = 0; i < MAXCOLORPLANES; i++)
 
424
     {
 
425
         count += NumRows[i] * ColorDepth[i];
 
426
     }
 
427
 
 
428
  return count;
 
429
} //PlaneCount
 
430
 
 
431
 
 
432
void Halftoner::CleanOddBits(unsigned int iColor, unsigned int iRow)
 
433
{
 
434
    int index = (OutputWidth[iColor]/8)-1;
 
435
 
 
436
    for (int i=0; i < ColorDepth[iColor]; i++)
 
437
    {
 
438
        BYTE lastbyte0 = ColorPlane[iColor][iRow][i][index];
 
439
        lastbyte0 = lastbyte0 >> oddbits;
 
440
        lastbyte0 = lastbyte0 << oddbits;
 
441
        ColorPlane[iColor][iRow][i][index] = lastbyte0;
 
442
    }
 
443
} // CleanOddBits
 
444
 
 
445
 
 
446
extern unsigned char BayerMatrix[];
 
447
 
 
448
bool Halftoner::Process
 
449
(
 
450
    RASTERDATA* pbyInputKRGBRaster
 
451
)
 
452
{
 
453
    unsigned int i;
 
454
    int j, k;
 
455
    if ((pbyInputKRGBRaster == NULL) ||
 
456
       (pbyInputKRGBRaster && pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR]==NULL && pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK]==NULL))
 
457
    {
 
458
        Restart();
 
459
        return false;   // no output
 
460
    }
 
461
    started=true;
 
462
 
 
463
    for (i=StartPlane; i < (ColorPlaneCount+StartPlane); i++)
 
464
    {
 
465
        for (j=0; j < NumRows[i]; j++)
 
466
        {
 
467
            for (k=0; k < ColorDepth[i]; k++)
 
468
            {
 
469
                int PlaneSize= (OutputWidth[i] + 7) / 8;
 
470
                memset(ColorPlane[i][j][k], 0, PlaneSize);
 
471
            }
 
472
        }
 
473
    }
 
474
    if (pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR])
 
475
    {
 
476
        // increment current raster
 
477
        ++nNextRaster;
 
478
        if ( -1 == nNextRaster )
 
479
            nNextRaster = 0;
 
480
 
 
481
        fRasterOdd        = ( 1 & nNextRaster ) ? 0 : 1;
 
482
 
 
483
        BYTE* input;
 
484
        unsigned int numpix;
 
485
 
 
486
        for (i=StartPlane; i <= EndPlane; i++)
 
487
        {
 
488
            if (OutputWidth[i] > AdjustedInputWidth)
 
489
            {
 
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);
 
495
                input=tempBuffer;
 
496
                numpix = OutputWidth[i];
 
497
            }
 
498
            else
 
499
            {
 
500
                input=pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR];
 
501
                numpix = AdjustedInputWidth;
 
502
            }
 
503
 
 
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
 
509
            if (i == K)
 
510
                fDitherParms[i].fFEDResPtr = fBlackFEDResPtr;
 
511
            else
 
512
                fDitherParms[i].fFEDResPtr = fColorFEDResPtr;
 
513
            fDitherParms[i].fRasterEvenOrOdd = fRasterOdd;
 
514
            fDitherParms[i].fHifipe = ColorDepth[i]>1;
 
515
 
 
516
            // for matrix //////////////
 
517
            if (usematrix)
 
518
            {
 
519
                fDitherParms[i].fSqueezeOffset=0;
 
520
                fDitherParms[i].fMatrixRowSize = BayerMatrix[1];
 
521
                BYTE colorindex = i + 2;
 
522
                if (i>=Y)
 
523
                    colorindex = 4;
 
524
                BYTE ditheroffset = BayerMatrix[colorindex];
 
525
                BYTE matrixrowsize = BayerMatrix[1];
 
526
                fDitherParms[i].fDitherCellOffset = ditheroffset;
 
527
                BYTE * matrixptr = (BYTE *)(
 
528
                    (((ditheroffset + nNextRaster) % matrixrowsize) * matrixrowsize)
 
529
                        + 5 + BayerMatrix);
 
530
 
 
531
                fDitherParms[i].fMatrixV1 = matrixptr;
 
532
            }
 
533
 
 
534
            ////////////////////////////////////
 
535
 
 
536
            for (j=0; j < NumRows[i]; j++)
 
537
            {
 
538
                fDitherParms[i].fOutput1 = ColorPlane[i][j][0];
 
539
                fDitherParms[i].fOutput2 = ColorPlane[i][j][1];
 
540
 
 
541
                if (usematrix)
 
542
                {
 
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);
 
547
                }
 
548
                else HTEDiffOpen   ((THTDitherParmsPtr) fDitherParms, i);
 
549
 
 
550
 
 
551
                // cleanup bits at end of row due to input-width not being divisible by 8
 
552
                CleanOddBits(i,j);
 
553
            }
 
554
 
 
555
            pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR] += InputWidth;
 
556
 
 
557
        }
 
558
    }
 
559
 
 
560
    if (pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK])
 
561
    {
 
562
        int factor = 1;
 
563
        if (OutputWidth[K] > AdjustedInputWidth)
 
564
        {
 
565
            memset(tempBuffer, 0, OutputWidth[K]);
 
566
            memcpy(tempBuffer,pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK],pbyInputKRGBRaster->rastersize[COLORTYPE_BLACK]);
 
567
 
 
568
            factor = NumRows[K] * ResBoost;
 
569
            PixelMultiply(tempBuffer, pbyInputKRGBRaster->rastersize[COLORTYPE_BLACK], factor);
 
570
        }
 
571
 
 
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++)
 
576
        {
 
577
            if (OutputWidth[K] > AdjustedInputWidth)
 
578
            {
 
579
                if (tempBuffer[i])
 
580
                {
 
581
                    originalKData[curByte] |= curBit;
 
582
                }
 
583
            }
 
584
            else
 
585
            {
 
586
                if (pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK][i])
 
587
                {
 
588
                    originalKData[curByte] |= curBit;
 
589
                }
 
590
            }
 
591
            if (curBit == 0x01)
 
592
            {
 
593
                curByte++;
 
594
                curBit = 0x80;
 
595
            }
 
596
            else
 
597
            {
 
598
                curBit = curBit >> 1;
 
599
            }
 
600
        }
 
601
        for (j=0; j < NumRows[K]; j++)
 
602
        {
 
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];
 
608
        }
 
609
    }
 
610
 
 
611
    iColor = StartPlane;
 
612
    iRow = iPlane = 0;
 
613
    iRastersReady = PlaneCount();
 
614
    iRastersDelivered = 0;
 
615
    return true;   // one raster in, one raster out
 
616
} //Process
 
617
 
 
618
 
 
619
void Halftoner::HTEDiffOpen
 
620
(
 
621
    THTDitherParmsPtr ditherParmsPtr,
 
622
    unsigned short count
 
623
)
 
624
{
 
625
 
 
626
 
 
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;
 
636
 
 
637
    if (hifipe)
 
638
    {
 
639
        outputPtr1 = ditherParms->fOutput1;
 
640
        outputPtr2 = ditherParms->fOutput2;
 
641
        outputPtr3 = ditherParms->fOutput3;
 
642
    }
 
643
 
 
644
    diffusionErrorPtr = errPtr;
 
645
 
 
646
    rasterByte1 = 0;
 
647
    rasterByte2 = 0;
 
648
    rasterByte3 = 0;
 
649
 
 
650
    if( ditherParms->fRasterEvenOrOdd == 1 )
 
651
    {
 
652
        tmpShortStore = *diffusionErrorPtr;
 
653
 
 
654
        *diffusionErrorPtr = 0;
 
655
 
 
656
        for (pixelCount = numLoop + 8; (pixelCount -= 8) > 0; )
 
657
        {
 
658
            if (pixelCount > 16) // if next 16 pixels are white, skip 8
 
659
            {
 
660
                doNext8Pixels = Forward16PixelsNonWhite(inputPtr);
 
661
            }
 
662
            else
 
663
            {
 
664
                doNext8Pixels = true;
 
665
            }
 
666
 
 
667
            if (doNext8Pixels)
 
668
            {
 
669
                thValue = HPRand();
 
670
                FORWARD_FED( thValue, 0x80 );
 
671
                thValue = HPRand();
 
672
                FORWARD_FED( thValue, 0x40 );
 
673
                thValue = HPRand();
 
674
                FORWARD_FED( thValue, 0x20 );
 
675
                thValue = HPRand();
 
676
                FORWARD_FED( thValue, 0x10 );
 
677
                thValue = HPRand();
 
678
                FORWARD_FED( thValue, 0x08 );
 
679
                thValue = HPRand();
 
680
                FORWARD_FED( thValue, 0x04 );
 
681
                thValue = HPRand();
 
682
                FORWARD_FED( thValue, 0x02 );
 
683
                thValue = HPRand();
 
684
                FORWARD_FED( thValue, 0x01 );
 
685
 
 
686
                *outputPtr1++ = rasterByte1;
 
687
                rasterByte1 = 0;
 
688
 
 
689
                if (hifipe)
 
690
                {
 
691
                    *outputPtr2++ = rasterByte2;
 
692
                    rasterByte2 = 0;
 
693
                }
 
694
            }
 
695
            else  // Do white space skipping
 
696
            {
 
697
                inputPtr += 8;
 
698
                *outputPtr1++ = 0;
 
699
                if (hifipe)
 
700
                {
 
701
                    *outputPtr2++ = 0;
 
702
                }
 
703
                *diffusionErrorPtr++ = 0;
 
704
                *diffusionErrorPtr++ = 0;
 
705
                *diffusionErrorPtr++ = 0;
 
706
                *diffusionErrorPtr++ = 0;
 
707
                *diffusionErrorPtr++ = 0;
 
708
                *diffusionErrorPtr++ = 0;
 
709
                *diffusionErrorPtr++ = 0;
 
710
                *diffusionErrorPtr++ = 0;
 
711
                rasterByte1 = 0;
 
712
                rasterByte2 = 0;
 
713
                tmpShortStore = 0;
 
714
            }
 
715
        } // for pixelCount
 
716
    }
 
717
    else
 
718
    {
 
719
        rasterByte1 = 0;
 
720
        rasterByte2 = 0;
 
721
        inputPtr  += ( numLoop-1 );
 
722
        outputPtr1 += ( numLoop/8 - 1 );
 
723
        outputPtr2 += ( numLoop/8 - 1 );
 
724
        diffusionErrorPtr += ( numLoop-1 );
 
725
 
 
726
        tmpShortStore = *diffusionErrorPtr;
 
727
 
 
728
        *diffusionErrorPtr = 0;
 
729
 
 
730
        for (pixelCount = numLoop + 8; (pixelCount -= 8) > 0; )
 
731
        {
 
732
            if (pixelCount > 16) // if next 16 pixels are white, skip 8
 
733
            {
 
734
                doNext8Pixels = Backward16PixelsNonWhite(inputPtr);
 
735
            }
 
736
            else
 
737
            {
 
738
                doNext8Pixels = true;
 
739
            }
 
740
 
 
741
            if (doNext8Pixels)
 
742
            {
 
743
                thValue = HPRand();
 
744
                BACKWARD_FED( thValue, 0x01 );
 
745
                thValue = HPRand();
 
746
                BACKWARD_FED( thValue, 0x02 );
 
747
                thValue = HPRand();
 
748
                BACKWARD_FED( thValue, 0x04 );
 
749
                thValue = HPRand();
 
750
                BACKWARD_FED( thValue, 0x08 );
 
751
                thValue = HPRand();
 
752
                BACKWARD_FED( thValue, 0x10 );
 
753
                thValue = HPRand();
 
754
                BACKWARD_FED( thValue, 0x20 );
 
755
                thValue = HPRand();
 
756
                BACKWARD_FED( thValue, 0x40 );
 
757
                thValue = HPRand();
 
758
                BACKWARD_FED( thValue, 0x80 );
 
759
 
 
760
                *outputPtr1-- = rasterByte1;
 
761
                rasterByte1 = 0;
 
762
 
 
763
                if (hifipe)
 
764
                {
 
765
                    *outputPtr2-- = rasterByte2;
 
766
                    rasterByte2 = 0;
 
767
                }
 
768
            }
 
769
            else  // Do white space skipping
 
770
            {
 
771
                inputPtr -= 8;
 
772
                *outputPtr1-- = 0;
 
773
                if (hifipe)
 
774
                {
 
775
                    *outputPtr2-- = 0;
 
776
                }
 
777
                *diffusionErrorPtr-- = 0;
 
778
                *diffusionErrorPtr-- = 0;
 
779
                *diffusionErrorPtr-- = 0;
 
780
                *diffusionErrorPtr-- = 0;
 
781
                *diffusionErrorPtr-- = 0;
 
782
                *diffusionErrorPtr-- = 0;
 
783
                *diffusionErrorPtr-- = 0;
 
784
                *diffusionErrorPtr-- = 0;
 
785
                rasterByte1 = 0;
 
786
                rasterByte2 = 0;
 
787
                tmpShortStore = 0;
 
788
            }
 
789
        }
 
790
    }
 
791
} //HTEDiffOpen
 
792
 
 
793
//////////////////////////////////////////////////////////
 
794
void Halftoner::FORWARD_FED
 
795
(
 
796
    short thresholdValue,
 
797
    unsigned int bitMask
 
798
)
 
799
{
 
800
    tone = (*inputPtr++ );
 
801
    fedResPtr = fedResTbl + (tone << 2);
 
802
    level = *fedResPtr++;
 
803
    if (tone != 0)
 
804
    {
 
805
    tone = ( tmpShortStore + (short)(*fedResPtr++) );
 
806
    if (tone >= thresholdValue)
 
807
        {
 
808
        tone -= 255;
 
809
        level++;
 
810
        }
 
811
        switch (level)
 
812
        {
 
813
            case 0:
 
814
            break;
 
815
            case 1:
 
816
            rasterByte1 |= bitMask;
 
817
            break;
 
818
            case 2:
 
819
            rasterByte2 |= bitMask;
 
820
            break;
 
821
            case 3:
 
822
            rasterByte2 |= bitMask; rasterByte1 |= bitMask;
 
823
            break;
 
824
            case 4:
 
825
            rasterByte3 |= bitMask;
 
826
            break;
 
827
            case 5:
 
828
            rasterByte3 |= bitMask; rasterByte1 |= bitMask;
 
829
            break;
 
830
            case 6:
 
831
            rasterByte3 |= bitMask; rasterByte2 |= bitMask;
 
832
            break;
 
833
            case 7:
 
834
            rasterByte3 |= bitMask; rasterByte2 |= bitMask; rasterByte1 |= bitMask;
 
835
            break;
 
836
        }
 
837
    }
 
838
    else
 
839
    {
 
840
    tone = tmpShortStore;
 
841
    }
 
842
    *diffusionErrorPtr++ = tone >> 1;
 
843
    tmpShortStore = *diffusionErrorPtr + (tone - (tone >> 1));
 
844
} //FORWARD_FED
 
845
 
 
846
 
 
847
void Halftoner::BACKWARD_FED
 
848
(
 
849
    short thresholdValue,
 
850
    unsigned int bitMask
 
851
)
 
852
{
 
853
    tone = (*inputPtr-- );
 
854
    fedResPtr = fedResTbl + (tone << 2);
 
855
    level = *fedResPtr++;
 
856
    if (tone != 0)
 
857
    {
 
858
    tone = ( tmpShortStore + (short)(*fedResPtr++) );
 
859
    if (tone >= thresholdValue)
 
860
        {
 
861
        tone -= 255;
 
862
        level++;
 
863
        }
 
864
        switch (level)
 
865
        {
 
866
            case 0:
 
867
            break;
 
868
            case 1:
 
869
            rasterByte1 |= bitMask;
 
870
            break;
 
871
            case 2:
 
872
            rasterByte2 |= bitMask;
 
873
            break;
 
874
            case 3:
 
875
            rasterByte2 |= bitMask; rasterByte1 |= bitMask;
 
876
            break;
 
877
            case 4:
 
878
            rasterByte3 |= bitMask;
 
879
            break;
 
880
            case 5:
 
881
            rasterByte3 |= bitMask; rasterByte1 |= bitMask;
 
882
            break;
 
883
            case 6:
 
884
            rasterByte3 |= bitMask; rasterByte2 |= bitMask;
 
885
            break;
 
886
            case 7:
 
887
            rasterByte3 |= bitMask; rasterByte2 |= bitMask; rasterByte1 |= bitMask;
 
888
            break;
 
889
        }
 
890
    }
 
891
    else
 
892
    {
 
893
    tone = tmpShortStore;
 
894
    }
 
895
    *diffusionErrorPtr-- = tone >> 1;
 
896
    tmpShortStore = *diffusionErrorPtr + (tone - (tone >> 1));
 
897
 
 
898
} // BACKWARD_FED
 
899
 
 
900
#define Dither4LevelHiFipe(matrix,bitMask)\
 
901
{\
 
902
    tone = (*inputPtr++ );\
 
903
    fedResPtr = fedResTbl + (tone << 2);\
 
904
    level = *fedResPtr++;\
 
905
    if (*(fedResPtr) >= (BYTE)matrix )\
 
906
    {\
 
907
            level++;\
 
908
    }\
 
909
        switch (level)\
 
910
        {\
 
911
            case 0:\
 
912
                break;\
 
913
            case 1:\
 
914
                rasterByte1 |= bitMask;\
 
915
                break;\
 
916
            case 2:\
 
917
                rasterByte2 |= bitMask;\
 
918
                break;\
 
919
            case 3:\
 
920
                rasterByte2 |= bitMask; rasterByte1 |= bitMask;\
 
921
                break;\
 
922
            case 4:\
 
923
                rasterByte3 |= bitMask;\
 
924
                break;\
 
925
            case 5:\
 
926
                rasterByte3 |= bitMask; rasterByte1 |= bitMask;\
 
927
                break;\
 
928
            case 6:\
 
929
                rasterByte3 |= bitMask; rasterByte2 |= bitMask;\
 
930
                break;\
 
931
            case 7:\
 
932
                rasterByte3 |= bitMask; rasterByte2 |= bitMask; rasterByte1 |= bitMask;\
 
933
                break;\
 
934
        }\
 
935
}
 
936
 
 
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
 
943
//
 
944
//    With matrix actually starting on the 6th Byte.
 
945
//
 
946
//    Black, cyan, and magenta are all offset into different
 
947
//    locations in the dither matrix.  (Yellow uses the same offsets as
 
948
//    magenta)
 
949
//
 
950
 
 
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
 
955
 
 
956
//    To select the right row of the matrix for each color
 
957
//
 
958
//    ditherParms->fMatrixV1 = ((matrixStart + rasterIndex + DitherCellOffset) % (MatrixRowSize)) * (MatrixRowSize)
 
959
 
 
960
DRIVER_ERROR Halftoner::HTMATRIXHI_KCMY   (THTDitherParmsPtr ditherParmsPtr,
 
961
                           unsigned short          count)
 
962
{
 
963
    THTDitherParmsPtr       ditherParms = ditherParmsPtr+count;
 
964
    BYTE                  tone;
 
965
    BYTE                 rasterByte1,rasterByte2, rasterByte3;
 
966
    BYTE                 level;
 
967
    short                 pixelCount;
 
968
 
 
969
    unsigned short                numLoop = ditherParms->fNumPix;
 
970
    BYTE *                inputPtr = ditherParms->fInput;
 
971
    BYTE *                outputPtr1;
 
972
    BYTE *                outputPtr2;
 
973
    BYTE *                outputPtr3;
 
974
 
 
975
    BYTE *                fedResTbl = (BYTE * )ditherParms->fFEDResPtr;
 
976
    BYTE *                fedResPtr;
 
977
 
 
978
    BYTE *        matrixV    = ditherParms->fMatrixV1;
 
979
    BYTE *        matrixH;
 
980
    unsigned short        index;
 
981
    unsigned short        matrixRowSize = ditherParms->fMatrixRowSize;
 
982
 
 
983
    rasterByte1 = 0;
 
984
    rasterByte2 = 0;
 
985
    rasterByte3 = 0;
 
986
 
 
987
    outputPtr1 = ditherParms->fOutput1;
 
988
    outputPtr2 = ditherParms->fOutput2;
 
989
    outputPtr3 = ditherParms->fOutput3;
 
990
 
 
991
    if (!ditherParms->fSymmetricFlag)
 
992
        return SYSTEM_ERROR;    // matrixHI_KCMY asymetric not supported
 
993
 
 
994
    index = (ditherParms->fDitherCellOffset + ditherParms->fSqueezeOffset) % (matrixRowSize);
 
995
    matrixH = matrixV + index;
 
996
 
 
997
    for (pixelCount = numLoop + 8; (pixelCount -= 8) > 0; )
 
998
    {
 
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 )
 
1002
        {
 
1003
            matrixH = matrixV;
 
1004
            index = 0;
 
1005
        }
 
1006
 
 
1007
        Dither4LevelHiFipe(*matrixH,0x80);
 
1008
        matrixH++;
 
1009
        Dither4LevelHiFipe(*matrixH,0x40);
 
1010
        matrixH++;
 
1011
        Dither4LevelHiFipe(*matrixH,0x20);
 
1012
        matrixH++;
 
1013
        Dither4LevelHiFipe(*matrixH,0x10);
 
1014
        matrixH++;
 
1015
        Dither4LevelHiFipe(*matrixH,0x08);
 
1016
        matrixH++;
 
1017
        Dither4LevelHiFipe(*matrixH,0x04);
 
1018
        matrixH++;
 
1019
        Dither4LevelHiFipe(*matrixH,0x02);
 
1020
        matrixH++;
 
1021
        Dither4LevelHiFipe(*matrixH,0x01);
 
1022
        matrixH++;
 
1023
 
 
1024
        *outputPtr1++ |= rasterByte1;
 
1025
        if (outputPtr2)
 
1026
            *outputPtr2++ |= rasterByte2;
 
1027
        rasterByte1 = 0;
 
1028
        rasterByte2 = 0;
 
1029
 
 
1030
        index += 8;
 
1031
    }
 
1032
    return NO_ERROR;
 
1033
}
 
1034
 
 
1035
unsigned char BayerMatrix[] =
 
1036
{
 
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,
 
1046
};
 
1047