Example #1
0
		// Emit a DHT marker
		static void emit_dht(jpeg_compress cinfo, int index, bool is_ac)
		{
			JHUFF_TBL htbl=null;

			if(is_ac)
			{
				htbl=cinfo.ac_huff_tbl_ptrs[index];
				index+=0x10; // output index has AC bit set
			}
			else htbl=cinfo.dc_huff_tbl_ptrs[index];

			if(htbl==null) ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_NO_HUFF_TABLE, index);

			if(!htbl.sent_table)
			{
				emit_marker(cinfo, JPEG_MARKER.M_DHT);

				int length=0;
				for(int i=1; i<=16; i++) length+=htbl.bits[i];

				emit_2bytes(cinfo, length+2+1+16);
				emit_byte(cinfo, index);

				for(int i=1; i<=16; i++) emit_byte(cinfo, htbl.bits[i]);
				for(int i=0; i<length; i++) emit_byte(cinfo, htbl.huffval[i]);

				htbl.sent_table=true;
			}
		}
        /// <summary>
        /// Finish up a statistics-gathering pass and create the new Huffman tables.
        /// </summary>
        private void finish_pass_gather_phuff()
        {
            /* Flush out buffered data (all we care about is counting the EOB symbol) */
            emit_eobrun();

            /* It's important not to apply jpeg_gen_optimal_table more than once
             * per table, because it clobbers the input frequency counts!
             */
            bool[] did = new bool [JpegConstants.NUM_HUFF_TBLS];

            bool is_DC_band = (m_cinfo.m_Ss == 0);

            for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
            {
                jpeg_component_info componentInfo = m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]];
                int tbl = componentInfo.Ac_tbl_no;

                if (is_DC_band)
                {
                    if (m_cinfo.m_Ah != 0) /* DC refinement needs no table */
                    {
                        continue;
                    }

                    tbl = componentInfo.Dc_tbl_no;
                }

                if (!did[tbl])
                {
                    JHUFF_TBL htblptr = null;
                    if (is_DC_band)
                    {
                        if (m_cinfo.m_dc_huff_tbl_ptrs[tbl] == null)
                        {
                            m_cinfo.m_dc_huff_tbl_ptrs[tbl] = new JHUFF_TBL();
                        }

                        htblptr = m_cinfo.m_dc_huff_tbl_ptrs[tbl];
                    }
                    else
                    {
                        if (m_cinfo.m_ac_huff_tbl_ptrs[tbl] == null)
                        {
                            m_cinfo.m_ac_huff_tbl_ptrs[tbl] = new JHUFF_TBL();
                        }

                        htblptr = m_cinfo.m_ac_huff_tbl_ptrs[tbl];
                    }

                    jpeg_gen_optimal_table(htblptr, m_count_ptrs[tbl]);
                    did[tbl] = true;
                }
            }
        }
Example #3
0
        public static JHUFF_TBL jpeg_alloc_huff_table(jpeg_common cinfo)
        {
            JHUFF_TBL tbl = null;

            try
            {
                tbl            = new JHUFF_TBL();
                tbl.sent_table = false;                 // make sure this is false in any new table
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }

            return(tbl);
        }
Example #4
0
        /// <summary>
        /// Emit a DHT marker
        /// </summary>
        private void emit_dht(int index, bool is_ac)
        {
            JHUFF_TBL htbl = m_cinfo.m_dc_huff_tbl_ptrs[index];

            if (is_ac)
            {
                htbl   = m_cinfo.m_ac_huff_tbl_ptrs[index];
                index += 0x10; /* output index has AC bit set */
            }

            if (htbl == null)
            {
                m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_NO_HUFF_TABLE, index);
            }

            if (!htbl.Sent_table)
            {
                emit_marker(JPEG_MARKER.DHT);

                int length = 0;
                for (int i = 1; i <= 16; i++)
                {
                    length += htbl.Bits[i];
                }

                emit_2bytes(length + 2 + 1 + 16);
                emit_byte(index);

                for (int i = 1; i <= 16; i++)
                {
                    emit_byte(htbl.Bits[i]);
                }

                for (int i = 0; i < length; i++)
                {
                    emit_byte(htbl.Huffval[i]);
                }

                htbl.Sent_table = true;
            }
        }
Example #5
0
        /// <summary>
        /// Expand a Huffman table definition into the derived format
        /// Compute the derived values for a Huffman table.
        /// This routine also performs some validation checks on the table.
        /// </summary>
        protected 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];
            }
        }
Example #6
0
        /// <summary>
        /// Generate the best Huffman code table for the given counts, fill htbl.
        ///
        /// The JPEG standard requires that no symbol be assigned a codeword of all
        /// one bits (so that padding bits added at the end of a compressed segment
        /// can't look like a valid code).  Because of the canonical ordering of
        /// codewords, this just means that there must be an unused slot in the
        /// longest codeword length category.  Section K.2 of the JPEG spec suggests
        /// reserving such a slot by pretending that symbol 256 is a valid symbol
        /// with count 1.  In theory that's not optimal; giving it count zero but
        /// including it in the symbol set anyway should give a better Huffman code.
        /// But the theoretically better code actually seems to come out worse in
        /// practice, because it produces more all-ones bytes (which incur stuffed
        /// zero bytes in the final file).  In any case the difference is tiny.
        ///
        /// The JPEG standard requires Huffman codes to be no more than 16 bits long.
        /// If some symbols have a very small but nonzero probability, the Huffman tree
        /// must be adjusted to meet the code length restriction.  We currently use
        /// the adjustment method suggested in JPEG section K.2.  This method is *not*
        /// optimal; it may not choose the best possible limited-length code.  But
        /// typically only very-low-frequency symbols will be given less-than-optimal
        /// lengths, so the code is almost optimal.  Experimental comparisons against
        /// an optimal limited-length-code algorithm indicate that the difference is
        /// microscopic --- usually less than a hundredth of a percent of total size.
        /// So the extra complexity of an optimal algorithm doesn't seem worthwhile.
        /// </summary>
        protected void jpeg_gen_optimal_table(JHUFF_TBL htbl, long[] freq)
        {
            byte[] bits = new byte[MAX_CLEN + 1]; /* bits[k] = # of symbols with code length k */
            int[]  codesize = new int[257];       /* codesize[k] = code length of symbol k */
            int[]  others = new int[257];         /* next symbol in current branch of tree */
            int    c1, c2;
            int    p, i, j;
            long   v;

            /* This algorithm is explained in section K.2 of the JPEG standard */
            for (i = 0; i < 257; i++)
            {
                others[i] = -1; /* init links to empty */
            }
            freq[256] = 1;      /* make sure 256 has a nonzero count */

            /* Including the pseudo-symbol 256 in the Huffman procedure guarantees
             * that no real symbol is given code-value of all ones, because 256
             * will be placed last in the largest codeword category.
             */

            /* Huffman's basic algorithm to assign optimal code lengths to symbols */

            for (;;)
            {
                /* Find the smallest nonzero frequency, set c1 = its symbol */
                /* In case of ties, take the larger symbol number */
                c1 = -1;
                v  = 1000000000L;
                for (i = 0; i <= 256; i++)
                {
                    if (freq[i] != 0 && freq[i] <= v)
                    {
                        v  = freq[i];
                        c1 = i;
                    }
                }

                /* Find the next smallest nonzero frequency, set c2 = its symbol */
                /* In case of ties, take the larger symbol number */
                c2 = -1;
                v  = 1000000000L;
                for (i = 0; i <= 256; i++)
                {
                    if (freq[i] != 0 && freq[i] <= v && i != c1)
                    {
                        v  = freq[i];
                        c2 = i;
                    }
                }

                /* Done if we've merged everything into one frequency */
                if (c2 < 0)
                {
                    break;
                }

                /* Else merge the two counts/trees */
                freq[c1] += freq[c2];
                freq[c2]  = 0;

                /* Increment the codesize of everything in c1's tree branch */
                codesize[c1]++;
                while (others[c1] >= 0)
                {
                    c1 = others[c1];
                    codesize[c1]++;
                }

                others[c1] = c2;        /* chain c2 onto c1's tree branch */

                /* Increment the codesize of everything in c2's tree branch */
                codesize[c2]++;
                while (others[c2] >= 0)
                {
                    c2 = others[c2];
                    codesize[c2]++;
                }
            }

            /* Now count the number of symbols of each code length */
            for (i = 0; i <= 256; i++)
            {
                if (codesize[i] != 0)
                {
                    /* The JPEG standard seems to think that this can't happen, */
                    /* but I'm paranoid... */
                    if (codesize[i] > MAX_CLEN)
                    {
                        m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_HUFF_CLEN_OVERFLOW);
                    }

                    bits[codesize[i]]++;
                }
            }

            /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
             * Huffman procedure assigned any such lengths, we must adjust the coding.
             * Here is what the JPEG spec says about how this next bit works:
             * Since symbols are paired for the longest Huffman code, the symbols are
             * removed from this length category two at a time.  The prefix for the pair
             * (which is one bit shorter) is allocated to one of the pair; then,
             * skipping the BITS entry for that prefix length, a code word from the next
             * shortest nonzero BITS entry is converted into a prefix for two code words
             * one bit longer.
             */

            for (i = MAX_CLEN; i > 16; i--)
            {
                while (bits[i] > 0)
                {
                    j = i - 2;      /* find length of new prefix to be used */
                    while (bits[j] == 0)
                    {
                        j--;
                    }

                    bits[i] -= 2;     /* remove two symbols */
                    bits[i - 1]++;    /* one goes in this length */
                    bits[j + 1] += 2; /* two new symbols in this length */
                    bits[j]--;        /* symbol of this length is now a prefix */
                }
            }

            /* Remove the count for the pseudo-symbol 256 from the largest codelength */
            while (bits[i] == 0)        /* find largest codelength still in use */
            {
                i--;
            }
            bits[i]--;

            /* Return final symbol counts (only for lengths 0..16) */
            Buffer.BlockCopy(bits, 0, htbl.Bits, 0, htbl.Bits.Length);

            /* Return a list of the symbols sorted by code length */

            /* It's not real clear to me why we don't need to consider the codelength
             * changes made above, but the JPEG spec seems to think this works.
             */
            p = 0;
            for (i = 1; i <= MAX_CLEN; i++)
            {
                for (j = 0; j <= 255; j++)
                {
                    if (codesize[j] == i)
                    {
                        htbl.Huffval[p] = (byte)j;
                        p++;
                    }
                }
            }

            /* Set sent_table false so updated table will be written to JPEG file. */
            htbl.Sent_table = false;
        }
        /// <summary>
        /// Generate the best Huffman code table for the given counts, fill htbl.
        /// 
        /// The JPEG standard requires that no symbol be assigned a codeword of all
        /// one bits (so that padding bits added at the end of a compressed segment
        /// can't look like a valid code).  Because of the canonical ordering of
        /// codewords, this just means that there must be an unused slot in the
        /// longest codeword length category.  Section K.2 of the JPEG spec suggests
        /// reserving such a slot by pretending that symbol 256 is a valid symbol
        /// with count 1.  In theory that's not optimal; giving it count zero but
        /// including it in the symbol set anyway should give a better Huffman code.
        /// But the theoretically better code actually seems to come out worse in
        /// practice, because it produces more all-ones bytes (which incur stuffed
        /// zero bytes in the final file).  In any case the difference is tiny.
        /// 
        /// The JPEG standard requires Huffman codes to be no more than 16 bits long.
        /// If some symbols have a very small but nonzero probability, the Huffman tree
        /// must be adjusted to meet the code length restriction.  We currently use
        /// the adjustment method suggested in JPEG section K.2.  This method is *not*
        /// optimal; it may not choose the best possible limited-length code.  But
        /// typically only very-low-frequency symbols will be given less-than-optimal
        /// lengths, so the code is almost optimal.  Experimental comparisons against
        /// an optimal limited-length-code algorithm indicate that the difference is
        /// microscopic --- usually less than a hundredth of a percent of total size.
        /// So the extra complexity of an optimal algorithm doesn't seem worthwhile.
        /// </summary>
        protected void jpeg_gen_optimal_table(JHUFF_TBL htbl, long[] freq)
        {
            byte[] bits = new byte[MAX_CLEN + 1];   /* bits[k] = # of symbols with code length k */
            int[] codesize = new int[257];      /* codesize[k] = code length of symbol k */
            int[] others = new int[257];        /* next symbol in current branch of tree */
            int c1, c2;
            int p, i, j;
            long v;

            /* This algorithm is explained in section K.2 of the JPEG standard */
            for (i = 0; i < 257; i++)
                others[i] = -1;     /* init links to empty */

            freq[256] = 1;      /* make sure 256 has a nonzero count */
            /* Including the pseudo-symbol 256 in the Huffman procedure guarantees
            * that no real symbol is given code-value of all ones, because 256
            * will be placed last in the largest codeword category.
            */

            /* Huffman's basic algorithm to assign optimal code lengths to symbols */

            for (;;)
            {
                /* Find the smallest nonzero frequency, set c1 = its symbol */
                /* In case of ties, take the larger symbol number */
                c1 = -1;
                v = 1000000000L;
                for (i = 0; i <= 256; i++)
                {
                    if (freq[i] != 0 && freq[i] <= v)
                    {
                        v = freq[i];
                        c1 = i;
                    }
                }

                /* Find the next smallest nonzero frequency, set c2 = its symbol */
                /* In case of ties, take the larger symbol number */
                c2 = -1;
                v = 1000000000L;
                for (i = 0; i <= 256; i++)
                {
                    if (freq[i] != 0 && freq[i] <= v && i != c1)
                    {
                        v = freq[i];
                        c2 = i;
                    }
                }

                /* Done if we've merged everything into one frequency */
                if (c2 < 0)
                    break;

                /* Else merge the two counts/trees */
                freq[c1] += freq[c2];
                freq[c2] = 0;

                /* Increment the codesize of everything in c1's tree branch */
                codesize[c1]++;
                while (others[c1] >= 0)
                {
                    c1 = others[c1];
                    codesize[c1]++;
                }

                others[c1] = c2;        /* chain c2 onto c1's tree branch */

                /* Increment the codesize of everything in c2's tree branch */
                codesize[c2]++;
                while (others[c2] >= 0)
                {
                    c2 = others[c2];
                    codesize[c2]++;
                }
            }

            /* Now count the number of symbols of each code length */
            for (i = 0; i <= 256; i++)
            {
                if (codesize[i] != 0)
                {
                    /* The JPEG standard seems to think that this can't happen, */
                    /* but I'm paranoid... */
                    if (codesize[i] > MAX_CLEN)
                        m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_HUFF_CLEN_OVERFLOW);

                    bits[codesize[i]]++;
                }
            }

            /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
            * Huffman procedure assigned any such lengths, we must adjust the coding.
            * Here is what the JPEG spec says about how this next bit works:
            * Since symbols are paired for the longest Huffman code, the symbols are
            * removed from this length category two at a time.  The prefix for the pair
            * (which is one bit shorter) is allocated to one of the pair; then,
            * skipping the BITS entry for that prefix length, a code word from the next
            * shortest nonzero BITS entry is converted into a prefix for two code words
            * one bit longer.
            */

            for (i = MAX_CLEN; i > 16; i--)
            {
                while (bits[i] > 0)
                {
                    j = i - 2;      /* find length of new prefix to be used */
                    while (bits[j] == 0)
                        j--;

                    bits[i] -= 2;       /* remove two symbols */
                    bits[i - 1]++;      /* one goes in this length */
                    bits[j + 1] += 2;       /* two new symbols in this length */
                    bits[j]--;      /* symbol of this length is now a prefix */
                }
            }

            /* Remove the count for the pseudo-symbol 256 from the largest codelength */
            while (bits[i] == 0)        /* find largest codelength still in use */
                i--;
            bits[i]--;

            /* Return final symbol counts (only for lengths 0..16) */
            Buffer.BlockCopy(bits, 0, htbl.Bits, 0, htbl.Bits.Length);

            /* Return a list of the symbols sorted by code length */
            /* It's not real clear to me why we don't need to consider the codelength
            * changes made above, but the JPEG spec seems to think this works.
            */
            p = 0;
            for (i = 1; i <= MAX_CLEN; i++)
            {
                for (j = 0; j <= 255; j++)
                {
                    if (codesize[j] == i)
                    {
                        htbl.Huffval[p] = (byte) j;
                        p++;
                    }
                }
            }

            /* Set sent_table false so updated table will be written to JPEG file. */
            htbl.Sent_table = false;
        }
Example #8
0
        /// <summary>
        /// Process a DHT marker
        /// </summary>
        private bool get_dht()
        {
            int length;

            if (!m_cinfo.m_src.GetTwoBytes(out length))
            {
                return(false);
            }

            length -= 2;

            byte[] bits    = new byte[17];
            byte[] huffval = new byte[256];
            while (length > 16)
            {
                int index;
                if (!m_cinfo.m_src.GetByte(out index))
                {
                    return(false);
                }

                m_cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_DHT, index);

                bits[0] = 0;
                int count = 0;
                for (int i = 1; i <= 16; i++)
                {
                    int temp = 0;
                    if (!m_cinfo.m_src.GetByte(out temp))
                    {
                        return(false);
                    }

                    bits[i] = (byte)temp;
                    count  += bits[i];
                }

                length -= 1 + 16;

                m_cinfo.TRACEMS(2, J_MESSAGE_CODE.JTRC_HUFFBITS, bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7], bits[8]);
                m_cinfo.TRACEMS(2, J_MESSAGE_CODE.JTRC_HUFFBITS, bits[9], bits[10], bits[11], bits[12], bits[13], bits[14], bits[15], bits[16]);

                /* Here we just do minimal validation of the counts to avoid walking
                 * off the end of our table space. huff_entropy_decoder will check more carefully.
                 */
                if (count > 256 || count > length)
                {
                    m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_HUFF_TABLE);
                }

                for (int i = 0; i < count; i++)
                {
                    int temp = 0;
                    if (!m_cinfo.m_src.GetByte(out temp))
                    {
                        return(false);
                    }

                    huffval[i] = (byte)temp;
                }

                length -= count;

                JHUFF_TBL htblptr = null;
                if ((index & 0x10) != 0)
                {
                    /* AC table definition */
                    index -= 0x10;
                    if (m_cinfo.m_ac_huff_tbl_ptrs[index] == null)
                    {
                        m_cinfo.m_ac_huff_tbl_ptrs[index] = new JHUFF_TBL();
                    }

                    htblptr = m_cinfo.m_ac_huff_tbl_ptrs[index];
                }
                else
                {
                    /* DC table definition */
                    if (m_cinfo.m_dc_huff_tbl_ptrs[index] == null)
                    {
                        m_cinfo.m_dc_huff_tbl_ptrs[index] = new JHUFF_TBL();
                    }

                    htblptr = m_cinfo.m_dc_huff_tbl_ptrs[index];
                }

                if (index < 0 || index >= JpegConstants.NUM_HUFF_TBLS)
                {
                    m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_DHT_INDEX, index);
                }

                Buffer.BlockCopy(bits, 0, htblptr.Bits, 0, htblptr.Bits.Length);
                Buffer.BlockCopy(huffval, 0, htblptr.Huffval, 0, htblptr.Huffval.Length);
            }

            if (length != 0)
            {
                m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_LENGTH);
            }

            return(true);
        }
        /// <summary>
        /// Expand a Huffman table definition into the derived format
        /// This routine also performs some validation checks on the table.
        /// </summary>
        protected 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);
                    }
                }
            }
        }
Example #10
0
        // Expand a Huffman table definition into the derived format
        // Compute the derived values for a Huffman table.
        // This routine also performs some validation checks on the table.
        static void jpeg_make_d_derived_tbl(jpeg_decompress cinfo, bool isDC, int tblno, ref d_derived_tbl pdtbl)
        {
            // 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 >= NUM_HUFF_TBLS)
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_NO_HUFF_TABLE, tblno);
            }
            JHUFF_TBL htbl = isDC?cinfo.dc_huff_tbl_ptrs[tblno]:cinfo.ac_huff_tbl_ptrs[tblno];

            if (htbl == null)
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_NO_HUFF_TABLE, tblno);
            }

            // Allocate a workspace if we haven't already done so.
            if (pdtbl == null)
            {
                try
                {
                    pdtbl = new d_derived_tbl();
                }
                catch
                {
                    ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
                }
            }

            d_derived_tbl dtbl = pdtbl;

            dtbl.pub = htbl;           // fill in back link

            // Figure C.1: make table of Huffman code length for each symbol
            byte[] huffsize = new byte[257];
            int    p        = 0;

            for (byte l = 1; l <= 16; l++)
            {
                int i = (int)htbl.bits[l];
                if (i < 0 || p + i > 256)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_HUFF_TABLE);                              // protect against table overrun
                }
                while ((i--) != 0)
                {
                    huffsize[p++] = l;
                }
            }
            huffsize[p] = 0;
            int numsymbols = p;

            // Figure C.2: generate the codes themselves
            // We also validate that the counts represent a legal Huffman code tree.
            uint[] huffcode = new uint[257];
            uint   code     = 0;
            int    si       = huffsize[0];

            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 (((int)code) >= (1 << si))
                {
                    ERREXIT(cinfo, 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] = (int)p - (int)huffcode[p];
                    p += htbl.bits[l];
                    dtbl.maxcode[l] = (int)huffcode[p - 1];                 // maximum code of length l
                }
                else
                {
                    dtbl.maxcode[l] = -1;                       // -1 if no codes of this length
                }
            }
            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.
            for (int i = 0; i < dtbl.look_nbits.Length; i++)
            {
                dtbl.look_nbits[i] = 0;
            }

            p = 0;
            for (int l = 1; l <= HUFF_LOOKAHEAD; l++)
            {
                for (int i = 1; i <= (int)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 = ((int)huffcode[p]) << (HUFF_LOOKAHEAD - l);
                    for (int ctr = 1 << (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..16.
            // (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 > 16)
                    {
                        ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_HUFF_TABLE);
                    }
                }
            }
        }