private void jpeg_make_d_derived_tbl(bool isDC, int tblno, ref d_derived_tbl dtbl)
{
/* Note that huffsize[] and huffcode[] are filled in code-length order,
* paralleling the order of the symbols themselves in htbl.huffval[].
*/
/* Find the input Huffman table */
if (tblno < 0 || tblno >= JpegConstants.NUM_HUFF_TBLS)
m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_NO_HUFF_TABLE, tblno);
JHUFF_TBL htbl = isDC ? m_cinfo.m_dc_huff_tbl_ptrs[tblno] : m_cinfo.m_ac_huff_tbl_ptrs[tblno];
if (htbl == null)
m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_NO_HUFF_TABLE, tblno);
/* Allocate a workspace if we haven't already done so. */
if (dtbl == null)
dtbl = new d_derived_tbl();
dtbl.pub = htbl; /* fill in back link */
/* Figure C.1: make table of Huffman code length for each symbol */
int p = 0;
char[] huffsize = new char[257];
for (int l = 1; l <= 16; l++)
{
int i = htbl.Bits[l];
if (i < 0 || p + i > 256) /* protect against table overrun */
m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_HUFF_TABLE);
while ((i--) != 0)
huffsize[p++] = (char)l;
}
huffsize[p] = (char)0;
int numsymbols = p;
/* Figure C.2: generate the codes themselves */
/* We also validate that the counts represent a legal Huffman code tree. */
int code = 0;
int si = huffsize[0];
int[] huffcode = new int[257];
p = 0;
while (huffsize[p] != 0)
{
while (((int)huffsize[p]) == si)
{
huffcode[p++] = code;
code++;
}
/* code is now 1 more than the last code used for codelength si; but
* it must still fit in si bits, since no code is allowed to be all ones.
*/
if (code >= (1 << si))
m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_HUFF_TABLE);
code <<= 1;
si++;
}
/* Figure F.15: generate decoding tables for bit-sequential decoding */
p = 0;
for (int l = 1; l <= 16; l++)
{
if (htbl.Bits[l] != 0)
{
/* valoffset[l] = huffval[] index of 1st symbol of code length l,
* minus the minimum code of length l
*/
dtbl.valoffset[l] = p - huffcode[p];
p += htbl.Bits[l];
dtbl.maxcode[l] = huffcode[p - 1]; /* maximum code of length l */
}
else
{
/* -1 if no codes of this length */
dtbl.maxcode[l] = -1;
}
}
dtbl.maxcode[17] = 0xFFFFF; /* ensures jpeg_huff_decode terminates */
/* Compute lookahead tables to speed up decoding.
* First we set all the table entries to 0, indicating "too long";
* then we iterate through the Huffman codes that are short enough and
* fill in all the entries that correspond to bit sequences starting
* with that code.
*/
Array.Clear(dtbl.look_nbits, 0, dtbl.look_nbits.Length);
p = 0;
for (int l = 1; l <= JpegConstants.HUFF_LOOKAHEAD; l++)
{
for (int i = 1; i <= htbl.Bits[l]; i++, p++)
{
/* l = current code's length, p = its index in huffcode[] & huffval[]. */
/* Generate left-justified code followed by all possible bit sequences */
int lookbits = huffcode[p] << (JpegConstants.HUFF_LOOKAHEAD - l);
for (int ctr = 1 << (JpegConstants.HUFF_LOOKAHEAD - l); ctr > 0; ctr--)
{
dtbl.look_nbits[lookbits] = l;
dtbl.look_sym[lookbits] = htbl.Huffval[p];
lookbits++;
}
}
}
/* Validate symbols as being reasonable.
* For AC tables, we make no check, but accept all byte values 0..255.
* For DC tables, we require the symbols to be in range 0..15.
* (Tighter bounds could be applied depending on the data depth and mode,
* but this is sufficient to ensure safe decoding.)
*/
if (isDC)
{
for (int i = 0; i < numsymbols; i++)
{
int sym = htbl.Huffval[i];
if (sym < 0 || sym > 15)
m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_HUFF_TABLE);
}
}
}