123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699 |
- /*
- * 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: ilcompressjpeg.c /main/4 1996/01/08 12:14:02 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 "ilcompress.h"
- #include "ilcodec.h"
- #include "ilerrors.h"
- #include "ilutiljpeg.h"
- #include "iljpgencode.h"
- /* ============================= JIF to Raw =================================== */
- /* This body of code supports converting JIF format JPEG to "raw" (stripped).
- */
- /* Private data for ilJIFToRawExecute() */
- typedef struct {
- ilJPEGData *pCompData; /* ptr to IL JPEG data */
- } ilJIFToRawPrivRec, *ilJIFToRawPrivPtr;
- /* ----------------------- ilJIFToRawDestroy ------------------------------ */
- /* Destroy() function for converting JIF format JPEG to "raw" JPEG.
- */
- static ilError ilJIFToRawDestroy (
- ilJIFToRawPrivPtr pPriv
- )
- {
- /* Free pCompData including associated tables */
- if (pPriv->pCompData) {
- _ilJPEGFreeTables (pPriv->pCompData);
- IL_FREE (pPriv->pCompData);
- }
- return IL_OK;
- }
- /* ----------------------- ilJIFToRawExecute ------------------------------ */
- /* Execute() function for converting JIF format JPEG to "raw" JPEG.
- */
- static ilError ilJIFToRawExecute (
- ilExecuteData *pData,
- unsigned long dstLine,
- unsigned long *pNLines
- )
- {
- ilJPEGDecodeStream streamRec;
- iljpgDataPtr pJPEGData;
- ilError error;
- int i;
- ilJPEGData *pCompData;
- ilImagePlaneInfo *pDstPlane;
- long dstOffset, nBytes;
- /* Parse the src data, which is a JIF data stream */
- streamRec.pData = pData->pSrcImage->plane[0].pPixels;
- streamRec.nBytesLeft = pData->compressed.nBytesToRead;
- if (error = iljpgDecodeJIF (&streamRec, &pJPEGData))
- return error;
- /* Point pCompData to tables decoded from JIF, and copy table indices. */
- pCompData = ((ilJIFToRawPrivPtr)pData->pPrivate)->pCompData;
- for (i = 0; i < 4; i++) {
- pCompData->QTables[i] = pJPEGData->QTables[i];
- pCompData->DCTables[i] = pJPEGData->DCTables[i];
- pCompData->ACTables[i] = pJPEGData->ACTables[i];
- }
- for (i = 0; i < ILJPG_MAX_COMPS; i++) {
- pCompData->sample[i].QTableIndex = pJPEGData->comp[i].QTableIndex;
- pCompData->sample[i].DCTableIndex = pJPEGData->comp[i].DCTableIndex;
- pCompData->sample[i].ACTableIndex = pJPEGData->comp[i].ACTableIndex;
- }
- /* Copy restartInterval from JIF info; it will be zero (0) if no DRI marker,
- implying no restart markers.
- */
- pCompData->restartInterval = pJPEGData->restartInterval;
-
- /* Free decode data but not tables; they will be freed by ilJIFToRawDestroy() */
- IL_FREE (pJPEGData);
- /* Write rest of data (actual JPEG data, after tables etc.) to next filter.
- Exclude the EOI marker if present (which it really should be).
- */
- nBytes = streamRec.nBytesLeft;
- if ((nBytes >= 2)
- && (streamRec.pData[nBytes-2] == ILJPGM_FIRST_BYTE)
- && (streamRec.pData[nBytes-1] == ILJPGM_EOI))
- nBytes -= 2; /* remove EOI marker */
- dstOffset = *pData->compressed.pDstOffset;
- pDstPlane = pData->pDstImage->plane;
- if (pDstPlane->bufferSize < (nBytes + dstOffset))
- if (!_ilReallocCompressedBuffer (pData->pDstImage, 0, (nBytes + dstOffset)))
- return IL_ERROR_MALLOC;
- bcopy ((char *)streamRec.pData,
- (char *)(pDstPlane->pPixels + dstOffset), nBytes);
- *pData->compressed.pNBytesWritten = nBytes;
- return IL_OK;
- }
- /* ----------------------- ilJIFToRaw ------------------------------ */
- /* Called by _ilCompressJPEG() when the pipe image is JIF format, to
- convert to "raw" JPEG format.
- */
- static ilBool ilJIFToRaw (
- ilPipe pipe,
- ilPipeInfo *pInfo,
- ilImageDes *pDes,
- ilImageFormat *pFormat
- )
- {
- ilJPEGData *pCompData;
- ilJIFToRawPrivPtr pPriv;
- ilDstElementData dstData;
- /* Allocate an IL raw JPEG data block; point to it for pipe element */
- if (!(pCompData = (ilJPEGData *)IL_MALLOC_ZERO (sizeof (ilJPEGData))))
- return ilDeclarePipeInvalid (pipe, IL_ERROR_MALLOC);
- dstData.producerObject = (ilObject)NULL;
- pDes->compInfo.JPEG.reserved |= IL_JPEGM_RAW; /* now writing raw JPEG */
- dstData.pDes = pDes;
- dstData.pFormat = pFormat;
- dstData.width = pInfo->width;
- dstData.height = pInfo->height;
- dstData.stripHeight = pInfo->height; /* write one strip = whole image */
- dstData.constantStrip = TRUE;
- dstData.pPalette = (unsigned short *)NULL;
- dstData.pCompData = (ilPtr)pCompData;
- pPriv = (ilJIFToRawPrivPtr)ilAddPipeElement (pipe, IL_FILTER,
- sizeof (ilJIFToRawPrivRec), 0, (ilSrcElementData *)NULL, &dstData,
- IL_NPF, IL_NPF, ilJIFToRawDestroy, ilJIFToRawExecute, 0);
- if (!pPriv)
- return FALSE;
- pPriv->pCompData = pCompData;
- return TRUE;
- }
- /* ============================= Raw to JIF =================================== */
- /* This body of code supports converting "raw" (stripped) format JPEG to JIF.
- */
- /* Private data for ilRawToJIFExecute() */
- typedef struct {
- ilJPEGData *pCompData; /* ptr to IL JPEG data */
- long width; /* width of image */
- long height; /* total # lines in image */
- long stripHeight; /* # lines per strip */
- ilBool nStripsWritten; /* inited to 0 by Init() */
- long nLinesWritten; /* inited to 0 by Init() */
- long dstOffset; /* inited to 0 by Init() */
- } ilRawToJIFPrivRec, *ilRawToJIFPrivPtr;
- /* ----------------------- ilRawToJIFInit ------------------------------ */
- /* Init() function for converting JIF format pipe image to raw format.
- */
- static ilError ilRawToJIFInit (
- ilRawToJIFPrivPtr pPriv,
- ilImageInfo *pSrcImage,
- ilImageInfo *pDstImage
- )
- {
- pPriv->nStripsWritten = 0;
- pPriv->nLinesWritten = 0;
- pPriv->dstOffset = 0;
- return IL_OK;
- }
- /* ----------------------- ilRawToJIFExecute ------------------------------ */
- /* Execute() function for converting "raw" JPEG to JIF format.
- */
- static ilError ilRawToJIFExecute (
- ilExecuteData *pData,
- unsigned long dstLine,
- unsigned long *pNLines
- )
- {
- ilJPEGEncodeStream streamRec;
- ilRawToJIFPrivPtr pPriv;
- iljpgDataRec data;
- ilImageInfo *pImage;
- ilError error;
- long nBytes, startOffset;
- ilBool lastStrip;
- pPriv = (ilRawToJIFPrivPtr)pData->pPrivate;
- /* Setup stream to point to dst image buffer; set size, offset also.
- "dstOffset" is offset into dst buffer; it is incremented by the # of
- bytes written on each strip. When done, it is size of JIF image written.
- */
- pImage = pData->pDstImage;
- streamRec.pBuffer = pImage->plane[0].pPixels;
- streamRec.pDst = streamRec.pBuffer + pPriv->dstOffset;
- streamRec.pPastEndBuffer = streamRec.pBuffer + pImage->plane[0].bufferSize;
- startOffset = ILJPG_ENCODE_OFFSET(&streamRec); /* stream offset before any writes */
- pImage = pData->pSrcImage; /* point to src (raw) image */
- /* If first strip write out the JIF header */
- if (pPriv->nStripsWritten == 0) {
- /* Setup iljpg data block: general info and tables from IL */
- _ilJPEGDataIn (pImage->pDes, pPriv->width, pPriv->height, &data);
- _ilJPEGTablesIn (pPriv->pCompData, &data);
- /* Set restart interval: if a single strip, it is the restart interval
- in the raw data (already set from above). If not a single strip, then
- the raw data must not have a restart interval or an error - can't code
- both of them! Otherwise restart interval is determined by strip size.
- */
- if (pPriv->stripHeight != pPriv->height) { /* not single strip */
- long mcuWidth, mcuHeight;
- if (data.restartInterval)
- return IL_ERROR_COMPRESSED_DATA; /* have restartInterval; error */
- mcuWidth = 8 * data.maxHoriFactor;
- mcuHeight = 8 * data.maxVertFactor;
- data.restartInterval = /* # of mcus across * # down */
- ((data.width + mcuWidth - 1) / mcuWidth) *
- ((pPriv->stripHeight + mcuHeight - 1) / mcuHeight);
- }
- /* Write JIF to output stream, from IL's comp data */
- if (error = iljpgEncodeJIF (&streamRec, &data, (iljpgJIFOffsetsPtr)NULL))
- return error;
- }
- /* Write data from this strip to output buffer, reallocating if necessary.
- Allocate 2 extra bytes for EOI or RSTn marker.
- */
- nBytes = pData->compressed.nBytesToRead;
- if ((streamRec.pDst + nBytes + 2) >= streamRec.pPastEndBuffer) {
- if (error = _ilReallocJPEGEncode (&streamRec, nBytes + 2))
- return error;
- }
- bcopy ((char *)(pImage->plane[0].pPixels + pData->compressed.srcOffset),
- (char *)streamRec.pDst, nBytes);
- streamRec.pDst += nBytes; /* bump past data just copied */
- /* If last strip, write 2 byte EOI marker else write 2 byte restart marker. */
- pPriv->nLinesWritten += *pNLines;
- lastStrip = (pPriv->nLinesWritten >= pPriv->height);
- if (lastStrip) {
- *streamRec.pDst++ = ILJPGM_FIRST_BYTE; /* last strip; write EOI marker */
- *streamRec.pDst++ = ILJPGM_EOI;
- }
- else {
- /* Not last strip; write RST marker, with modulo 8 strip count */
- *streamRec.pDst++ = ILJPGM_FIRST_BYTE;
- *streamRec.pDst++ = ILJPGM_RST0 | (pPriv->nStripsWritten & 7);
- }
- pPriv->nStripsWritten += 1;
- /* Store stream data into dst image; bump dst offset by # bytes written */
- pImage = pData->pDstImage;
- pImage->plane[0].pPixels = streamRec.pBuffer;
- pImage->plane[0].bufferSize = streamRec.pPastEndBuffer - streamRec.pBuffer;
- pPriv->dstOffset += ILJPG_ENCODE_OFFSET(&streamRec) - startOffset;
- /* If last strip, pass # bytes written to next filter (= current dst offset;
- note that dst offset set to 0 on first strip), and return # lines =
- height of image, as JIF is one big strip. If not last strip, return
- # lines as zero and next filter will not be called.
- */
- if (lastStrip) {
- *pNLines = pPriv->height;
- *pData->compressed.pNBytesWritten = pPriv->dstOffset;
- }
- else *pNLines = 0;
- return IL_OK;
- }
- /* ----------------------- ilRawToJIF ------------------------------ */
- /* Called by _ilCompressJPEG() when the pipe image is "raw" JPEG format,
- to convert to JIF format.
- */
- static ilBool ilRawToJIF (
- ilPipe pipe,
- ilPipeInfo *pInfo,
- ilImageDes *pDes,
- ilImageFormat *pFormat
- )
- {
- ilRawToJIFPrivPtr pPriv;
- ilDstElementData dstData;
- dstData.producerObject = (ilObject)NULL;
- pDes->compInfo.JPEG.reserved &= ~IL_JPEGM_RAW; /* now writing JIF, not raw JPEG */
- dstData.pDes = pDes;
- dstData.pFormat = pFormat;
- dstData.width = pInfo->width;
- dstData.height = pInfo->height;
- dstData.stripHeight = pInfo->height; /* write one strip = whole image */
- dstData.constantStrip = TRUE;
- dstData.pPalette = (unsigned short *)NULL;
- dstData.pCompData = (ilPtr)NULL;
- /* Add the filter. "Hold dst" flag set because filter will write to
- output buffer, returning # lines = 0 until last strip written, after which
- whole output buffer will be passed to next filter, # lines = height.
- */
- pPriv = (ilRawToJIFPrivPtr)ilAddPipeElement (pipe, IL_FILTER,
- sizeof (ilRawToJIFPrivRec), IL_ADD_PIPE_HOLD_DST, (ilSrcElementData *)NULL,
- &dstData, ilRawToJIFInit, IL_NPF, IL_NPF, ilRawToJIFExecute, 0);
- if (!pPriv)
- return FALSE;
- pPriv->pCompData = (ilJPEGData *)pInfo->pCompData;
- pPriv->width = pInfo->width;
- pPriv->height = pInfo->height;
- pPriv->stripHeight = pInfo->stripHeight; /* input strip height */
- return TRUE;
- }
- /* ============================= Compress Raw =================================== */
- /* This body of code supports compressing to JPEG "raw" format.
- */
- /* Private data for ilCompressJPEGExecute() */
- typedef struct {
- ilJPEGData *pCompData; /* ptr to IL's view of JPEG data */
- iljpgDataRec jpgData; /* data for iljpg functions */
- iljpgPtr jpgPriv; /* pointer to iljpg private data */
- } ilCompressJPEGPrivRec, *ilCompressJPEGPrivPtr;
- /* -------------------- ilCompressJPEGInit -------------------------- */
- /* Init() function for compressing to "raw" JPEG.
- */
- static ilError ilCompressJPEGInit (
- ilCompressJPEGPrivPtr pPriv,
- ilImageInfo *pSrcImage,
- ilImageInfo *pDstImage
- )
- {
- ilError error;
- /* Init iljpg package for compression */
- if (error = iljpgEncodeInit (&pPriv->jpgData, &pPriv->jpgPriv))
- return error;
- return IL_OK;
- }
- /* -------------------- ilCompressJPEGCleanup -------------------------- */
- /* Cleanup() function for compressing to "raw" JPEG.
- */
- static ilError ilCompressJPEGCleanup (
- ilCompressJPEGPrivPtr pPriv,
- ilBool aborting
- )
- {
- ilError error;
- /* Call iljpg package cleanup function */
- return iljpgEncodeCleanup (pPriv->jpgPriv);
- }
- /* ----------------------- ilCompressJPEGDestroy ------------------------------ */
- /* Destroy() function for compressing to "raw" JPEG.
- */
- static ilError ilCompressJPEGDestroy (
- ilCompressJPEGPrivPtr pPriv
- )
- {
- int i;
- ilPtr pTable;
- ilJPEGData *pCompData;
- /* Free pCompData and any non-default Q tables */
- if (pCompData = pPriv->pCompData) {
- for (i = 0; i < 4; i++) {
- if ((pTable = pCompData->QTables[i])
- && (pTable != iljpgLuminanceQTable)
- && (pTable != iljpgChrominanceQTable))
- IL_FREE (pTable);
- }
- IL_FREE (pCompData);
- }
- return IL_OK;
- }
- /* ----------------------- ilCompressJPEGExecute ------------------------------ */
- /* Execute() function for compressing to "raw" JPEG.
- */
- static ilError ilCompressJPEGExecute (
- ilExecuteData *pData,
- unsigned long dstLine,
- unsigned long *pNLines
- )
- {
- ilCompressJPEGPrivPtr pPriv;
- ilJPEGEncodeStream streamRec;
- ilImageInfo *pImage;
- ilImagePlaneInfo *pSrcPlane;
- long nBytes, startOffset;
- ilError error;
- int i;
- iljpgPtr pSrcPixels[IL_MAX_SAMPLES];
- long nSrcBytesPerRow[IL_MAX_SAMPLES];
- pPriv = (ilCompressJPEGPrivPtr)pData->pPrivate;
- /* Setup stream to point to dst image buffer; set size, offset also */
- pImage = pData->pDstImage;
- streamRec.pBuffer = pImage->plane[0].pPixels;
- streamRec.pDst = streamRec.pBuffer + *pData->compressed.pDstOffset;
- streamRec.pPastEndBuffer = streamRec.pBuffer + pImage->plane[0].bufferSize;
- startOffset = ILJPG_ENCODE_OFFSET(&streamRec); /* stream offset before any writes */
- /* Encode one strip, writing output to dst buffer (pointed to by streamRec).
- Input is from src buffer, starting at srcLine, divided by subsample factor
- (which is "inverse" of JPEG factors; = max factor / component factor).
- */
- pSrcPlane = pData->pSrcImage->plane;
- for (i = 0; i < pPriv->jpgData.nComps; i++, pSrcPlane++) {
- pSrcPixels[i] = pSrcPlane->pPixels + (pData->srcLine *
- pPriv->jpgData.comp[i].vertFactor / pPriv->jpgData.maxVertFactor) *
- pSrcPlane->nBytesPerRow;
- nSrcBytesPerRow[i] = pSrcPlane->nBytesPerRow;
- }
- if (error = iljpgEncodeExecute (pPriv->jpgPriv, &streamRec, *pNLines,
- pSrcPixels, nSrcBytesPerRow))
- return error;
- /* Set stream data back into dst image structure. Inform next filter of
- the # bytes written = current stream offset - start offset.
- */
- pImage->plane[0].pPixels = streamRec.pBuffer;
- pImage->plane[0].bufferSize = streamRec.pPastEndBuffer - streamRec.pBuffer;
- *pData->compressed.pNBytesWritten = ILJPG_ENCODE_OFFSET(&streamRec) - startOffset;
- return IL_OK;
- }
- /* ------------------------- _ilScaleQTable -------------------------------- */
- /* Malloc a new 64 byte table, copy given src Q table scaling by given Q factor
- and return ptr to new table, or null if error.
- */
- static ilPtr _ilScaleQTable (
- ilPtr pSrc, /* ptr to 64 byte Q table to scale */
- int Q /* IL Q factor: != 0, or no scale needed */
- )
- {
- ilPtr pTable;
- ilPtr pDst;
- int i, value;
- if (!(pTable = (ilPtr)IL_MALLOC (64)))
- return (ilPtr)NULL;
- /* Scale src to dst (pTable) by: dst = src * Qfactor / 50.
- I don't know where this came from, but it is how the old code worked.
- The old code however only allowed a max Q of 255; larger values became 255.
- Here we will allow the maximum value of a short.
- */
- for (i = 0, pDst = pTable; i < 64; i++) {
- value = (*pSrc++ * Q) / 50;
- if (value > 255)
- value = 255;
- else if (value < 1)
- value = 1;
- *pDst++ = value;
- }
- return pTable;
- }
- /* ----------------------- _ilCompressJPEG ------------------------------ */
- /* Called by ilCompress() when desired compression is JPEG. The image
- may already be JPEG-compressed, but possibly in the wrong format (JIF/raw).
- This function handles conversions between those cases, or does
- nothing if image is already in correct format.
- On entry, the image must be either JPEG-compressed or uncompressed.
- */
- IL_PRIVATE ilBool _ilCompressJPEG (
- ilPipe pipe,
- ilPipeInfo *pInfo,
- ilImageDes *pDes,
- ilImageFormat *pFormat,
- ilSrcElementData *pSrcData,
- ilPtr pEncodeData
- )
- {
- ilCompressJPEGPrivPtr pPriv;
- ilJPEGData *pCompData;
- ilDstElementData dstData;
- ilJPEGEncodeControl *pEncode;
- int i, tableIndex, luminanceMask;
- ilPtr pTable;
- ilBool mustConvert;
- long stripHeight, maxVert;
- static ilJPEGEncodeControl ilDefaultJpegEncodeControl = {
- 0, /* short mustbezero; */
- 0 /* short Q; */
- };
- /* Check given encode data; default to JIF format, Q of 0 if null.
- Unused part of mustbezero must be zero or error.
- */
- if (!pEncodeData)
- pEncode = &ilDefaultJpegEncodeControl;
- else pEncode = (ilJPEGEncodeControl *)pEncodeData;
- if (pEncode->mustbezero & ~IL_JPEGM_RAW)
- return ilDeclarePipeInvalid (pipe, IL_ERROR_PAR_NOT_ZERO);
- /* If already JPEG-compressed cvt to requested format (JIF/raw) if necessary */
- if (pDes->compression == IL_JPEG) {
- if (pDes->compInfo.JPEG.reserved & IL_JPEGM_RAW) /* src is raw */
- if (pEncode->mustbezero & IL_JPEGM_RAW) { /* raw->raw */
- pipe->context->error = IL_OK;
- return TRUE;
- }
- else { /* raw->JIF */
- return ilRawToJIF (pipe, pInfo, pDes, pFormat);
- }
- else /* src is JIF */
- if (pEncode->mustbezero & IL_JPEGM_RAW) { /* JIF->raw */
- return ilJIFToRaw (pipe, pInfo, pDes, pFormat);
- }
- else { /* JIF->JIF */
- pipe->context->error = IL_OK;
- return TRUE;
- }
- }
- /* Image is not JPEG; must be uncompressed. Check for supported image type.
- Set maxVert to max vert subsampling; luminanceMask to sample #.
- */
- switch (pDes->type) {
- case IL_GRAY:
- maxVert = 1;
- luminanceMask = 1; /* gray is luminance */
- break;
- case IL_RGB:
- maxVert = 1; /* no subsampling of RGB */
- luminanceMask = ~0; /* use luminance tables for all components */
- break;
- case IL_YCBCR:
- maxVert = 1;
- if (pDes->typeInfo.YCbCr.sample[1].subsampleVert > maxVert)
- maxVert = pDes->typeInfo.YCbCr.sample[1].subsampleVert;
- if (pDes->typeInfo.YCbCr.sample[2].subsampleVert > maxVert)
- maxVert = pDes->typeInfo.YCbCr.sample[2].subsampleVert;
- luminanceMask = 1; /* Y is luminance */
- break;
- default:
- return ilDeclarePipeInvalid (pipe, IL_ERROR_IMAGE_TYPE);
- }
- /* Force all samples to be 8 bit, 256 levels / sample */
- for (i = 0, mustConvert = FALSE; i < pDes->nSamplesPerPixel; i++) {
- if (pDes->nLevelsPerSample[i] != 256) {
- pDes->nLevelsPerSample[i] = 256;
- mustConvert = TRUE;
- }
- if (pFormat->nBitsPerSample[i] != 8) {
- pFormat->nBitsPerSample[i] = 8;
- mustConvert = TRUE;
- }
- }
- if (mustConvert)
- if (!ilConvert (pipe, pDes, pFormat, 0, (ilPtr)NULL))
- return FALSE;
- /* Convert to planar format if more than 1 sample/pixel. */
- if ((pDes->nSamplesPerPixel > 1) && (pFormat->sampleOrder != IL_SAMPLE_PLANES)) {
- pFormat->sampleOrder = IL_SAMPLE_PLANES;
- if (!ilConvert (pipe, (ilImageDes *)NULL, pFormat, 0, (ilPtr)NULL))
- return FALSE;
- }
- /* Check pSrcData->stripHeight: make it a multiple of MCU. */
- maxVert *= 8; /* now height of an MCU */
- stripHeight = ((pSrcData->stripHeight + maxVert - 1) / maxVert) * maxVert;
- if (stripHeight <= 0)
- stripHeight = maxVert;
- if (stripHeight > pInfo->height)
- stripHeight = pInfo->height;
- pSrcData->stripHeight = stripHeight;
- /* Allocate an IL raw JPEG data block; point to it for pipe element */
- if (!(pCompData = (ilJPEGData *)IL_MALLOC_ZERO (sizeof (ilJPEGData))))
- return ilDeclarePipeInvalid (pipe, IL_ERROR_MALLOC);
- /* Add the pipe element */
- dstData.producerObject = (ilObject)NULL;
- pDes->compInfo.JPEG.reserved |= IL_JPEGM_RAW; /* now writing raw JPEG */
- pDes->compression = IL_JPEG;
- dstData.pDes = pDes;
- pFormat->sampleOrder = IL_SAMPLE_PIXELS; /* JPEG interleaved order */
- dstData.pFormat = pFormat;
- dstData.width = pInfo->width;
- dstData.height = pInfo->height;
- dstData.stripHeight = stripHeight;
- dstData.constantStrip = TRUE;
- dstData.pPalette = (unsigned short *)NULL;
- dstData.pCompData = (ilPtr)pCompData;
- pPriv = (ilCompressJPEGPrivPtr)ilAddPipeElement (pipe, IL_FILTER,
- sizeof (ilCompressJPEGPrivRec), 0, pSrcData, &dstData,
- ilCompressJPEGInit, ilCompressJPEGCleanup, ilCompressJPEGDestroy,
- ilCompressJPEGExecute, 0);
- if (!pPriv)
- return FALSE;
- /* Init tables to use: default luminance (index 0) or chrominance (index 1).
- If "Q" not zero, scale up Q tables; must destroy them in Destroy().
- */
- pPriv->pCompData = pCompData;
- pCompData->restartInterval = 0; /* no restart markers added */
- for (i = 0; i < pDes->nSamplesPerPixel; i++) {
- if ((1 << i) & luminanceMask) {
- pCompData->DCTables[0] = iljpgLuminanceDCTable;
- pCompData->ACTables[0] = iljpgLuminanceACTable;
- tableIndex = 0;
- pTable = iljpgLuminanceQTable;
- }
- else {
- pCompData->DCTables[1] = iljpgChrominanceDCTable;
- pCompData->ACTables[1] = iljpgChrominanceACTable;
- tableIndex = 1;
- pTable = iljpgChrominanceQTable;
- }
- if (!pCompData->QTables[tableIndex]) { /* no Q table here yet; make one */
- if (pEncode->Q) /* Q != 0; scale copy of Q table */
- if (!(pTable = _ilScaleQTable (pTable, pEncode->Q)))
- return ilDeclarePipeInvalid (pipe, IL_ERROR_MALLOC);
- pCompData->QTables[tableIndex] = pTable;
- }
- pCompData->sample[i].QTableIndex = pCompData->sample[i].DCTableIndex =
- pCompData->sample[i].ACTableIndex = tableIndex;
- }
- /* Init iljpg package data in private, based on IL view of JPEG comp data */
- _ilJPEGDataIn (pDes, pInfo->width, pInfo->height, &pPriv->jpgData);
- _ilJPEGTablesIn (pCompData, &pPriv->jpgData);
- /* Data is now compressed to "raw" format. Convert to JIF if requested */
- if (!(pEncode->mustbezero & IL_JPEGM_RAW)) {
- ilGetPipeInfo (pipe, FALSE, pInfo, pDes, pFormat); /* update pipe info */
- return ilRawToJIF (pipe, pInfo, pDes, pFormat);
- }
- return TRUE;
- }
|