733 lines
29 KiB
C
733 lines
29 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
|
|
*/
|
|
/* $TOG: iljpgdehuff.c /main/5 1999/10/14 13:19:16 mgreess $ */
|
|
/**---------------------------------------------------------------------
|
|
***
|
|
*** (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"
|
|
|
|
/*
|
|
utilities for fast table-based huffman decoder
|
|
|
|
NOTES
|
|
Author: G. Seroussi, HPL, PaloAlto. May 21, 1992
|
|
Modifications: V. Bhaskaran, HPL, PaloAlto. May 29, 1992.
|
|
email: bhaskara@hplvab.hpl.hp.com
|
|
*/
|
|
|
|
typedef struct tree_node {
|
|
int c;
|
|
struct tree_node *left;
|
|
struct tree_node *right;
|
|
} tree_node;
|
|
|
|
typedef int LOOKUP;
|
|
|
|
struct table_set {
|
|
LOOKUP *lookup_symb;
|
|
LOOKUP *lookup_len;
|
|
tree_node *tree_nodes;
|
|
};
|
|
|
|
typedef unsigned int BITBUF;
|
|
|
|
#define LOOKUP_BITS 9
|
|
#define FOUND_EOI 0x80
|
|
|
|
#define ABSIZE 256 /* max size of alphabet for Huffman encoding */
|
|
#define NOLEN 0
|
|
#define BLOCK_COEFFS 64 /* number of coefficients per block */
|
|
#define NOLEAF (BITBUF)(-1)
|
|
#define BITBUFSIZE (8*sizeof(BITBUF))
|
|
#define SHIFTBUF ( BITBUFSIZE - 8 )
|
|
#define BUFMSB ( ((BITBUF) 1) << ( BITBUFSIZE - 1 ) )
|
|
|
|
/* Data private to this file. Pointed to by iljpgDecodePrivRec.pHuffPriv */
|
|
typedef struct {
|
|
unsigned int bitbuf;
|
|
int bitsleft;
|
|
int resetDone;
|
|
struct table_set table_set_dc[4];
|
|
struct table_set table_set_ac[4];
|
|
} iljpgDehuffRec, *iljpgDehuffPtr;
|
|
|
|
|
|
/* Characteristc vector of the upper 4x4 block in zig-zag order */
|
|
static int fourx4_table[] =
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 0, 1, 1, 1, 0, 0,
|
|
0, 1, 1, 0, 0, 0, 0, 0,
|
|
1, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0
|
|
};
|
|
|
|
|
|
/* Build a lookup table and a partial binary tree for the Huffman dictionary.
|
|
Return absize of table; = 0 if tables are invalid.
|
|
*/
|
|
|
|
/* The lookup tables are used by the Huffman decoding engine as follows:
|
|
a fixed number N of bits are read from the encoded stream (N is
|
|
given by the "lookup_bits" parameter). Let P denote the binary
|
|
number formed by the N bits read.
|
|
P is used as an index into two lookup tables: lookup_symb[]
|
|
and lookup_len[]. If P uniquely identifies a Huffman code (i.e. if its
|
|
N-bit pattern contains a Huffman code as a prefix), then the encoded
|
|
symbol is given by lookup_symb[P], and the length of the corresponding
|
|
Huffman code is given by lookup_len[P]. The latter is used to determine
|
|
how many bits from the input stream were "used".
|
|
If P does not uniquely identify a Huffman code (i.e. it is a prefix of
|
|
a Huffman code), then lookup_len[P] = NOLEN (currently set to 0),
|
|
and lookup_symb[P] is an index into an array of tree nodes, giving the
|
|
Huffman subtree determined by the prefix P. The rest of the Huffman
|
|
code is obtained by traversing this subtree according to the input bits
|
|
following P in the encoded stream.
|
|
|
|
Notice that a given Huffman code may have many entries in the lookup
|
|
tables. For example, if N=9 and 01 is a Huffman code,
|
|
then all the entries with indices 01XXXXXXX will contain the same
|
|
symbol (the one represented by the code 01) and length.
|
|
|
|
*/
|
|
|
|
static int build_intermediate_tables (
|
|
iljpgPtr bits,
|
|
iljpgPtr vals,
|
|
int max_absize,
|
|
int *hufvals, /* must be of length max_absize+1; all zeros */
|
|
int *hufcodes, /* ditto */
|
|
int *huflen /* ditto */
|
|
)
|
|
{
|
|
long int i, j, k, code, si;
|
|
int absize;
|
|
int length, sumLengths;
|
|
|
|
/* generate code lengths: return 0 (error) if sum > 256 */
|
|
for (i = 0, k = 0, sumLengths = 0; i < 16; i++) {
|
|
length = bits[i];
|
|
if ((sumLengths += length) > max_absize)
|
|
return 0; /* table too long; return error */
|
|
for (j = 0; j < length; j++)
|
|
huflen[k++] = i+1;
|
|
}
|
|
|
|
/* generate values until huflen[i] == 0 - at least one is, because array
|
|
is "max_absize+1" entries long and zeroed, and above set at most max_absize.
|
|
*/
|
|
for ( i=0; huflen[i]; i++ )
|
|
hufvals[i] = vals[i];
|
|
|
|
absize = i; /* actual number of Huffman-encoded symbols */
|
|
|
|
/* now generate codes using the JPEG document procedure */
|
|
k=0;
|
|
code = 0;
|
|
si = huflen[0];
|
|
|
|
while (1) {
|
|
do {
|
|
hufcodes[k] = code;
|
|
code ++;
|
|
k ++;
|
|
|
|
}
|
|
while ( huflen[k] == si );
|
|
|
|
if ( huflen[k] == 0 )
|
|
break; /* done */
|
|
|
|
do {
|
|
code <<= 1;
|
|
si ++;
|
|
}
|
|
while ( huflen[k] != si );
|
|
}
|
|
|
|
return absize;
|
|
}
|
|
|
|
|
|
static iljpgError build_huffman_tables (
|
|
iljpgPtr bits, /* "Bits" table as specified in the JPEG standard */
|
|
iljpgPtr vals, /* "Vals" table as specified in the JPEG standard */
|
|
int lookup_bits, /* # of Huffman bits that are looked up in the tables */
|
|
struct table_set *table_setp /* pointer to a struct of pointers to lookup tables */
|
|
)
|
|
{
|
|
int next_node = 0, /* index to next available tree node */
|
|
c, len, s, i, j, n;
|
|
long numnodes, /* max number nodes in Huffman tree */
|
|
lookup_index,
|
|
lookup_size,
|
|
code, mask;
|
|
tree_node *tree_nodes, /* pointer to pool of tree nodes */
|
|
*nodep, *leafp = NULL, **followp; /* misc aux. tree pointers */
|
|
LOOKUP *lookup_symb, *lookup_len; /* pointers to lookup tables */
|
|
int absize; /* actual number of Huffman-encoded symbols */
|
|
int *hufvals, *hufcodes, *huflen; /* intermediate tables */
|
|
iljpgError error;
|
|
|
|
|
|
/* Init all ptrs to allocated data to null. If any allocation fails
|
|
deallocate all and return malloc error.
|
|
*/
|
|
hufvals = hufcodes = huflen = (int *)NULL;
|
|
lookup_symb = lookup_len = (LOOKUP *)NULL;
|
|
tree_nodes = (tree_node *)NULL;
|
|
|
|
error = ILJPG_ERROR_DECODE_MALLOC; /* assumed malloc error for now */
|
|
if (!(hufvals = (int *)ILJPG_MALLOC_ZERO ((ABSIZE+1) * sizeof(int))))
|
|
goto BuildTablesError;
|
|
if (!(hufcodes = (int *)ILJPG_MALLOC_ZERO ((ABSIZE+1) * sizeof(int))))
|
|
goto BuildTablesError;
|
|
if (!(huflen = (int *)ILJPG_MALLOC_ZERO ((ABSIZE+1) * sizeof(int))))
|
|
goto BuildTablesError;
|
|
|
|
absize = build_intermediate_tables(bits, vals, ABSIZE, hufvals,
|
|
hufcodes, huflen);
|
|
if (absize <= 0) {
|
|
error = ILJPG_ERROR_DECODE_DCAC_TABLE;
|
|
goto BuildTablesError;
|
|
}
|
|
|
|
lookup_size = ( 1L << lookup_bits );
|
|
|
|
/* allocate lookup tables */
|
|
if (!(lookup_symb = (LOOKUP *)ILJPG_MALLOC_ZERO (lookup_size * sizeof(LOOKUP))))
|
|
goto BuildTablesError;
|
|
if (!(lookup_len = (LOOKUP *)ILJPG_MALLOC_ZERO (lookup_size * sizeof(LOOKUP))))
|
|
goto BuildTablesError;
|
|
|
|
/* allocate tree nodes */
|
|
numnodes = 2*absize + 1; /* the max number of leaves is absize+1, since
|
|
a leave is created for code 111...111 even
|
|
though JPEG doesn't use it */
|
|
|
|
if (!(tree_nodes = (tree_node *)ILJPG_MALLOC_ZERO (numnodes * sizeof(tree_node))))
|
|
goto BuildTablesError;
|
|
|
|
/* initialize lookup tables */
|
|
for ( i=0; i<lookup_size; i++ ) {
|
|
lookup_symb[i] = -1;
|
|
lookup_len[i] = NOLEN;
|
|
}
|
|
|
|
/* now go thru the Huffman table, build a lookup table,
|
|
and also parts of the Huffman tree for codes that
|
|
are not fully in the lookup table */
|
|
for ( s = 0; s < absize; s++ ) {
|
|
|
|
c = hufvals[s];
|
|
code = hufcodes[s];
|
|
len = huflen[s];
|
|
|
|
if ( len == NOLEN ) /* no entry for this character */
|
|
continue;
|
|
|
|
if ( len <= lookup_bits ) { /* enter in lookup table */
|
|
lookup_index = code << ( lookup_bits - len );
|
|
/* number of entries for this code */
|
|
n = 1 << ( lookup_bits - len );
|
|
for ( j=0; j<n; j++ ) {
|
|
lookup_symb[ lookup_index + j ] = c;
|
|
lookup_len[ lookup_index + j ] = len;
|
|
}
|
|
|
|
}
|
|
else {
|
|
/* build the part of the Huffman tree for the
|
|
end of this code */
|
|
lookup_index = code >> ( len - lookup_bits );
|
|
|
|
/* check that the lookup entry is not occupied by
|
|
a full coded symb */
|
|
if ( lookup_len[lookup_index] != NOLEN ) {
|
|
#if DEBUG
|
|
fprintf(stderr,"*** ERROR: lookup_len[%ld] = %d\n",lookup_index,lookup_len[lookup_index]);
|
|
#endif
|
|
error = ILJPG_ERROR_DECODE_INTERNAL;
|
|
goto BuildTablesError;
|
|
}
|
|
/* see if the prefix is already in the table */
|
|
if ( (j = lookup_symb[lookup_index]) != -1 ) {
|
|
/* it's there */
|
|
nodep = tree_nodes + j; /* get tree pointer */
|
|
}
|
|
else {
|
|
/* create a tree node */
|
|
/* check that there are available nodes
|
|
(this should never fail) */
|
|
if ( next_node >= numnodes ) {
|
|
#if DEBUG
|
|
fprintf(stderr,"build_huffman_tables: *** ERROR: ran out of tree nodes (a)\n");
|
|
#endif
|
|
error = ILJPG_ERROR_DECODE_INTERNAL;
|
|
goto BuildTablesError;
|
|
}
|
|
lookup_symb[lookup_index] = next_node;
|
|
nodep = tree_nodes + next_node;
|
|
nodep->left = NULL;
|
|
nodep->right = NULL;
|
|
next_node ++;
|
|
lookup_len[lookup_index] = NOLEN;
|
|
}
|
|
|
|
|
|
mask = (1L<<(len - lookup_bits - 1));
|
|
|
|
/* now go down the tree branch, building as needed */
|
|
for ( i = lookup_bits; i < len; i++ ) {
|
|
followp = (code & mask) ? &nodep->left : &nodep->right;
|
|
if ( *followp == NULL ) {
|
|
/* build a new node */
|
|
/* check that there are available nodes
|
|
(this should never fail) */
|
|
if ( next_node >= numnodes ) {
|
|
#if DEBUG
|
|
fprintf(stderr,"build_huffman_tables: *** ERROR: ran out of tree nodes (b)\n");
|
|
#endif
|
|
error = ILJPG_ERROR_DECODE_INTERNAL;
|
|
goto BuildTablesError;
|
|
}
|
|
*followp = &tree_nodes[next_node++];
|
|
leafp = *followp; /* remember leaf */
|
|
|
|
(*followp)->left = NULL;
|
|
(*followp)->right= NULL;
|
|
(*followp)->c = -1;
|
|
}
|
|
nodep = *followp;
|
|
mask >>= 1;
|
|
}
|
|
|
|
leafp->c = c; /* write symbol in leaf */
|
|
}
|
|
}
|
|
/* return pointers to lookup tables */
|
|
table_setp->lookup_symb = lookup_symb;
|
|
table_setp->lookup_len = lookup_len;
|
|
table_setp->tree_nodes = tree_nodes;
|
|
|
|
/* deallocate temporary data and return success */
|
|
ILJPG_FREE (hufvals);
|
|
ILJPG_FREE (hufcodes);
|
|
ILJPG_FREE (huflen);
|
|
return 0;
|
|
|
|
/* Goto point on error: deallocate all non-null and return "error". */
|
|
BuildTablesError:
|
|
if (lookup_symb) ILJPG_FREE (lookup_symb);
|
|
if (lookup_len) ILJPG_FREE (lookup_len);
|
|
if (tree_nodes) ILJPG_FREE (tree_nodes);
|
|
if (hufvals) ILJPG_FREE (hufvals);
|
|
if (hufcodes) ILJPG_FREE (hufcodes);
|
|
if (huflen) ILJPG_FREE (huflen);
|
|
return error;
|
|
}
|
|
|
|
|
|
|
|
/* -------------------- _iljpgDehuffInit -------------------------- */
|
|
/* Called by iljpgDecodeInit() to init for Huffman decoding.
|
|
*/
|
|
ILJPG_PRIVATE_EXTERN
|
|
iljpgError _iljpgDehuffInit (
|
|
iljpgDecodePrivPtr pPriv
|
|
)
|
|
{
|
|
iljpgDehuffPtr pHuffPriv;
|
|
iljpgDataPtr pData;
|
|
iljpgPtr pTable;
|
|
iljpgError error;
|
|
int i;
|
|
|
|
/* Allocate Huffman private area and point to it in decode private */
|
|
pData = pPriv->pData;
|
|
pHuffPriv = (iljpgDehuffPtr)ILJPG_MALLOC_ZERO (sizeof (iljpgDehuffRec));
|
|
if (!pHuffPriv)
|
|
return ILJPG_ERROR_DECODE_MALLOC;
|
|
pPriv->pHuffPriv = (iljpgPtr)pHuffPriv;
|
|
|
|
/* Clear buffer and count of input bits, and flag that reset was done */
|
|
pHuffPriv->bitbuf = 0;
|
|
pHuffPriv->bitsleft = 0;
|
|
pHuffPriv->resetDone = 0;
|
|
|
|
/* Build lookup tables from DC/AC tables from caller (*pPriv->pData) */
|
|
for (i = 0; i < 4; i++) {
|
|
if ((pTable = pData->DCTables[i])) {
|
|
if ((error = build_huffman_tables (pTable, (pTable+16), LOOKUP_BITS,
|
|
&pHuffPriv->table_set_dc[i])))
|
|
return error;
|
|
}
|
|
if ((pTable = pData->ACTables[i])) {
|
|
if ((error = build_huffman_tables (pTable, (pTable+16), LOOKUP_BITS,
|
|
&pHuffPriv->table_set_ac[i])))
|
|
return error;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* -------------------- _iljpgDehuffCleanup -------------------------- */
|
|
/* Called by iljpgDecodeCleanup() to cleanup after Huffman decoding.
|
|
*/
|
|
ILJPG_PRIVATE_EXTERN
|
|
iljpgError _iljpgDehuffCleanup (
|
|
iljpgDecodePrivPtr pPriv
|
|
)
|
|
{
|
|
iljpgDehuffPtr pHuffPriv;
|
|
int i;
|
|
|
|
/* Free the Huffman decode private data including lookup tables */
|
|
pHuffPriv = (iljpgDehuffPtr)pPriv->pHuffPriv;
|
|
if (pHuffPriv) {
|
|
for (i = 0; i < 4; i++) {
|
|
if (pHuffPriv->table_set_dc[i].lookup_symb)
|
|
ILJPG_FREE (pHuffPriv->table_set_dc[i].lookup_symb);
|
|
if (pHuffPriv->table_set_dc[i].lookup_len)
|
|
ILJPG_FREE (pHuffPriv->table_set_dc[i].lookup_len);
|
|
if (pHuffPriv->table_set_dc[i].tree_nodes)
|
|
ILJPG_FREE (pHuffPriv->table_set_dc[i].tree_nodes);
|
|
if (pHuffPriv->table_set_ac[i].lookup_symb)
|
|
ILJPG_FREE (pHuffPriv->table_set_ac[i].lookup_symb);
|
|
if (pHuffPriv->table_set_ac[i].lookup_len)
|
|
ILJPG_FREE (pHuffPriv->table_set_ac[i].lookup_len);
|
|
if (pHuffPriv->table_set_ac[i].tree_nodes)
|
|
ILJPG_FREE (pHuffPriv->table_set_ac[i].tree_nodes);
|
|
}
|
|
ILJPG_FREE (pHuffPriv);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* -------------------- _iljpgDehuffReset -------------------------- */
|
|
/* Reset for Huffman decoding, when a restart marker is seen or at the
|
|
beginning of a strip, which implicitly is a restart.
|
|
*/
|
|
ILJPG_PRIVATE_EXTERN
|
|
iljpgError _iljpgDehuffReset (
|
|
iljpgDecodePrivPtr pPriv
|
|
)
|
|
{
|
|
iljpgDehuffPtr pHuffPriv;
|
|
int comp;
|
|
|
|
/* Clear buffer and count of input bits */
|
|
pHuffPriv = (iljpgDehuffPtr)pPriv->pHuffPriv;
|
|
pHuffPriv->bitbuf = 0;
|
|
pHuffPriv->bitsleft = 0;
|
|
|
|
/* Flag that reset done, to signal DehuffExecute to eat restart marker */
|
|
pHuffPriv->resetDone = 1;
|
|
|
|
/* Clear set lastDC to 0, as per JPEG spec on a restart marker */
|
|
for (comp = 0; comp < pPriv->pData->nComps; comp++)
|
|
pPriv->compData[comp].lastDC = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* -------------------- _iljpgDehuffExecute -------------------------- */
|
|
/* Decode 64 bytes of huffman bits from "stream" into "mb", for component
|
|
index "comp". Return a code (e.g. HUFF_FULL) for what is non-zero in the
|
|
block to "*pBlockType".
|
|
*/
|
|
ILJPG_PRIVATE_EXTERN
|
|
iljpgError _iljpgDehuffExecute (
|
|
iljpgDecodePrivPtr pPriv,
|
|
ILJPG_DECODE_STREAM stream,
|
|
int comp,
|
|
int *mb,
|
|
unsigned int *pBlockType /* RETURNED */
|
|
)
|
|
{
|
|
iljpgDehuffPtr pHuffPriv;
|
|
int coeff_ct = 0;
|
|
#define is_dc (!coeff_ct) /* First coefficient is DC */
|
|
int delta;
|
|
int len, zrun;
|
|
BITBUF bitbuf, ch, c;
|
|
int bitsleft;
|
|
iljpgError error = 0; /* assume no error */
|
|
int index;
|
|
int is_fourx4 = 1, is_dconly = 0;
|
|
int coeff;
|
|
tree_node *nodep;
|
|
struct table_set *pTableSet;
|
|
LOOKUP *lookup_symb, *lookup_len;
|
|
tree_node *tree_nodes;
|
|
BITBUF markerValue = 0; /* 0 or code for marker seen */
|
|
|
|
/* macros for outputting coefficients to a memory buffer */
|
|
# define WRITE_COEFF(x) (*mb++ = (int)x)
|
|
# define WRITE_ZRUN(n) ( mb += n )
|
|
|
|
/* Get the next byte from stream into "_byte". If a 0xff,
|
|
eat next char ifit is a null, otherwise it is a marker:
|
|
if a restart marker ignore it; else store in markerValue, which if
|
|
!= 0 when this is invoked means a marker has already been seen (error).
|
|
If an end-of-data error, set markerValue to non-zero.
|
|
Thus any invocation of this macro after end-of-data or
|
|
a non-restart marker seen is an error - but the first one is allowed.
|
|
Apparently the code here fetches one byte ahead.
|
|
*/
|
|
# define DECODE_GET_BYTE(_byte) { \
|
|
if (markerValue) { \
|
|
error = ILJPG_ERROR_DECODE_DATA; \
|
|
goto out_mainloop; \
|
|
} \
|
|
if (!ILJPG_DECODE_GET_BYTE (stream, _byte, error)) { \
|
|
if (error == ILJPG_ERROR_DECODE_EOD) { \
|
|
markerValue = 1; \
|
|
_byte = 0xff; \
|
|
error = 0; \
|
|
} \
|
|
else goto out_mainloop; \
|
|
} \
|
|
else if (_byte == 0xff) { \
|
|
if (!ILJPG_DECODE_GET_BYTE (stream, markerValue, error)) { \
|
|
if (error == ILJPG_ERROR_DECODE_EOD) { \
|
|
markerValue = 1; \
|
|
error = 0; \
|
|
} \
|
|
else goto out_mainloop; \
|
|
} \
|
|
if ((markerValue & ~7) == ILJPGM_RST0) \
|
|
markerValue = 0; \
|
|
} \
|
|
}
|
|
|
|
|
|
/* clear output buffer */
|
|
memset(mb, 0, BLOCK_COEFFS*sizeof(int));
|
|
|
|
/* Get bit buffer and count from private */
|
|
pHuffPriv = (iljpgDehuffPtr)pPriv->pHuffPriv;
|
|
bitbuf = pHuffPriv->bitbuf;
|
|
bitsleft = pHuffPriv->bitsleft;
|
|
|
|
/* If a reset was just done, eat the next marker if present and get
|
|
next byte (which can't be a marker or error!); set into bitbuf.
|
|
*/
|
|
if (pHuffPriv->resetDone) {
|
|
pHuffPriv->resetDone = 0;
|
|
if (!ILJPG_DECODE_GET_BYTE (stream, ch, error))
|
|
return error; /* must be more bytes after restart */
|
|
if (ch == 0xff) { /* marker or 0xff,0 = 0xff */
|
|
if (!ILJPG_DECODE_GET_BYTE (stream, ch, error))
|
|
return error;
|
|
if (ch == 0)
|
|
ch = 0xff; /* ff,0 => ff in data stream */
|
|
else if ((ch & ~7) == ILJPGM_RST0) {
|
|
/* Restart marker; get another byte, or two if ff */
|
|
if (!ILJPG_DECODE_GET_BYTE (stream, ch, error))
|
|
return error;
|
|
if (ch == 0xff) {
|
|
if (!ILJPG_DECODE_GET_BYTE (stream, ch, error))
|
|
return error;
|
|
if (ch == 0)
|
|
ch = 0xff; /* ff,0 => ff in data stream */
|
|
}
|
|
}
|
|
else return ILJPG_ERROR_DECODE_DATA; /* other marker; error */
|
|
}
|
|
bitbuf = ( ch << SHIFTBUF );
|
|
bitsleft = 8; /* one byte; bitsleft 0 after restart */
|
|
}
|
|
|
|
/* Point to DC tables for this component ("comp"). */
|
|
pTableSet = &pHuffPriv->table_set_dc[pPriv->pData->comp[comp].DCTableIndex];
|
|
lookup_symb = pTableSet->lookup_symb;
|
|
lookup_len = pTableSet->lookup_len;
|
|
tree_nodes = pTableSet->tree_nodes;
|
|
|
|
while ( coeff_ct < BLOCK_COEFFS ) {
|
|
|
|
while ( bitsleft < LOOKUP_BITS ) {
|
|
DECODE_GET_BYTE (ch)
|
|
ch <<= (SHIFTBUF - bitsleft);
|
|
bitbuf += ch;
|
|
bitsleft += 8;
|
|
}
|
|
|
|
index = bitbuf >> ( BITBUFSIZE - LOOKUP_BITS );
|
|
ch = *(lookup_symb + index);
|
|
len = *(lookup_len + index);
|
|
|
|
if ( len != NOLEN ) { /* can get value from lookup table */
|
|
bitbuf <<= len;
|
|
bitsleft -= len;
|
|
}
|
|
else { /* has to go down the tree */
|
|
bitbuf <<= LOOKUP_BITS;
|
|
bitsleft -= LOOKUP_BITS;
|
|
/* point to a node in the tree */
|
|
nodep = tree_nodes + ch;
|
|
while ( 1 ) {
|
|
if ( !bitsleft ) {
|
|
DECODE_GET_BYTE (ch)
|
|
bitbuf = ( ch << SHIFTBUF );
|
|
bitsleft = 8;
|
|
}
|
|
if ( bitbuf & BUFMSB ) /* next bit is a one */
|
|
nodep = nodep->left;
|
|
else
|
|
nodep = nodep->right;
|
|
bitbuf <<= 1;
|
|
bitsleft --;
|
|
|
|
/* if nodep is null, error in data */
|
|
if (!nodep)
|
|
return ILJPG_ERROR_DECODE_DATA;
|
|
if ( (ch = nodep->c) != NOLEAF ) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ! is_dc ) {
|
|
/* Handling of AC coefficients */
|
|
|
|
/* at this point, ch contains RRRRSSSS, where
|
|
RRRR = length of a run of zero coeffs.
|
|
SSSS = number of the "bin" containing the next coeff.
|
|
*/
|
|
|
|
/* first handle RRRR: */
|
|
zrun = ch >> 4;
|
|
|
|
if ( zrun ) {
|
|
WRITE_ZRUN(zrun);
|
|
coeff_ct += zrun;
|
|
ch &= 0x0f;
|
|
}
|
|
|
|
}
|
|
else { /* we've done a DC case: set pointers for next
|
|
coefficient to AC tables. */
|
|
pTableSet = &pHuffPriv->table_set_ac
|
|
[pPriv->pData->comp[comp].ACTableIndex];
|
|
lookup_symb = pTableSet->lookup_symb;
|
|
lookup_len = pTableSet->lookup_len;
|
|
tree_nodes = pTableSet->tree_nodes;
|
|
}
|
|
|
|
/* rest of AC case is identical to DC case */
|
|
|
|
/* at this point, ch contains the "bin" number:
|
|
read that number of bits from the input stream */
|
|
if ( ch ) {
|
|
/* SSSS is not zero */
|
|
while ( bitsleft < ch ) {
|
|
DECODE_GET_BYTE (c)
|
|
bitbuf = bitbuf +
|
|
( c << (SHIFTBUF - bitsleft) );
|
|
bitsleft += 8;
|
|
}
|
|
|
|
/* the desired number is now at the MS part of bitbuf */
|
|
|
|
/* NOTE: Following code should be broken into a big
|
|
SWITCH statement, with one case per value of ch
|
|
between 1 and 11 */
|
|
|
|
/* shift to lower part */
|
|
coeff = bitbuf >> (BITBUFSIZE - ch);
|
|
if ( (bitbuf & BUFMSB) == 0 ) /* leading bit is a zero */
|
|
coeff -= (( 1L << ch ) - 1 );
|
|
bitbuf <<= ch;
|
|
bitsleft -= ch;
|
|
|
|
WRITE_COEFF(coeff); /* write a nonzero coefficient */
|
|
|
|
/* check if the nonzero coefficient is inside the
|
|
upper left 4x4 sub-block */
|
|
if ( is_fourx4 )
|
|
is_fourx4 &= fourx4_table[ coeff_ct ];
|
|
|
|
coeff_ct ++;
|
|
}
|
|
else {
|
|
/* SSSS is zero */
|
|
if ( !is_dc && zrun == 0 ) {
|
|
/* we got RRRRSSSS = 00000000, pad rest of the
|
|
block with zeroes */
|
|
|
|
delta = BLOCK_COEFFS-coeff_ct;
|
|
WRITE_ZRUN(delta);
|
|
coeff_ct += delta;
|
|
is_dconly = ( delta == BLOCK_COEFFS-1);
|
|
|
|
}
|
|
else {
|
|
/* write an isolated zero coefficient */
|
|
WRITE_ZRUN(1);
|
|
coeff_ct ++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Goto point for exiting: "error" must contain current error code */
|
|
out_mainloop:
|
|
/* Store bit buffer and count into private */
|
|
pHuffPriv->bitbuf = bitbuf;
|
|
pHuffPriv->bitsleft = bitsleft;
|
|
|
|
if ( is_dconly )
|
|
*pBlockType = HUFF_DC_ONLY;
|
|
else if ( is_fourx4 )
|
|
*pBlockType = HUFF_FOURX4;
|
|
else *pBlockType = HUFF_FULL;
|
|
return error;
|
|
}
|
|
|
|
|
|
|
|
|