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