Bitreading working state within an MCU
Ejemplo n.º 1
0
        /// <summary>
        /// MCU decoding for DC successive approximation refinement scan.
        /// Note: we assume such scans can be multi-component, although the spec
        /// is not very clear on the point.
        /// </summary>
        private bool decode_mcu_DC_refine(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);
                    }
                }
            }

            /* Not worth the cycles to check insufficient_data here,
             * since we will not change the data anyway if we read zeroes.
             */

            /* 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);

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

            for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
            {
                /* Encoded data is simply the next bit of the two's-complement DC value */
                if (!CHECK_BIT_BUFFER(ref br_state, 1, ref get_buffer, ref bits_left))
                {
                    return(false);
                }

                if (GET_BITS(1, get_buffer, ref bits_left) != 0)
                {
                    /* 1 in the bit position being coded */
                    MCU_data[blkn][0] |= (short)(1 << m_cinfo.m_Al);
                }

                /* Note: since we use |=, repeating the assignment later is safe */
            }

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

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

            return(true);
        }
        /*
         * These methods provide the in-line portion of bit fetching.
         * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer
         * before using GET_BITS, PEEK_BITS, or DROP_BITS.
         * The variables get_buffer and bits_left are assumed to be locals,
         * but the state struct might not be (jpeg_huff_decode needs this).
         *  CHECK_BIT_BUFFER(state,n,action);
         *      Ensure there are N bits in get_buffer; if suspend, take action.
         *      val = GET_BITS(n);
         *      Fetch next N bits.
         *      val = PEEK_BITS(n);
         *      Fetch next N bits without removing them from the buffer.
         *  DROP_BITS(n);
         *      Discard next N bits.
         * The value N should be a simple variable, not an expression, because it
         * is evaluated multiple times.
         */

        protected static bool CHECK_BIT_BUFFER(ref bitread_working_state state, int nbits, ref int get_buffer, ref int bits_left)
        {
            if (bits_left < nbits)
            {
                if (!jpeg_fill_bit_buffer(ref state, get_buffer, bits_left, nbits))
                {
                    return(false);
                }

                get_buffer = state.get_buffer;
                bits_left  = state.bits_left;
            }

            return(true);
        }
        /*
         * Code for extracting next Huffman-coded symbol from input bit stream.
         * Again, this is time-critical and we make the main paths be macros.
         *
         * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits
         * without looping.  Usually, more than 95% of the Huffman codes will be 8
         * or fewer bits long.  The few overlength codes are handled with a loop,
         * which need not be inline code.
         *
         * Notes about the HUFF_DECODE macro:
         * 1. Near the end of the data segment, we may fail to get enough bits
         *    for a lookahead.  In that case, we do it the hard way.
         * 2. If the lookahead table contains no entry, the next code must be
         *    more than HUFF_LOOKAHEAD bits long.
         * 3. jpeg_huff_decode returns -1 if forced to suspend.
         */
        protected static bool HUFF_DECODE(out int result, ref bitread_working_state state, d_derived_tbl htbl, ref int get_buffer, ref int bits_left)
        {
            int  nb     = 0;
            bool doSlow = false;

            if (bits_left < JpegConstants.HUFF_LOOKAHEAD)
            {
                if (!jpeg_fill_bit_buffer(ref state, get_buffer, bits_left, 0))
                {
                    result = -1;
                    return(false);
                }

                get_buffer = state.get_buffer;
                bits_left  = state.bits_left;
                if (bits_left < JpegConstants.HUFF_LOOKAHEAD)
                {
                    nb     = 1;
                    doSlow = true;
                }
            }

            if (!doSlow)
            {
                int look = PEEK_BITS(JpegConstants.HUFF_LOOKAHEAD, get_buffer, bits_left);
                if ((nb = htbl.look_nbits[look]) != 0)
                {
                    DROP_BITS(nb, ref bits_left);
                    result = htbl.look_sym[look];
                    return(true);
                }

                nb = JpegConstants.HUFF_LOOKAHEAD + 1;
            }

            result = jpeg_huff_decode(ref state, get_buffer, bits_left, htbl, nb);
            if (result < 0)
            {
                return(false);
            }

            get_buffer = state.get_buffer;
            bits_left  = state.bits_left;

            return(true);
        }
        /* Out-of-line case for Huffman code fetching */
        protected static int jpeg_huff_decode(ref bitread_working_state state, int get_buffer, int bits_left, d_derived_tbl htbl, int min_bits)
        {
            /* HUFF_DECODE has determined that the code is at least min_bits */
            /* bits long, so fetch that many bits in one swoop. */
            int l = min_bits;

            if (!CHECK_BIT_BUFFER(ref state, l, ref get_buffer, ref bits_left))
            {
                return(-1);
            }

            int code = GET_BITS(l, get_buffer, ref bits_left);

            /* Collect the rest of the Huffman code one bit at a time. */
            /* This is per Figure F.16 in the JPEG spec. */

            while (code > htbl.maxcode[l])
            {
                code <<= 1;
                if (!CHECK_BIT_BUFFER(ref state, 1, ref get_buffer, ref bits_left))
                {
                    return(-1);
                }

                code |= GET_BITS(1, get_buffer, ref bits_left);
                l++;
            }

            /* Unload the local registers */
            state.get_buffer = get_buffer;
            state.bits_left  = bits_left;

            /* With garbage input we may reach the sentinel value l = 17. */

            if (l > 16)
            {
                state.cinfo.WARNMS(J_MESSAGE_CODE.JWRN_HUFF_BAD_CODE);
                /* fake a zero as the safest result */
                return(0);
            }

            return(htbl.pub.Huffval[code + htbl.valoffset[l]]);
        }
        /*
        * These methods provide the in-line portion of bit fetching.
        * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer
        * before using GET_BITS, PEEK_BITS, or DROP_BITS.
        * The variables get_buffer and bits_left are assumed to be locals,
        * but the state struct might not be (jpeg_huff_decode needs this).
        *  CHECK_BIT_BUFFER(state,n,action);
        *      Ensure there are N bits in get_buffer; if suspend, take action.
        *      val = GET_BITS(n);
        *      Fetch next N bits.
        *      val = PEEK_BITS(n);
        *      Fetch next N bits without removing them from the buffer.
        *  DROP_BITS(n);
        *      Discard next N bits.
        * The value N should be a simple variable, not an expression, because it
        * is evaluated multiple times.
        */

        protected static bool CHECK_BIT_BUFFER(ref bitread_working_state state, int nbits, ref int get_buffer, ref int bits_left)
        {
            if (bits_left < nbits)
            {
                if (!jpeg_fill_bit_buffer(ref state, get_buffer, bits_left, nbits))
                    return false;

                get_buffer = state.get_buffer;
                bits_left = state.bits_left;
            }

            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;
        }
Ejemplo n.º 7
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);
        }
 protected void BITREAD_LOAD_STATE(bitread_perm_state bitstate, out int get_buffer, out int bits_left, ref bitread_working_state br_state)
 {
     br_state.cinfo = m_cinfo;
     get_buffer     = bitstate.get_buffer;
     bits_left      = bitstate.bits_left;
 }
Ejemplo n.º 9
0
        /// <summary>
        /// MCU decoding for AC initial scan (either spectral selection,
        /// or first pass of successive approximation).
        /// </summary>
        private bool decode_mcu_AC_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.
                 * We can avoid loading/saving bitread state if in an EOB run.
                 */
                int EOBRUN = m_saved.EOBRUN; /* only part of saved state we need */

                /* There is always only one block per MCU */

                if (EOBRUN > 0)
                {
                    /* if it's a band of zeroes... */
                    /* ...process it now (we do nothing) */
                    EOBRUN--;
                }
                else
                {
                    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);

                    for (int k = m_cinfo.m_Ss; k <= m_cinfo.m_Se; k++)
                    {
                        int s;
                        if (!HUFF_DECODE(out s, ref br_state, m_ac_derived_tbl, 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);

                            /* Scale and output coefficient in natural (dezigzagged) order */
                            MCU_data[0][JpegUtils.jpeg_natural_order[k]] = (short)(s << m_cinfo.m_Al);
                        }
                        else
                        {
                            if (r == 15)
                            {
                                /* ZRL */
                                k += 15;        /* skip 15 zeroes in band */
                            }
                            else
                            {
                                /* EOBr, run length is 2^r + appended bits */
                                EOBRUN = 1 << r;
                                if (r != 0)
                                {
                                    /* EOBr, r > 0 */
                                    if (!CHECK_BIT_BUFFER(ref br_state, r, ref get_buffer, ref bits_left))
                                    {
                                        return(false);
                                    }

                                    r       = GET_BITS(r, get_buffer, ref bits_left);
                                    EOBRUN += r;
                                }

                                EOBRUN--;   /* this band is processed at this moment */
                                break;      /* force end-of-band */
                            }
                        }
                    }

                    BITREAD_SAVE_STATE(ref m_bitstate, get_buffer, bits_left);
                }

                /* Completed MCU, so update state */
                m_saved.EOBRUN = EOBRUN; /* only part of saved state we need */
            }

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

            return(true);
        }
        /* Out-of-line case for Huffman code fetching */
        protected static int jpeg_huff_decode(ref bitread_working_state state, int get_buffer, int bits_left, d_derived_tbl htbl, int min_bits)
        {
            /* HUFF_DECODE has determined that the code is at least min_bits */
            /* bits long, so fetch that many bits in one swoop. */
            int l = min_bits;
            if (!CHECK_BIT_BUFFER(ref state, l, ref get_buffer, ref bits_left))
                return -1;

            int code = GET_BITS(l, get_buffer, ref bits_left);

            /* Collect the rest of the Huffman code one bit at a time. */
            /* This is per Figure F.16 in the JPEG spec. */

            while (code > htbl.maxcode[l])
            {
                code <<= 1;
                if (!CHECK_BIT_BUFFER(ref state, 1, ref get_buffer, ref bits_left))
                    return -1;

                code |= GET_BITS(1, get_buffer, ref bits_left);
                l++;
            }

            /* Unload the local registers */
            state.get_buffer = get_buffer;
            state.bits_left = bits_left;

            /* With garbage input we may reach the sentinel value l = 17. */

            if (l > 16)
            {
                state.cinfo.WARNMS(J_MESSAGE_CODE.JWRN_HUFF_BAD_CODE);
                /* fake a zero as the safest result */
                return 0;
            }

            return htbl.pub.Huffval[code + htbl.valoffset[l]];
        }
        /// <summary>
        /// MCU decoding for DC successive approximation refinement scan.
        /// Note: we assume such scans can be multi-component, although the spec
        /// is not very clear on the point.
        /// </summary>
        private bool decode_mcu_DC_refine(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;
                }
            }

            /* Not worth the cycles to check insufficient_data here,
             * since we will not change the data anyway if we read zeroes.
             */

            /* 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);

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

            for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
            {
                /* Encoded data is simply the next bit of the two's-complement DC value */
                if (!CHECK_BIT_BUFFER(ref br_state, 1, ref get_buffer, ref bits_left))
                    return false;

                if (GET_BITS(1, get_buffer, ref bits_left) != 0)
                {
                    /* 1 in the bit position being coded */
                    MCU_data[blkn][0] = (short)((ushort)MCU_data[blkn][0] | (ushort)(1 << m_cinfo.m_Al));
                }

                /* Note: since we use |=, repeating the assignment later is safe */
            }

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

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

            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;
        }
        // There is always only one block per MCU
        private bool decode_mcu_AC_refine(JBLOCK[] MCU_data)
        {
            int p1 = 1 << m_cinfo.m_Al;    /* 1 in the bit position being coded */
            int m1 = -1 << m_cinfo.m_Al; /* -1 in the bit position being coded */

            /* 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, don't modify the MCU.
             */
            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);
                int EOBRUN = m_saved.EOBRUN; /* only part of saved state we need */

                /* If we are forced to suspend, we must undo the assignments to any newly
                 * nonzero coefficients in the block, because otherwise we'd get confused
                 * next time about which coefficients were already nonzero.
                 * But we need not undo addition of bits to already-nonzero coefficients;
                 * instead, we can test the current bit to see if we already did it.
                 */
                int num_newnz = 0;
                int[] newnz_pos = new int[JpegConstants.DCTSIZE2];

                /* initialize coefficient loop counter to start of band */
                int k = m_cinfo.m_Ss;

                if (EOBRUN == 0)
                {
                    for (; k <= m_cinfo.m_Se; k++)
                    {
                        int s;
                        if (!HUFF_DECODE(out s, ref br_state, m_ac_derived_tbl, ref get_buffer, ref bits_left))
                        {
                            undo_decode_mcu_AC_refine(MCU_data, newnz_pos, num_newnz);
                            return false;
                        }

                        int r = s >> 4;
                        s &= 15;
                        if (s != 0)
                        {
                            if (s != 1)
                            {
                                /* size of new coef should always be 1 */
                                m_cinfo.WARNMS(J_MESSAGE_CODE.JWRN_HUFF_BAD_CODE);
                            }

                            if (!CHECK_BIT_BUFFER(ref br_state, 1, ref get_buffer, ref bits_left))
                            {
                                undo_decode_mcu_AC_refine(MCU_data, newnz_pos, num_newnz);
                                return false;
                            }

                            if (GET_BITS(1, get_buffer, ref bits_left) != 0)
                            {
                                /* newly nonzero coef is positive */
                                s = p1;
                            }
                            else
                            {
                                /* newly nonzero coef is negative */
                                s = m1;
                            }
                        }
                        else
                        {
                            if (r != 15)
                            {
                                EOBRUN = 1 << r;    /* EOBr, run length is 2^r + appended bits */
                                if (r != 0)
                                {
                                    if (!CHECK_BIT_BUFFER(ref br_state, r, ref get_buffer, ref bits_left))
                                    {
                                        undo_decode_mcu_AC_refine(MCU_data, newnz_pos, num_newnz);
                                        return false;
                                    }

                                    r = GET_BITS(r, get_buffer, ref bits_left);
                                    EOBRUN += r;
                                }
                                break;      /* rest of block is handled by EOB logic */
                            }
                            /* note s = 0 for processing ZRL */
                        }
                        /* Advance over already-nonzero coefs and r still-zero coefs,
                         * appending correction bits to the nonzeroes.  A correction bit is 1
                         * if the absolute value of the coefficient must be increased.
                         */
                        do
                        {
                            int blockIndex = JpegUtils.jpeg_natural_order[k];
                            short thiscoef = MCU_data[0][blockIndex];
                            if (thiscoef != 0)
                            {
                                if (!CHECK_BIT_BUFFER(ref br_state, 1, ref get_buffer, ref bits_left))
                                {
                                    undo_decode_mcu_AC_refine(MCU_data, newnz_pos, num_newnz);
                                    return false;
                                }

                                if (GET_BITS(1, get_buffer, ref bits_left) != 0)
                                {
                                    if ((thiscoef & p1) == 0)
                                    {
                                        /* do nothing if already set it */
                                        if (thiscoef >= 0)
                                            MCU_data[0][blockIndex] += (short)p1;
                                        else
                                            MCU_data[0][blockIndex] += (short)m1;
                                    }
                                }
                            }
                            else
                            {
                                if (--r < 0)
                                    break;      /* reached target zero coefficient */
                            }

                            k++;
                        }
                        while (k <= m_cinfo.m_Se);

                        if (s != 0)
                        {
                            int pos = JpegUtils.jpeg_natural_order[k];

                            /* Output newly nonzero coefficient */
                            MCU_data[0][pos] = (short)s;

                            /* Remember its position in case we have to suspend */
                            newnz_pos[num_newnz++] = pos;
                        }
                    }
                }

                if (EOBRUN > 0)
                {
                    /* Scan any remaining coefficient positions after the end-of-band
                     * (the last newly nonzero coefficient, if any).  Append a correction
                     * bit to each already-nonzero coefficient.  A correction bit is 1
                     * if the absolute value of the coefficient must be increased.
                     */
                    for (; k <= m_cinfo.m_Se; k++)
                    {
                        int blockIndex = JpegUtils.jpeg_natural_order[k];
                        short thiscoef = MCU_data[0][blockIndex];
                        if (thiscoef != 0)
                        {
                            if (!CHECK_BIT_BUFFER(ref br_state, 1, ref get_buffer, ref bits_left))
                            {
                                //undo_decode_mcu_AC_refine(MCU_data[0], newnz_pos, num_newnz);
                                undo_decode_mcu_AC_refine(MCU_data, newnz_pos, num_newnz);
                                return false;
                            }

                            if (GET_BITS(1, get_buffer, ref bits_left) != 0)
                            {
                                if ((thiscoef & p1) == 0)
                                {
                                    /* do nothing if already changed it */
                                    if (thiscoef >= 0)
                                        MCU_data[0][blockIndex] += (short)p1;
                                    else
                                        MCU_data[0][blockIndex] += (short)m1;
                                }
                            }
                        }
                    }

                    /* Count one block completed in EOB run */
                    EOBRUN--;
                }

                /* Completed MCU, so update state */
                BITREAD_SAVE_STATE(ref m_bitstate, get_buffer, bits_left);
                m_saved.EOBRUN = EOBRUN; /* only part of saved state we need */
            }

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

            return true;
        }
        /// <summary>
        /// MCU decoding for AC initial scan (either spectral selection,
        /// or first pass of successive approximation).
        /// </summary>
        private bool decode_mcu_AC_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.
                 * We can avoid loading/saving bitread state if in an EOB run.
                 */
                int EOBRUN = m_saved.EOBRUN; /* only part of saved state we need */

                /* There is always only one block per MCU */

                if (EOBRUN > 0)
                {
                    /* if it's a band of zeroes... */
                    /* ...process it now (we do nothing) */
                    EOBRUN--;
                }
                else
                {
                    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);

                    for (int k = m_cinfo.m_Ss; k <= m_cinfo.m_Se; k++)
                    {
                        int s;
                        if (!HUFF_DECODE(out s, ref br_state, m_ac_derived_tbl, 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);

                            /* Scale and output coefficient in natural (dezigzagged) order */
                            MCU_data[0][JpegUtils.jpeg_natural_order[k]] = (short)(s << m_cinfo.m_Al);
                        }
                        else
                        {
                            if (r == 15)
                            {
                                /* ZRL */
                                k += 15;        /* skip 15 zeroes in band */
                            }
                            else
                            {
                                /* EOBr, run length is 2^r + appended bits */
                                EOBRUN = 1 << r;
                                if (r != 0)
                                {
                                    /* EOBr, r > 0 */
                                    if (!CHECK_BIT_BUFFER(ref br_state, r, ref get_buffer, ref bits_left))
                                        return false;

                                    r = GET_BITS(r, get_buffer, ref bits_left);
                                    EOBRUN += r;
                                }

                                EOBRUN--;       /* this band is processed at this moment */
                                break;      /* force end-of-band */
                            }
                        }
                    }

                    BITREAD_SAVE_STATE(ref m_bitstate, get_buffer, bits_left);
                }

                /* Completed MCU, so update state */
                m_saved.EOBRUN = EOBRUN; /* only part of saved state we need */
            }

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

            return true;
        }
Ejemplo n.º 15
0
        // There is always only one block per MCU
        private bool decode_mcu_AC_refine(JBLOCK[] MCU_data)
        {
            int p1 = 1 << m_cinfo.m_Al;  /* 1 in the bit position being coded */
            int m1 = -1 << m_cinfo.m_Al; /* -1 in the bit position being coded */

            /* 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, don't modify the MCU.
             */
            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);
                int EOBRUN = m_saved.EOBRUN; /* only part of saved state we need */

                /* If we are forced to suspend, we must undo the assignments to any newly
                 * nonzero coefficients in the block, because otherwise we'd get confused
                 * next time about which coefficients were already nonzero.
                 * But we need not undo addition of bits to already-nonzero coefficients;
                 * instead, we can test the current bit to see if we already did it.
                 */
                int   num_newnz = 0;
                int[] newnz_pos = new int[JpegConstants.DCTSIZE2];

                /* initialize coefficient loop counter to start of band */
                int k = m_cinfo.m_Ss;

                if (EOBRUN == 0)
                {
                    for (; k <= m_cinfo.m_Se; k++)
                    {
                        int s;
                        if (!HUFF_DECODE(out s, ref br_state, m_ac_derived_tbl, ref get_buffer, ref bits_left))
                        {
                            undo_decode_mcu_AC_refine(MCU_data, newnz_pos, num_newnz);
                            return(false);
                        }

                        int r = s >> 4;
                        s &= 15;
                        if (s != 0)
                        {
                            if (s != 1)
                            {
                                /* size of new coef should always be 1 */
                                m_cinfo.WARNMS(J_MESSAGE_CODE.JWRN_HUFF_BAD_CODE);
                            }

                            if (!CHECK_BIT_BUFFER(ref br_state, 1, ref get_buffer, ref bits_left))
                            {
                                undo_decode_mcu_AC_refine(MCU_data, newnz_pos, num_newnz);
                                return(false);
                            }

                            if (GET_BITS(1, get_buffer, ref bits_left) != 0)
                            {
                                /* newly nonzero coef is positive */
                                s = p1;
                            }
                            else
                            {
                                /* newly nonzero coef is negative */
                                s = m1;
                            }
                        }
                        else
                        {
                            if (r != 15)
                            {
                                EOBRUN = 1 << r;    /* EOBr, run length is 2^r + appended bits */
                                if (r != 0)
                                {
                                    if (!CHECK_BIT_BUFFER(ref br_state, r, ref get_buffer, ref bits_left))
                                    {
                                        undo_decode_mcu_AC_refine(MCU_data, newnz_pos, num_newnz);
                                        return(false);
                                    }

                                    r       = GET_BITS(r, get_buffer, ref bits_left);
                                    EOBRUN += r;
                                }
                                break;      /* rest of block is handled by EOB logic */
                            }
                            /* note s = 0 for processing ZRL */
                        }

                        /* Advance over already-nonzero coefs and r still-zero coefs,
                         * appending correction bits to the nonzeroes.  A correction bit is 1
                         * if the absolute value of the coefficient must be increased.
                         */
                        do
                        {
                            int   blockIndex = JpegUtils.jpeg_natural_order[k];
                            short thiscoef   = MCU_data[0][blockIndex];
                            if (thiscoef != 0)
                            {
                                if (!CHECK_BIT_BUFFER(ref br_state, 1, ref get_buffer, ref bits_left))
                                {
                                    undo_decode_mcu_AC_refine(MCU_data, newnz_pos, num_newnz);
                                    return(false);
                                }

                                if (GET_BITS(1, get_buffer, ref bits_left) != 0)
                                {
                                    if ((thiscoef & p1) == 0)
                                    {
                                        /* do nothing if already set it */
                                        if (thiscoef >= 0)
                                        {
                                            MCU_data[0][blockIndex] += (short)p1;
                                        }
                                        else
                                        {
                                            MCU_data[0][blockIndex] += (short)m1;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if (--r < 0)
                                {
                                    break;      /* reached target zero coefficient */
                                }
                            }

                            k++;
                        }while (k <= m_cinfo.m_Se);

                        if (s != 0)
                        {
                            int pos = JpegUtils.jpeg_natural_order[k];

                            /* Output newly nonzero coefficient */
                            MCU_data[0][pos] = (short)s;

                            /* Remember its position in case we have to suspend */
                            newnz_pos[num_newnz++] = pos;
                        }
                    }
                }

                if (EOBRUN > 0)
                {
                    /* Scan any remaining coefficient positions after the end-of-band
                     * (the last newly nonzero coefficient, if any).  Append a correction
                     * bit to each already-nonzero coefficient.  A correction bit is 1
                     * if the absolute value of the coefficient must be increased.
                     */
                    for (; k <= m_cinfo.m_Se; k++)
                    {
                        int   blockIndex = JpegUtils.jpeg_natural_order[k];
                        short thiscoef   = MCU_data[0][blockIndex];
                        if (thiscoef != 0)
                        {
                            if (!CHECK_BIT_BUFFER(ref br_state, 1, ref get_buffer, ref bits_left))
                            {
                                //undo_decode_mcu_AC_refine(MCU_data[0], newnz_pos, num_newnz);
                                undo_decode_mcu_AC_refine(MCU_data, newnz_pos, num_newnz);
                                return(false);
                            }

                            if (GET_BITS(1, get_buffer, ref bits_left) != 0)
                            {
                                if ((thiscoef & p1) == 0)
                                {
                                    /* do nothing if already changed it */
                                    if (thiscoef >= 0)
                                    {
                                        MCU_data[0][blockIndex] += (short)p1;
                                    }
                                    else
                                    {
                                        MCU_data[0][blockIndex] += (short)m1;
                                    }
                                }
                            }
                        }
                    }

                    /* Count one block completed in EOB run */
                    EOBRUN--;
                }

                /* Completed MCU, so update state */
                BITREAD_SAVE_STATE(ref m_bitstate, get_buffer, bits_left);
                m_saved.EOBRUN = EOBRUN; /* only part of saved state we need */
            }

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

            return(true);
        }
        /* Load up the bit buffer to a depth of at least nbits */
        protected static bool jpeg_fill_bit_buffer(ref bitread_working_state state, int get_buffer, int bits_left, int nbits)
        {
            /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */
            /* (It is assumed that no request will be for more than that many bits.) */
            /* We fail to do so only if we hit a marker or are forced to suspend. */

            bool noMoreBytes = false;

            if (state.cinfo.m_unread_marker == 0)
            {
                /* cannot advance past a marker */
                while (bits_left < MIN_GET_BITS)
                {
                    int c;
                    state.cinfo.m_src.GetByte(out c);

                    /* If it's 0xFF, check and discard stuffed zero byte */
                    if (c == 0xFF)
                    {
                        /* Loop here to discard any padding FF's on terminating marker,
                        * so that we can save a valid unread_marker value.  NOTE: we will
                        * accept multiple FF's followed by a 0 as meaning a single FF data
                        * byte.  This data pattern is not valid according to the standard.
                        */
                        do
                        {
                            state.cinfo.m_src.GetByte(out c);
                        }
                        while (c == 0xFF);

                        if (c == 0)
                        {
                            /* Found FF/00, which represents an FF data byte */
                            c = 0xFF;
                        }
                        else
                        {
                            /* Oops, it's actually a marker indicating end of compressed data.
                            * Save the marker code for later use.
                            * Fine point: it might appear that we should save the marker into
                            * bitread working state, not straight into permanent state.  But
                            * once we have hit a marker, we cannot need to suspend within the
                            * current MCU, because we will read no more bytes from the data
                            * source.  So it is OK to update permanent state right away.
                            */
                            state.cinfo.m_unread_marker = c;
                            /* See if we need to insert some fake zero bits. */
                            noMoreBytes = true;
                            break;
                        }
                    }

                    /* OK, load c into get_buffer */
                    get_buffer = (get_buffer << 8) | c;
                    bits_left += 8;
                } /* end while */
            }
            else
                noMoreBytes = true;

            if (noMoreBytes)
            {
                /* We get here if we've read the marker that terminates the compressed
                * data segment.  There should be enough bits in the buffer register
                * to satisfy the request; if so, no problem.
                */
                if (nbits > bits_left)
                {
                    /* Uh-oh.  Report corrupted data to user and stuff zeroes into
                    * the data stream, so that we can produce some kind of image.
                    * We use a nonvolatile flag to ensure that only one warning message
                    * appears per data segment.
                    */
                    if (!state.cinfo.m_entropy.m_insufficient_data)
                    {
                        state.cinfo.WARNMS(J_MESSAGE_CODE.JWRN_HIT_MARKER);
                        state.cinfo.m_entropy.m_insufficient_data = true;
                    }

                    /* Fill the buffer with zero bits */
                    get_buffer <<= MIN_GET_BITS - bits_left;
                    bits_left = MIN_GET_BITS;
                }
            }

            /* Unload the local registers */
            state.get_buffer = get_buffer;
            state.bits_left = bits_left;

            return true;
        }
        /*
        * Code for extracting next Huffman-coded symbol from input bit stream.
        * Again, this is time-critical and we make the main paths be macros.
        *
        * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits
        * without looping.  Usually, more than 95% of the Huffman codes will be 8
        * or fewer bits long.  The few overlength codes are handled with a loop,
        * which need not be inline code.
        *
        * Notes about the HUFF_DECODE macro:
        * 1. Near the end of the data segment, we may fail to get enough bits
        *    for a lookahead.  In that case, we do it the hard way.
        * 2. If the lookahead table contains no entry, the next code must be
        *    more than HUFF_LOOKAHEAD bits long.
        * 3. jpeg_huff_decode returns -1 if forced to suspend.
        */
        protected static bool HUFF_DECODE(out int result, ref bitread_working_state state, d_derived_tbl htbl, ref int get_buffer, ref int bits_left)
        {
            int nb = 0;
            bool doSlow = false;

            if (bits_left < JpegConstants.HUFF_LOOKAHEAD)
            {
                if (!jpeg_fill_bit_buffer(ref state, get_buffer, bits_left, 0))
                {
                    result = -1;
                    return false;
                }

                get_buffer = state.get_buffer;
                bits_left = state.bits_left;
                if (bits_left < JpegConstants.HUFF_LOOKAHEAD)
                {
                    nb = 1;
                    doSlow = true;
                }
            }

            if (!doSlow)
            {
                int look = PEEK_BITS(JpegConstants.HUFF_LOOKAHEAD, get_buffer, bits_left);
                if ((nb = htbl.look_nbits[look]) != 0)
                {
                    DROP_BITS(nb, ref bits_left);
                    result = htbl.look_sym[look];
                    return true;
                }

                nb = JpegConstants.HUFF_LOOKAHEAD + 1;
            }

            result = jpeg_huff_decode(ref state, get_buffer, bits_left, htbl, nb);
            if (result < 0)
                return false;

            get_buffer = state.get_buffer;
            bits_left = state.bits_left;

            return true;
        }
Ejemplo n.º 18
0
        /* Load up the bit buffer to a depth of at least nbits */
        protected static bool jpeg_fill_bit_buffer(ref bitread_working_state state, int get_buffer, int bits_left, int nbits)
        {
            /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */
            /* (It is assumed that no request will be for more than that many bits.) */
            /* We fail to do so only if we hit a marker or are forced to suspend. */

            bool noMoreBytes = false;

            if (state.cinfo.m_unread_marker == 0)
            {
                /* cannot advance past a marker */
                while (bits_left < MIN_GET_BITS)
                {
                    int c;
                    state.cinfo.m_src.GetByte(out c);

                    /* If it's 0xFF, check and discard stuffed zero byte */
                    if (c == 0xFF)
                    {
                        /* Loop here to discard any padding FF's on terminating marker,
                         * so that we can save a valid unread_marker value.  NOTE: we will
                         * accept multiple FF's followed by a 0 as meaning a single FF data
                         * byte.  This data pattern is not valid according to the standard.
                         */
                        do
                        {
                            state.cinfo.m_src.GetByte(out c);
                        }while (c == 0xFF);

                        if (c == 0)
                        {
                            /* Found FF/00, which represents an FF data byte */
                            c = 0xFF;
                        }
                        else
                        {
                            /* Oops, it's actually a marker indicating end of compressed data.
                             * Save the marker code for later use.
                             * Fine point: it might appear that we should save the marker into
                             * bitread working state, not straight into permanent state.  But
                             * once we have hit a marker, we cannot need to suspend within the
                             * current MCU, because we will read no more bytes from the data
                             * source.  So it is OK to update permanent state right away.
                             */
                            state.cinfo.m_unread_marker = c;
                            /* See if we need to insert some fake zero bits. */
                            noMoreBytes = true;
                            break;
                        }
                    }

                    /* OK, load c into get_buffer */
                    get_buffer = (get_buffer << 8) | c;
                    bits_left += 8;
                } /* end while */
            }
            else
            {
                noMoreBytes = true;
            }

            if (noMoreBytes)
            {
                /* We get here if we've read the marker that terminates the compressed
                 * data segment.  There should be enough bits in the buffer register
                 * to satisfy the request; if so, no problem.
                 */
                if (nbits > bits_left)
                {
                    /* Uh-oh.  Report corrupted data to user and stuff zeroes into
                     * the data stream, so that we can produce some kind of image.
                     * We use a nonvolatile flag to ensure that only one warning message
                     * appears per data segment.
                     */
                    if (!state.cinfo.m_entropy.m_insufficient_data)
                    {
                        state.cinfo.WARNMS(J_MESSAGE_CODE.JWRN_HIT_MARKER);
                        state.cinfo.m_entropy.m_insufficient_data = true;
                    }

                    /* Fill the buffer with zero bits */
                    get_buffer <<= MIN_GET_BITS - bits_left;
                    bits_left    = MIN_GET_BITS;
                }
            }

            /* Unload the local registers */
            state.get_buffer = get_buffer;
            state.bits_left  = bits_left;

            return(true);
        }
 protected void BITREAD_LOAD_STATE(bitread_perm_state bitstate, out int get_buffer, out int bits_left, ref bitread_working_state br_state)
 {
     br_state.cinfo = m_cinfo;
     get_buffer = bitstate.get_buffer;
     bits_left = bitstate.bits_left;
 }
Ejemplo n.º 20
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);
        }