private bool decode_mcu_AC_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;
}
}
/* If we've run out of data, don't modify the MCU.
*/
if (!m_insufficient_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 */
int[] natural_order = m_cinfo.natural_order;
/* 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);
uint 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)
{
do
{
int s;
if (!HUFF_DECODE(out s, ref br_state, 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 = (uint)(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 += (uint)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 = 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 = 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;
}
k++;
} while (k <= m_cinfo.m_Se);
}
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.
*/
do
{
int blockIndex = 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;
}
}
}
k++;
} while (k <= m_cinfo.m_Se);
/* 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;
}