Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
373
cde/lib/DtHelp/il/ilwriteimage.c
Normal file
373
cde/lib/DtHelp/il/ilwriteimage.c
Normal file
@@ -0,0 +1,373 @@
|
||||
/* $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
|
||||
)
|
||||
{
|
||||
register ilImagePlaneInfo *pImagePlane;
|
||||
register 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 dont 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 (
|
||||
register ilExecuteData *pData,
|
||||
long dstLine,
|
||||
long *pNLines
|
||||
)
|
||||
{
|
||||
register ilImagePrivPtr pPriv;
|
||||
register 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
|
||||
)
|
||||
{
|
||||
register ilImagePtr pImage;
|
||||
ilPipeInfo info;
|
||||
ilImageDes des;
|
||||
ilImageFormat format;
|
||||
ilBool mustConvert;
|
||||
register ilImagePrivPtr pPriv;
|
||||
ilSrcElementData srcData;
|
||||
long stripHeight;
|
||||
ilPtr pCompData;
|
||||
|
||||
/* Get pipe info, dont 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 (
|
||||
register 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
|
||||
)
|
||||
{
|
||||
register ilImagePtr pImage;
|
||||
register ilImagePrivPtr pPriv;
|
||||
register 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 succesfully 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user