Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / DtHelp / il / ilbigray.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: ilbigray.c /main/6 1996/09/24 17:12:45 drk $ */
24 /**---------------------------------------------------------------------
25 ***     
26 ***    (c)Copyright 1991 Hewlett-Packard Co.
27 ***    
28 ***                             RESTRICTED RIGHTS LEGEND
29 ***    Use, duplication, or disclosure by the U.S. Government is subject to
30 ***    restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
31 ***    Technical Data and Computer Software clause in DFARS 252.227-7013.
32 ***                             Hewlett-Packard Company
33 ***                             3000 Hanover Street
34 ***                             Palo Alto, CA 94304 U.S.A.
35 ***    Rights for non-DOD U.S. Government Departments and Agencies are as set
36 ***    forth in FAR 52.227-19(c)(1,2).
37 ***
38 ***-------------------------------------------------------------------*/
39
40         /*  /ilc/ilbigray.c : Contains ilBitonalToGray(), which adds a pipe element 
41             to convert the pipe image (which must be IL_BITONAL) to gray scale.
42         */
43
44 #include "ilint.h"
45 #include "ilpipelem.h"
46 #include "ilscaleint.h"
47 #include "ilerrors.h"
48
49 #ifdef LSB_BIT_ORDER
50 extern void flip_bits(register ilPtr start, register unsigned n);
51 #else
52 # define flip_bits(s,n)          /*EMPTY*/
53 #endif
54
55 #define IL_FILTER_SIZE         3                   /* size of one side of filter square */
56 #define IL_FILTER_SQUARE (IL_FILTER_SIZE*IL_FILTER_SIZE)  /* square size of filter */
57 #define MIN_DESIRED_STRIP     16                   /* arbitrary: desired size of strips */
58
59         /*  Private data for pipe elements.
60             See comments under ilInit9BitFilter() for a description of "filterValues".
61         */
62 typedef struct {
63
64         /*  Data inited by ilScaleBitonalToGray() when pipe element added. */
65     ilByte          filterValues [512];         /* should be first for efficiency! */
66     ilBool          bitonalOutput;              /* true: outputting bitonal, else gray */
67     int            *pGrayThreshold;             /* bitonal out only: ptr to threshold */
68     int             defaultGrayThreshold;       /* pGrayThreshold -> this if defaulting */
69     long            srcWidth, srcHeight;        /* size of src (pipe) image */
70     long            dstWidth, dstHeight;        /* size of dst (output) image */
71     long            widthDiff, heightDiff;      /* src - dst of width/height */
72     long            srcBufferHeight;            /* height of perm src image, else 0 */
73
74         /*  Data inited by ilBiGrayInit() */
75     unsigned int    grayThreshold;              /* *pGrayThreshold for this pass */
76     long            lineAcc;                    /* line accumulator for vert scaling */
77     long            srcRowBytes;                /* bytes/row of src image */
78     ilPtr           pSrcPixels;                 /* ptr to start of src pixels */
79     long            dstRowBytes;                /* bytes/row of dst image */
80     ilPtr           pDstPixels;                 /* ptr to start of dst pixels */
81     } ilBiGrayPrivRec, *ilBiGrayPrivPtr;
82
83
84         /*  --------------------------- ilInit9BitFilter ---------------------------- */
85         /*  Init "*pTable", a 512 entry table, with the values to be indexed by a 9 bit
86             number formed as follows:
87                              -----------
88                             | 8 | 7 | 6 |   <- top source line
89                              -----------
90                             | 5 | 4 | 3 |   <- bit "4" is logical center point
91                              -----------
92                             | 2 | 1 | 0 |
93                              -----------
94             The bits are shifted into a 9 bit number, as above, then used as an index
95             into the table.  The value in entry 0xff (all bits on) should equal
96             the max gray value ("nLevels" - 1).
97         */
98 static void ilInit9BitFilter (
99     long            srcWidth,
100     long            srcHeight,
101     long            dstWidth,
102     long            dstHeight,
103     unsigned long   nLevels,
104     ilBool          blackIsZero,
105     ilByte         *pTable
106     )
107 {
108 double              filter [IL_FILTER_SQUARE];
109 double              fraction, widthScale, heightScale, totalArea, widthSmall, heightSmall;
110 long                value, nLevelsM1;
111 int                 i;
112
113         /*  Setup "filter" with the fractional (0..1) contribution of each pixel to
114             the whole, in the bit order described above (bit 0 is the top-left pixel).
115             The sum of all values should ~= 1.0.  The portion of each pixel selected
116             is based on a square of size "srcWidth/dstWidth" by "srcHeight/dstHeight",
117             mapped over the source pixels, centered on pixel 4 (above).  If the scale
118             factor is greater than 3.0 in either direction, make it 3.0 (all pixels
119             contribute equally in that direction.
120         */
121     widthScale = (double)srcWidth / (double)dstWidth;
122     if (widthScale > 3.0)
123         widthScale = 3.0;
124     heightScale = (double)srcHeight / (double)dstHeight;
125     if (heightScale > 3.0)
126         heightScale = 3.0;
127     totalArea = widthScale * heightScale;
128
129         /*  The center pixel is a 1x1 square.
130             The four corner pixels are overlayed by a rect of width or height (wh) =
131             (wh - 1) / 2: the whole side is "wh", - 1 for center, / 2 cause there are 2.
132             The four side pixels have width/height of corner pixels, but other dim = 1.
133         */
134     filter [4] = 1.0 / totalArea;
135     widthSmall = (widthScale - 1.0) / 2.0;
136     heightSmall = (heightScale - 1.0) / 2.0;
137     filter [0] = filter [2] = filter [6] = filter [8] = 
138         (widthSmall * heightSmall) / totalArea;
139     filter [1] = filter [7] = heightSmall / totalArea;
140     filter [3] = filter [5] = widthSmall / totalArea;
141
142         /*  Convert the filter to an array indexed by a 9 bit number: the filter bits
143             as shown above, in order "876543210".  If whitePixel is 0, add the filter
144             fraction if bit is off. If whitePixel not zero than add the filter fraction 
145             if bit is on.
146         */
147     nLevelsM1 = nLevels - 1;
148     if (!blackIsZero) {
149         for (i = 0; i < 512; i++) {
150             fraction = 0.0;
151             if (!(i & 1))   fraction += filter [0];
152             if (!(i & 2))   fraction += filter [1];
153             if (!(i & 4))   fraction += filter [2];
154             if (!(i & 8))   fraction += filter [3];
155             if (!(i & 16))  fraction += filter [4];
156             if (!(i & 32))  fraction += filter [5];
157             if (!(i & 64))  fraction += filter [6];
158             if (!(i & 128)) fraction += filter [7];
159             if (!(i & 256)) fraction += filter [8];
160             value = fraction * nLevelsM1 + 0.5;
161             if (value > nLevelsM1)
162                 value = nLevelsM1;
163             pTable [i] = value;
164             }
165         }
166     else {          /* a 1 is white */
167         for (i = 0; i < 512; i++) {
168             fraction = 0.0;
169             if (i & 1)   fraction += filter [0];
170             if (i & 2)   fraction += filter [1];
171             if (i & 4)   fraction += filter [2];
172             if (i & 8)   fraction += filter [3];
173             if (i & 16)  fraction += filter [4];
174             if (i & 32)  fraction += filter [5];
175             if (i & 64)  fraction += filter [6];
176             if (i & 128) fraction += filter [7];
177             if (i & 256) fraction += filter [8];
178             value = fraction * nLevelsM1 + 0.5;
179             if (value > nLevelsM1)
180                 value = nLevelsM1;
181             pTable [i] = value;
182             }
183         }
184 }
185
186         /*  --------------------- ilBiGrayInit -------------------------- */
187         /*  Init() function: copy values from given images to private for fast reference.
188         */
189 static ilError ilBiGrayInit (
190     ilBiGrayPrivPtr        pPriv,
191     ilImageInfo        *pSrcImage,
192     ilImageInfo        *pDstImage
193     )
194 {
195
196     pPriv->lineAcc = pPriv->heightDiff;
197     pPriv->srcRowBytes = pSrcImage->plane[0].nBytesPerRow;
198     pPriv->pSrcPixels = pSrcImage->plane[0].pPixels;
199     pPriv->dstRowBytes = pDstImage->plane[0].nBytesPerRow;
200     pPriv->pDstPixels = pDstImage->plane[0].pPixels;
201
202         /*  Copy caller's threshold if scaling to bitonal.
203         */
204     if (pPriv->bitonalOutput)
205         pPriv->grayThreshold = *pPriv->pGrayThreshold;
206
207     return IL_OK;
208 }
209
210         /*  --------------------- ilBiGrayExecute -------------------------- */
211         /*  Execute() pipe element function for scaling bitonal to gray.
212         */
213 static ilError ilBiGrayExecute (
214     ilExecuteData          *pData,
215     long                    dstLine,
216     long                   *pNLines
217     )
218 {
219 #define ULPTR               CARD32 *
220 #ifdef LSB_BIT_ORDER
221 # define SPECIAL_MASK_BIT    0x00000001          /* for LSB bit order */
222 # define SHIFT_MASK(m)       ((m) <<= 1)
223 #else
224 # define SPECIAL_MASK_BIT    0x80000000          /* for MSB bit order */
225 # define SHIFT_MASK(m)       ((m) >>= 1)
226 #endif
227 long                        nLines, nLinesWritten;
228 ilPtr                       pSrcLine, pDstLine;
229 long                        colAcc, nDstBits, dstWidth, bottomLine, line;
230 register long               srcBytesAbove, srcBytesBelow;
231 register ilBiGrayPrivPtr    pPriv;
232 register CARD32             index, *pSrc;
233 register int                shift, bitNumber;
234
235         /*  Point pSrcLine to srcLine: = middle line of 3x3 matrix.
236             Set bottomLine to last available line in the buffer.
237         */
238     pPriv = (ilBiGrayPrivPtr)pData->pPrivate;
239     dstWidth = pPriv->dstWidth;
240     pSrcLine = pPriv->pSrcPixels + pData->srcLine * pPriv->srcRowBytes;
241     pDstLine = pPriv->pDstPixels + dstLine * pPriv->dstRowBytes;
242
243     nLines = *pNLines;
244     if (nLines <= 0)
245         return;                                 /* no lines, EXIT */
246     if (pPriv->srcBufferHeight)
247          bottomLine = pPriv->srcBufferHeight - 1;
248     else bottomLine = pData->srcLine + nLines - 1;
249     line = pData->srcLine - 1;                  /* line of top of 3x3 matrix */
250
251     nLinesWritten = 0;
252     while (TRUE) {
253         while (pPriv->lineAcc > 0) {
254             if (nLines-- <= 0) goto BGLinesDone;
255             pPriv->lineAcc -= pPriv->dstHeight;
256             pSrcLine += pPriv->srcRowBytes;
257             line++;
258             }
259         if (nLines-- <= 0) goto BGLinesDone;
260         pPriv->lineAcc += pPriv->heightDiff;
261
262             /*  Algorithm: skip src bits, using basic scale algorithm.  To form dst bit,
263                 form 9 bit value from 3x3, with top bits in high order bits.  Lookup
264                 the 9 bit value in table of correct gray scale.  "bitNumber" is the
265                 # of the left bit of 3x3; 31 = left bit of long.  If bitNumber is < 2,
266                 the bits cross a long boundary: get bits from bytes, low order of this
267                 long and high order byte of next long.
268                     pSrc will point to the middle line of 3x3; the line above is 
269                 "-srcBytesAbove" away; the line below is "srcBytesBelow" away.  If the 3x3
270                 is outside of the buffer being read, set "srcBytesAbove/Below" to 0,
271                 causing the middle line to be re-read and replicated to replace the
272                 unaccessible line.
273             */
274         srcBytesAbove = (line < 0) ? 0 : pPriv->srcRowBytes;
275         srcBytesBelow = ((line + 2) > bottomLine) ? 0 : pPriv->srcRowBytes;
276         nDstBits = pPriv->dstWidth;
277
278             /*  Set pSrc and bitNumber to point to the rightmost bit of the long before
279                 the first long.  The "colAcc > 0" check below will be true, causing a bump
280                 to the next bit (first bit in row), _except_ when "widthDiff" is 0 (no
281                 hori scaling).  In this case, set colAcc to 1, forcing the first colAcc>0
282                 check to be true and bumping past first bit - the rest proceeds normally.
283             */
284         pSrc = ((ULPTR)pSrcLine) - 1;
285         bitNumber = 0;
286         colAcc = pPriv->widthDiff;
287         if (colAcc <= 0)
288             colAcc = 1;
289
290             /*  If bitonal output, logically produce a gray pixel, then output a 1 if
291                 gray is < threshold.
292             */
293         if (pPriv->bitonalOutput) {
294             ULPTR           pDst;
295             CARD32          mask, outLong;
296
297             pDst = (ULPTR)pDstLine;
298             mask = SPECIAL_MASK_BIT;
299             outLong = 0;                /* fill with 1's as necessary */
300
301             while (TRUE) {
302                 while (colAcc > 0) {
303                     colAcc -= dstWidth;
304                     if (--bitNumber < 0) {
305                         pSrc++;
306                         bitNumber = 31;
307                         }
308                     }
309                 colAcc += pPriv->widthDiff;
310
311                    /*  If done and mask != left bit on, output bits in "outLong". */
312                 if (nDstBits <= 0) {
313                     if (mask != SPECIAL_MASK_BIT) {
314                          flip_bits((ilPtr)&outLong, sizeof(outLong));
315                         *pDst++ = outLong;
316                      }
317                     break;                      /* done this line; exit while */
318                     }
319                 if (--nDstBits <= 0) {
320                     INT32 rightBit = (((ilPtr)pSrc - pSrcLine) << 3) + 34 - bitNumber;
321                     if ((rightBit > pPriv->srcWidth) && (pPriv->srcWidth > 3))
322                         if (++bitNumber > 31) {bitNumber = 0; pSrc--; }
323                     }
324                 if (bitNumber >= 2) {
325                     shift = bitNumber - 2;
326                     index = (*((ULPTR)((ilPtr)pSrc - srcBytesAbove)) >> shift) & 7;
327                     index <<= 3;
328                     index |= (*pSrc >> shift) & 7;
329                     index <<= 3;
330                     index |= (*((ULPTR)((ilPtr)pSrc + srcBytesBelow)) >> shift) & 7;
331                     }
332                 else {
333                     ilPtr pSrcTemp = (ilPtr)pSrc - srcBytesAbove + 3;
334                     shift = 6 + bitNumber;
335                     index = ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
336                     index <<= 3;
337                     pSrcTemp += srcBytesAbove;
338                     index |= ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
339                     index <<= 3;
340                     pSrcTemp += srcBytesBelow;
341                     index |= ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
342                     }
343                 if (pPriv->filterValues [index] < pPriv->grayThreshold)
344                     outLong |= mask;
345                 if (!(SHIFT_MASK(mask))) {
346                     flip_bits((ilPtr)&outLong, sizeof(outLong));
347                     *pDst++ = outLong;
348                     mask = SPECIAL_MASK_BIT;
349                     outLong = 0;
350                     }
351                 if (--bitNumber < 0) {              /* next src bit */
352                     pSrc++;
353                     bitNumber = 31;
354                     }
355                 }   /* END column loop */
356             }
357         else {      /* outputting gray */
358             ilPtr       pDst;
359             pDst = pDstLine;
360
361             while (TRUE) {
362                 while (colAcc > 0) {
363                     colAcc -= dstWidth;
364                     if (--bitNumber < 0) {
365                         pSrc++;
366                         bitNumber = 31;
367                         }
368                     }
369                 colAcc += pPriv->widthDiff;
370                 if (nDstBits <= 0)
371                     break;                      /* done this line; exit while */
372                 if (--nDstBits <= 0) {
373                     INT32 rightBit = (((ilPtr)pSrc - pSrcLine) << 3) + 34 - bitNumber;
374                     if ((rightBit > pPriv->srcWidth) && (pPriv->srcWidth > 3))
375                         if (++bitNumber > 31) {bitNumber = 0; pSrc--; }
376                     }
377                 if (bitNumber >= 2) {
378                     shift = bitNumber - 2;
379                     index = (*((ULPTR)((ilPtr)pSrc - srcBytesAbove)) >> shift) & 7;
380                     index <<= 3;
381                     index |= (*pSrc >> shift) & 7;
382                     index <<= 3;
383                     index |= (*((ULPTR)((ilPtr)pSrc + srcBytesBelow)) >> shift) & 7;
384                     }
385                 else {
386                     ilPtr pSrcTemp = (ilPtr)pSrc - srcBytesAbove + 3;
387                     shift = 6 + bitNumber;
388                     index = ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
389                     index <<= 3;
390                     pSrcTemp += srcBytesAbove;
391                     index |= ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
392                     index <<= 3;
393                     pSrcTemp += srcBytesBelow;
394                     index |= ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
395                     }
396                 *pDst++ = pPriv->filterValues [index];
397                 if (--bitNumber < 0) {              /* next src bit */
398                     pSrc++;
399                     bitNumber = 31;
400                     }
401                 }   /* END column loop */
402             }
403
404             /*  Line done; next src, dst lines; inc line index and # lines written.
405             */
406         pSrcLine += pPriv->srcRowBytes;
407         line++;
408         pDstLine += pPriv->dstRowBytes;
409         nLinesWritten++;
410         }       /* END loop, one dst line */
411
412 BGLinesDone:
413     *pNLines = nLinesWritten;
414     return IL_OK;
415 }
416
417
418     /*  ------------------------- ilScaleBitonalToGray ---------------------------- */
419     /*  Called by ilScale().
420         Adds an element to "pipe" to scale the pipe image to "dstWidth" by "dstHeight"
421         which both must be > 0.  The input pipe image must be a bitonal,
422         bit-per-pixel image, with the given "blackIsZero".  "pInfo" points to the
423         pipe info, "dstWidth/Height" is the (> 0) size to scale to, and nGrayLevels
424         is the number of levels of gray.  The output image is a gray image.
425             Only a scale down in both directions is allowed; the following must be true:
426         srcWidth must be >= dstWidth and srcHeight must be >= dstHeight!
427     */
428 IL_PRIVATE void _ilScaleBitonalToGray (
429     ilPipe              pipe,
430     unsigned long       dstWidth,
431     unsigned long       dstHeight,
432     unsigned long       nGrayLevels,
433     ilBool              blackIsZero,
434     ilPipeInfo         *pInfo
435     )
436 {
437 register ilBiGrayPrivPtr pPriv;
438 ilDstElementData        dstData;
439 ilImageDes              des;
440
441
442     /* Idiot check the number of gray levels */
443
444     if ((nGrayLevels < 2) || (nGrayLevels > 256)) {
445         ilDeclarePipeInvalid (pipe, IL_ERROR_LEVELS_PER_SAMPLE);
446         return;                                                     /* EXIT */
447         }
448
449         /*  Add a filter to do the scale, then init *pPriv.
450         */
451     dstData.producerObject = (ilObject)NULL;
452     des = *IL_DES_GRAY;
453     des.nLevelsPerSample[0] = nGrayLevels;
454     dstData.pDes = &des;
455     dstData.pFormat = IL_FORMAT_BYTE;
456     dstData.width = dstWidth;
457     dstData.height = dstHeight;
458     dstData.stripHeight = ((dstHeight * pInfo->recommendedStripHeight) / pInfo->height) + 1;
459     dstData.constantStrip = FALSE;
460     dstData.pPalette = (unsigned short *)NULL;
461     pPriv = (ilBiGrayPrivPtr)ilAddPipeElement (pipe, IL_FILTER, sizeof (ilBiGrayPrivRec), 
462                          IL_ADD_PIPE_HOLD_SRC, (ilSrcElementData *)NULL, &dstData, 
463                          ilBiGrayInit, IL_NPF, IL_NPF, ilBiGrayExecute, NULL, 0);
464     if (!pPriv)
465         return;
466
467         /*  Pipe element added, init pPriv.  If not a tempImage, reading directly from
468             a permanent image: set srcHeight to image height; else set to 0.
469         */
470     pPriv->bitonalOutput = FALSE;
471     pPriv->srcWidth = pInfo->width;
472     pPriv->srcHeight = pInfo->height;
473     pPriv->dstWidth = dstWidth;
474     pPriv->dstHeight = dstHeight;
475     pPriv->widthDiff = pInfo->width - dstWidth;
476     pPriv->heightDiff = pInfo->height - dstHeight;
477     if (!pInfo->tempImage)
478          pPriv->srcBufferHeight = pInfo->height;
479     else pPriv->srcBufferHeight = 0;
480
481         /*  Init the filter table in private based on scale factors and # gray levels.
482         */
483     ilInit9BitFilter (pPriv->srcWidth, pPriv->srcHeight, pPriv->dstWidth, 
484                       pPriv->dstHeight, nGrayLevels, blackIsZero, pPriv->filterValues);
485
486     pipe->context->error = IL_OK;
487 }
488
489
490     /*  ------------------------- ilAreaScaleBitonal ---------------------------- */
491     /*  Called by ilScale().
492         Adds an element to "pipe" to scale the pipe image to "dstWidth" by "dstHeight"
493         which both must be > 0.  The input pipe image must be a bitonal,
494         bit-per-pixel image, with _any_ "blackIsZero".  The resulting image is of the 
495         same type. "pInfo" points to the pipe info, "dstWidth/Height" is the (> 0) size 
496         to scale to.
497             Only a scale down in both directions is allowed; the following must be true:
498         srcWidth must be >= dstWidth and srcHeight must be >= dstHeight!
499             Logically the same as ilScaleBitonalToGray(): a gray byte is produced for
500         each destination pixel, using 256 levels of gray.  If that byte is 
501         >= "*pGrayThreshold"; a white pixel is written; else a black pixel is written.
502             NOTE: the value at "*pGrayThreshold" is read each time the pipe is executed
503         (during Init()); the caller change its value and get different results without
504         recreating the pipe.  If "pGrayThreshold" is NULL, a default value is used.
505     */
506 IL_PRIVATE void _ilAreaScaleBitonal (
507     ilPipe              pipe,
508     unsigned long       dstWidth,
509     unsigned long       dstHeight,
510     int                *pGrayThreshold,
511     ilPipeInfo         *pInfo
512     )
513 {
514 register ilBiGrayPrivPtr pPriv;
515 ilDstElementData        dstData;
516 #define                 DEFAULT_GRAY_THRESHOLD  128     /* assumes 256 levels */
517
518         /*  Add a filter to do the scale, then init *pPriv. 
519         */
520     dstData.producerObject = (ilObject)NULL;
521     dstData.pDes = (ilImageDes *)NULL;
522     dstData.pFormat = IL_FORMAT_BIT;
523     dstData.width = dstWidth;
524     dstData.height = dstHeight;
525     dstData.stripHeight = ((dstHeight * pInfo->recommendedStripHeight) / pInfo->height) + 1;
526     dstData.constantStrip = FALSE;
527     dstData.pPalette = (unsigned short *)NULL;
528     pPriv = (ilBiGrayPrivPtr)ilAddPipeElement (pipe, IL_FILTER, sizeof (ilBiGrayPrivRec), 
529                          IL_ADD_PIPE_HOLD_SRC, (ilSrcElementData *)NULL, &dstData, 
530                          ilBiGrayInit, IL_NPF, IL_NPF, ilBiGrayExecute, NULL, 0);
531     if (!pPriv)
532         return;
533
534         /*  Pipe element added, init pPriv.  If not a tempImage, reading directly from
535             a permanent image: set srcHeight to image height; else set to 0.
536         */
537     pPriv->bitonalOutput = TRUE;
538     if (pGrayThreshold)
539         pPriv->pGrayThreshold = pGrayThreshold;
540     else {
541         pPriv->defaultGrayThreshold = DEFAULT_GRAY_THRESHOLD;
542         pPriv->pGrayThreshold = &pPriv->defaultGrayThreshold;
543         }
544     pPriv->srcWidth = pInfo->width;
545     pPriv->srcHeight = pInfo->height;
546     pPriv->dstWidth = dstWidth;
547     pPriv->dstHeight = dstHeight;
548     pPriv->widthDiff = pInfo->width - dstWidth;
549     pPriv->heightDiff = pInfo->height - dstHeight;
550     if (!pInfo->tempImage)
551          pPriv->srcBufferHeight = pInfo->height;
552     else pPriv->srcBufferHeight = 0;
553
554         /*  Init the filter table in private based on scale factors and 256 gray levels.
555             Note that "blackIsZero" is passed as FALSE below, because we want to output
556             the same blackIsZero as input.  We output a zero when the gray is 
557             >= threshold; this works for either sense of blackIsZero.
558         */
559     ilInit9BitFilter (pPriv->srcWidth, pPriv->srcHeight, pPriv->dstWidth, 
560                       pPriv->dstHeight, 256, FALSE, pPriv->filterValues);
561
562     pipe->context->error = IL_OK;
563 }
564
565