BitMiracle.LibJpeg.Classic.Internal.huff_entropy_encoder.encode_mcu_AC_refine C# (CSharp) Method

encode_mcu_AC_refine() private method

MCU encoding for AC successive approximation refinement scan.
private encode_mcu_AC_refine ( JBLOCK MCU_data ) : bool
MCU_data JBLOCK
return bool
        private bool encode_mcu_AC_refine(JBLOCK[][] MCU_data)
        {
            /* Emit restart marker if needed */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                    emit_restart_e(m_next_restart_num);
            }

            /* Encode the MCU data block */

            /* It is convenient to make a pre-pass to determine the transformed
             * coefficients' absolute values and the EOB position.
             */
            int EOB = 0;
            int[] natural_order = m_cinfo.natural_order;
            int[] absvalues = new int[JpegConstants.DCTSIZE2];
            for (int k = m_cinfo.m_Ss; k <= m_cinfo.m_Se; k++)
            {
                int temp = MCU_data[0][0][natural_order[k]];

                /* We must apply the point transform by Al.  For AC coefficients this
                 * is an integer division with rounding towards 0.  To do this portably
                 * in C, we shift after obtaining the absolute value.
                 */
                if (temp < 0)
                    temp = -temp;       /* temp is abs value of input */

                temp >>= m_cinfo.m_Al;        /* apply the point transform */
                absvalues[k] = temp;    /* save abs value for main pass */

                if (temp == 1)
                {
                    /* EOB = index of last newly-nonzero coef */
                    EOB = k;
                }
            }

            /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */

            int r = 0;          /* r = run length of zeros */
            uint BR = 0;         /* BR = count of buffered bits added now */
            uint bitBufferOffset = BE; /* Append bits to buffer */

            for (int k = m_cinfo.m_Ss; k <= m_cinfo.m_Se; k++)
            {
                int temp = absvalues[k];
                if (temp == 0)
                {
                    r++;
                    continue;
                }

                /* Emit any required ZRLs, but not if they can be folded into EOB */
                while (r > 15 && k <= EOB)
                {
                    /* emit any pending EOBRUN and the BE correction bits */
                    emit_eobrun();

                    /* Emit ZRL */
                    emit_ac_symbol(ac_tbl_no, 0xF0);
                    r -= 16;

                    /* Emit buffered correction bits that must be associated with ZRL */
                    emit_buffered_bits(bitBufferOffset, BR);
                    bitBufferOffset = 0;/* BE bits are gone now */
                    BR = 0;
                }

                /* If the coef was previously nonzero, it only needs a correction bit.
                 * NOTE: a straight translation of the spec's figure G.7 would suggest
                 * that we also need to test r > 15.  But if r > 15, we can only get here
                 * if k > EOB, which implies that this coefficient is not 1.
                 */
                if (temp > 1)
                {
                    /* The correction bit is the next bit of the absolute value. */
                    bit_buffer[bitBufferOffset + BR] = (char)(temp & 1);
                    BR++;
                    continue;
                }

                /* Emit any pending EOBRUN and the BE correction bits */
                emit_eobrun();

                /* Count/emit Huffman symbol for run length / number of bits */
                emit_ac_symbol(ac_tbl_no, (r << 4) + 1);

                /* Emit output bit for newly-nonzero coef */
                temp = (MCU_data[0][0][natural_order[k]] < 0) ? 0 : 1;
                emit_bits_e(temp, 1);

                /* Emit buffered correction bits that must be associated with this code */
                emit_buffered_bits(bitBufferOffset, BR);
                bitBufferOffset = 0;/* BE bits are gone now */
                BR = 0;
                r = 0;          /* reset zero run length */
            }

            if (r > 0 || BR > 0)
            {
                /* If there are trailing zeroes, */
                EOBRUN++;      /* count an EOB */
                BE += BR;      /* concat my correction bits to older ones */

                /* We force out the EOB if we risk either:
                 * 1. overflow of the EOB counter;
                 * 2. overflow of the correction bit buffer during the next MCU.
                 */
                if (EOBRUN == 0x7FFF || BE > (MAX_CORR_BITS - JpegConstants.DCTSIZE2 + 1))
                    emit_eobrun();
            }

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