123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- /*
- * 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: iljpgdecode.c /main/3 1995/10/23 15:54:14 rswiston $ */
- /**---------------------------------------------------------------------
- ***
- *** (c)Copyright 1992 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 "iljpgdecodeint.h"
- /* -------------------- iljpgDecodeInit -------------------------- */
- /* Init for JPEG decoding and return ptr to private block.
- */
- ILJPG_PUBLIC_EXTERN
- iljpgError iljpgDecodeInit (
- iljpgDataPtr pData,
- iljpgPtr *pPrivate /* RETURNED */
- )
- {
- iljpgDecodePrivPtr pPriv;
- iljpgCompPtr pComp;
- int comp;
- iljpgCompDataPtr pCompData;
- iljpgError error;
- /* Validate *pData: valid hori/vertFactor, tables present, etc. */
- if (!_iljpgValidPars (pData))
- return ILJPG_ERROR_DECODE_PARS;
- /* Allocate and return private block */
- pPriv = (iljpgDecodePrivPtr)ILJPG_MALLOC_ZERO (sizeof (iljpgDecodePrivRec));
- if (!pPriv)
- return ILJPG_ERROR_DECODE_MALLOC;
- pPriv->pData = pData;
- *pPrivate = (iljpgPtr)pPriv;
- pPriv->mcuRestartCount = 0;
- /* Init Huffman and DCT decoders */
- if ((error = _iljpgDehuffInit (pPriv))
- || (error = _iljpgDeDCTInit (pPriv))) {
- ILJPG_FREE (pPriv);
- return error;
- }
- /* Setup static part of per-comp data; copy from other places */
- for (comp = 0, pCompData = pData->comp, pComp = pPriv->compData;
- comp < pData->nComps; comp++, pCompData++, pComp++) {
- pComp->pRevScale = pPriv->DCTRevScaleTables[pCompData->QTableIndex];
- pComp->horiFactor = pCompData->horiFactor;
- pComp->vertFactor = pCompData->vertFactor;
- pComp->width = pData->width * pCompData->horiFactor / pData->maxHoriFactor;
- pComp->mcuXInc = 8 * pCompData->horiFactor;
- pComp->mcuYInc = 8 * pCompData->vertFactor;
- }
- return 0;
- }
- /* -------------------- iljpgDecodeCleanup -------------------------- */
- /* Cleanup after JPEG decoding.
- */
- ILJPG_PUBLIC_EXTERN
- iljpgError iljpgDecodeCleanup (
- iljpgPtr pPrivate
- )
- {
- iljpgError error1, error2;
- /* Call the Huffman and DCT cleanup functions.
- */
- error1 = _iljpgDehuffCleanup ((iljpgDecodePrivPtr)pPrivate);
- error2 = _iljpgDeDCTCleanup ((iljpgDecodePrivPtr)pPrivate);
- /* Free the given private data. Note that pPrivate->pData is not
- freed; that is done when the caller calls iljpgFreeData().
- */
- ILJPG_FREE (pPrivate);
- /* Return first error code or success if neither an error */
- if (error1)
- return error1;
- if (error2)
- return error2;
- return 0;
- }
- /* -------------------- iljpgDecodeExecute -------------------------- */
- /* Decode (decompress) the JPEG data read using "stream", into the per-plane
- buffers pointed to by "pPixels": one ptr per component (# of components =
- "nComps" in the iljpgData passed to iljpgDecodeInit()).
- "nBytesPerRow" is length of each row in the corresponding buffers
- in "pPixels". "pPrivate" is the ptr returned by iljpgDecodeInit().
- "nDstLines" is the # of lines to write; decoding stops when nDstLines
- scan lines have been decoded. "nDstLines" should be a multiple of the MCU
- height, except at the last strip where it should be the # of lines remaining
- to be decoded; this function will clip.
- "doReset" is true if an implicit reset should be done at the beginning
- of this function, i.e. if an implicit restart is assumed before each strip.
- */
- ILJPG_PUBLIC_EXTERN
- iljpgError iljpgDecodeExecute (
- iljpgPtr pPrivate,
- ILJPG_DECODE_STREAM stream,
- int doReset,
- long nDstLines,
- iljpgPtr pDstPixels[],
- long nDstBytesPerRow[]
- )
- {
- iljpgDecodePrivPtr pPriv;
- iljpgDataPtr pData;
- int comp, v, h, mcuWidth, mcuHeight;
- unsigned int blockType;
- iljpgPtr pPixels;
- iljpgError error;
- long nBytesPerRow, mcuMaxX, mcuMaxY, bX, bY;
- int outHuff[64];
- iljpgByte outDCT[64];
- int restartInterval;
- iljpgCompPtr pComp;
- int nBytesInit;
- int nLines, dc;
- iljpgPtr pDstLine;
- pPriv = (iljpgDecodePrivPtr)pPrivate;
- pData = pPriv->pData;
- /* Decode "interleaved" JPEG data, where all components are grouped together
- in Minimum Coded Unit (MCU) size, = 8 * max hori(width) or vert(height)
- factor. The "factors" are the inverse of IL subsample factors. For
- example, if component 0 is not subsampled and 1 and 2 are subsampled by 2,
- then hori/vertFactor for comp 0 is 2, for comps 1..2 is 1, and max hori/vert
- factor is 2 (there are 4x as many comp 0 pixels as comps 1 or 2).
- So: loop over y, and over x within y, and decode one MCU (all components),
- advancing x by mcuWidth and y by mcuHeight.
- */
- mcuWidth = 8 * pData->maxHoriFactor;
- mcuHeight = 8 * pData->maxVertFactor;
- restartInterval = pData->restartInterval;
- /* Reset temp vars in comp data in private; "height" is size of one strip */
- for (comp = 0, pComp = pPriv->compData; comp < pData->nComps; comp++, pComp++) {
- pComp->height = nDstLines * pComp->vertFactor / pData->maxVertFactor;
- pComp->x = 0;
- pComp->y = 0;
- }
- /* Reset Huffman decoding: beginning of a strip/restart interval */
- if (doReset) {
- if ((error = _iljpgDehuffReset (pPriv)))
- return error;
- }
- /* Loop over y, and over x within y, and decode one MCU (all components),
- advancing x by mcuWidth and y by mcuHeight.
- */
- for (mcuMaxY = 0; mcuMaxY < nDstLines; mcuMaxY += mcuHeight) {
- for (mcuMaxX = 0; mcuMaxX < pData->width; mcuMaxX += mcuWidth) {
- /* Decode one MCU, all components, to (mcuX, mcuY). For each component
- there are horiFactor * vertFactor 8x8 blocks that go across then down.
- If a restart interval and mcu count >, do a reset/restart.
- */
- if (restartInterval && (pPriv->mcuRestartCount >= restartInterval)) {
- if ((error = _iljpgDehuffReset (pPriv)))
- return error;
- pPriv->mcuRestartCount = 0;
- }
- for (comp = 0, pComp = pPriv->compData; comp < pData->nComps; comp++, pComp++) {
- nBytesPerRow = nDstBytesPerRow[comp];
- pPixels = pDstPixels[comp];
- for (v = 0, bY = pComp->y; v < pComp->vertFactor; v++, bY += 8) {
- for (h = 0, bX = pComp->x; h < pComp->horiFactor; h++, bX += 8) {
- if ((error = _iljpgDehuffExecute (pPriv, stream, comp, outHuff,
- &blockType)))
- return error;
- /* Add previous DC to this one, save away for next */
- dc = outHuff[0] + pComp->lastDC;
- pComp->lastDC = dc;
- /* If an 8x8 block fits in output buffer, decode the DCT
- (based on return from Huffman decode) directly into
- the output buffer; otherwise decode into "outDCT" and
- copy top-left part of it into buffer below.
- */
- pDstLine = pPixels + (bY * nBytesPerRow) + bX;
- nLines = pComp->height - bY;
- nBytesInit = pComp->width - bX;
- if ((nLines >= 8) && (nBytesInit >= 8)) {
- switch (blockType) {
- case HUFF_DC_ONLY:
- dc = (int)(dc * *pComp->pRevScale + 128.0);
- if (dc < 0) dc = 0; else if (dc > 255) dc = 255;
- nLines = 7;
- do {
- pDstLine[0] = dc;
- pDstLine[1] = dc;
- pDstLine[2] = dc;
- pDstLine[3] = dc;
- pDstLine[4] = dc;
- pDstLine[5] = dc;
- pDstLine[6] = dc;
- pDstLine[7] = dc;
- pDstLine += nBytesPerRow;
- } while (--nLines >= 0);
- break;
- case HUFF_FOURX4:
- outHuff[0] = dc;
- _iljpgDeDCT4x4 (outHuff, nBytesPerRow, pDstLine,
- pComp->pRevScale);
- break;
- case HUFF_FULL:
- outHuff[0] = dc;
- _iljpgDeDCTFull (outHuff, nBytesPerRow, pDstLine,
- pComp->pRevScale);
- break;
- }
- } /* END whole 8x8 block */
- else { /* no space for 8x8; clip */
- outHuff[0] = dc;
- switch (blockType) {
- case HUFF_DC_ONLY:
- _iljpgDeDCTDCOnly (outHuff, 8, outDCT, pComp->pRevScale);
- break;
- case HUFF_FOURX4:
- _iljpgDeDCT4x4 (outHuff, 8, outDCT, pComp->pRevScale);
- break;
- case HUFF_FULL:
- _iljpgDeDCTFull (outHuff, 8, outDCT, pComp->pRevScale);
- break;
- }
- /* Clip and output 8x8 block to position (bX, bY) */
- { int nBytesM1;
- iljpgPtr pSrc, pSrcLine, pDst;
- if (nBytesInit > 8)
- nBytesInit = 8;
- if (nLines > 8)
- nLines = 8;
- if ((nLines > 0) && (nBytesInit > 0)) {
- nLines--; /* make # lines/bytes - 1 */
- nBytesInit--;
- pSrcLine = outDCT;
- do {
- nBytesM1 = nBytesInit;
- pSrc = pSrcLine;
- pSrcLine += 8;
- pDst = pDstLine;
- pDstLine += nBytesPerRow;
- do {
- *pDst++ = *pSrc++;
- } while (--nBytesM1 >= 0);
- } while (--nLines >= 0);
- }
- }
- } /* END clip */
- } /* END hori, one 8x8 block */
- } /* END vert */
- pComp->x += pComp->mcuXInc; /* move component one MCU to right */
- } /* END one component */
- pPriv->mcuRestartCount++; /* inc count of mcus since restart */
- } /* END one hori MCU */
- /* Move each component one MCU down, reset to left edge */
- for (comp = 0, pComp = pPriv->compData; comp < pData->nComps; comp++, pComp++) {
- pComp->y += pComp->mcuYInc;
- pComp->x = 0;
- }
- } /* END one vert MCU */
- return 0;
- }
|