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