private void jpeg_make_c_derived_tbl(bool isDC, int tblno, ref c_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 c_derived_tbl();
/* 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 lastp = 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];
p = 0;
int[] huffcode = new int[257];
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 C.3: generate encoding tables */
/* These are code and size indexed by symbol value */
/* Set all codeless symbols to have code length 0;
* this lets us detect duplicate VAL entries here, and later
* allows emit_bits to detect any attempt to emit such symbols.
*/
Array.Clear(dtbl.ehufsi, 0, dtbl.ehufsi.Length);
/* This is also a convenient place to check for out-of-range
* and duplicated VAL entries. We allow 0..255 for AC symbols
* but only 0..15 for DC. (We could constrain them further
* based on data depth and mode, but this seems enough.)
*/
int maxsymbol = isDC ? 15 : 255;
for (p = 0; p < lastp; p++)
{
int i = htbl.Huffval[p];
if (i < 0 || i > maxsymbol || dtbl.ehufsi[i] != 0)
m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_HUFF_TABLE);
dtbl.ehufco[i] = huffcode[p];
dtbl.ehufsi[i] = huffsize[p];
}
}