123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796 |
- /*
- * 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 <stdlib.h>
- #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<<nBits)))
- return IL_ERROR_LEVELS_PER_SAMPLE;
- }
- }
- else {
- for (i = 0; i < nSamplesPerPixel; i++) {
- nLevels = pDes->nLevelsPerSample [i];
- if ((nLevels < 2) || (nLevels > (1<<MAX_BITS_PER_SAMPLE)))
- return IL_ERROR_LEVELS_PER_SAMPLE;
- }
- }
- /* Format and des are valid, excluding image type considerations.
- Validated based on type; allow user type only if caller said to.
- Note that no check is made on nBitsPerSample based on type.
- That is, it is allowed to create a bitonal image with 8 bits/pixel.
- It's just that the IL (probably) will never provide a conversion
- to 1 bit/pixel, so IL intrinsic functions are used on this image
- an error will occur - but client pipe elements could work on that image.
- */
- switch (pDes->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;
- }
|