/* * 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: ilimage.c /main/3 1995/10/23 15:48:58 rswiston $ */ /**--------------------------------------------------------------------- *** *** (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). *** ***-------------------------------------------------------------------*/ /* /ilc/ilimage.c : General image handling code. */ #include #include "ilint.h" #include "ilpipelem.h" #include "ilimage.h" #include "ilcontext.h" #include "ilerrors.h" #include "ilutiljpeg.h" /* Table of supported compression modes for each image type. */ static unsigned long ilSupportedCompressions [IL_MAX_TYPE+1] = { /* IL_BITONAL */ ((1 << IL_UNCOMPRESSED) | (1 << IL_G3) | (1 << IL_G4) | (1 << IL_LZW) | (1 << IL_PACKBITS)), /* IL_GRAY */ ((1 << IL_UNCOMPRESSED) | (1 << IL_LZW) | (1 << IL_PACKBITS) | (1 << IL_JPEG)), /* IL_PALETTE */ ((1 << IL_UNCOMPRESSED) | (1 << IL_PACKBITS) | (1 << IL_LZW)), /* IL_RGB */ ((1 << IL_UNCOMPRESSED) | (1 << IL_LZW) | (1 << IL_JPEG)), /* IL_YCRCB */ ((1 << IL_UNCOMPRESSED) | (1 << IL_LZW) | (1 << IL_JPEG)) }; /* (ilBool) IL_VALID_COMPRESSION(comp, imageType) returns TRUE if "comp" is a valid compression for "imageType", a valid image type (e.g. IL_BITONAL). */ #define IL_VALID_COMPRESSION(_comp, _imageType) \ ((01L << (_comp)) & ilSupportedCompressions[_imageType]) /* ------------------------ ilValidateDesFormat ---------------------------- */ /* Validate the given image descriptor at "pDes" and the image format at "pFormat" if it is non-null and validate that they are compatible with each other. If "allowPrivateTypes" is true, private image type codes are allowed; otherwise an error is declared. Should be true for client images. Return 0 (IL_OK) if valid, else error code. NOTE: this function defines valid compressions and nBitsPerSample. */ IL_PRIVATE ilError _ilValidateDesFormat ( ilBool allowPrivateTypes, const ilImageDes *pDes, const ilImageFormat *pFormat ) { #define MAX_BITS_PER_SAMPLE 24 /* maximum # of bits/sample supported */ unsigned int i, j, nBits, nLevels, nSamplesPerPixel; const ilYCbCrSampleInfo *pSample; /* reserved must = 0; # samples must be 1 .. IL_MAX_SAMPLES. */ for (i = 0; i < IL_DES_RESERVED_SIZE; i++) if (pDes->reserved[i] != 0) return IL_ERROR_RESERVED_NOT_ZERO; nSamplesPerPixel = pDes->nSamplesPerPixel; if ((nSamplesPerPixel <= 0) || (nSamplesPerPixel > IL_MAX_SAMPLES)) return IL_ERROR_SAMPLES_PER_PIXEL; /* unused bits in flags must = 0; if dithered palette bit set, must be a palette image with levels whose product is <= # levels. */ if (pDes->flags & ~(IL_DITHERED_PALETTE)) return IL_ERROR_RESERVED_NOT_ZERO; if (pDes->flags & IL_DITHERED_PALETTE) { if ((pDes->type != IL_PALETTE) || ((pDes->typeInfo.palette.levels[0] * pDes->typeInfo.palette.levels[1] * pDes->typeInfo.palette.levels[2]) > pDes->nLevelsPerSample[0])) return IL_ERROR_PALETTE_INFO; } /* If validating format: all values must be as documented in spec. For each sample: bits must be 1..MAX_BITS_PER_SAMPLE, and levels be >= 2 and fit in those bits. If no format, levels must be 1..2**MAX_BITS_PER_SAMPLE. */ if (pFormat) { if (pFormat->byteOrder > IL_MAX_BYTE_ORDER) return IL_ERROR_BYTE_ORDER; if (pFormat->sampleOrder > IL_MAX_SAMPLE_ORDER) return IL_ERROR_SAMPLE_ORDER; /* NOTE: currently only pixel sample order supported if compressed */ if ((pDes->compression != IL_UNCOMPRESSED) && (pFormat->sampleOrder != IL_SAMPLE_PIXELS)) return IL_ERROR_SAMPLE_ORDER; nBits = pFormat->rowBitAlign; if ((nBits != 8) && (nBits != 16) && (nBits != 32)) return IL_ERROR_ROW_BIT_ALIGN; for (i = 0; i < IL_FORMAT_RESERVED_SIZE; i++) if (pFormat->reserved[i] != 0) return IL_ERROR_RESERVED_NOT_ZERO; for (i = 0; i < nSamplesPerPixel; i++) { nBits = pFormat->nBitsPerSample[i]; if ((nBits <= 0) || (nBits > MAX_BITS_PER_SAMPLE)) return IL_ERROR_BITS_PER_SAMPLE; nLevels = pDes->nLevelsPerSample[i]; if ((nLevels < 2) || (nLevels > (1<nLevelsPerSample [i]; if ((nLevels < 2) || (nLevels > (1<type) { case IL_BITONAL: if (nSamplesPerPixel != 1) return IL_ERROR_SAMPLES_PER_PIXEL; break; case IL_PALETTE: if (pDes->nLevelsPerSample[0] > 256) return IL_ERROR_LEVELS_PER_SAMPLE; case IL_GRAY: if (nSamplesPerPixel != 1) return IL_ERROR_SAMPLES_PER_PIXEL; break; case IL_RGB: if (nSamplesPerPixel != 3) return IL_ERROR_SAMPLES_PER_PIXEL; break; /* Validate YCbCr data; subsamples must be 1, 2 or 4, refWhite > refBlack. Image must be planar, 8 bits per sample. */ case IL_YCBCR: if (nSamplesPerPixel != 3) return IL_ERROR_SAMPLES_PER_PIXEL; pSample = pDes->typeInfo.YCbCr.sample; i = 3; while (i-- > 0) { j = pSample->subsampleHoriz; if ((j != 1) && (j != 2) && (j != 4)) return IL_ERROR_YCBCR_DATA; j = pSample->subsampleVert; if ((j != 1) && (j != 2) && (j != 4)) return IL_ERROR_YCBCR_DATA; if (pSample->refBlack >= pSample->refWhite) return IL_ERROR_YCBCR_DATA; pSample++; } if (pDes->typeInfo.YCbCr.positioning != 0) return IL_ERROR_YCBCR_DATA; if (pFormat) { if ((pFormat->nBitsPerSample[0] != 8) || (pFormat->nBitsPerSample[1] != 8) || (pFormat->nBitsPerSample[2] != 8)) return IL_ERROR_YCBCR_FORMAT; } break; /* Unknown type: error or ok if private types allowed. */ default: return (allowPrivateTypes) ? IL_OK : IL_ERROR_IMAGE_TYPE; break; } /* Validate compression: not a user image type (exited above) */ if (!IL_VALID_COMPRESSION (pDes->compression, pDes->type)) return IL_ERROR_COMPRESSION; return IL_OK; } /* ----------------------- ilGetBytesPerRow ------------------------------ */ /* Public function: see spec. Returns the # bytes / row into "pnBytesPerRow" (for each plane of image), for an image of size "width", with "nSamplesPerPixel" (from des) and the format "*pFormat". */ void ilGetBytesPerRow ( const ilImageDes *pDes, const ilImageFormat *pFormat, long width, long *pnBytesPerRow /* RETURNED */ ) { const unsigned short *pNBits; int rowBitAlign, nBits, nSamplesPerPixel, i; pNBits = pFormat->nBitsPerSample; rowBitAlign = pFormat->rowBitAlign; if (rowBitAlign < 8) rowBitAlign = 8; nSamplesPerPixel = pDes->nSamplesPerPixel; /* Calculate nBytesPerRow: # bits * width, rounded up by rowBitAlign. For 8 < bits/pixel <= 16, use word/pixel; <= 32, use long (TIFF std). Allocation size for each plane is then nBytesPerRow * height of image. If a YCBCrImage, take horizontal subsampling into account. */ if (pFormat->sampleOrder == IL_SAMPLE_PIXELS) { /* Pixel order: one row contains all of the bits for each pixel, in sample order. Sum the bits for one pixel; always start on a byte boundary for samples > 8 bits. */ nBits = 0; while (nSamplesPerPixel-- > 0) { i = *pNBits++; if (i > 8) { nBits = ((nBits + 7) / 8) * 8; /* round nBits to byte boundary */ if (i <= 16) i = 16; else i = 32; } nBits += i; } *pnBytesPerRow = ((nBits * width + rowBitAlign - 1) / rowBitAlign) * (rowBitAlign / 8); } else { const ilYCbCrSampleInfo *pYCbCr; /* Planar order: each plane is independent; return nSamplesPerPixel rowbytes. Take into account subsampling if YCbCr image. */ pYCbCr = (pDes->type == IL_YCBCR) ? pDes->typeInfo.YCbCr.sample : (ilYCbCrSampleInfo *)NULL; while (nSamplesPerPixel-- > 0) { nBits = *pNBits++; if (nBits > 8) { if (nBits <= 16) nBits = 16; else nBits = 32; } if (pYCbCr) { i = width >> _ilSubsampleShift[pYCbCr->subsampleHoriz]; if (i <= 0) i = 1; pYCbCr++; } else i = width; *pnBytesPerRow++ = ((nBits * i + rowBitAlign - 1) / rowBitAlign) * (rowBitAlign / 8); } } } /* ------------------------ ilMallocImagePixels ---------------------------- */ /* For uncompressed images: create a buffer for the pixels of image "*pImage", based on pImage->des, pImage->format, and pImage->height. For compressed images: just null pPixels and bufferSize; code that writes to a compressed image must check the bufferSize and malloc (first time) or realloc as necessary. Set ownPixels to true in either case. Returns: zero if success, else error code. */ IL_PRIVATE ilError _ilMallocImagePixels ( ilImagePtr pImage ) { int plane, nPlanes; int MCUMinus1 = 0; long nBytesToAlloc, nBytesPerRow, allocHeight; ilPtr pPixels; long rowBytesPerPlane [IL_MAX_SAMPLES]; ilYCbCrSampleInfo *pYCbCr; /* Get the bytes per row, set into the image. */ ilGetBytesPerRow (&pImage->des, &pImage->format, pImage->i.width, rowBytesPerPlane); /* Alloc each plane; on failure, backtrack and free those already created. Don't allocate buffer for compressed image! If YCbCr image point pYCbCr and calc maxVertSubsample (1,2,4) and MCU (Minimum Coded Unit) = 8 * maxVertSubsample. */ nPlanes = (pImage->format.sampleOrder == IL_SAMPLE_PIXELS) ? 1 : pImage->des.nSamplesPerPixel; if (pImage->des.type == IL_YCBCR) { pYCbCr = pImage->des.typeInfo.YCbCr.sample; MCUMinus1 = pYCbCr[0].subsampleVert; if (pYCbCr[1].subsampleVert > MCUMinus1) MCUMinus1 = pYCbCr[1].subsampleVert; if (pYCbCr[2].subsampleVert > MCUMinus1) MCUMinus1 = pYCbCr[2].subsampleVert; MCUMinus1 = MCUMinus1 * 8 - 1; /* e.g. if max = 4 MCUMinus1 is 31 */ } else pYCbCr = (ilYCbCrSampleInfo *)NULL; for (plane = 0; plane < nPlanes; plane++) { nBytesPerRow = rowBytesPerPlane [plane]; if (pImage->des.compression != IL_UNCOMPRESSED) nBytesToAlloc = 0; else { /* If YCbCr image, alloc smaller buffer (divide by subsample) but first rounded up to the MCU. For example, if max subsample is 2, an make unsubsampled buffer a mult of 16; a 2 subsampled mult of 8. "allocHeight" is height rounded up to MCU / vertSubsample. */ if (pYCbCr) { allocHeight = ((pImage->i.height + MCUMinus1) & ~MCUMinus1) >> _ilSubsampleShift[pYCbCr->subsampleVert]; pYCbCr++; } else allocHeight = pImage->i.height; nBytesToAlloc = nBytesPerRow * allocHeight; } if (!nBytesToAlloc) pPixels = (ilPtr)NULL; else { pPixels = (ilPtr)IL_MALLOC (nBytesToAlloc); if (!pPixels) { /* error; free those already created */ while ((plane != 0)) { plane--; if ((pPixels = pImage->i.plane[plane].pPixels)) IL_FREE (pPixels); } pImage->i.clientPixels = TRUE; /* so IL does not deallocate them */ return IL_ERROR_MALLOC; /* EXIT */ } } pImage->i.plane[plane].pPixels = pPixels; pImage->i.plane[plane].nBytesPerRow = nBytesPerRow; pImage->i.plane[plane].bufferSize = nBytesToAlloc; } /* END each plane */ pImage->i.clientPixels = FALSE; return IL_OK; } /* ------------------------ ilFreeImagePixels ----------------------------- */ /* Destroy() function for client and internal image objects. Also used to discard pixels when writing images or loading client images. Free the pixels of the image only if the IL owns them. */ IL_PRIVATE void _ilFreeImagePixels ( ilImagePtr pImage ) { int plane; ilPtr pPixels; /* If the IL owns the pixels (it does not if "clientPixels" true to ilCreateClientImage()), then free them if non-null. If pixel sample order, just one plane, else nSamplesPerPixel planes. */ if (!pImage->i.clientPixels) { for (plane = 0; plane < IL_NPLANES(pImage); plane++) { pPixels = pImage->i.plane[plane].pPixels; if (pPixels) IL_FREE (pPixels); } pImage->i.clientPixels = TRUE; /* so IL does not deallocate them */ } /* If own palette and it is non-null free it. */ if (!pImage->i.clientPalette && pImage->i.pPalette) { IL_FREE (pImage->i.pPalette); pImage->i.clientPalette = TRUE; } /* If own comp data and it is non-null free it and associated (JPEG) tables */ if (!pImage->i.clientCompData && pImage->i.pCompData) { if (pImage->des.compression == IL_JPEG) _ilJPEGFreeTables ((ilJPEGData *)pImage->i.pCompData); IL_FREE (pImage->i.pCompData); pImage->i.pCompData = (ilPtr)NULL; pImage->i.clientCompData = TRUE; } /* If strip offset array non-null free it */ if (pImage->pStripOffsets) { IL_FREE (pImage->pStripOffsets); pImage->pStripOffsets = (long *)NULL; } } /* ------------------------ ilAllocStripOffsets ----------------------------- */ /* For compressed images only: allocate strip offsets array (pStripOffsets) using the given "stripHeight", or use the default strip height if "stripHeight" is zero (0). Locks image to that strip height. */ IL_PRIVATE ilBool _ilAllocStripOffsets ( ilImagePtr pImage, long stripHeight ) { long nStrips; if (stripHeight <= 0) stripHeight = ilRecommendedStripHeight (pImage->i.pDes, pImage->i.pFormat, pImage->i.width, pImage->i.height); if (stripHeight > pImage->i.height) stripHeight = pImage->i.height; nStrips = (pImage->i.height + stripHeight - 1) / stripHeight; pImage->pStripOffsets = (long *)IL_MALLOC_ZERO ((nStrips + 1) * sizeof(long)); if (!pImage->pStripOffsets) { pImage->o.p.context->error = IL_ERROR_MALLOC; return FALSE; } pImage->nStrips = nStrips; pImage->stripHeight = stripHeight; pImage->o.p.context->error = IL_OK; return TRUE; } /* ---------------------- ilCreateInternalImage --------------------------- */ /* Public function: see spec. */ ilInternalImage ilCreateInternalImage ( ilContext context, long width, long height, ilImageDes *pDes, unsigned long mustBeZero ) { ilImagePtr pImage; ilError error; if (mustBeZero != 0) { context->error = IL_ERROR_PAR_NOT_ZERO; return (ilInternalImage)NULL; } /* Null (zero-sized) images not allowed; exit w/ error if so. */ if ((width <= 0) || (height <= 0)) { context->error = IL_ERROR_ZERO_SIZE_IMAGE; return (ilInternalImage)NULL; } /* Validate pDes: don't allow user-defined types. */ if ((context->error = _ilValidateDesFormat (FALSE, pDes, (ilImageFormat *)NULL))) return (ilInternalImage)NULL; /* Create the object and add it to context. */ pImage = (ilImagePtr)_ilCreateObject (context, IL_INTERNAL_IMAGE, _ilFreeImagePixels, sizeof (ilImageRec)); if (!pImage) return (ilInternalImage)NULL; /* Fill in the image structure, excluding object header (.o). Init the format to std format, based on image type, which is not private type. For bits per sample (other than bitonal): use 4 bits if levels/sample <= 16, else use 8 bits. Could use other values (e.g. min # bits for levels/sample), but at this point there are no conversions other than for 4<->8 bits. */ pImage->des = *pDes; switch (pDes->type) { case IL_BITONAL: pImage->format = *IL_FORMAT_BIT; break; case IL_GRAY: case IL_PALETTE: pImage->format = *IL_FORMAT_BYTE; if (pDes->nLevelsPerSample[0] <= 16) pImage->format.nBitsPerSample[0] = 4; break; case IL_RGB: pImage->format = *IL_FORMAT_3BYTE_PIXEL; if ((pDes->nLevelsPerSample[0] <= 16) && (pDes->nLevelsPerSample[1] <= 16) && (pDes->nLevelsPerSample[2] <= 16)) pImage->format.nBitsPerSample[0] = pImage->format.nBitsPerSample[1] = pImage->format.nBitsPerSample[2] = 4; break; /* YCbCr: always use 8 bits / pixel. If uncompressed use planar format, but if compressed use pixel (e.g. JPEG interleaved format). */ case IL_YCBCR: pImage->format = (pDes->compression == IL_UNCOMPRESSED) ? *IL_FORMAT_3BYTE_PLANE : *IL_FORMAT_3BYTE_PIXEL; break; default: context->error = IL_ERROR_IMAGE_TYPE; return (ilInternalImage)NULL; } /* Init image data, allocate pixels if uncompressed */ pImage->nStrips = 0; /* if compressed, strip height not set yet */ pImage->stripHeight = 0; pImage->pStripOffsets = (long *)NULL; pImage->i.pDes = &pImage->des; pImage->i.pFormat = &pImage->format; pImage->i.width = width; pImage->i.height = height; pImage->i.pCompData = (ilPtr)NULL; pImage->i.clientCompData = TRUE; pImage->i.pPalette = (unsigned short *)NULL; pImage->i.clientPalette = TRUE; if ((error = _ilMallocImagePixels (pImage))) { ilDestroyObject ((ilObject)pImage); context->error = error; return (ilInternalImage)NULL; } /* If a palette image, create an empty palette. */ if (pDes->type == IL_PALETTE) { pImage->i.pPalette = (unsigned short *) IL_MALLOC_ZERO (sizeof (unsigned short) * (3 * 256)); if (!pImage->i.pPalette) { ilDestroyObject ((ilObject)pImage); context->error = IL_ERROR_MALLOC; return (ilInternalImage)NULL; } pImage->i.clientPalette = FALSE; } /* If raw JPEG compressed, point pCompData to allocated JPEG info block, else init pCompData to null, owned by client (i.e. not freed when destroyed). */ if ((pDes->compression == IL_JPEG) && (pDes->compInfo.JPEG.reserved & IL_JPEGM_RAW)) { if (!(pImage->i.pCompData = (ilPtr)IL_MALLOC_ZERO (sizeof (ilJPEGData)))) { ilDestroyObject ((ilObject)pImage); context->error = IL_ERROR_MALLOC; return (ilInternalImage)NULL; } pImage->i.clientCompData = FALSE; /* IL must now destroy comp data */ } context->error = IL_OK; return (ilInternalImage)pImage; } /* ------------------------ ilQueryInternalImage ----------------------------- */ /* Public function: see spec. */ ilBool ilQueryInternalImage ( ilInternalImage image, long *pWidth, /* RETURNED */ long *pHeight, /* RETURNED */ ilImageDes *pDes, /* RETURNED */ unsigned long mustBeZero ) { ilImagePtr pImage; /* Check that given image is an internal image. */ pImage = (ilImagePtr)image; if (mustBeZero != 0) { pImage->o.p.context->error = IL_ERROR_PAR_NOT_ZERO; return 0; /* EXIT */ } if (pImage->o.p.objectType != IL_INTERNAL_IMAGE) { pImage->o.p.context->error = IL_ERROR_OBJECT_TYPE; return 0; /* EXIT */ } pImage->o.p.context->error = IL_OK; /* Right type of image: return values to non-null ptrs. */ if (pWidth) *pWidth = pImage->i.width; if (pHeight) *pHeight = pImage->i.height; if (pDes) *pDes = pImage->des; return TRUE; } /* ---------------------- ilCreateClientImage --------------------------- */ /* Public function: see spec. */ ilClientImage ilCreateClientImage ( ilContext context, ilImageInfo *pInfo, unsigned long mustBeZero ) { ilImagePtr pImage; ilError error; int plane, nPlanes; if (mustBeZero != 0) { context->error = IL_ERROR_PAR_NOT_ZERO; return (ilClientImage)NULL; } /* Null (zero-sized) images not allowed; exit w/ error if so. */ if ((pInfo->width <= 0) || (pInfo->height <= 0)) { context->error = IL_ERROR_ZERO_SIZE_IMAGE; return (ilClientImage)NULL; } /* Validate pDes and pFormat: do allow user-defined types. */ if ((context->error = _ilValidateDesFormat (TRUE, pInfo->pDes, pInfo->pFormat))) return (ilClientImage)NULL; /* Create the object and add it to context. */ pImage = (ilImagePtr)_ilCreateObject (context, IL_CLIENT_IMAGE, _ilFreeImagePixels, sizeof (ilImageRec)); if (!pImage) return (ilClientImage)NULL; /* Fill in the image structure, excluding object header (.o). Copy caller's des, and if "raw" JPEG force to non-raw. Client must be able to access image, and non-raw (JIF) format only meaningful way to do so. */ pImage->des = *pInfo->pDes; if (pImage->des.compression == IL_JPEG) pImage->des.compInfo.JPEG.reserved = 0; pImage->format = *pInfo->pFormat; pImage->nStrips = 0; /* if compressed, no data present yet */ pImage->stripHeight = 0; pImage->pStripOffsets = (long *)NULL; pImage->i.pDes = &pImage->des; pImage->i.pFormat = &pImage->format; pImage->i.width = pInfo->width; pImage->i.height = pInfo->height; pImage->i.pPalette = (unsigned short *)NULL; /* assume no palette or comp data */ pImage->i.clientPalette = TRUE; pImage->i.pCompData = (ilPtr)NULL; pImage->i.clientCompData = TRUE; pImage->i.clientPixels = pInfo->clientPixels; /* If a palette image, point to the one from the caller if pPalette not null; if null, create one here and the IL owns it. */ if (pImage->des.type == IL_PALETTE) { if (pInfo->pPalette && pInfo->clientPalette) { pImage->i.pPalette = pInfo->pPalette; pImage->i.clientPalette = TRUE; } else { pImage->i.pPalette = (unsigned short *) IL_MALLOC_ZERO (sizeof (unsigned short) * (3 * 256)); if (!pImage->i.pPalette) { ilDestroyObject ((ilObject)pImage); context->error = IL_ERROR_MALLOC; return (ilClientImage)NULL; } pImage->i.clientPalette = FALSE; } } /* multi-plane planar compressed images not supported */ nPlanes = IL_NPLANES(pImage); if ((pImage->des.compression != IL_UNCOMPRESSED) && (nPlanes > 1)) { ilDestroyObject ((ilObject)pImage); context->error = IL_ERROR_SAMPLE_ORDER; return (ilClientImage)NULL; } /* If caller providing pixels (clientPixels == true), point to them, otherwise allocate buffer space; if failure delete object and return error. */ if (pInfo->clientPixels) { for (plane = 0; plane < nPlanes; plane++) pImage->i.plane[plane] = pInfo->plane[plane]; } else { /* no pixels from client; allocate them here if uncompressed image */ if ((error = _ilMallocImagePixels (pImage))) { ilDestroyObject ((ilObject)pImage); context->error = error; return (ilClientImage)NULL; } } /* Compressed client images stored as one big strip; allocate strip offset array. If client pixels, offset[0] = 0, offset[1] = nBytes - all data in 1 strip. */ if (pImage->des.compression != IL_UNCOMPRESSED) { if (!_ilAllocStripOffsets (pImage, pImage->i.height)) { error = context->error; ilDestroyObject ((ilObject)pImage); context->error = error; return (ilClientImage)NULL; } if (pInfo->clientPixels) { pImage->pStripOffsets[0] = 0; pImage->pStripOffsets[1] = pImage->i.plane[0].bufferSize; } } context->error = IL_OK; return (ilClientImage)pImage; } /* ------------------------ ilQueryClientImage ----------------------------- */ /* Public function: see spec. */ ilBool ilQueryClientImage ( ilClientImage image, ilImageInfo **ppInfo, /* RETURNED */ unsigned long mustBeZero ) { ilImagePtr pImage; /* Validate given image of correct type; return false if not realized. */ pImage = (ilImagePtr)image; if (mustBeZero != 0) { pImage->o.p.context->error = IL_ERROR_PAR_NOT_ZERO; return FALSE; } if (pImage->o.p.objectType != IL_CLIENT_IMAGE) { pImage->o.p.context->error = IL_ERROR_OBJECT_TYPE; return FALSE; } if (ppInfo) *ppInfo = &pImage->i; pImage->o.p.context->error = IL_OK; return TRUE; }