2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $XConsortium: ilconvert.c /main/5 1996/06/19 12:24:11 ageorge $ */
24 /**---------------------------------------------------------------------
26 *** (c)Copyright 1991 Hewlett-Packard Co.
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).
38 ***-------------------------------------------------------------------*/
41 #include "ilpipelem.h"
42 #include "ilconvert.h"
46 /* ---------------------- ilAddConversionFilter --------------------------- */
47 /* Add a conversion filter to the given pipe, given a ptr to a structure
48 which defines the filter and its pipe element. If failure, declare pipe
49 invalid (which sets error code) and return false; else true.
50 pInfo must point to the current pipe info; pSrcDes/Format to the pipe
51 des/format. The information they point to is updated after the pipe
52 element(s) is/are added; on return they will contain up-to-date data.
54 static ilBool ilAddConversionFilter (
58 ilImageFormat *pSrcFormat,
60 register ilConvertPtr pCvtData
64 ilDstElementData dstData;
67 /* Check src format against code for src format demanded by this filter.
68 If not the same, do ilConvert() to that format (recurse!), exit if error.
70 switch (pCvtData->srcFormatCode) {
71 case IL_DONT_CHECK_STD_FORMAT: /* filter converts format: dont check */
74 case IL_STD_FORMAT_BIT:
75 if ((pSrcFormat->rowBitAlign != 32)
76 || (pSrcFormat->nBitsPerSample[0] != 1)) {
77 *pSrcFormat = *IL_FORMAT_BIT;
78 ilConvert (pipe, (ilImageDes *)NULL, pSrcFormat, 0, NULL);
79 if (pipe->context->error) return FALSE;
80 ilGetPipeInfo (pipe, FALSE, pInfo, (ilImageDes *)NULL, (ilImageFormat *)NULL);
84 case IL_STD_FORMAT_BYTE:
85 if (pSrcFormat->nBitsPerSample[0] != 8) {
86 *pSrcFormat = *IL_FORMAT_BYTE;
87 ilConvert (pipe, (ilImageDes *)NULL, pSrcFormat, 0, NULL);
88 if (pipe->context->error) return FALSE;
89 ilGetPipeInfo (pipe, FALSE, pInfo, (ilImageDes *)NULL, (ilImageFormat *)NULL);
93 case IL_STD_FORMAT_3BYTE_PIXEL:
94 if ((pSrcFormat->sampleOrder != IL_SAMPLE_PIXELS)
95 || (pSrcFormat->nBitsPerSample[0] != 8)
96 || (pSrcFormat->nBitsPerSample[1] != 8)
97 || (pSrcFormat->nBitsPerSample[2] != 8)) {
98 *pSrcFormat = *IL_FORMAT_3BYTE_PIXEL;
99 ilConvert (pipe, (ilImageDes *)NULL, pSrcFormat, 0, NULL);
100 if (pipe->context->error) return FALSE;
101 ilGetPipeInfo (pipe, FALSE, pInfo, (ilImageDes *)NULL, (ilImageFormat *)NULL);
106 /* Add a filter, from in *pCvtData. Only the des and format may change;
107 other info (width, stripHeight, etc.) stays the same.
109 dstData.producerObject = (ilObject)NULL;
110 dstData.pDes = pCvtData->pDstDes;
111 dstData.pFormat = pCvtData->pDstFormat;
112 dstData.width = pInfo->width;
113 dstData.height = pInfo->height;
114 dstData.stripHeight = 0;
115 dstData.constantStrip = FALSE;
116 dstData.pPalette = (unsigned short *)NULL;
117 pPriv = ilAddPipeElement (pipe, IL_FILTER, pCvtData->nBytesPrivate, 0,
118 (ilSrcElementData *)NULL, &dstData, pCvtData->Init, pCvtData->Cleanup,
119 pCvtData->Destroy, pCvtData->Execute, NULL, 0);
120 if (!pPriv) return FALSE; /* EXIT */
122 /* If successful: call converters init function if non-null, return true.
124 if (pCvtData->AddElement) {
125 error = (*pCvtData->AddElement) (pPriv, pInfo->pPalette, pOptionData);
127 ilDeclarePipeInvalid (pipe, error);
128 return FALSE; /* EXIT */
132 /* Update the pipe info, return success.
134 ilGetPipeInfo (pipe, FALSE, pInfo, pSrcDes, pSrcFormat);
139 /* ---------------------- ilAddFormatFilter --------------------------- */
140 /* Add a filter to the given pipe which converts format only to *pNewFormat.
141 Similar to ilAddConversionFilter() but simpler.
142 *pInfo is updated with the new pipe info.
144 static ilBool ilAddFormatFilter (
147 const ilImageFormat *pNewFormat,
148 register ilFormatPtr pData
152 ilDstElementData dstData;
155 /* Add a filter, from in *pData. Only the format may change;
156 other info (des, width, stripHeight, etc.) stays the same.
158 dstData.producerObject = (ilObject)NULL;
159 dstData.pDes = (ilImageDes *)NULL;
160 dstData.pFormat = pNewFormat;
161 dstData.width = pInfo->width;
162 dstData.height = pInfo->height;
163 dstData.stripHeight = 0;
164 dstData.constantStrip = FALSE;
165 dstData.pPalette = (unsigned short *)NULL;
166 pPriv = ilAddPipeElement (pipe, IL_FILTER, pData->nBytesPrivate, 0,
167 (ilSrcElementData *)NULL, &dstData, pData->Init, pData->Cleanup,
168 pData->Destroy, pData->Execute, NULL, 0);
169 if (!pPriv) return FALSE; /* EXIT */
171 /* If successful: call converters init function if non-null, return true.
173 if (pData->AddElement) {
174 error = (*pData->AddElement) (pPriv, pInfo->pPalette);
176 ilDeclarePipeInvalid (pipe, error);
177 return FALSE; /* EXIT */
181 /* Update the pipe info, return success. */
182 ilGetPipeInfo (pipe, FALSE, pInfo, (ilImageDes *)NULL, (ilImageFormat *)NULL);
187 /* ---------------------------- ilConvert -------------------------------- */
188 /* Public function; see spec.
189 Convert the current pipe image to the given description (*pDes) and
190 format (*pFormat). Either or both (a noop) may be null. A null pDes means
191 "the same as before"; a null pFormat means "whatever is easiest/most
193 If the current pipe image already fits the bill, no pipe element is added.
194 Note: compression is ignored in "pDes" - call ilCompress() to compress.
198 const ilImageDes *pDes,
199 const ilImageFormat *pFormat,
206 ilImageFormat pipeFormat;
208 ilBool doConvert, doSubsample;
209 static unsigned long defaultThreshold = 128; /* dflt threshold for gray->bitonal cvt */
210 #define ADD_CVT_FILTER(_filter) \
211 (ilAddConversionFilter (pipe, &info, &pipeDes, &pipeFormat, pOptionData, (_filter)))
213 /* Macro to determine if the given YCbCr must be upsampled (any bits != 1) */
214 #define MUST_UPSAMPLE(_des) \
215 ( ((_des).typeInfo.YCbCr.sample[0].subsampleHoriz | \
216 (_des).typeInfo.YCbCr.sample[0].subsampleVert | \
217 (_des).typeInfo.YCbCr.sample[1].subsampleHoriz | \
218 (_des).typeInfo.YCbCr.sample[1].subsampleVert | \
219 (_des).typeInfo.YCbCr.sample[2].subsampleHoriz | \
220 (_des).typeInfo.YCbCr.sample[2].subsampleVert) != 1)
222 /* Overall approach: if pDes specified, try to convert image descriptor
223 if different, by adding filters with ilAddConversionFilter(): the des
224 converting filter may add a reformat filter before it, and may change
225 the format - the new des and format are returned if changed.
226 After converting the description if necessary, check format if
227 pFormat is non-null and reformat as necessary. A format converter
228 cannot change the des.
229 Note that we need not validate the format and des together.
230 ilAddPipeElement() will do that and return an error if they are incompatible
231 (e.g. des.type = IL_RGB with des.nSamplesPerPixel != 3).
234 /* Get pipe info and decompress! if not ready for a filter, exit.
236 if (ilGetPipeInfo (pipe, TRUE, &info, &pipeDes, &pipeFormat) != IL_PIPE_FORMING) {
237 if (!pipe->context->error)
238 ilDeclarePipeInvalid (pipe, IL_ERROR_PIPE_STATE);
239 return FALSE; /* EXIT */
242 /* If no pDes, point pDes to pipe des for format check below, else check for
243 descriptor conversions.
245 doSubsample = FALSE; /* assume no subsampling; may be set below */
250 /* ilConvert() does not compress - use ilCompress() to compress. */
251 if (pDes->compression != IL_UNCOMPRESSED)
252 return ilDeclarePipeInvalid (pipe, IL_ERROR_CONVERT_COMPRESSION);
254 if (pipeDes.type == pDes->type) /* cvt within type */
255 switch (pipeDes.type) {
257 /* Within YCbCr: check for changes to luma or refBlack/White. If any,
258 convert to RGB; below cvt back to YCbCr will handle luma and ref.
261 const ilYCbCrSampleInfo *pSrcSample, *pDstSample;
264 /* If must convert refBlack/White or lumaRed/Green/Blue, convert to
265 RGB and back to YCbCr; only those conversions handle this.
267 if ((pipeDes.typeInfo.YCbCr.lumaRed != pDes->typeInfo.YCbCr.lumaRed)
268 || (pipeDes.typeInfo.YCbCr.lumaGreen != pDes->typeInfo.YCbCr.lumaGreen)
269 || (pipeDes.typeInfo.YCbCr.lumaBlue != pDes->typeInfo.YCbCr.lumaBlue))
272 for (pSrcSample = pipeDes.typeInfo.YCbCr.sample,
273 pDstSample = pDes->typeInfo.YCbCr.sample,
274 doCvtYCbCr = FALSE, sample = 0;
275 sample < 3; sample++, pSrcSample++, pDstSample++)
276 if ((pSrcSample->refBlack != pDstSample->refBlack)
277 || (pSrcSample->refWhite != pDstSample->refWhite))
280 if (doCvtYCbCr) { /* cvt to RGB */
281 if (!ilConvert (pipe, IL_DES_RGB, (ilImageFormat *)NULL, 0, NULL))
283 ilGetPipeInfo (pipe, FALSE, &info, &pipeDes, &pipeFormat);
288 /* Within palette: if option is zero (0), or if option says to dither
289 and image already dithered to requested levels: fine, done; otherwise
290 cvt first to RGB, so below conversion to palette will be enabled.
294 break; /* default = accept as is; fine */
295 if (option == IL_CONVERT_TO_PALETTE) {
296 ilConvertToPaletteInfo *pData = (ilConvertToPaletteInfo *)pOptionData;
297 if ((pipeDes.flags & IL_DITHERED_PALETTE)
298 && (pipeDes.typeInfo.palette.levels[0] == pData->levels[0])
299 && (pipeDes.typeInfo.palette.levels[1] == pData->levels[1])
300 && (pipeDes.typeInfo.palette.levels[2] == pData->levels[2]))
301 break; /* dithered to requested levels; fine */
303 if (!ADD_CVT_FILTER (&_ilPaletteToRGBByte)) /* cvt up to RGB */
306 } /* END cvt within type */
308 /* Loop converting image type until desired type reached. May take some
309 iterations, e.g pal->bitonal = pal->rgb; rgb->gray; gray->bitonal.
310 For conversion to YCbCr, cvt to RGB first.
311 For conversion to palette, cvt to RGB first.
313 while (pipeDes.type != pDes->type) {
314 switch (pipeDes.type) {
316 /* Bitonal: cvt to gray, then to other types as necessary. */
318 switch (pDes->type) {
323 if (!ilScale (pipe, info.width, info.height, IL_SCALE_BITONAL_TO_GRAY, NULL))
325 ilGetPipeInfo (pipe, FALSE, &info, &pipeDes, &pipeFormat);
330 goto CantConvert; /* unsupported conversion(s) */
336 /* If not 256 levels/sample, cvt to 256 if possible. */
337 if (pipeDes.nLevelsPerSample[0] != 256)
338 if (!_ilAddLevelConversionFilter (pipe, &info, &pipeDes, IL_DES_GRAY, &pipeFormat))
341 switch (pDes->type) {
343 if (option == IL_CONVERT_THRESHOLD) {
345 pOptionData = &defaultThreshold;
346 if (!ADD_CVT_FILTER (&_ilThresholdGrayToBitonal))
347 return FALSE; /* error, EXIT */
349 else if (!ADD_CVT_FILTER (&_ilDiffuseGrayToBitonal))
350 return FALSE; /* error, EXIT */
356 if (!ADD_CVT_FILTER (&_ilGrayToRGB))
357 return FALSE; /* error, EXIT */
361 goto CantConvert; /* unsupported conversion(s) */
365 /* Palette to anything (except self - but that case wont get here)
366 is currently done by converting to RGB, then to des type if necessary.
369 if (!ADD_CVT_FILTER (&_ilPaletteToRGBByte))
370 return FALSE; /* error, EXIT */
373 /* RGB goes to gray for gray or bitonal; handle conversion to YCbCr.
374 If not 256 levels/sample, cvt to 256 if possible.
377 if ((pipeDes.nLevelsPerSample[0] != 256)
378 || (pipeDes.nLevelsPerSample[1] != 256)
379 || (pipeDes.nLevelsPerSample[2] != 256))
380 if (!_ilAddLevelConversionFilter (pipe, &info, &pipeDes, IL_DES_RGB, &pipeFormat))
383 switch (pDes->type) {
386 if (!ADD_CVT_FILTER (&_ilRGBToGray))
387 return FALSE; /* error, EXIT */
391 if (!_ilConvertRGBToYCbCr (pipe, &info, &pipeDes, pDes, &pipeFormat))
395 /* Cvt RGB to palette: set pipeDes.type to IL_PALETTE to terminate
396 loop: private type may actually have been created.
399 if (!_ilConvertRGBToPalette (pipe, &info, &pipeDes, &pipeFormat,
400 option, (ilConvertToPaletteInfo *)pOptionData))
402 pipeDes.type = IL_PALETTE; /* see note above */
406 goto CantConvert; /* unsupported conversion(s) */
410 /* YCbCr (aka LUV): convert based on dst type and set "convertDone"
411 to true, else convert to RGB, and then loop again until desired type.
414 ilBool convertDone, upSample;
416 upSample = MUST_UPSAMPLE (pipeDes);
419 switch (pDes->type) {
421 case IL_GRAY: /* extract Y plane if Y range 0..255 */
422 if ((pipeDes.typeInfo.YCbCr.sample[0].refBlack == 0)
423 && (pipeDes.typeInfo.YCbCr.sample[0].refWhite == 255)) {
424 if (!_ilUpsampleYCbCr (pipe, &info, &pipeDes, &pipeFormat, TRUE,
430 case IL_PALETTE: /* try direct YCbCr to palette conversion */
431 if (_ilDitherYCbCr (pipe, &info, &pipeDes, &pipeFormat, option,
432 (ilConvertToPaletteInfo *)pOptionData)) {
434 pipeDes.type = IL_PALETTE; /* see note above RGB->palette */
436 else if (pipe->context->error)
437 return FALSE; /* otherwise, no error; filter just cant do it */
441 if (!convertDone) { /* no conversion; convert YCbCr to RGB */
442 if (upSample && !_ilUpsampleYCbCr (pipe, &info, &pipeDes,
443 &pipeFormat, FALSE, upSample))
445 if (!_ilConvertYCbCrToRGB (pipe, &info, &pipeDes, &pipeFormat))
450 } /* END switch source type */
451 } /* END while convert type */
454 /* Image type converted if different; check rest of des. */
455 if (pipeDes.nSamplesPerPixel != pDes->nSamplesPerPixel)
458 /* Check levels/sample, but not for palette images, where the levels/sample
459 must be in range 2 .. (1<<nbits) - 1, but is otherwise ignored.
461 for (sample = 0; sample < pDes->nSamplesPerPixel; sample++)
462 if (pipeDes.nLevelsPerSample[sample] != pDes->nLevelsPerSample[sample]) {
463 if ((pipeDes.type != IL_PALETTE) &&
464 !_ilAddLevelConversionFilter (pipe, &info, &pipeDes, pDes, &pipeFormat))
469 /* Do image type-specific checks and conversions. */
470 switch (pipeDes.type) {
472 /* "blackIsZero" applies only to bitonal and gray scale images. If different
473 then invert bits if not "soft" invert (which means leave bits alone);
474 if same, invert bits if "hard" invert (which means invert bits).
478 if (pipeDes.blackIsZero != pDes->blackIsZero) {
479 pipeDes.blackIsZero = pDes->blackIsZero;
480 if (option == IL_CONVERT_SOFT_INVERT)
481 _ilSetPipeDesFormat (pipe, &pipeDes, (ilImageFormat *)NULL);
482 else if (!_ilAddInvertFilter (pipe, &pipeDes, &info))
487 /* YCbCr: check sub/upsampling; up/subsample as necessary */
489 const ilYCbCrSampleInfo *pSrcSample, *pDstSample;
492 doSubsample = FALSE; /* checked below */
493 for (pSrcSample = pipeDes.typeInfo.YCbCr.sample,
494 pDstSample = pDes->typeInfo.YCbCr.sample,
495 doUpsample = FALSE, sample = 0;
496 sample < 3; sample++, pSrcSample++, pDstSample++)
498 if (pSrcSample->subsampleHoriz < pDstSample->subsampleHoriz)
500 else if (pSrcSample->subsampleHoriz > pDstSample->subsampleHoriz)
502 if (pSrcSample->subsampleVert < pDstSample->subsampleVert)
504 else if (pSrcSample->subsampleVert > pDstSample->subsampleVert)
508 if (!_ilUpsampleYCbCr (pipe, &info, &pipeDes, &pipeFormat, FALSE, TRUE))
511 pipeDes = *pDes; /* pass subsample pars; des convert done */
512 if (!_ilSubsampleYCbCr (pipe, &info, &pipeDes, &pipeFormat))
518 } /* END check pDes */
521 /* If pFormat given, convert to requested format.
522 WARNING !!!!! - ilCheckPipeFormat() below also does format conversions -
523 May have to change it when adding new format filters !!!!
527 /* Check if bits/sample needs conversion and if that conversion supported.
528 Currently supported: 4 to 8 bit, pixel mode only if multi-sample.
531 for (sample = 0; sample < pDes->nSamplesPerPixel; sample++)
532 if (pipeFormat.nBitsPerSample[sample] != pFormat->nBitsPerSample[sample]) {
537 /* If any format conversions and YCbCr, upsample if necessary.
538 However, if subsampling was done before, error: cant convert.
540 if ((pipeDes.type == IL_YCBCR)
541 && MUST_UPSAMPLE (pipeDes)
542 && (doConvert || (pipeFormat.sampleOrder != pFormat->sampleOrder)
543 || (pipeFormat.rowBitAlign != pFormat->rowBitAlign))) {
545 goto CantConvert; /* cant upsample - subsampled before */
546 if (!_ilUpsampleYCbCr (pipe, &info, &pipeDes, &pipeFormat, FALSE, TRUE))
550 /* If doConvert, then pipe image does not have desired # of bits/sample.
551 Check if all planes have same # src, dst bits; else can't convert.
552 Currently can convert 4->8 or 8->4.
555 int nSrcBits, nDstBits;
556 if ((pipeDes.nSamplesPerPixel > 1) && (pFormat->sampleOrder != IL_SAMPLE_PIXELS))
558 nSrcBits = pipeFormat.nBitsPerSample[0];
559 nDstBits = pFormat->nBitsPerSample[0];
560 for (sample = 1; sample < pDes->nSamplesPerPixel; sample++)
561 if ((nSrcBits != pipeFormat.nBitsPerSample[sample])
562 || (nDstBits != pFormat->nBitsPerSample[sample]))
563 goto CantConvert; /* not same # src,dst bits each plane */
565 if ((nSrcBits == 4) && (nDstBits == 8)) {
566 if (!ilAddFormatFilter (pipe, &info, pFormat, &_ilFormat4To8Bit))
569 else if ((nSrcBits == 8) && (nDstBits == 4)) {
570 if (!ilAddFormatFilter (pipe, &info, pFormat, &_ilFormat8To4Bit))
573 else goto CantConvert;
576 /* Change sample order: only handles 3 samples, each 8 bits. */
577 if (pipeFormat.sampleOrder != pFormat->sampleOrder) {
578 if ((pipeDes.nSamplesPerPixel != 3)
579 || (pipeFormat.nBitsPerSample[0] != 8)
580 || (pipeFormat.nBitsPerSample[1] != 8)
581 || (pipeFormat.nBitsPerSample[2] != 8))
583 if (pipeFormat.sampleOrder == IL_SAMPLE_PIXELS) {
584 if (!ilAddFormatFilter (pipe, &info, pFormat, &_ilFormat8Bit3PixelToPlane))
587 else if (!ilAddFormatFilter (pipe, &info, pFormat, &_ilFormat8Bit3PlaneToPixel))
591 if (pipeFormat.rowBitAlign != pFormat->rowBitAlign) {
592 if (!ilAddFormatFilter (pipe, &info, pFormat, &_ilFormatRowBitAlign))
597 /* Succesful conversion.
599 pipe->context->error = IL_OK;
600 return TRUE; /* EXIT */
603 /* GOTO point for when conversion not supported.
606 ilDeclarePipeInvalid (pipe, IL_ERROR_CANT_CONVERT);
612 IN PROGRESS - NOT DONE YET !!!!!!!!!!
614 /* ------------------------ ilCheckPipeFormat --------------------------------- */
615 /* Return an IL_CPF_? code for the current pipe image format, or
616 IL_CPF_ERROR if error or can't match formats in "formatMask".
617 The pipe info, des and/or format are returned to non-null
618 pInfo/Des/Format if IL_CPF_ERROR not returned.
620 unsigned int ilCheckPipeFormat (
622 register unsigned long formatMask,
623 ilPipeInfo *pInfo, /* RETURNED */
624 register ilImageDes *pDes, /* RETURNED */
625 register ilImageFormat *pFormat /* RETURNED */
628 ilPipeInfo localInfo;
630 ilImageFormat localFormat;
632 /* Point pInfo/Des/Format to local structs if caller passed NULL */
633 if (!pInfo) pInfo = &localInfo;
634 if (!pDes) pDes = &localDes;
635 if (!pFormat) pFormat = &localFormat;
637 /* Get pipe info and decompress; if pipe not in IL_PIPE_FORMING state: error. */
638 if (ilGetPipeInfo (pipe, TRUE, pInfo, pDes, pFormat) != IL_PIPE_FORMING) {
639 if (!pipe->context->error)
640 ilDeclarePipeInvalid (pipe, IL_ERROR_PIPE_STATE);
644 /* Look at des, format and try to match/convert to format(s) caller accepts */
645 if (pDes->nSamplesPerPixel == 1) {
647 /* 1 sample/pixel: if bit/pixel and caller accepts, check rowBitAlign */
648 if ((formatMask & IL_CPF_BIT) && (pFormat->nBitsPerSample[0] == 1)) {
649 if (pFormat->rowBitAlign != 32) {
650 pFormat->rowBitAlign = 32;
651 if (!ilAddFormatFilter (pipe, pInfo, pFormat, &ilFormatRowBitAlign))
653 return IL_CPF_BIT; /* match found: bit/pixel */
657 /* 1 sample, bit not accepted; error if byte not accepted, make byte */
658 if (!(formatMask & IL_CPF_BYTE))
660 if (pFormat->nBitsPerSample[0] != 8) {
661 if (pFormat->nBitsPerSample[0] == 4) {
662 pFormat->nBitsPerSample[0] = 8;
663 if (!ilAddFormatFilter (pipe, pInfo, pFormat, &ilFormat4To8Bit))
666 else return IL_CPF_ERROR; /* NOTE!! currently only 4-8 supported!!! */
668 return IL_CPF_BYTE; /* match found: 1 byte/pixel */
670 } /* END 1 sample/pixel */
671 else { /* multi-sample/pixel */