1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/cde/lib/DtHelp/il/ilimage.c
Pascal Stumpf 7e0a9517e3 Silence lots of warnings in lib/DtHelp.
* 64bit warnings
* Missing prototypes
* explicit parentheses / brackets

There's still some work to be done, but, as always, it's a start ...
2013-07-22 17:19:13 -06:00

796 lines
29 KiB
C

/*
* 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 librararies 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,
register const ilImageDes *pDes,
register const ilImageFormat *pFormat
)
{
#define MAX_BITS_PER_SAMPLE 24 /* maximum # of bits/sample supported */
register 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 (
register const ilImageDes *pDes,
register const ilImageFormat *pFormat,
long width,
long *pnBytesPerRow /* RETURNED */
)
{
register const unsigned short *pNBits;
register 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 {
register 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 (
register ilImagePtr pImage
)
{
register int plane, nPlanes;
int MCUMinus1;
register long nBytesToAlloc, nBytesPerRow, allocHeight;
ilPtr pPixels;
long rowBytesPerPlane [IL_MAX_SAMPLES];
register 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 (
register 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 (
register ilImagePtr pImage,
register long stripHeight
)
{
register 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
)
{
register 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
)
{
register 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; /* EXIT */
}
if (pImage->o.p.objectType != IL_INTERNAL_IMAGE) {
pImage->o.p.context->error = IL_ERROR_OBJECT_TYPE;
return; /* 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
)
{
register 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
)
{
register 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;
}