Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / lib / DtHelp / il / ilformat.c
1 /* $XConsortium: ilformat.c /main/5 1996/06/19 12:21:36 ageorge $ */
2 /**---------------------------------------------------------------------
3 ***     
4 ***    (c)Copyright 1991 Hewlett-Packard Co.
5 ***    
6 ***                             RESTRICTED RIGHTS LEGEND
7 ***    Use, duplication, or disclosure by the U.S. Government is subject to
8 ***    restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
9 ***    Technical Data and Computer Software clause in DFARS 252.227-7013.
10 ***                             Hewlett-Packard Company
11 ***                             3000 Hanover Street
12 ***                             Palo Alto, CA 94304 U.S.A.
13 ***    Rights for non-DOD U.S. Government Departments and Agencies are as set
14 ***    forth in FAR 52.227-19(c)(1,2).
15 ***
16 ***-------------------------------------------------------------------*/
17
18         /*  /ilc/ilformat.c : Reference by ilConvert in /ilc/ilconvert.c .
19             Contains pipe functions and an ilFormatRec, which points to the functions
20             and defines how the formatter should be added by ilConvert().
21         */
22 #include "ilint.h"
23 #include "ilpipelem.h"
24 #include "ilconvert.h"
25 #include "ilerrors.h"
26
27         /*  ------------------------- ilExecuteBitAlign ------------------------- */
28         /*  Execute() function: convert the given # of src lines, changing
29             the rowBitAlign.  Easy; just bcopy each line, bump by src/dstRowBytes,
30             which presumably are different because of different bit alignment.
31         */
32 static ilError ilExecuteBitAlign (
33     ilExecuteData          *pData,
34     long                    dstLine,
35     long                   *pNLines
36     )
37 {
38 ilImagePlaneInfo           *pImagePlane;
39 long                        srcRowBytes, dstRowBytes;
40 register long               nLinesM1, nBytes;
41 register ilPtr              pSrc, pDst;
42
43         /*  Use bcopy to copy each line; copy the lesser of the src/dstRowBytes.
44             Exit if no lines or pixels.
45         */
46     pImagePlane = &pData->pSrcImage->plane[0];
47     srcRowBytes = pImagePlane->nBytesPerRow;
48     pSrc = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
49
50     pImagePlane = &pData->pDstImage->plane[0];
51     dstRowBytes = pImagePlane->nBytesPerRow;
52     pDst = pImagePlane->pPixels + dstLine * dstRowBytes;
53
54     nBytes = (srcRowBytes < dstRowBytes) ? srcRowBytes : dstRowBytes;
55     if (nBytes <= 0)
56         return IL_OK;
57     nLinesM1 = *pNLines;
58     if (nLinesM1 <= 0)
59         return IL_OK;
60     nLinesM1--;
61
62     do {
63         bcopy ((char *)pSrc, (char *)pDst, nBytes);
64         pSrc += srcRowBytes;
65         pDst += dstRowBytes;
66         } while (--nLinesM1 >= 0);
67
68     return IL_OK;
69 }
70
71         /*  Table exported to ilConvert(), declared in /ilc/ilconvert.h .
72         */
73 IL_PRIVATE ilFormatRec _ilFormatRowBitAlign = {
74     IL_NPF,                                     /* AddElement() */
75     0,                                          /* nBytesPrivate */
76     IL_NPF,                                     /* Init() */
77     IL_NPF,                                     /* Cleanup() */
78     IL_NPF,                                     /* Destroy() */
79     ilExecuteBitAlign                           /* Execute() */
80     };
81
82
83         /*  ------------------------- ilExecute8Bit3PlaneToPixel ------------------------- */
84         /*  Execute() function: convert the given # of src lines, changing
85             format from planar to pixel.  Handles 3 planes of 8 bits/pixel only.
86         */
87 static ilError ilExecute8Bit3PlaneToPixel (
88     ilExecuteData          *pData,
89     long                    dstLine,
90     long                   *pNLines
91     )
92 {
93 ilImagePlaneInfo           *pImagePlane;
94 long                        src0RowBytes, src1RowBytes, src2RowBytes, dstRowBytes;
95 long                        nPixelsM1Init;
96 register long               nLinesM1, nPixelsM1;
97 ilPtr                       pSrc0Line, pSrc1Line, pSrc2Line, pDstLine;
98 register ilPtr              pSrc0, pSrc1, pSrc2, pDst;
99
100         /*  Get ptr to start of 3 src planes and to dst */
101     pImagePlane = pData->pSrcImage->plane;
102     src0RowBytes = pImagePlane->nBytesPerRow;
103     pSrc0Line = pImagePlane->pPixels + pData->srcLine * src0RowBytes;
104     pImagePlane++;
105     src1RowBytes = pImagePlane->nBytesPerRow;
106     pSrc1Line = pImagePlane->pPixels + pData->srcLine * src1RowBytes;
107     pImagePlane++;
108     src2RowBytes = pImagePlane->nBytesPerRow;
109     pSrc2Line = pImagePlane->pPixels + pData->srcLine * src2RowBytes;
110
111     pImagePlane = pData->pDstImage->plane;
112     dstRowBytes = pImagePlane->nBytesPerRow;
113     pDstLine = pImagePlane->pPixels + dstLine * dstRowBytes;
114
115         /*  Exit if no lines or pixels. */
116     nPixelsM1Init = pData->pSrcImage->width;
117     if (nPixelsM1Init <= 0)
118         return IL_OK;
119     nPixelsM1Init--;
120     nLinesM1 = *pNLines;
121     if (nLinesM1 <= 0)
122         return IL_OK;
123     nLinesM1--;
124
125     do {
126         pSrc0 = pSrc0Line;
127         pSrc0Line += src0RowBytes;
128         pSrc1 = pSrc1Line;
129         pSrc1Line += src1RowBytes;
130         pSrc2 = pSrc2Line;
131         pSrc2Line += src2RowBytes;
132         pDst = pDstLine;
133         pDstLine += dstRowBytes;
134         nPixelsM1 = nPixelsM1Init;
135         do {
136             *pDst++ = *pSrc0++;
137             *pDst++ = *pSrc1++;
138             *pDst++ = *pSrc2++;
139             } while (--nPixelsM1 >= 0);
140         } while (--nLinesM1 >= 0);
141
142     return IL_OK;
143 }
144
145         /*  Table exported to ilConvert(), declared in /ilc/ilconvert.h .
146         */
147 IL_PRIVATE ilFormatRec _ilFormat8Bit3PlaneToPixel = {
148     IL_NPF,                                     /* AddElement() */
149     0,                                          /* nBytesPrivate */
150     IL_NPF,                                     /* Init() */
151     IL_NPF,                                     /* Cleanup() */
152     IL_NPF,                                     /* Destroy() */
153     ilExecute8Bit3PlaneToPixel                  /* Execute() */
154     };
155
156         /*  ------------------------- ilExecute8Bit3PixelToPlane ------------------------- */
157         /*  Execute() function: convert the given # of src lines, changing
158             format from pixel to planar.  Handles 3 planes of 8 bits/pixel only.
159         */
160 static ilError ilExecute8Bit3PixelToPlane (
161     ilExecuteData          *pData,
162     long                    dstLine,
163     long                   *pNLines
164     )
165 {
166 ilImagePlaneInfo           *pImagePlane;
167 long                        dst0RowBytes, dst1RowBytes, dst2RowBytes, srcRowBytes;
168 long                        nPixelsM1Init;
169 register long               nLinesM1, nPixelsM1;
170 ilPtr                       pDst0Line, pDst1Line, pDst2Line, pSrcLine;
171 register ilPtr              pDst0, pDst1, pDst2, pSrc;
172
173         /*  Get ptr to start src plane and to 3 dst planes */
174     pImagePlane = pData->pSrcImage->plane;
175     srcRowBytes = pImagePlane->nBytesPerRow;
176     pSrcLine = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
177
178     pImagePlane = pData->pDstImage->plane;
179     dst0RowBytes = pImagePlane->nBytesPerRow;
180     pDst0Line = pImagePlane->pPixels + dstLine * dst0RowBytes;
181     pImagePlane++;
182     dst1RowBytes = pImagePlane->nBytesPerRow;
183     pDst1Line = pImagePlane->pPixels + dstLine * dst1RowBytes;
184     pImagePlane++;
185     dst2RowBytes = pImagePlane->nBytesPerRow;
186     pDst2Line = pImagePlane->pPixels + dstLine * dst2RowBytes;
187
188         /*  Exit if no lines or pixels. */
189     nPixelsM1Init = pData->pSrcImage->width;
190     if (nPixelsM1Init <= 0)
191         return IL_OK;
192     nPixelsM1Init--;
193     nLinesM1 = *pNLines;
194     if (nLinesM1 <= 0)
195         return IL_OK;
196     nLinesM1--;
197
198     do {
199         pSrc = pSrcLine;
200         pSrcLine += srcRowBytes;
201         pDst0 = pDst0Line;
202         pDst0Line += dst0RowBytes;
203         pDst1 = pDst1Line;
204         pDst1Line += dst1RowBytes;
205         pDst2 = pDst2Line;
206         pDst2Line += dst2RowBytes;
207         nPixelsM1 = nPixelsM1Init;
208         do {
209             *pDst0++ = *pSrc++;
210             *pDst1++ = *pSrc++;
211             *pDst2++ = *pSrc++;
212             } while (--nPixelsM1 >= 0);
213         } while (--nLinesM1 >= 0);
214
215     return IL_OK;
216 }
217
218         /*  Table exported to ilConvert(), declared in /ilc/ilconvert.h .
219         */
220 IL_PRIVATE ilFormatRec _ilFormat8Bit3PixelToPlane = {
221     IL_NPF,                                     /* AddElement() */
222     0,                                          /* nBytesPrivate */
223     IL_NPF,                                     /* Init() */
224     IL_NPF,                                     /* Cleanup() */
225     IL_NPF,                                     /* Destroy() */
226     ilExecute8Bit3PixelToPlane                  /* Execute() */
227     };
228
229
230         /*  ------------------------- ilExecute4To8Bit ------------------------- */
231         /*  Execute() function: convert the given # of src lines, changing nibbles
232             to bytes, by copying the nibbles to the low order of the bytes.
233                 Handles any number of samples, but pixel order only if multi-sample.
234         */
235 static ilError ilExecute4To8Bit (
236     ilExecuteData          *pData,
237     long                    dstLine,
238     long                   *pNLines
239     )
240 {
241 ilImageInfo                *pSrcImage;
242 ilImagePlaneInfo           *pImagePlane;
243 long                        srcRowBytes, dstRowBytes, nBytesM1Init, nLinesM1;
244 ilBool                      oddNumberOfNibbles;
245 ilPtr                       pSrcLine, pDstLine;
246 register long               nBytesM1;
247 register ilPtr              pSrc, pDst;
248 register ilByte             byte;
249
250         /*  Exit if no lines or pixels. */
251     pSrcImage = pData->pSrcImage;
252     pImagePlane = &pSrcImage->plane[0];
253     srcRowBytes = pImagePlane->nBytesPerRow;
254     pSrcLine = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
255
256     pImagePlane = &pData->pDstImage->plane[0];
257     dstRowBytes = pImagePlane->nBytesPerRow;
258     pDstLine = pImagePlane->pPixels + dstLine * dstRowBytes;
259
260     nLinesM1 = *pNLines;
261     if (nLinesM1 <= 0)
262         return IL_OK;
263     nLinesM1--;
264
265         /*  Set "nBytesM1Init" to whole # of src bytes to do (2 nibbles each),
266             where the # of nibbles is width * nSamplesPerPixel.
267             Set "oddNumberOfNibbles" true if width is odd (do one last nibble).
268             Copy each src byte (2 nibbles) to two dst bytes; do optional last nibble.
269         */
270     nBytesM1Init = pSrcImage->width * pSrcImage->pDes->nSamplesPerPixel;
271     oddNumberOfNibbles = ((nBytesM1Init & 1) != 0);
272     nBytesM1Init = (nBytesM1Init >> 1) - 1;             /* width/2 - 1 */
273     do {
274         pSrc = pSrcLine;
275         pSrcLine += srcRowBytes;
276         pDst = pDstLine;
277         pDstLine += dstRowBytes;
278         nBytesM1 = nBytesM1Init;
279         if (nBytesM1 >= 0) {
280             do {
281                 byte = *pSrc++;
282                 *pDst++ = byte >> 4;
283                 *pDst++ = byte & 0xf;
284                 } while (--nBytesM1 >= 0);
285             }
286         if (oddNumberOfNibbles) {
287             byte = *pSrc++;
288             *pDst++ = byte >> 4;
289             }
290         } while (--nLinesM1 >= 0);
291
292     return IL_OK;
293 }
294
295         /*  Table exported to ilConvert(), declared in /ilc/ilconvert.h .
296         */
297 IL_PRIVATE ilFormatRec _ilFormat4To8Bit = {
298     IL_NPF,                                     /* AddElement() */
299     0,                                          /* nBytesPrivate */
300     IL_NPF,                                     /* Init() */
301     IL_NPF,                                     /* Cleanup() */
302     IL_NPF,                                     /* Destroy() */
303     ilExecute4To8Bit                            /* Execute() */
304     };
305
306
307         /*  ------------------------- ilExecute8To4Bit ------------------------- */
308         /*  Pack pipe image which is byte/pixel into nibble/pixel.
309             Handles any number of samples, but pixel order only if multi-sample.
310         */
311 static ilError ilExecute8To4Bit (
312     ilExecuteData          *pData,
313     long                    dstLine,
314     long                   *pNLines
315     )
316 {
317 ilImageInfo                *pSrcImage;
318 ilImagePlaneInfo           *pImagePlane;
319 long                        srcRowBytes, dstRowBytes, nBytesM1Init, nLinesM1;
320 ilBool                      oddNumberOfNibbles;
321 ilPtr                       pSrcLine, pDstLine;
322 register long               nBytesM1;
323 register ilPtr              pSrc, pDst;
324 register ilByte             byte0, byte1;
325
326         /*  Exit if no lines or pixels. */
327     pSrcImage = pData->pSrcImage;
328     pImagePlane = &pSrcImage->plane[0];
329     srcRowBytes = pImagePlane->nBytesPerRow;
330     pSrcLine = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
331
332     pImagePlane = &pData->pDstImage->plane[0];
333     dstRowBytes = pImagePlane->nBytesPerRow;
334     pDstLine = pImagePlane->pPixels + dstLine * dstRowBytes;
335
336     nLinesM1 = *pNLines;
337     if (nLinesM1 <= 0)
338         return IL_OK;
339     nLinesM1--;
340
341         /*  Set "nBytesM1Init" to whole # of dst bytes to do (2 nibbles each),
342             where the # of nibbles is width * nSamplesPerPixel.
343             Set "oddNumberOfNibbles" true if width is odd (do one last nibble).
344             Pack each pair of src bytes into one dst nibble; do optional last nibble.
345         */
346     nBytesM1Init = pSrcImage->width * pSrcImage->pDes->nSamplesPerPixel;
347     oddNumberOfNibbles = ((nBytesM1Init & 1) != 0);
348     nBytesM1Init = (nBytesM1Init >> 1) - 1;             /* width/2 - 1 */
349     do {
350         pSrc = pSrcLine;
351         pSrcLine += srcRowBytes;
352         pDst = pDstLine;
353         pDstLine += dstRowBytes;
354         nBytesM1 = nBytesM1Init;
355         if (nBytesM1 >= 0) {
356             do {
357                 byte0 = *pSrc++;
358                 byte1 = *pSrc++;
359                 *pDst++ = (byte0 << 4) | (byte1 & 0xf);
360                 } while (--nBytesM1 >= 0);
361             }
362         if (oddNumberOfNibbles) {
363             byte0 = *pSrc++;
364             *pDst++ = byte0 << 4;
365             }
366         } while (--nLinesM1 >= 0);
367
368     return IL_OK;
369 }
370
371         /*  Table exported to ilConvert(), declared in /ilc/ilconvert.h .
372         */
373 IL_PRIVATE ilFormatRec _ilFormat8To4Bit = {
374     IL_NPF,                                     /* AddElement() */
375     0,                                          /* nBytesPrivate */
376     IL_NPF,                                     /* Init() */
377     IL_NPF,                                     /* Cleanup() */
378     IL_NPF,                                     /* Destroy() */
379     ilExecute8To4Bit                            /* Execute() */
380     };
381
382
383         /*  ------------------------- ilExecute4To8BitScaled ------------------------- */
384         /*  Execute() function: convert the given # of src lines, changing nibbles
385             to bytes, by copying the nibbles to the low order and high order nibbles
386             of the bytes, thus scaling from 0..15 to 0..255.
387                 Handles any number of samples, but pixel order only if multi-sample.
388         */
389 static ilError ilExecute4To8BitScaled (
390     ilExecuteData          *pData,
391     long                    dstLine,
392     long                   *pNLines
393     )
394 {
395 ilImageInfo                *pSrcImage;
396 ilImagePlaneInfo           *pImagePlane;
397 long                        srcRowBytes, dstRowBytes, nBytesM1Init, nLinesM1;
398 ilBool                      oddNumberOfNibbles;
399 ilPtr                       pSrcLine, pDstLine;
400 register long               nBytesM1;
401 register ilPtr              pSrc, pDst;
402 register ilByte             byte;
403
404         /*  Use bcopy to copy each line; copy the lesser of the src/dstRowBytes.
405             Exit if no lines or pixels.
406         */
407     pSrcImage = pData->pSrcImage;
408     pImagePlane = &pSrcImage->plane[0];
409     srcRowBytes = pImagePlane->nBytesPerRow;
410     pSrcLine = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
411
412     pImagePlane = &pData->pDstImage->plane[0];
413     dstRowBytes = pImagePlane->nBytesPerRow;
414     pDstLine = pImagePlane->pPixels + dstLine * dstRowBytes;
415
416     nLinesM1 = *pNLines;
417     if (nLinesM1 <= 0)
418         return IL_OK;
419     nLinesM1--;
420
421         /*  Set "nBytesM1Init" to whole # of src bytes to do (2 nibbles each),
422             where the # of nibbles is width * nSamplesPerPixel.
423             Set "oddNumberOfNibbles" true if width is odd (do one last nibble).
424             Make from each src byte (2 nibbles) two dst bytes; do optional last nibble.
425             Replicate each src nibble to upper/lower nibble of dst byte, thus scaling
426             to new # of levels (from 16 to 256): 0 => 0, 1 => 17, 15 => 255.
427         */
428     nBytesM1Init = pSrcImage->width * pSrcImage->pDes->nSamplesPerPixel;
429     oddNumberOfNibbles = ((nBytesM1Init & 1) != 0);
430     nBytesM1Init = (nBytesM1Init >> 1) - 1;             /* width/2 - 1 */
431     do {
432         pSrc = pSrcLine;
433         pSrcLine += srcRowBytes;
434         pDst = pDstLine;
435         pDstLine += dstRowBytes;
436         nBytesM1 = nBytesM1Init;
437         if (nBytesM1 >= 0) {
438             do {
439                 byte = *pSrc++;
440                 *pDst++ = (byte & 0xf0) | (byte >> 4);
441                 byte &= 0xf;
442                 *pDst++ = (byte << 4) | byte;
443                 } while (--nBytesM1 >= 0);
444             }
445         if (oddNumberOfNibbles) {
446             byte = *pSrc++;
447             *pDst++ = (byte & 0xf0) | (byte >> 4);
448             }
449         } while (--nLinesM1 >= 0);
450
451     return IL_OK;
452 }
453
454
455         /*  ------------------------- ilExecuteByte16To256Level ---------------------- */
456         /*  Execute() function: convert the given # of src lines, changing bytes from
457             16 levels to 256 levels, by replicating the low-order nibble to the high
458             order nibble, thus scaling from 0..15 to 0..255.
459                 Handles any number of samples, but pixel order only if multi-sample.
460         */
461 static ilError ilExecuteByte16To256Level (
462     ilExecuteData          *pData,
463     long                    dstLine,
464     long                   *pNLines
465     )
466 {
467 ilImageInfo                *pSrcImage;
468 ilImagePlaneInfo           *pImagePlane;
469 long                        srcRowBytes, dstRowBytes, nBytesM1Init, nLinesM1;
470 ilPtr                       pSrcLine, pDstLine;
471 register long               nBytesM1;
472 register ilPtr              pSrc, pDst;
473 register ilByte             byte;
474
475         /*  Use bcopy to copy each line; copy the lesser of the src/dstRowBytes.
476             Exit if no lines or pixels.
477         */
478     pSrcImage = pData->pSrcImage;
479     pImagePlane = &pSrcImage->plane[0];
480     srcRowBytes = pImagePlane->nBytesPerRow;
481     pSrcLine = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
482
483     pImagePlane = &pData->pDstImage->plane[0];
484     dstRowBytes = pImagePlane->nBytesPerRow;
485     pDstLine = pImagePlane->pPixels + dstLine * dstRowBytes;
486
487     nLinesM1 = *pNLines;
488     if (nLinesM1 <= 0)
489         return IL_OK;
490     nLinesM1--;
491
492         /*  Set "nBytesM1Init" to whole # of src bytes to do, = width * # samples/pixel
493             (note that each sample must be a byte!)
494             Replicate low-order nibble to upper nibble of dst byte, thus scaling
495             to new # of levels (from 16 to 256): 0 => 0, 1 => 17, 15 => 255.
496         */
497     nBytesM1Init = pSrcImage->width * pSrcImage->pDes->nSamplesPerPixel - 1;
498     if (nBytesM1Init < 0)
499         return IL_OK;
500
501     do {
502         pSrc = pSrcLine;
503         pSrcLine += srcRowBytes;
504         pDst = pDstLine;
505         pDstLine += dstRowBytes;
506         nBytesM1 = nBytesM1Init;
507         do {
508             byte = *pSrc++;
509             byte &= 0xf;
510             *pDst++ = (byte << 4) | byte;
511             } while (--nBytesM1 >= 0);
512         } while (--nLinesM1 >= 0);
513
514     return IL_OK;
515 }
516
517
518         /*  ---------------------- ilAddLevelConversionFilter ------------------------ */
519         /*  Add a conversion filter to the given pipe which converts from the levels
520             in "*pPipeDes" (i.e. the levels of the current pipe image) to those in
521             "*pDes" (note - only nLevelsPerSample is reference from pDes).
522             If failure, declares pipe invalid (which sets error code) and returns false; 
523             else returns true and "*pInfo", "*pPipeDes" and "*pFormat" are updated
524             with the new pipe state info.
525         */
526 IL_PRIVATE ilBool _ilAddLevelConversionFilter (
527     ilPipe                  pipe,
528     ilPipeInfo             *pInfo,
529     ilImageDes             *pPipeDes,
530     const ilImageDes       *pDes,
531     ilImageFormat          *pFormat
532     )
533 {
534 unsigned int                sample;
535 ilPtr                       pPriv;
536 ilDstElementData            dstData;
537 ilError                     (*executeFunction)();
538 ilBool                      all4Bit, all8Bit;
539
540         /*  Determine if we support requested conversion.
541             Currently only support: 4 or 8 bit, 16 level => 8 bit, 256 level, any # of
542             samples/pixel, but pixel mode only if # samples > 1.
543         */
544     if ((pDes->nSamplesPerPixel > 1) && (pFormat->sampleOrder != IL_SAMPLE_PIXELS))
545         return ilDeclarePipeInvalid (pipe, IL_ERROR_CANT_CONVERT);
546
547     all4Bit = all8Bit = TRUE;
548     for (sample = 0; sample < pPipeDes->nSamplesPerPixel; sample++) {
549         if ((pPipeDes->nLevelsPerSample[sample] != 16)
550          || (pDes->nLevelsPerSample[sample] != 256))
551             return ilDeclarePipeInvalid (pipe, IL_ERROR_CANT_CONVERT);
552         pPipeDes->nLevelsPerSample[sample] = 256;
553
554         if (pFormat->nBitsPerSample[sample] == 4) {
555             all8Bit = FALSE;
556             pFormat->nBitsPerSample[sample] = 8;
557             }
558         else if (pFormat->nBitsPerSample[sample] == 8)
559             all4Bit = FALSE;
560         else return ilDeclarePipeInvalid (pipe, IL_ERROR_CANT_CONVERT);
561         }
562
563         /*  All src # levels == 16, dst == 256.  If all src formats are 4 bit or 8 bit,
564             can handle, else error.  pFormat->nBitsPerSample now == 8 for all samples.
565         */
566     if (all4Bit)
567         executeFunction = ilExecute4To8BitScaled;
568     else if (all8Bit)
569         executeFunction = ilExecuteByte16To256Level;
570     else return ilDeclarePipeInvalid (pipe, IL_ERROR_CANT_CONVERT);
571
572         /*  Update *pPipeDes, *pFormat and add filter or error.
573             Update pInfo after successful add; pPipeDes and pFormat already updated.
574         */
575     dstData.producerObject = (ilObject)NULL;
576     dstData.pDes = pPipeDes;
577     dstData.pFormat = pFormat;
578     dstData.width = pInfo->width;
579     dstData.height = pInfo->height;
580     dstData.stripHeight = 0;
581     dstData.constantStrip = FALSE;
582     dstData.pPalette = pInfo->pPalette;
583     dstData.pCompData = pInfo->pCompData;
584     pPriv = ilAddPipeElement (pipe, IL_FILTER, 0, 0,
585                 (ilSrcElementData *)NULL, &dstData, 
586                 IL_NPF, IL_NPF, IL_NPF, executeFunction, NULL, 0);
587     if (!pPriv) return FALSE;                               /* EXIT */
588
589     ilGetPipeInfo (pipe, FALSE, pInfo, (ilImageDes *)NULL, (ilImageFormat *)NULL);
590     return TRUE;
591 }
592
593