123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /* $XConsortium: ilconvert.c /main/5 1996/06/19 12:24:11 ageorge $ */
- /**---------------------------------------------------------------------
- ***
- *** (c)Copyright 1991 Hewlett-Packard Co.
- ***
- *** RESTRICTED RIGHTS LEGEND
- *** Use, duplication, or disclosure by the U.S. Government is subject to
- *** restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
- *** Technical Data and Computer Software clause in DFARS 252.227-7013.
- *** Hewlett-Packard Company
- *** 3000 Hanover Street
- *** Palo Alto, CA 94304 U.S.A.
- *** Rights for non-DOD U.S. Government Departments and Agencies are as set
- *** forth in FAR 52.227-19(c)(1,2).
- ***
- ***-------------------------------------------------------------------*/
- #include "ilint.h"
- #include "ilpipeint.h"
- #include "ilpipelem.h"
- #include "ilconvert.h"
- #include "ilerrors.h"
- /* ---------------------- ilAddConversionFilter --------------------------- */
- /* Add a conversion filter to the given pipe, given a ptr to a structure
- which defines the filter and its pipe element. If failure, declare pipe
- invalid (which sets error code) and return false; else true.
- pInfo must point to the current pipe info; pSrcDes/Format to the pipe
- des/format. The information they point to is updated after the pipe
- element(s) is/are added; on return they will contain up-to-date data.
- */
- static ilBool ilAddConversionFilter (
- ilPipe pipe,
- ilPipeInfo *pInfo,
- ilImageDes *pSrcDes,
- ilImageFormat *pSrcFormat,
- void *pOptionData,
- ilConvertPtr pCvtData
- )
- {
- ilPtr pPriv;
- ilDstElementData dstData;
- ilError error;
- /* Check src format against code for src format demanded by this filter.
- If not the same, do ilConvert() to that format (recurse!), exit if error.
- */
- switch (pCvtData->srcFormatCode) {
- case IL_DONT_CHECK_STD_FORMAT: /* filter converts format: don't check */
- break;
- case IL_STD_FORMAT_BIT:
- if ((pSrcFormat->rowBitAlign != 32)
- || (pSrcFormat->nBitsPerSample[0] != 1)) {
- *pSrcFormat = *IL_FORMAT_BIT;
- ilConvert (pipe, (ilImageDes *)NULL, pSrcFormat, 0, NULL);
- if (pipe->context->error) return FALSE;
- ilGetPipeInfo (pipe, FALSE, pInfo, (ilImageDes *)NULL, (ilImageFormat *)NULL);
- }
- break;
- case IL_STD_FORMAT_BYTE:
- if (pSrcFormat->nBitsPerSample[0] != 8) {
- *pSrcFormat = *IL_FORMAT_BYTE;
- ilConvert (pipe, (ilImageDes *)NULL, pSrcFormat, 0, NULL);
- if (pipe->context->error) return FALSE;
- ilGetPipeInfo (pipe, FALSE, pInfo, (ilImageDes *)NULL, (ilImageFormat *)NULL);
- }
- break;
- case IL_STD_FORMAT_3BYTE_PIXEL:
- if ((pSrcFormat->sampleOrder != IL_SAMPLE_PIXELS)
- || (pSrcFormat->nBitsPerSample[0] != 8)
- || (pSrcFormat->nBitsPerSample[1] != 8)
- || (pSrcFormat->nBitsPerSample[2] != 8)) {
- *pSrcFormat = *IL_FORMAT_3BYTE_PIXEL;
- ilConvert (pipe, (ilImageDes *)NULL, pSrcFormat, 0, NULL);
- if (pipe->context->error) return FALSE;
- ilGetPipeInfo (pipe, FALSE, pInfo, (ilImageDes *)NULL, (ilImageFormat *)NULL);
- }
- break;
- }
- /* Add a filter, from in *pCvtData. Only the des and format may change;
- other info (width, stripHeight, etc.) stays the same.
- */
- dstData.producerObject = (ilObject)NULL;
- dstData.pDes = pCvtData->pDstDes;
- dstData.pFormat = pCvtData->pDstFormat;
- dstData.width = pInfo->width;
- dstData.height = pInfo->height;
- dstData.stripHeight = 0;
- dstData.constantStrip = FALSE;
- dstData.pPalette = (unsigned short *)NULL;
- pPriv = ilAddPipeElement (pipe, IL_FILTER, pCvtData->nBytesPrivate, 0,
- (ilSrcElementData *)NULL, &dstData, pCvtData->Init, pCvtData->Cleanup,
- pCvtData->Destroy, pCvtData->Execute, NULL, 0);
- if (!pPriv) return FALSE; /* EXIT */
- /* If successful: call converters init function if non-null, return true.
- */
- if (pCvtData->AddElement) {
- error = (*pCvtData->AddElement) (pPriv, pInfo->pPalette, pOptionData);
- if (error) {
- ilDeclarePipeInvalid (pipe, error);
- return FALSE; /* EXIT */
- }
- }
- /* Update the pipe info, return success.
- */
- ilGetPipeInfo (pipe, FALSE, pInfo, pSrcDes, pSrcFormat);
- return TRUE;
- }
- /* ---------------------- ilAddFormatFilter --------------------------- */
- /* Add a filter to the given pipe which converts format only to *pNewFormat.
- Similar to ilAddConversionFilter() but simpler.
- *pInfo is updated with the new pipe info.
- */
- static ilBool ilAddFormatFilter (
- ilPipe pipe,
- ilPipeInfo *pInfo,
- const ilImageFormat *pNewFormat,
- ilFormatPtr pData
- )
- {
- ilPtr pPriv;
- ilDstElementData dstData;
- ilError error;
- /* Add a filter, from in *pData. Only the format may change;
- other info (des, width, stripHeight, etc.) stays the same.
- */
- dstData.producerObject = (ilObject)NULL;
- dstData.pDes = (ilImageDes *)NULL;
- dstData.pFormat = pNewFormat;
- dstData.width = pInfo->width;
- dstData.height = pInfo->height;
- dstData.stripHeight = 0;
- dstData.constantStrip = FALSE;
- dstData.pPalette = (unsigned short *)NULL;
- pPriv = ilAddPipeElement (pipe, IL_FILTER, pData->nBytesPrivate, 0,
- (ilSrcElementData *)NULL, &dstData, pData->Init, pData->Cleanup,
- pData->Destroy, pData->Execute, NULL, 0);
- if (!pPriv) return FALSE; /* EXIT */
- /* If successful: call converters init function if non-null, return true.
- */
- if (pData->AddElement) {
- error = (*pData->AddElement) (pPriv, pInfo->pPalette);
- if (error) {
- ilDeclarePipeInvalid (pipe, error);
- return FALSE; /* EXIT */
- }
- }
- /* Update the pipe info, return success. */
- ilGetPipeInfo (pipe, FALSE, pInfo, (ilImageDes *)NULL, (ilImageFormat *)NULL);
- return TRUE;
- }
- /* ---------------------------- ilConvert -------------------------------- */
- /* Public function; see spec.
- Convert the current pipe image to the given description (*pDes) and
- format (*pFormat). Either or both (a noop) may be null. A null pDes means
- "the same as before"; a null pFormat means "whatever is easiest/most
- efficient."
- If the current pipe image already fits the bill, no pipe element is added.
- Note: compression is ignored in "pDes" - call ilCompress() to compress.
- */
- ilBool ilConvert (
- ilPipe pipe,
- const ilImageDes *pDes,
- const ilImageFormat *pFormat,
- int option,
- void *pOptionData
- )
- {
- ilPipeInfo info;
- ilImageDes pipeDes;
- ilImageFormat pipeFormat;
- unsigned int sample;
- ilBool doConvert, doSubsample;
- static unsigned long defaultThreshold = 128; /* dflt threshold for gray->bitonal cvt */
- #define ADD_CVT_FILTER(_filter) \
- (ilAddConversionFilter (pipe, &info, &pipeDes, &pipeFormat, pOptionData, (_filter)))
- /* Macro to determine if the given YCbCr must be upsampled (any bits != 1) */
- #define MUST_UPSAMPLE(_des) \
- ( ((_des).typeInfo.YCbCr.sample[0].subsampleHoriz | \
- (_des).typeInfo.YCbCr.sample[0].subsampleVert | \
- (_des).typeInfo.YCbCr.sample[1].subsampleHoriz | \
- (_des).typeInfo.YCbCr.sample[1].subsampleVert | \
- (_des).typeInfo.YCbCr.sample[2].subsampleHoriz | \
- (_des).typeInfo.YCbCr.sample[2].subsampleVert) != 1)
- /* Overall approach: if pDes specified, try to convert image descriptor
- if different, by adding filters with ilAddConversionFilter(): the des
- converting filter may add a reformat filter before it, and may change
- the format - the new des and format are returned if changed.
- After converting the description if necessary, check format if
- pFormat is non-null and reformat as necessary. A format converter
- cannot change the des.
- Note that we need not validate the format and des together.
- ilAddPipeElement() will do that and return an error if they are incompatible
- (e.g. des.type = IL_RGB with des.nSamplesPerPixel != 3).
- */
- /* Get pipe info and decompress! if not ready for a filter, exit.
- */
- if (ilGetPipeInfo (pipe, TRUE, &info, &pipeDes, &pipeFormat) != IL_PIPE_FORMING) {
- if (!pipe->context->error)
- ilDeclarePipeInvalid (pipe, IL_ERROR_PIPE_STATE);
- return FALSE; /* EXIT */
- }
- /* If no pDes, point pDes to pipe des for format check below, else check for
- descriptor conversions.
- */
- doSubsample = FALSE; /* assume no subsampling; may be set below */
- if (!pDes)
- pDes = &pipeDes;
- else {
- /* ilConvert() does not compress - use ilCompress() to compress. */
- if (pDes->compression != IL_UNCOMPRESSED)
- return ilDeclarePipeInvalid (pipe, IL_ERROR_CONVERT_COMPRESSION);
- if (pipeDes.type == pDes->type) /* cvt within type */
- switch (pipeDes.type) {
- /* Within YCbCr: check for changes to luma or refBlack/White. If any,
- convert to RGB; below cvt back to YCbCr will handle luma and ref.
- */
- case IL_YCBCR: {
- const ilYCbCrSampleInfo *pSrcSample, *pDstSample;
- ilBool doCvtYCbCr;
- /* If must convert refBlack/White or lumaRed/Green/Blue, convert to
- RGB and back to YCbCr; only those conversions handle this.
- */
- if ((pipeDes.typeInfo.YCbCr.lumaRed != pDes->typeInfo.YCbCr.lumaRed)
- || (pipeDes.typeInfo.YCbCr.lumaGreen != pDes->typeInfo.YCbCr.lumaGreen)
- || (pipeDes.typeInfo.YCbCr.lumaBlue != pDes->typeInfo.YCbCr.lumaBlue))
- doCvtYCbCr = TRUE;
- else {
- for (pSrcSample = pipeDes.typeInfo.YCbCr.sample,
- pDstSample = pDes->typeInfo.YCbCr.sample,
- doCvtYCbCr = FALSE, sample = 0;
- sample < 3; sample++, pSrcSample++, pDstSample++)
- if ((pSrcSample->refBlack != pDstSample->refBlack)
- || (pSrcSample->refWhite != pDstSample->refWhite))
- doCvtYCbCr = TRUE;
- }
- if (doCvtYCbCr) { /* cvt to RGB */
- if (!ilConvert (pipe, IL_DES_RGB, (ilImageFormat *)NULL, 0, NULL))
- return FALSE;
- ilGetPipeInfo (pipe, FALSE, &info, &pipeDes, &pipeFormat);
- }
- break;
- }
- /* Within palette: if option is zero (0), or if option says to dither
- and image already dithered to requested levels: fine, done; otherwise
- cvt first to RGB, so below conversion to palette will be enabled.
- */
- case IL_PALETTE:
- if (option == 0)
- break; /* default = accept as is; fine */
- if (option == IL_CONVERT_TO_PALETTE) {
- ilConvertToPaletteInfo *pData = (ilConvertToPaletteInfo *)pOptionData;
- if ((pipeDes.flags & IL_DITHERED_PALETTE)
- && (pipeDes.typeInfo.palette.levels[0] == pData->levels[0])
- && (pipeDes.typeInfo.palette.levels[1] == pData->levels[1])
- && (pipeDes.typeInfo.palette.levels[2] == pData->levels[2]))
- break; /* dithered to requested levels; fine */
- }
- if (!ADD_CVT_FILTER (&_ilPaletteToRGBByte)) /* cvt up to RGB */
- return FALSE;
- break;
- } /* END cvt within type */
- /* Loop converting image type until desired type reached. May take some
- iterations, e.g pal->bitonal = pal->rgb; rgb->gray; gray->bitonal.
- For conversion to YCbCr, cvt to RGB first.
- For conversion to palette, cvt to RGB first.
- */
- while (pipeDes.type != pDes->type) {
- switch (pipeDes.type) {
- /* Bitonal: cvt to gray, then to other types as necessary. */
- case IL_BITONAL:
- switch (pDes->type) {
- case IL_GRAY:
- case IL_YCBCR:
- case IL_PALETTE:
- case IL_RGB: {
- if (!ilScale (pipe, info.width, info.height, IL_SCALE_BITONAL_TO_GRAY, NULL))
- return FALSE;
- ilGetPipeInfo (pipe, FALSE, &info, &pipeDes, &pipeFormat);
- break;
- }
- default:
- goto CantConvert; /* unsupported conversion(s) */
- }
- break;
- case IL_GRAY:
- /* If not 256 levels/sample, cvt to 256 if possible. */
- if (pipeDes.nLevelsPerSample[0] != 256)
- if (!_ilAddLevelConversionFilter (pipe, &info, &pipeDes, IL_DES_GRAY, &pipeFormat))
- return FALSE;
- switch (pDes->type) {
- case IL_BITONAL:
- if (option == IL_CONVERT_THRESHOLD) {
- if (!pOptionData)
- pOptionData = &defaultThreshold;
- if (!ADD_CVT_FILTER (&_ilThresholdGrayToBitonal))
- return FALSE; /* error, EXIT */
- }
- else if (!ADD_CVT_FILTER (&_ilDiffuseGrayToBitonal))
- return FALSE; /* error, EXIT */
- break;
- case IL_YCBCR:
- case IL_PALETTE:
- case IL_RGB:
- if (!ADD_CVT_FILTER (&_ilGrayToRGB))
- return FALSE; /* error, EXIT */
- break;
- default:
- goto CantConvert; /* unsupported conversion(s) */
- }
- break;
- /* Palette to anything (except self - but that case wont get here)
- is currently done by converting to RGB, then to des type if necessary.
- */
- case IL_PALETTE:
- if (!ADD_CVT_FILTER (&_ilPaletteToRGBByte))
- return FALSE; /* error, EXIT */
- break;
- /* RGB goes to gray for gray or bitonal; handle conversion to YCbCr.
- If not 256 levels/sample, cvt to 256 if possible.
- */
- case IL_RGB:
- if ((pipeDes.nLevelsPerSample[0] != 256)
- || (pipeDes.nLevelsPerSample[1] != 256)
- || (pipeDes.nLevelsPerSample[2] != 256))
- if (!_ilAddLevelConversionFilter (pipe, &info, &pipeDes, IL_DES_RGB, &pipeFormat))
- return FALSE;
-
- switch (pDes->type) {
- case IL_BITONAL:
- case IL_GRAY:
- if (!ADD_CVT_FILTER (&_ilRGBToGray))
- return FALSE; /* error, EXIT */
- break;
- case IL_YCBCR:
- if (!_ilConvertRGBToYCbCr (pipe, &info, &pipeDes, pDes, &pipeFormat))
- return FALSE;
- break;
- /* Cvt RGB to palette: set pipeDes.type to IL_PALETTE to terminate
- loop: private type may actually have been created.
- */
- case IL_PALETTE:
- if (!_ilConvertRGBToPalette (pipe, &info, &pipeDes, &pipeFormat,
- option, (ilConvertToPaletteInfo *)pOptionData))
- return FALSE;
- pipeDes.type = IL_PALETTE; /* see note above */
- break;
- default:
- goto CantConvert; /* unsupported conversion(s) */
- }
- break;
- /* YCbCr (aka LUV): convert based on dst type and set "convertDone"
- to true, else convert to RGB, and then loop again until desired type.
- */
- case IL_YCBCR: {
- ilBool convertDone, upSample;
- upSample = MUST_UPSAMPLE (pipeDes);
- convertDone = FALSE;
- switch (pDes->type) {
- case IL_BITONAL:
- case IL_GRAY: /* extract Y plane if Y range 0..255 */
- if ((pipeDes.typeInfo.YCbCr.sample[0].refBlack == 0)
- && (pipeDes.typeInfo.YCbCr.sample[0].refWhite == 255)) {
- if (!_ilUpsampleYCbCr (pipe, &info, &pipeDes, &pipeFormat, TRUE,
- upSample))
- return FALSE;
- convertDone = TRUE;
- }
- break;
- case IL_PALETTE: /* try direct YCbCr to palette conversion */
- if (_ilDitherYCbCr (pipe, &info, &pipeDes, &pipeFormat, option,
- (ilConvertToPaletteInfo *)pOptionData)) {
- convertDone = TRUE;
- pipeDes.type = IL_PALETTE; /* see note above RGB->palette */
- }
- else if (pipe->context->error)
- return FALSE; /* otherwise, no error; filter just cant do it */
- break;
- }
- if (!convertDone) { /* no conversion; convert YCbCr to RGB */
- if (upSample && !_ilUpsampleYCbCr (pipe, &info, &pipeDes,
- &pipeFormat, FALSE, upSample))
- return FALSE;
- if (!_ilConvertYCbCrToRGB (pipe, &info, &pipeDes, &pipeFormat))
- return FALSE;
- }
- break;
- }
- } /* END switch source type */
- } /* END while convert type */
- /* Image type converted if different; check rest of des. */
- if (pipeDes.nSamplesPerPixel != pDes->nSamplesPerPixel)
- goto CantConvert;
- /* Check levels/sample, but not for palette images, where the levels/sample
- must be in range 2 .. (1<<nbits) - 1, but is otherwise ignored.
- */
- for (sample = 0; sample < pDes->nSamplesPerPixel; sample++)
- if (pipeDes.nLevelsPerSample[sample] != pDes->nLevelsPerSample[sample]) {
- if ((pipeDes.type != IL_PALETTE) &&
- !_ilAddLevelConversionFilter (pipe, &info, &pipeDes, pDes, &pipeFormat))
- return FALSE;
- break;
- }
- /* Do image type-specific checks and conversions. */
- switch (pipeDes.type) {
- /* "blackIsZero" applies only to bitonal and gray scale images. If different
- then invert bits if not "soft" invert (which means leave bits alone);
- if same, invert bits if "hard" invert (which means invert bits).
- */
- case IL_BITONAL:
- case IL_GRAY:
- if (pipeDes.blackIsZero != pDes->blackIsZero) {
- pipeDes.blackIsZero = pDes->blackIsZero;
- if (option == IL_CONVERT_SOFT_INVERT)
- _ilSetPipeDesFormat (pipe, &pipeDes, (ilImageFormat *)NULL);
- else if (!_ilAddInvertFilter (pipe, &pipeDes, &info))
- goto CantConvert;
- }
- break;
- /* YCbCr: check sub/upsampling; up/subsample as necessary */
- case IL_YCBCR: {
- const ilYCbCrSampleInfo *pSrcSample, *pDstSample;
- ilBool doUpsample;
- doSubsample = FALSE; /* checked below */
- for (pSrcSample = pipeDes.typeInfo.YCbCr.sample,
- pDstSample = pDes->typeInfo.YCbCr.sample,
- doUpsample = FALSE, sample = 0;
- sample < 3; sample++, pSrcSample++, pDstSample++)
- {
- if (pSrcSample->subsampleHoriz < pDstSample->subsampleHoriz)
- doSubsample = TRUE;
- else if (pSrcSample->subsampleHoriz > pDstSample->subsampleHoriz)
- doUpsample = TRUE;
- if (pSrcSample->subsampleVert < pDstSample->subsampleVert)
- doSubsample = TRUE;
- else if (pSrcSample->subsampleVert > pDstSample->subsampleVert)
- doUpsample = TRUE;
- }
- if (doUpsample)
- if (!_ilUpsampleYCbCr (pipe, &info, &pipeDes, &pipeFormat, FALSE, TRUE))
- return FALSE;
- if (doSubsample) {
- pipeDes = *pDes; /* pass subsample pars; des convert done */
- if (!_ilSubsampleYCbCr (pipe, &info, &pipeDes, &pipeFormat))
- return FALSE;
- }
- } /* END YCbCr */
- break;
- }
- } /* END check pDes */
- /* If pFormat given, convert to requested format.
- WARNING !!!!! - ilCheckPipeFormat() below also does format conversions -
- May have to change it when adding new format filters !!!!
- */
- if (pFormat) {
- /* Check if bits/sample needs conversion and if that conversion supported.
- Currently supported: 4 to 8 bit, pixel mode only if multi-sample.
- */
- doConvert = FALSE;
- for (sample = 0; sample < pDes->nSamplesPerPixel; sample++)
- if (pipeFormat.nBitsPerSample[sample] != pFormat->nBitsPerSample[sample]) {
- doConvert = TRUE;
- break;
- }
- /* If any format conversions and YCbCr, upsample if necessary.
- However, if subsampling was done before, error: cant convert.
- */
- if ((pipeDes.type == IL_YCBCR)
- && MUST_UPSAMPLE (pipeDes)
- && (doConvert || (pipeFormat.sampleOrder != pFormat->sampleOrder)
- || (pipeFormat.rowBitAlign != pFormat->rowBitAlign))) {
- if (doSubsample)
- goto CantConvert; /* cant upsample - subsampled before */
- if (!_ilUpsampleYCbCr (pipe, &info, &pipeDes, &pipeFormat, FALSE, TRUE))
- return FALSE;
- }
- /* If doConvert, then pipe image does not have desired # of bits/sample.
- Check if all planes have same # src, dst bits; else can't convert.
- Currently can convert 4->8 or 8->4.
- */
- if (doConvert) {
- int nSrcBits, nDstBits;
- if ((pipeDes.nSamplesPerPixel > 1) && (pFormat->sampleOrder != IL_SAMPLE_PIXELS))
- goto CantConvert;
- nSrcBits = pipeFormat.nBitsPerSample[0];
- nDstBits = pFormat->nBitsPerSample[0];
- for (sample = 1; sample < pDes->nSamplesPerPixel; sample++)
- if ((nSrcBits != pipeFormat.nBitsPerSample[sample])
- || (nDstBits != pFormat->nBitsPerSample[sample]))
- goto CantConvert; /* not same # src,dst bits each plane */
- if ((nSrcBits == 4) && (nDstBits == 8)) {
- if (!ilAddFormatFilter (pipe, &info, pFormat, &_ilFormat4To8Bit))
- return FALSE;
- }
- else if ((nSrcBits == 8) && (nDstBits == 4)) {
- if (!ilAddFormatFilter (pipe, &info, pFormat, &_ilFormat8To4Bit))
- return FALSE;
- }
- else goto CantConvert;
- }
- /* Change sample order: only handles 3 samples, each 8 bits. */
- if (pipeFormat.sampleOrder != pFormat->sampleOrder) {
- if ((pipeDes.nSamplesPerPixel != 3)
- || (pipeFormat.nBitsPerSample[0] != 8)
- || (pipeFormat.nBitsPerSample[1] != 8)
- || (pipeFormat.nBitsPerSample[2] != 8))
- goto CantConvert;
- if (pipeFormat.sampleOrder == IL_SAMPLE_PIXELS) {
- if (!ilAddFormatFilter (pipe, &info, pFormat, &_ilFormat8Bit3PixelToPlane))
- return FALSE;
- }
- else if (!ilAddFormatFilter (pipe, &info, pFormat, &_ilFormat8Bit3PlaneToPixel))
- return FALSE;
- }
- if (pipeFormat.rowBitAlign != pFormat->rowBitAlign) {
- if (!ilAddFormatFilter (pipe, &info, pFormat, &_ilFormatRowBitAlign))
- return FALSE;
- }
- }
- /* Succesful conversion.
- */
- pipe->context->error = IL_OK;
- return TRUE; /* EXIT */
- /* GOTO point for when conversion not supported.
- */
- CantConvert:
- ilDeclarePipeInvalid (pipe, IL_ERROR_CANT_CONVERT);
- return FALSE;
- }
- #ifdef NOTDEF
- IN PROGRESS - NOT DONE YET !!!!!!!!!!
- /* ------------------------ ilCheckPipeFormat --------------------------------- */
- /* Return an IL_CPF_? code for the current pipe image format, or
- IL_CPF_ERROR if error or can't match formats in "formatMask".
- The pipe info, des and/or format are returned to non-null
- pInfo/Des/Format if IL_CPF_ERROR not returned.
- */
- unsigned int ilCheckPipeFormat (
- ilPipe pipe,
- unsigned long formatMask,
- ilPipeInfo *pInfo, /* RETURNED */
- ilImageDes *pDes, /* RETURNED */
- ilImageFormat *pFormat /* RETURNED */
- )
- {
- ilPipeInfo localInfo;
- ilImageDes localDes;
- ilImageFormat localFormat;
- /* Point pInfo/Des/Format to local structs if caller passed NULL */
- if (!pInfo) pInfo = &localInfo;
- if (!pDes) pDes = &localDes;
- if (!pFormat) pFormat = &localFormat;
- /* Get pipe info and decompress; if pipe not in IL_PIPE_FORMING state: error. */
- if (ilGetPipeInfo (pipe, TRUE, pInfo, pDes, pFormat) != IL_PIPE_FORMING) {
- if (!pipe->context->error)
- ilDeclarePipeInvalid (pipe, IL_ERROR_PIPE_STATE);
- return IL_CPF_ERROR;
- }
- /* Look at des, format and try to match/convert to format(s) caller accepts */
- if (pDes->nSamplesPerPixel == 1) {
- /* 1 sample/pixel: if bit/pixel and caller accepts, check rowBitAlign */
- if ((formatMask & IL_CPF_BIT) && (pFormat->nBitsPerSample[0] == 1)) {
- if (pFormat->rowBitAlign != 32) {
- pFormat->rowBitAlign = 32;
- if (!ilAddFormatFilter (pipe, pInfo, pFormat, &ilFormatRowBitAlign))
- return IL_CPF_ERROR;
- return IL_CPF_BIT; /* match found: bit/pixel */
- }
- }
- else {
- /* 1 sample, bit not accepted; error if byte not accepted, make byte */
- if (!(formatMask & IL_CPF_BYTE))
- return IL_CPF_ERROR;
- if (pFormat->nBitsPerSample[0] != 8) {
- if (pFormat->nBitsPerSample[0] == 4) {
- pFormat->nBitsPerSample[0] = 8;
- if (!ilAddFormatFilter (pipe, pInfo, pFormat, &ilFormat4To8Bit))
- return IL_CPF_ERROR;
- }
- else return IL_CPF_ERROR; /* NOTE!! currently only 4-8 supported!!! */
- }
- return IL_CPF_BYTE; /* match found: 1 byte/pixel */
- }
- } /* END 1 sample/pixel */
- else { /* multi-sample/pixel */
- }
- }
- #endif
|