123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- /*
- * 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: ilwriteimage.c /main/4 1996/01/08 12:17:24 lehors $ */
- /**---------------------------------------------------------------------
- ***
- *** (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 "ilpipelem.h"
- #include "ilimage.h"
- #include "ilerrors.h"
- #include "ilutiljpeg.h"
- /* Private data for Read/WriteImage pipe functions. */
- typedef struct {
- ilImagePtr pImage; /* ptr to image read/written */
- unsigned short *pPalette; /* ptr to palette or null if not palette image */
- ilPtr pCompData; /* ptr to comp data or null if none */
- long nLinesWritten; /* Init(): # of lines written so far */
- /* Remaining fields used only for compressed images */
- long nStripsWritten; /* Init(): # of strips written to image */
- } ilImagePrivRec, *ilImagePrivPtr;
- /* ------------------------- ilWriteImageInit ----------------------------------- */
- /* Init() function for ilWriteImage().
- */
- static ilError ilWriteImageInit (
- ilImagePrivPtr pPriv,
- ilImageInfo *pSrcImage,
- ilImageInfo *pDstImage
- )
- {
- pPriv->nStripsWritten = 0;
- pPriv->nLinesWritten = 0;
- return IL_OK;
- }
- /* ------------------------ ilWriteImageDestroy ------------------------------ */
- /* Destroy() function for ilWriteImage(). Calls ilDestroyObject() with
- element's pObject, which should point to the image. The image's refCount
- is inc'd when pipe element added. ilDestroyObject() will dec it and free
- the image if the refCount is 0. Using refCount this way prevents the user
- from destroying an image still attached to a pipe.
- */
- static ilError ilWriteImageDestroy (
- ilImagePrivPtr pPriv
- )
- {
- ilDestroyObject ((ilObject)pPriv->pImage);
- return IL_OK;
- }
- /* ============================ WRITE COMPRESSED CODE ============================= */
- /* ------------------------ ilWriteCompressedCleanup ------------------------- */
- /* Cleanup() function for ilWriteImage(), writing compressed images.
- */
- static ilError ilWriteCompressedCleanup (
- ilImagePrivPtr pPriv,
- ilBool aborting
- )
- {
- ilImagePlaneInfo *pImagePlane;
- ilImagePtr pImage;
- ilError error;
- pImage = pPriv->pImage;
- pImagePlane = &pImage->i.plane[0];
- /* If # of strips written by pipe is not equal to # of strips in image, error */
- if (!aborting && (pPriv->nStripsWritten != pImage->nStrips)) {
- aborting = TRUE; /* take error path below */
- error = IL_ERROR_MALFORMED_IMAGE_WRITE;
- }
- else error = IL_OK;
- /* If aborting, free up pixels if they don't belong to client */
- if (aborting) {
- if (!pImage->i.clientPixels && pImagePlane->pPixels) {
- IL_FREE (pImagePlane->pPixels);
- pImagePlane->pPixels = (ilPtr)NULL;
- pImagePlane->bufferSize = 0;
- }
- }
- else {
- /* Success: realloc (shrink) the image down to the written size (offset to
- strip past last strip), to free up extra unused-but-allocated space.
- */
- pImagePlane->bufferSize = pImage->pStripOffsets[pImage->nStrips];
- if (pImagePlane->pPixels)
- pImagePlane->pPixels = (ilPtr)IL_REALLOC (pImagePlane->pPixels,
- pImagePlane->bufferSize);
- }
- return error;
- }
- /* ------------------------ ilWriteCompressedExecute ------------------------- */
- /* Execute() function for ilWriteImage(), writing compressed images.
- */
- static ilError ilWriteCompressedExecute (
- ilExecuteData *pData,
- long dstLine,
- long *pNLines
- )
- {
- ilImagePrivPtr pPriv;
- ilImagePtr pImage;
- pPriv = (ilImagePrivPtr)pData->pPrivate;
- pImage = pPriv->pImage;
- /* If first strip: copy non-null pipe palette (pPriv->pPalette) and comp data
- (NOTE: assumed to be JPEG!), after freeing old tables, to the image.
- */
- if (pData->srcLine <= 0) {
- if (pPriv->pPalette)
- bcopy ((char *)pPriv->pPalette, (char *)pPriv->pImage->i.pPalette,
- sizeof (unsigned short) * (3 * 256));
- if (pPriv->pCompData) {
- _ilJPEGFreeTables ((ilJPEGData *)pPriv->pImage->i.pCompData);
- if (!_ilJPEGCopyData ((ilJPEGData *)pPriv->pCompData,
- (ilJPEGData *)pPriv->pImage->i.pCompData))
- return IL_ERROR_MALLOC;
- }
- }
- /* Bump srcLine (index to next line); if > # lines in image, error */
- pData->srcLine += *pNLines;
- if (pData->srcLine > pImage->i.height)
- return IL_ERROR_MALFORMED_IMAGE_WRITE;
- /* If # lines written != strip size and not last strip, inconstant strips */
- if ((*pNLines != pImage->stripHeight) && (pData->srcLine != pImage->i.height))
- return IL_ERROR_MALFORMED_IMAGE_WRITE;
- /* Store offset to this and next strip; bump offset for next write */
- pImage->pStripOffsets[pPriv->nStripsWritten++] = pData->compressed.srcOffset;
- pData->compressed.srcOffset += pData->compressed.nBytesToRead;
- pImage->pStripOffsets[pPriv->nStripsWritten] = pData->compressed.srcOffset;
- return IL_OK;
- }
- /* -------------------- ilWriteCompressedImage -------------------- */
- /* Called by ilWriteImage() to add a consumer to "pipe" which writes compressed
- data to the given "image". "pipe" and "image" are guaranteed to be the correct
- object types and to belong to the same context. The pipe is guaranteed to
- be in the correct state (IL_PIPE_FORMING) and "image" is guaranteed to be the
- correct size (size of the pipe image).
- */
- static ilBool ilWriteCompressedImage (
- ilPipe pipe,
- ilObject image
- )
- {
- ilImagePtr pImage;
- ilPipeInfo info;
- ilImageDes des;
- ilImageFormat format;
- ilBool mustConvert;
- ilImagePrivPtr pPriv;
- ilSrcElementData srcData;
- long stripHeight;
- ilPtr pCompData;
- /* Get pipe info, don't force decompression (yet). */
- ilGetPipeInfo (pipe, FALSE, &info, &des, &format);
- /* Convert (and decompress) as necessary to dest image des */
- pImage = (ilImagePtr)image;
- mustConvert = FALSE;
- if ((des.type != pImage->des.type)
- || (des.blackIsZero != pImage->des.blackIsZero)
- || (des.nSamplesPerPixel != pImage->des.nSamplesPerPixel))
- mustConvert = TRUE;
- else {
- int plane;
- for (plane = 0; plane < des.nSamplesPerPixel; plane++)
- if ((des.nLevelsPerSample[plane] != pImage->des.nLevelsPerSample[plane])
- || (format.nBitsPerSample[plane] != pImage->format.nBitsPerSample[plane])) {
- mustConvert = TRUE;
- break;
- }
- }
- if (mustConvert) {
- ilImageDes tempDes;
- tempDes = *pImage->i.pDes;
- tempDes.compression = IL_UNCOMPRESSED; /* ilConvert() error otherwise */
- if (!ilConvert (pipe, &tempDes, (ilImageFormat *)NULL, 0, (ilPtr)NULL))
- return FALSE;
- des.compression = IL_UNCOMPRESSED; /* force recompress below */
- }
- /* Compress to compression type of image, including type-specific (G3/JPEG)
- compression data. Compress to image's strip height if is established
- (pStripOffsets non-null), else set "stripHeight" to 0 and use default.
- */
- if (pImage->des.compression == IL_G3)
- pCompData = (ilPtr)&pImage->des.compInfo.g3.flags;
- else if (pImage->des.compression == IL_G4)
- pCompData = (ilPtr)&pImage->des.compInfo.g4.flags;
- else if (pImage->des.compression == IL_JPEG)
- pCompData = (ilPtr)&pImage->des.compInfo.JPEG;
- else pCompData = (ilPtr)NULL;
- stripHeight = (pImage->pStripOffsets) ? pImage->stripHeight : 0;
- if (!ilCompress (pipe, pImage->des.compression, pCompData, stripHeight, 0))
- return FALSE;
- ilGetPipeInfo (pipe, FALSE, &info, (ilImageDes *)NULL, (ilImageFormat *)NULL);
- /* If image does not yet have a strip height, set it to pipe's strip height */
- if (!stripHeight)
- if (!_ilAllocStripOffsets (pImage, info.stripHeight))
- return ilDeclarePipeInvalid (pipe, pipe->context->error);
- /* Add a consumer to write to the image - merely bumps offsets. */
- srcData.consumerImage = (ilObject)pImage;
- srcData.stripHeight = 0;
- srcData.constantStrip = FALSE;
- srcData.minBufferHeight = 0;
- pPriv = (ilImagePrivPtr)ilAddPipeElement(pipe, IL_CONSUMER, sizeof(ilImagePrivRec), 0,
- &srcData, (ilDstElementData *)NULL, ilWriteImageInit, ilWriteCompressedCleanup,
- ilWriteImageDestroy, ilWriteCompressedExecute, 0);
- if (!pPriv)
- return FALSE;
- pPriv->pImage = pImage;
- pPriv->pPalette = (pImage->des.type == IL_PALETTE) ? info.pPalette :
- (unsigned short *)NULL;
- /* NOTE: assumes JPEG pCompData! Point to pipe comp data if raw JPEG */
- if ((pImage->des.compression == IL_JPEG)
- && (pImage->des.compInfo.JPEG.reserved & IL_JPEGM_RAW))
- pPriv->pCompData = info.pCompData;
- else pPriv->pCompData = (ilPtr)NULL;
- pImage->o.refCount++; /* see ilWriteImageDestroy() */
- pipe->context->error = IL_OK;
- return TRUE;
- }
- /* ============================ WRITE UNCOMPRESSED CODE ============================= */
- /* --------------------- ilWriteImageExecute -------------------------------- */
- /* Execute() for WriteImage(): merely bumps srcLine by # lines written.
- */
- static ilError ilWriteImageExecute (
- ilExecuteData *pData,
- long dstLine,
- long *pNLines
- )
- {
- ilImagePrivPtr pPriv;
- pPriv = (ilImagePrivPtr)pData->pPrivate;
- /* If first strip, copy pipe palette (pPriv->pPalette) to the image palette. */
- if ((pData->srcLine <= 0) && pPriv->pPalette) {
- bcopy ((char *)pPriv->pPalette, (char *)pPriv->pImage->i.pPalette,
- sizeof (unsigned short) * (3 * 256));
- }
- /* Bump srcLine (index to next line); if > # lines in image, error */
- pData->srcLine += *pNLines;
- if (pData->srcLine > pPriv->pImage->i.height)
- return IL_ERROR_MALFORMED_IMAGE_WRITE;
- return IL_OK;
- }
- /* ------------------------ ilWriteImage ---------------------------------- */
- /* Public function: see spec.
- Adds the given image as a producer of the pipe.
- */
- ilBool ilWriteImage (
- ilPipe pipe,
- ilObject image
- )
- {
- ilImagePtr pImage;
- ilImagePrivPtr pPriv;
- ilContext context;
- ilPipeInfo info;
- ilSrcElementData srcData;
- /* Validate that pipe and image are such, and that they have the same context. */
- pImage = (ilImagePtr)image;
- context = pipe->context;
- if (pipe->objectType != IL_PIPE) {
- context->error = IL_ERROR_OBJECT_TYPE;
- return;
- }
- if ((pImage->o.p.objectType != IL_INTERNAL_IMAGE)
- && (pImage->o.p.objectType != IL_CLIENT_IMAGE))
- return ilDeclarePipeInvalid (pipe, IL_ERROR_OBJECT_TYPE);
- if (pImage->o.p.context != context)
- return ilDeclarePipeInvalid (pipe, IL_ERROR_CONTEXT_MISMATCH);
- /* Get pipe info; if pipe not in IL_PIPE_FORMING state: error.
- If producerObject is the given image, error: cant read/write same image.
- */
- if (ilGetPipeInfo (pipe, FALSE, &info,
- (ilImageDes *)NULL, (ilImageFormat *)NULL) != IL_PIPE_FORMING) {
- if (!context->error)
- ilDeclarePipeInvalid (pipe, IL_ERROR_PIPE_STATE);
- return FALSE;
- }
- if (info.producerObject == (ilObject)pImage)
- return ilDeclarePipeInvalid (pipe, IL_ERROR_CIRCULAR_PIPE);
- /* Validate pipe image. width, height and descriptor must be the same. */
- if ((info.width != pImage->i.width) || (info.height != pImage->i.height))
- return ilDeclarePipeInvalid (pipe, IL_ERROR_IMAGE_SIZE);
- /* If a writing to a compressed image, call separate function and exit. */
- if (pImage->des.compression != IL_UNCOMPRESSED)
- return ilWriteCompressedImage (pipe, image); /* EXIT */
- /* Convert des and/or format if not same as the images format; exit if error. */
- if (!ilConvert (pipe, pImage->i.pDes, pImage->i.pFormat, 0, NULL))
- return FALSE;
- ilGetPipeInfo (pipe, TRUE, &info, (ilImageDes *)NULL, (ilImageFormat *)NULL);
- /* Add a consumer element which writes to the given image.
- If writing a palette image, supply an Init() function to copy the palette.
- */
- srcData.consumerImage = (ilObject)pImage;
- srcData.stripHeight = 0;
- srcData.constantStrip = FALSE;
- srcData.minBufferHeight = 0;
- pPriv = (ilImagePrivPtr)ilAddPipeElement (pipe, IL_CONSUMER, sizeof (ilImagePrivRec),
- 0, &srcData, (ilDstElementData *)NULL, ilWriteImageInit, IL_NPF,
- ilWriteImageDestroy, ilWriteImageExecute, 0);
- if (!pPriv)
- return FALSE;
- /* Element successfully added; setup private data.
- Increment the refCount in the image; see notes for ilImageDestroy().
- */
- pPriv->pImage = pImage;
- pPriv->pPalette = (pImage->des.type == IL_PALETTE) ? info.pPalette :
- (unsigned short *)NULL;
- pImage->o.refCount++; /* see ilWriteImageDestroy() */
- context->error = IL_OK;
- return TRUE;
- }
|