cdesktopenv/cde/lib/DtHelp/il/ilcompressjpeg.c

700 lines
27 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 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;
}