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

encode_mcu_AC_first() private method

MCU encoding for AC initial scan (either spectral selection, or first pass of successive approximation).
private encode_mcu_AC_first ( JBLOCK MCU_data ) : bool
MCU_data JBLOCK
return bool
        private bool encode_mcu_AC_first(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);
            }

            int[] natural_order = m_cinfo.natural_order;
            /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */
            /* r = run length of zeros */
            int r = 0;
            for (int k = m_cinfo.m_Ss; k <= m_cinfo.m_Se; k++)
            {
                int temp = MCU_data[0][0][natural_order[k]];
                if (temp == 0)
                {
                    r++;
                    continue;
                }

                /* 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; so the code is
                 * interwoven with finding the abs value (temp) and output bits (temp2).
                 */
                int temp2;
                if (temp < 0)
                {
                    temp = -temp;       /* temp is abs value of input */
                    temp >>= m_cinfo.m_Al;        /* apply the point transform */
                    /* For a negative coef, want temp2 = bitwise complement of abs(coef) */
                    temp2 = ~temp;
                }
                else
                {
                    temp >>= m_cinfo.m_Al;        /* apply the point transform */
                    temp2 = temp;
                }

                /* Watch out for case that nonzero coef is zero after point transform */
                if (temp == 0)
                {
                    r++;
                    continue;
                }

                /* Emit any pending EOBRUN */
                if (EOBRUN > 0)
                    emit_eobrun();

                /* if run length > 15, must emit special run-length-16 codes (0xF0) */
                while (r > 15)
                {
                    emit_ac_symbol(ac_tbl_no, 0xF0);
                    r -= 16;
                }

                /* Find the number of bits needed for the magnitude of the coefficient */
                int 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_COEF_BITS)
                    m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_DCT_COEF);

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

                /* Emit that number of bits of the value, if positive, */
                /* or the complement of its magnitude, if negative. */
                emit_bits_e(temp2, nbits);

                r = 0;          /* reset zero run length */
            }

            if (r > 0)
            {
                /* If there are trailing zeroes, */
                EOBRUN++;      /* count an EOB */
                if (EOBRUN == 0x7FFF)
                    emit_eobrun();   /* force it out to avoid overflow */
            }

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