/// <summary>
        /// Emit a restart marker and resynchronize predictions.
        /// </summary>
        private bool emit_restart(savable_state state, int restart_num)
        {
            if (!flush_bits(state))
            {
                return(false);
            }

            if (!emit_byte(0xFF))
            {
                return(false);
            }

            if (!emit_byte((int)(JPEG_MARKER.RST0 + restart_num)))
            {
                return(false);
            }

            /* Re-initialize DC predictions to 0 */
            for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
            {
                state.last_dc_val[ci] = 0;
            }

            /* The restart counter is not updated until we successfully write the MCU. */
            return(true);
        }
            public int[] last_dc_val = new int[JpegConstants.MAX_COMPS_IN_SCAN]; /* last DC coef for each component */

            public void ASSIGN_STATE(savable_state src)
            {
                put_buffer = src.put_buffer;
                put_bits = src.put_bits;

                for (int i = 0; i < last_dc_val.Length; i++)
                    last_dc_val[i] = src.last_dc_val[i];
            }
        private bool flush_bits(savable_state state)
        {
            if (!emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */
            {
                return(false);
            }

            state.put_buffer = 0;  /* and reset bit-buffer to empty */
            state.put_bits   = 0;
            return(true);
        }
        /// <summary>
        /// Encode and output one MCU's worth of Huffman-compressed coefficients.
        /// </summary>
        private bool encode_mcu_huff(JBLOCK[][] MCU_data)
        {
            /* Load up working state */
            savable_state state;

            state = m_saved;

            /* Emit restart marker if needed */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    if (!emit_restart(state, m_next_restart_num))
                    {
                        return(false);
                    }
                }
            }

            /* Encode the MCU data blocks */
            for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
            {
                int ci = m_cinfo.m_MCU_membership[blkn];
                if (!encode_one_block(state, MCU_data[blkn][0].data, state.last_dc_val[ci],
                                      m_dc_derived_tbls[m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]].Dc_tbl_no],
                                      m_ac_derived_tbls[m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]].Ac_tbl_no]))
                {
                    return(false);
                }

                /* Update last_dc_val */
                state.last_dc_val[ci] = MCU_data[blkn][0][0];
            }

            /* Completed MCU, so update state */
            m_saved = state;

            /* Update restart-interval state too */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    m_restarts_to_go = m_cinfo.m_restart_interval;
                    m_next_restart_num++;
                    m_next_restart_num &= 7;
                }

                m_restarts_to_go--;
            }

            return(true);
        }
        /// <summary>
        /// Finish up at the end of a Huffman-compressed scan.
        /// </summary>
        private void finish_pass_huff()
        {
            /* Load up working state ... flush_bits needs it */
            savable_state state;

            state = m_saved;

            /* Flush out the last data */
            if (!flush_bits(state))
            {
                m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CANT_SUSPEND);
            }

            /* Update state */
            m_saved = state;
        }
        /// <summary>
        /// Only the right 24 bits of put_buffer are used; the valid bits are
        /// left-justified in this part.  At most 16 bits can be passed to emit_bits
        /// in one call, and we never retain more than 7 bits in put_buffer
        /// between calls, so 24 bits are sufficient.
        /// </summary>
        private bool emit_bits(savable_state state, int code, int size)
        {
            // Emit some bits; return true if successful, false if must suspend
            /* This routine is heavily used, so it's worth coding tightly. */
            int put_buffer = code;
            int put_bits   = state.put_bits;

            /* if size is 0, caller used an invalid Huffman table entry */
            if (size == 0)
            {
                m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_HUFF_MISSING_CODE);
            }

            put_buffer  &= (1 << size) - 1;  /* mask off any extra bits in code */
            put_bits    += size;             /* new number of bits in buffer */
            put_buffer <<= 24 - put_bits;    /* align incoming bits */
            put_buffer  |= state.put_buffer; /* and merge with old buffer contents */

            while (put_bits >= 8)
            {
                int c = (put_buffer >> 16) & 0xFF;
                if (!emit_byte(c))
                {
                    return(false);
                }

                if (c == 0xFF)
                {
                    /* need to stuff a zero byte? */
                    if (!emit_byte(0))
                    {
                        return(false);
                    }
                }

                put_buffer <<= 8;
                put_bits    -= 8;
            }

            state.put_buffer = put_buffer; /* update state variables */
            state.put_bits   = put_bits;

            return(true);
        }
Esempio n. 7
0
        /// <summary>
        /// Only the right 24 bits of put_buffer are used; the valid bits are
        /// left-justified in this part.  At most 16 bits can be passed to emit_bits
        /// in one call, and we never retain more than 7 bits in put_buffer
        /// between calls, so 24 bits are sufficient.
        /// </summary>
        private bool emit_bits(savable_state state, int code, int size)
        {
            // Emit some bits; return true if successful, false if must suspend
            /* This routine is heavily used, so it's worth coding tightly. */
            int put_buffer = code;
            int put_bits = state.put_bits;

            /* if size is 0, caller used an invalid Huffman table entry */
            if (size == 0)
                m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_HUFF_MISSING_CODE);

            put_buffer &= (1 << size) - 1; /* mask off any extra bits in code */
            put_bits += size;       /* new number of bits in buffer */
            put_buffer <<= 24 - put_bits; /* align incoming bits */
            put_buffer |= state.put_buffer; /* and merge with old buffer contents */

            while (put_bits >= 8)
            {
                int c = (put_buffer >> 16) & 0xFF;
                if (!emit_byte(c))
                    return false;

                if (c == 0xFF)
                {
                    /* need to stuff a zero byte? */
                    if (!emit_byte(0))
                        return false;
                }

                put_buffer <<= 8;
                put_bits -= 8;
            }

            state.put_buffer = put_buffer; /* update state variables */
            state.put_bits = put_bits;

            return true;
        }
Esempio n. 8
0
        /// <summary>
        /// Encode a single block's worth of coefficients
        /// </summary>
        private bool encode_one_block(savable_state state, short[] block, int last_dc_val, c_derived_tbl dctbl, c_derived_tbl actbl)
        {
            /* Encode the DC coefficient difference per section F.1.2.1 */
            int temp = block[0] - last_dc_val;
            int temp2 = temp;
            if (temp < 0)
            {
                temp = -temp;       /* temp is abs value of input */
                /* For a negative input, want temp2 = bitwise complement of abs(input) */
                /* This code assumes we are on a two's complement machine */
                temp2--;
            }

            /* Find the number of bits needed for the magnitude of the coefficient */
            int nbits = 0;
            while (temp != 0)
            {
                nbits++;
                temp >>= 1;
            }

            /* Check for out-of-range coefficient values.
             * Since we're encoding a difference, the range limit is twice as much.
             */
            if (nbits > MAX_HUFFMAN_COEF_BITS + 1)
                m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_DCT_COEF);

            /* Emit the Huffman-coded symbol for the number of bits */
            if (!emit_bits(state, dctbl.ehufco[nbits], dctbl.ehufsi[nbits]))
                return false;

            /* Emit that number of bits of the value, if positive, */
            /* or the complement of its magnitude, if negative. */
            if (nbits != 0)
            {
                /* emit_bits rejects calls with size 0 */
                if (!emit_bits(state, temp2, nbits))
                    return false;
            }

            /* Encode the AC coefficients per section F.1.2.2 */
            int r = 0;          /* r = run length of zeros */
            for (int k = 1; k < JpegConstants.DCTSIZE2; k++)
            {
                temp = block[JpegUtils.jpeg_natural_order[k]];
                if (temp == 0)
                {
                    r++;
                }
                else
                {
                    /* if run length > 15, must emit special run-length-16 codes (0xF0) */
                    while (r > 15)
                    {
                        if (!emit_bits(state, actbl.ehufco[0xF0], actbl.ehufsi[0xF0]))
                            return false;
                        r -= 16;
                    }

                    temp2 = temp;
                    if (temp < 0)
                    {
                        temp = -temp;       /* temp is abs value of input */
                        /* This code assumes we are on a two's complement machine */
                        temp2--;
                    }

                    /* Find the number of bits needed for the magnitude of the coefficient */
                    nbits = 1;      /* there must be at least one 1 bit */
                    while ((temp >>= 1) != 0)
                        nbits++;

                    /* Check for out-of-range coefficient values */
                    if (nbits > MAX_HUFFMAN_COEF_BITS)
                        m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_DCT_COEF);

                    /* Emit Huffman symbol for run length / number of bits */
                    int i = (r << 4) + nbits;
                    if (!emit_bits(state, actbl.ehufco[i], actbl.ehufsi[i]))
                        return false;

                    /* Emit that number of bits of the value, if positive, */
                    /* or the complement of its magnitude, if negative. */
                    if (!emit_bits(state, temp2, nbits))
                        return false;

                    r = 0;
                }
            }

            /* If the last coef(s) were zero, emit an end-of-block code */
            if (r > 0)
            {
                if (!emit_bits(state, actbl.ehufco[0], actbl.ehufsi[0]))
                    return false;
            }

            return true;
        }
Esempio n. 9
0
        /// <summary>
        /// Finish up at the end of a Huffman-compressed scan.
        /// </summary>
        private void finish_pass_huff()
        {
            /* Load up working state ... flush_bits needs it */
            savable_state state;
            state = m_saved;

            /* Flush out the last data */
            if (!flush_bits(state))
                m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CANT_SUSPEND);

            /* Update state */
            m_saved = state;
        }
Esempio n. 10
0
        /// <summary>
        /// Encode and output one MCU's worth of Huffman-compressed coefficients.
        /// </summary>
        private bool encode_mcu_huff(JBLOCK[][] MCU_data)
        {
            /* Load up working state */
            savable_state state;
            state = m_saved;

            /* Emit restart marker if needed */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    if (!emit_restart(state, m_next_restart_num))
                        return false;
                }
            }

            /* Encode the MCU data blocks */
            for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
            {
                int ci = m_cinfo.m_MCU_membership[blkn];
                if (!encode_one_block(state, MCU_data[blkn][0].data, state.last_dc_val[ci],
                    m_dc_derived_tbls[m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]].Dc_tbl_no],
                    m_ac_derived_tbls[m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]].Ac_tbl_no]))
                {
                    return false;
                }

                /* Update last_dc_val */
                state.last_dc_val[ci] = MCU_data[blkn][0][0];
            }

            /* Completed MCU, so update state */
            m_saved = state;

            /* Update restart-interval state too */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    m_restarts_to_go = m_cinfo.m_restart_interval;
                    m_next_restart_num++;
                    m_next_restart_num &= 7;
                }

                m_restarts_to_go--;
            }

            return true;
        }
Esempio n. 11
0
            public int[] last_dc_val = new int[JpegConstants.MAX_COMPS_IN_SCAN]; /* last DC coef for each component */

            public void Assign(savable_state ss)
            {
                Buffer.BlockCopy(ss.last_dc_val, 0, last_dc_val, 0, last_dc_val.Length * sizeof(int));
            }
            public int[] last_dc_val = new int[JpegConstants.MAX_COMPS_IN_SCAN]; /* last DC coef for each component */

            #endregion Fields

            #region Methods

            public void Assign(savable_state ss)
            {
                Buffer.BlockCopy(ss.last_dc_val, 0, last_dc_val, 0, last_dc_val.Length * sizeof(int));
            }
Esempio n. 13
0
        /// <summary>
        /// Encode a single block's worth of coefficients
        /// </summary>
        private bool encode_one_block(savable_state state, short[] block, int last_dc_val, c_derived_tbl dctbl, c_derived_tbl actbl)
        {
            /* Encode the DC coefficient difference per section F.1.2.1 */
            int temp  = block[0] - last_dc_val;
            int temp2 = temp;

            if (temp < 0)
            {
                temp = -temp;       /* temp is abs value of input */
                /* For a negative input, want temp2 = bitwise complement of abs(input) */
                /* This code assumes we are on a two's complement machine */
                temp2--;
            }

            /* Find the number of bits needed for the magnitude of the coefficient */
            int nbits = 0;

            while (temp != 0)
            {
                nbits++;
                temp >>= 1;
            }

            /* Check for out-of-range coefficient values.
             * Since we're encoding a difference, the range limit is twice as much.
             */
            if (nbits > MAX_HUFFMAN_COEF_BITS + 1)
            {
                m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_DCT_COEF);
            }

            /* Emit the Huffman-coded symbol for the number of bits */
            if (!emit_bits(state, dctbl.ehufco[nbits], dctbl.ehufsi[nbits]))
            {
                return(false);
            }

            /* Emit that number of bits of the value, if positive, */
            /* or the complement of its magnitude, if negative. */
            if (nbits != 0)
            {
                /* emit_bits rejects calls with size 0 */
                if (!emit_bits(state, temp2, nbits))
                {
                    return(false);
                }
            }

            /* Encode the AC coefficients per section F.1.2.2 */
            int r = 0;          /* r = run length of zeros */

            for (int k = 1; k < JpegConstants.DCTSIZE2; k++)
            {
                temp = block[JpegUtils.jpeg_natural_order[k]];
                if (temp == 0)
                {
                    r++;
                }
                else
                {
                    /* if run length > 15, must emit special run-length-16 codes (0xF0) */
                    while (r > 15)
                    {
                        if (!emit_bits(state, actbl.ehufco[0xF0], actbl.ehufsi[0xF0]))
                        {
                            return(false);
                        }
                        r -= 16;
                    }

                    temp2 = temp;
                    if (temp < 0)
                    {
                        temp = -temp;       /* temp is abs value of input */
                        /* This code assumes we are on a two's complement machine */
                        temp2--;
                    }

                    /* Find the number of bits needed for the magnitude of the coefficient */
                    nbits = 1;      /* there must be at least one 1 bit */
                    while ((temp >>= 1) != 0)
                    {
                        nbits++;
                    }

                    /* Check for out-of-range coefficient values */
                    if (nbits > MAX_HUFFMAN_COEF_BITS)
                    {
                        m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_DCT_COEF);
                    }

                    /* Emit Huffman symbol for run length / number of bits */
                    int i = (r << 4) + nbits;
                    if (!emit_bits(state, actbl.ehufco[i], actbl.ehufsi[i]))
                    {
                        return(false);
                    }

                    /* Emit that number of bits of the value, if positive, */
                    /* or the complement of its magnitude, if negative. */
                    if (!emit_bits(state, temp2, nbits))
                    {
                        return(false);
                    }

                    r = 0;
                }
            }

            /* If the last coef(s) were zero, emit an end-of-block code */
            if (r > 0)
            {
                if (!emit_bits(state, actbl.ehufco[0], actbl.ehufsi[0]))
                {
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 14
0
        /*
         * Huffman MCU decoding.
         * Each of these routines decodes and returns one MCU's worth of
         * Huffman-compressed coefficients.
         * The coefficients are reordered from zigzag order into natural array order,
         * but are not dequantized.
         *
         * The i'th block of the MCU is stored into the block pointed to by
         * MCU_data[i].  WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER.
         *
         * We return false if data source requested suspension.  In that case no
         * changes have been made to permanent state.  (Exception: some output
         * coefficients may already have been assigned.  This is harmless for
         * spectral selection, since we'll just re-assign them on the next call.
         * Successive approximation AC refinement has to be more careful, however.)
         */

        /// <summary>
        /// MCU decoding for DC initial scan (either spectral selection,
        /// or first pass of successive approximation).
        /// </summary>
        private bool decode_mcu_DC_first(JBLOCK[] MCU_data)
        {
            /* Process restart marker if needed; may have to suspend */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    if (!process_restart())
                    {
                        return(false);
                    }
                }
            }

            /* If we've run out of data, just leave the MCU set to zeroes.
             * This way, we return uniform gray for the remainder of the segment.
             */
            if (!m_insufficient_data)
            {
                /* Load up working state */
                int get_buffer;
                int bits_left;
                bitread_working_state br_state = new bitread_working_state();
                BITREAD_LOAD_STATE(m_bitstate, out get_buffer, out bits_left, ref br_state);
                savable_state state = new savable_state();
                state.Assign(m_saved);

                /* Outer loop handles each block in the MCU */
                for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
                {
                    int ci = m_cinfo.m_MCU_membership[blkn];

                    /* Decode a single block's worth of coefficients */

                    /* Section F.2.2.1: decode the DC coefficient difference */
                    int s;
                    if (!HUFF_DECODE(out s, ref br_state, m_derived_tbls[m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[ci]].Dc_tbl_no], ref get_buffer, ref bits_left))
                    {
                        return(false);
                    }

                    if (s != 0)
                    {
                        if (!CHECK_BIT_BUFFER(ref br_state, s, ref get_buffer, ref bits_left))
                        {
                            return(false);
                        }

                        int r = GET_BITS(s, get_buffer, ref bits_left);
                        s = HUFF_EXTEND(r, s);
                    }

                    /* Convert DC difference to actual value, update last_dc_val */
                    s += state.last_dc_val[ci];
                    state.last_dc_val[ci] = s;

                    /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */
                    MCU_data[blkn][0] = (short)(s << m_cinfo.m_Al);
                }

                /* Completed MCU, so update state */
                BITREAD_SAVE_STATE(ref m_bitstate, get_buffer, bits_left);
                m_saved.Assign(state);
            }

            /* Account for restart interval (no-op if not using restarts) */
            m_restarts_to_go--;

            return(true);
        }
Esempio n. 15
0
        private bool flush_bits(savable_state state)
        {
            if (!emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */
                return false;

            state.put_buffer = 0;  /* and reset bit-buffer to empty */
            state.put_bits = 0;
            return true;
        }
        /*
         * Huffman MCU decoding.
         * Each of these routines decodes and returns one MCU's worth of
         * Huffman-compressed coefficients.
         * The coefficients are reordered from zigzag order into natural array order,
         * but are not dequantized.
         *
         * The i'th block of the MCU is stored into the block pointed to by
         * MCU_data[i].  WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER.
         *
         * We return false if data source requested suspension.  In that case no
         * changes have been made to permanent state.  (Exception: some output
         * coefficients may already have been assigned.  This is harmless for
         * spectral selection, since we'll just re-assign them on the next call.
         * Successive approximation AC refinement has to be more careful, however.)
         */
        /// <summary>
        /// MCU decoding for DC initial scan (either spectral selection,
        /// or first pass of successive approximation).
        /// </summary>
        private bool decode_mcu_DC_first(JBLOCK[] MCU_data)
        {
            /* Process restart marker if needed; may have to suspend */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    if (!process_restart())
                        return false;
                }
            }

            /* If we've run out of data, just leave the MCU set to zeroes.
             * This way, we return uniform gray for the remainder of the segment.
             */
            if (!m_insufficient_data)
            {
                /* Load up working state */
                int get_buffer;
                int bits_left;
                bitread_working_state br_state = new bitread_working_state();
                BITREAD_LOAD_STATE(m_bitstate, out get_buffer, out bits_left, ref br_state);
                savable_state state = new savable_state();
                state.Assign(m_saved);

                /* Outer loop handles each block in the MCU */
                for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
                {
                    int ci = m_cinfo.m_MCU_membership[blkn];

                    /* Decode a single block's worth of coefficients */

                    /* Section F.2.2.1: decode the DC coefficient difference */
                    int s;
                    if (!HUFF_DECODE(out s, ref br_state, m_derived_tbls[m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[ci]].Dc_tbl_no], ref get_buffer, ref bits_left))
                        return false;

                    if (s != 0)
                    {
                        if (!CHECK_BIT_BUFFER(ref br_state, s, ref get_buffer, ref bits_left))
                            return false;

                        int r = GET_BITS(s, get_buffer, ref bits_left);
                        s = HUFF_EXTEND(r, s);
                    }

                    /* Convert DC difference to actual value, update last_dc_val */
                    s += state.last_dc_val[ci];
                    state.last_dc_val[ci] = s;

                    /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */
                    MCU_data[blkn][0] = (short)(s << m_cinfo.m_Al);
                }

                /* Completed MCU, so update state */
                BITREAD_SAVE_STATE(ref m_bitstate, get_buffer, bits_left);
                m_saved.Assign(state);
            }

            /* Account for restart interval (no-op if not using restarts) */
            m_restarts_to_go--;

            return true;
        }
Esempio n. 17
0
        /// <summary>
        /// Emit a restart marker and resynchronize predictions.
        /// </summary>
        private bool emit_restart(savable_state state, int restart_num)
        {
            if (!flush_bits(state))
                return false;

            if (!emit_byte(0xFF))
                return false;

            if (!emit_byte((int)(JPEG_MARKER.RST0 + restart_num)))
                return false;

            /* Re-initialize DC predictions to 0 */
            for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
                state.last_dc_val[ci] = 0;

            /* The restart counter is not updated until we successfully write the MCU. */
            return true;
        }
Esempio n. 18
0
        /// <summary>
        /// Decode and return one MCU's worth of Huffman-compressed coefficients.
        /// The coefficients are reordered from zigzag order into natural array order,
        /// but are not dequantized.
        ///
        /// The i'th block of the MCU is stored into the block pointed to by
        /// MCU_data[i].  WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER.
        /// (Wholesale zeroing is usually a little faster than retail...)
        ///
        /// Returns false if data source requested suspension.  In that case no
        /// changes have been made to permanent state.  (Exception: some output
        /// coefficients may already have been assigned.  This is harmless for
        /// this module, since we'll just re-assign them on the next call.)
        /// </summary>
        public override bool decode_mcu(JBLOCK[] MCU_data)
        {
            /* Process restart marker if needed; may have to suspend */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    if (!process_restart())
                    {
                        return(false);
                    }
                }
            }

            /* If we've run out of data, just leave the MCU set to zeroes.
             * This way, we return uniform gray for the remainder of the segment.
             */
            if (!m_insufficient_data)
            {
                /* Load up working state */
                int get_buffer;
                int bits_left;
                bitread_working_state br_state = new bitread_working_state();
                BITREAD_LOAD_STATE(m_bitstate, out get_buffer, out bits_left, ref br_state);
                savable_state state = new savable_state();
                state.Assign(m_saved);

                /* Outer loop handles each block in the MCU */

                for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
                {
                    /* Decode a single block's worth of coefficients */

                    /* Section F.2.2.1: decode the DC coefficient difference */
                    int s;
                    if (!HUFF_DECODE(out s, ref br_state, m_dc_cur_tbls[blkn], ref get_buffer, ref bits_left))
                    {
                        return(false);
                    }

                    if (s != 0)
                    {
                        if (!CHECK_BIT_BUFFER(ref br_state, s, ref get_buffer, ref bits_left))
                        {
                            return(false);
                        }

                        int r = GET_BITS(s, get_buffer, ref bits_left);
                        s = HUFF_EXTEND(r, s);
                    }

                    if (m_dc_needed[blkn])
                    {
                        /* Convert DC difference to actual value, update last_dc_val */
                        int ci = m_cinfo.m_MCU_membership[blkn];
                        s += state.last_dc_val[ci];
                        state.last_dc_val[ci] = s;

                        /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
                        MCU_data[blkn][0] = (short)s;
                    }

                    if (m_ac_needed[blkn])
                    {
                        /* Section F.2.2.2: decode the AC coefficients */
                        /* Since zeroes are skipped, output area must be cleared beforehand */
                        for (int k = 1; k < JpegConstants.DCTSIZE2; k++)
                        {
                            if (!HUFF_DECODE(out s, ref br_state, m_ac_cur_tbls[blkn], ref get_buffer, ref bits_left))
                            {
                                return(false);
                            }

                            int r = s >> 4;
                            s &= 15;

                            if (s != 0)
                            {
                                k += r;
                                if (!CHECK_BIT_BUFFER(ref br_state, s, ref get_buffer, ref bits_left))
                                {
                                    return(false);
                                }
                                r = GET_BITS(s, get_buffer, ref bits_left);
                                s = HUFF_EXTEND(r, s);

                                /* Output coefficient in natural (dezigzagged) order.
                                 * Note: the extra entries in jpeg_natural_order[] will save us
                                 * if k >= DCTSIZE2, which could happen if the data is corrupted.
                                 */
                                MCU_data[blkn][JpegUtils.jpeg_natural_order[k]] = (short)s;
                            }
                            else
                            {
                                if (r != 15)
                                {
                                    break;
                                }

                                k += 15;
                            }
                        }
                    }
                    else
                    {
                        /* Section F.2.2.2: decode the AC coefficients */
                        /* In this path we just discard the values */
                        for (int k = 1; k < JpegConstants.DCTSIZE2; k++)
                        {
                            if (!HUFF_DECODE(out s, ref br_state, m_ac_cur_tbls[blkn], ref get_buffer, ref bits_left))
                            {
                                return(false);
                            }

                            int r = s >> 4;
                            s &= 15;

                            if (s != 0)
                            {
                                k += r;
                                if (!CHECK_BIT_BUFFER(ref br_state, s, ref get_buffer, ref bits_left))
                                {
                                    return(false);
                                }

                                DROP_BITS(s, ref bits_left);
                            }
                            else
                            {
                                if (r != 15)
                                {
                                    break;
                                }

                                k += 15;
                            }
                        }
                    }
                }

                /* Completed MCU, so update state */
                BITREAD_SAVE_STATE(ref m_bitstate, get_buffer, bits_left);
                m_saved.Assign(state);
            }

            /* Account for restart interval (no-op if not using restarts) */
            m_restarts_to_go--;

            return(true);
        }
        /// <summary>
        /// Decode and return one MCU's worth of Huffman-compressed coefficients.
        /// The coefficients are reordered from zigzag order into natural array order,
        /// but are not dequantized.
        /// 
        /// The i'th block of the MCU is stored into the block pointed to by
        /// MCU_data[i].  WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER.
        /// (Wholesale zeroing is usually a little faster than retail...)
        /// 
        /// Returns false if data source requested suspension.  In that case no
        /// changes have been made to permanent state.  (Exception: some output
        /// coefficients may already have been assigned.  This is harmless for
        /// this module, since we'll just re-assign them on the next call.)
        /// </summary>
        public override bool decode_mcu(JBLOCK[] MCU_data)
        {
            /* Process restart marker if needed; may have to suspend */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    if (!process_restart())
                        return false;
                }
            }

            /* If we've run out of data, just leave the MCU set to zeroes.
             * This way, we return uniform gray for the remainder of the segment.
             */
            if (!m_insufficient_data)
            {
                /* Load up working state */
                int get_buffer;
                int bits_left;
                bitread_working_state br_state = new bitread_working_state();
                BITREAD_LOAD_STATE(m_bitstate, out get_buffer, out bits_left, ref br_state);
                savable_state state = new savable_state();
                state.Assign(m_saved);

                /* Outer loop handles each block in the MCU */

                for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
                {
                    /* Decode a single block's worth of coefficients */

                    /* Section F.2.2.1: decode the DC coefficient difference */
                    int s;
                    if (!HUFF_DECODE(out s, ref br_state, m_dc_cur_tbls[blkn], ref get_buffer, ref bits_left))
                        return false;

                    if (s != 0)
                    {
                        if (!CHECK_BIT_BUFFER(ref br_state, s, ref get_buffer, ref bits_left))
                            return false;

                        int r = GET_BITS(s, get_buffer, ref bits_left);
                        s = HUFF_EXTEND(r, s);
                    }

                    if (m_dc_needed[blkn])
                    {
                        /* Convert DC difference to actual value, update last_dc_val */
                        int ci = m_cinfo.m_MCU_membership[blkn];
                        s += state.last_dc_val[ci];
                        state.last_dc_val[ci] = s;

                        /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
                        MCU_data[blkn][0] = (short) s;
                    }

                    if (m_ac_needed[blkn])
                    {
                        /* Section F.2.2.2: decode the AC coefficients */
                        /* Since zeroes are skipped, output area must be cleared beforehand */
                        for (int k = 1; k < JpegConstants.DCTSIZE2; k++)
                        {
                            if (!HUFF_DECODE(out s, ref br_state, m_ac_cur_tbls[blkn], ref get_buffer, ref bits_left))
                                return false;

                            int r = s >> 4;
                            s &= 15;

                            if (s != 0)
                            {
                                k += r;
                                if (!CHECK_BIT_BUFFER(ref br_state, s, ref get_buffer, ref bits_left))
                                    return false;
                                r = GET_BITS(s, get_buffer, ref bits_left);
                                s = HUFF_EXTEND(r, s);

                                /* Output coefficient in natural (dezigzagged) order.
                                   * Note: the extra entries in jpeg_natural_order[] will save us
                                   * if k >= DCTSIZE2, which could happen if the data is corrupted.
                                   */
                                MCU_data[blkn][JpegUtils.jpeg_natural_order[k]] = (short) s;
                            }
                            else
                            {
                                if (r != 15)
                                    break;

                                k += 15;
                            }
                        }
                    }
                    else
                    {
                        /* Section F.2.2.2: decode the AC coefficients */
                        /* In this path we just discard the values */
                        for (int k = 1; k < JpegConstants.DCTSIZE2; k++)
                        {
                            if (!HUFF_DECODE(out s, ref br_state, m_ac_cur_tbls[blkn], ref get_buffer, ref bits_left))
                                return false;

                            int r = s >> 4;
                            s &= 15;

                            if (s != 0)
                            {
                                k += r;
                                if (!CHECK_BIT_BUFFER(ref br_state, s, ref get_buffer, ref bits_left))
                                    return false;

                                DROP_BITS(s, ref bits_left);
                            }
                            else
                            {
                                if (r != 15)
                                    break;

                                k += 15;
                            }
                        }
                    }
                }

                /* Completed MCU, so update state */
                BITREAD_SAVE_STATE(ref m_bitstate, get_buffer, bits_left);
                m_saved.Assign(state);
            }

            /* Account for restart interval (no-op if not using restarts) */
            m_restarts_to_go--;

            return true;
        }
        /// <summary>
        /// Finish up at the end of a Huffman-compressed scan.
        /// </summary>
        private void finish_pass_huff()
        {
            if (m_cinfo.m_progressive_mode)
            {
                /* Flush out any buffered data */
                emit_eobrun();
                flush_bits_e();
            }
            else
            {
                /* Load up working state ... flush_bits needs it */
                savable_state state = new savable_state();
                state.ASSIGN_STATE(m_saved);

                /* Flush out the last data */
                if (!flush_bits_s(state))
                    m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CANT_SUSPEND);

                /* Update state */
                m_saved.ASSIGN_STATE(state);
            }
        }