286 lines
10 KiB
C
286 lines
10 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: ilutiljpeg.c /main/3 1995/10/23 16:02:31 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).
|
|
***
|
|
***-------------------------------------------------------------------*/
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "ilint.h"
|
|
#include "ilerrors.h"
|
|
#include "iljpgdecode.h"
|
|
#include "iljpgencode.h"
|
|
#include "ilutiljpeg.h"
|
|
|
|
|
|
/* -------------------- _ilJPEGDataIn -------------------------- */
|
|
/* Copy general data (but *not* table info) from IL data into
|
|
IL JPG package format.
|
|
*/
|
|
IL_PRIVATE void _ilJPEGDataIn (
|
|
const ilImageDes *pDes,
|
|
long width,
|
|
long height,
|
|
iljpgDataPtr pDst
|
|
)
|
|
{
|
|
int maxSubsample;
|
|
|
|
pDst->width = width;
|
|
pDst->height = height;
|
|
pDst->nComps = pDes->nSamplesPerPixel;
|
|
|
|
/* Set IL subsample info into iljpg Hori/VertFactor info, which is essentially
|
|
the inverse of IL subsample data: for each sample/comp, hori/vert:
|
|
iljpgFactor[comp] = maxILSubsample/ILSubsample[comp]
|
|
NOTE: currently only YCbCr data in IL is subsampled!
|
|
*/
|
|
if (pDes->type == IL_YCBCR) {
|
|
const ilYCbCrSampleInfo *pSample = pDes->typeInfo.YCbCr.sample;
|
|
|
|
maxSubsample = pSample[0].subsampleHoriz;
|
|
if (pSample[1].subsampleHoriz > maxSubsample)
|
|
maxSubsample = pSample[1].subsampleHoriz;
|
|
if (pSample[2].subsampleHoriz > maxSubsample)
|
|
maxSubsample = pSample[2].subsampleHoriz;
|
|
pDst->maxHoriFactor = maxSubsample;
|
|
pDst->comp[0].horiFactor = maxSubsample / pSample[0].subsampleHoriz;
|
|
pDst->comp[1].horiFactor = maxSubsample / pSample[1].subsampleHoriz;
|
|
pDst->comp[2].horiFactor = maxSubsample / pSample[2].subsampleHoriz;
|
|
|
|
maxSubsample = pSample[0].subsampleVert;
|
|
if (pSample[1].subsampleVert > maxSubsample)
|
|
maxSubsample = pSample[1].subsampleVert;
|
|
if (pSample[2].subsampleVert > maxSubsample)
|
|
maxSubsample = pSample[2].subsampleVert;
|
|
pDst->maxVertFactor = maxSubsample;
|
|
pDst->comp[0].vertFactor = maxSubsample / pSample[0].subsampleVert;
|
|
pDst->comp[1].vertFactor = maxSubsample / pSample[1].subsampleVert;
|
|
pDst->comp[2].vertFactor = maxSubsample / pSample[2].subsampleVert;
|
|
}
|
|
else {
|
|
pDst->maxHoriFactor = 1;
|
|
pDst->maxVertFactor = 1;
|
|
pDst->comp[0].horiFactor = 1;
|
|
pDst->comp[0].vertFactor = 1;
|
|
pDst->comp[1].horiFactor = 1;
|
|
pDst->comp[1].vertFactor = 1;
|
|
pDst->comp[2].horiFactor = 1;
|
|
pDst->comp[2].vertFactor = 1;
|
|
pDst->comp[3].horiFactor = 1;
|
|
pDst->comp[3].vertFactor = 1;
|
|
}
|
|
}
|
|
|
|
/* -------------------- _ilJPEGTablesIn -------------------------- */
|
|
/* Copy table info from IL format into IL JPG package format.
|
|
Note: the restartInterval is also copied.
|
|
*/
|
|
IL_PRIVATE void _ilJPEGTablesIn (
|
|
ilJPEGData *pSrc,
|
|
iljpgDataPtr pDst
|
|
)
|
|
{
|
|
|
|
/* Copy the restartInterval; just convenient to do so in this function */
|
|
pDst->restartInterval = pSrc->restartInterval;
|
|
|
|
/* Tables are independent of samples; copy all 4 */
|
|
pDst->QTables[0] = pSrc->QTables[0];
|
|
pDst->QTables[1] = pSrc->QTables[1];
|
|
pDst->QTables[2] = pSrc->QTables[2];
|
|
pDst->QTables[3] = pSrc->QTables[3];
|
|
|
|
pDst->DCTables[0] = pSrc->DCTables[0];
|
|
pDst->DCTables[1] = pSrc->DCTables[1];
|
|
pDst->DCTables[2] = pSrc->DCTables[2];
|
|
pDst->DCTables[3] = pSrc->DCTables[3];
|
|
|
|
pDst->ACTables[0] = pSrc->ACTables[0];
|
|
pDst->ACTables[1] = pSrc->ACTables[1];
|
|
pDst->ACTables[2] = pSrc->ACTables[2];
|
|
pDst->ACTables[3] = pSrc->ACTables[3];
|
|
|
|
/* Copy 4 samples / components of indices into above tables */
|
|
pDst->comp[0].QTableIndex = pSrc->sample[0].QTableIndex;
|
|
pDst->comp[0].DCTableIndex = pSrc->sample[0].DCTableIndex;
|
|
pDst->comp[0].ACTableIndex = pSrc->sample[0].ACTableIndex;
|
|
|
|
pDst->comp[1].QTableIndex = pSrc->sample[1].QTableIndex;
|
|
pDst->comp[1].DCTableIndex = pSrc->sample[1].DCTableIndex;
|
|
pDst->comp[1].ACTableIndex = pSrc->sample[1].ACTableIndex;
|
|
|
|
pDst->comp[2].QTableIndex = pSrc->sample[2].QTableIndex;
|
|
pDst->comp[2].DCTableIndex = pSrc->sample[2].DCTableIndex;
|
|
pDst->comp[2].ACTableIndex = pSrc->sample[2].ACTableIndex;
|
|
|
|
pDst->comp[3].QTableIndex = pSrc->sample[3].QTableIndex;
|
|
pDst->comp[3].DCTableIndex = pSrc->sample[3].DCTableIndex;
|
|
pDst->comp[3].ACTableIndex = pSrc->sample[3].ACTableIndex;
|
|
}
|
|
|
|
|
|
/* -------------------- _ilJPEGFreeTables -------------------------- */
|
|
/* Free the tables in the given IL JPEG data block, which is not freed.
|
|
*/
|
|
IL_PRIVATE void _ilJPEGFreeTables (
|
|
ilJPEGData *pData
|
|
)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
if (pData->QTables[i]) {
|
|
IL_FREE (pData->QTables[i]);
|
|
pData->QTables[i] = (ilPtr)NULL;
|
|
}
|
|
if (pData->DCTables[i]) {
|
|
IL_FREE (pData->DCTables[i]);
|
|
pData->DCTables[i] = (ilPtr)NULL;
|
|
}
|
|
if (pData->ACTables[i]) {
|
|
IL_FREE (pData->ACTables[i]);
|
|
pData->ACTables[i] = (ilPtr)NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* -------------------- _ilJPEGCopyHuffmanTable -------------------------- */
|
|
/* Copy the given JPEG Huffman table into a malloc'd space and return a ptr
|
|
to it or null if malloc failed.
|
|
*/
|
|
static ilPtr _ilJPEGCopyHuffmanTable (
|
|
ilPtr pSrc
|
|
)
|
|
{
|
|
int i, nBytes;
|
|
ilPtr pDst;
|
|
|
|
/* Huffman tables are: 16 bytes of # occurrences each # bits, followed by
|
|
bytes for each of those # occurrences. Size of table = 16 + sum(0..15).
|
|
*/
|
|
for (i = 0, nBytes = 16; i < 16; i++)
|
|
nBytes += pSrc[i];
|
|
if (!(pDst = (ilPtr)IL_MALLOC (nBytes)))
|
|
return (ilPtr)NULL;
|
|
bcopy ((char *)pSrc, (char *)pDst, nBytes);
|
|
return pDst;
|
|
}
|
|
|
|
|
|
/* -------------------- _ilJPEGCopyData -------------------------- */
|
|
/* Copy data from pSrc to pDst, mallocing and copying contents of tables.
|
|
If an error, free all malloc'd tables in dest, null them and return false.
|
|
*/
|
|
IL_PRIVATE ilBool _ilJPEGCopyData (
|
|
ilJPEGData *pSrc,
|
|
ilJPEGData *pDst
|
|
)
|
|
{
|
|
int i;
|
|
|
|
/* Zero table ptrs in *pDst in case of error; copy index info */
|
|
bzero ((char *)pDst, sizeof (ilJPEGData));
|
|
for (i = 0; i < IL_MAX_SAMPLES; i++)
|
|
pDst->sample[i] = pSrc->sample[i];
|
|
|
|
/* For each non-null table in *pSrc, malloc space, copy contents, set pDst */
|
|
for (i = 0; i < 4; i++) {
|
|
if (pSrc->QTables[i]) {
|
|
if (!(pDst->QTables[i] = (ilPtr)IL_MALLOC (64)))
|
|
goto cdMallocError;
|
|
bcopy ((char *)pSrc->QTables[i], (char *)pDst->QTables[i], 64);
|
|
}
|
|
if (pSrc->DCTables[i])
|
|
if (!(pDst->DCTables[i] = _ilJPEGCopyHuffmanTable (pSrc->DCTables[i])))
|
|
goto cdMallocError;
|
|
if (pSrc->ACTables[i])
|
|
if (!(pDst->ACTables[i] = _ilJPEGCopyHuffmanTable (pSrc->ACTables[i])))
|
|
goto cdMallocError;
|
|
}
|
|
|
|
/* Copy restart interval */
|
|
pDst->restartInterval = pSrc->restartInterval;
|
|
|
|
return TRUE;
|
|
|
|
/* Goto point on malloc error: free all tables in pDst, return false */
|
|
cdMallocError:
|
|
_ilJPEGFreeTables (pDst);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/* -------------------- _ilReallocJPEGEncode -------------------------- */
|
|
/* Called by ILJPG_ENCODE_PUT_BYTE() macro to reallocate the buffer
|
|
defined by "pStream" so that there is space for *exactly* "nBytes" bytes
|
|
to be written. Zero (0) is returned if success else an error code.
|
|
*/
|
|
IL_PRIVATE iljpgError _ilReallocJPEGEncode (
|
|
ilJPEGEncodeStreamPtr pStream,
|
|
long nBytes
|
|
)
|
|
{
|
|
long offset;
|
|
|
|
/* Allocate space so exactly "nBytes" more bytes will fit in output buffer.
|
|
There are "offset" bytes in the buffer now so allocate offset + nBytes.
|
|
*/
|
|
if (pStream->pBuffer) {
|
|
offset = pStream->pDst - pStream->pBuffer;
|
|
pStream->pBuffer = (ilPtr)IL_REALLOC (pStream->pBuffer, offset + nBytes);
|
|
}
|
|
else {
|
|
offset = 0; /* no buffer yet; allocate one */
|
|
pStream->pBuffer = (ilPtr)IL_MALLOC (offset + nBytes);
|
|
}
|
|
if (!pStream->pBuffer) {
|
|
pStream->pDst = pStream->pPastEndBuffer = (ilPtr)NULL;
|
|
return ILJPG_ERROR_ENCODE_MALLOC;
|
|
}
|
|
|
|
/* Successful realloc: set end of buffer to pBuffer + new size; set pDst
|
|
to pBuffer + offset and return success.
|
|
*/
|
|
pStream->pPastEndBuffer = pStream->pBuffer + offset + nBytes;
|
|
pStream->pDst = pStream->pBuffer + offset;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|