/// <summary> /// Emit a restart marker and resynchronize predictions. /// </summary> private bool emit_restart(savable_state state, int restart_num) { if (!flush_bits(state)) { return(false); } if (!emit_byte(0xFF)) { return(false); } if (!emit_byte((int)(JPEG_MARKER.RST0 + restart_num))) { return(false); } /* Re-initialize DC predictions to 0 */ for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++) { state.last_dc_val[ci] = 0; } /* The restart counter is not updated until we successfully write the MCU. */ return(true); }
public int[] last_dc_val = new int[JpegConstants.MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ public void ASSIGN_STATE(savable_state src) { put_buffer = src.put_buffer; put_bits = src.put_bits; for (int i = 0; i < last_dc_val.Length; i++) last_dc_val[i] = src.last_dc_val[i]; }
private bool flush_bits(savable_state state) { if (!emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ { return(false); } state.put_buffer = 0; /* and reset bit-buffer to empty */ state.put_bits = 0; return(true); }
/// <summary> /// Encode and output one MCU's worth of Huffman-compressed coefficients. /// </summary> private bool encode_mcu_huff(JBLOCK[][] MCU_data) { /* Load up working state */ savable_state state; state = m_saved; /* Emit restart marker if needed */ if (m_cinfo.m_restart_interval != 0) { if (m_restarts_to_go == 0) { if (!emit_restart(state, m_next_restart_num)) { return(false); } } } /* Encode the MCU data blocks */ for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++) { int ci = m_cinfo.m_MCU_membership[blkn]; if (!encode_one_block(state, MCU_data[blkn][0].data, state.last_dc_val[ci], m_dc_derived_tbls[m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]].Dc_tbl_no], m_ac_derived_tbls[m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]].Ac_tbl_no])) { return(false); } /* Update last_dc_val */ state.last_dc_val[ci] = MCU_data[blkn][0][0]; } /* Completed MCU, so update state */ m_saved = state; /* 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); }
/// <summary> /// Finish up at the end of a Huffman-compressed scan. /// </summary> private void finish_pass_huff() { /* Load up working state ... flush_bits needs it */ savable_state state; state = m_saved; /* Flush out the last data */ if (!flush_bits(state)) { m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CANT_SUSPEND); } /* Update state */ m_saved = state; }
/// <summary> /// Only the right 24 bits of put_buffer are used; the valid bits are /// left-justified in this part. At most 16 bits can be passed to emit_bits /// in one call, and we never retain more than 7 bits in put_buffer /// between calls, so 24 bits are sufficient. /// </summary> private bool emit_bits(savable_state state, int code, int size) { // Emit some bits; return true if successful, false if must suspend /* This routine is heavily used, so it's worth coding tightly. */ int put_buffer = code; int put_bits = state.put_bits; /* if size is 0, caller used an invalid Huffman table entry */ if (size == 0) { m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_HUFF_MISSING_CODE); } put_buffer &= (1 << size) - 1; /* mask off any extra bits in code */ put_bits += size; /* new number of bits in buffer */ put_buffer <<= 24 - put_bits; /* align incoming bits */ put_buffer |= state.put_buffer; /* and merge with old buffer contents */ while (put_bits >= 8) { int c = (put_buffer >> 16) & 0xFF; if (!emit_byte(c)) { return(false); } if (c == 0xFF) { /* need to stuff a zero byte? */ if (!emit_byte(0)) { return(false); } } put_buffer <<= 8; put_bits -= 8; } state.put_buffer = put_buffer; /* update state variables */ state.put_bits = put_bits; return(true); }
/// <summary> /// Only the right 24 bits of put_buffer are used; the valid bits are /// left-justified in this part. At most 16 bits can be passed to emit_bits /// in one call, and we never retain more than 7 bits in put_buffer /// between calls, so 24 bits are sufficient. /// </summary> private bool emit_bits(savable_state state, int code, int size) { // Emit some bits; return true if successful, false if must suspend /* This routine is heavily used, so it's worth coding tightly. */ int put_buffer = code; int put_bits = state.put_bits; /* if size is 0, caller used an invalid Huffman table entry */ if (size == 0) m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_HUFF_MISSING_CODE); put_buffer &= (1 << size) - 1; /* mask off any extra bits in code */ put_bits += size; /* new number of bits in buffer */ put_buffer <<= 24 - put_bits; /* align incoming bits */ put_buffer |= state.put_buffer; /* and merge with old buffer contents */ while (put_bits >= 8) { int c = (put_buffer >> 16) & 0xFF; if (!emit_byte(c)) return false; if (c == 0xFF) { /* need to stuff a zero byte? */ if (!emit_byte(0)) return false; } put_buffer <<= 8; put_bits -= 8; } state.put_buffer = put_buffer; /* update state variables */ state.put_bits = put_bits; return true; }
/// <summary> /// Encode a single block's worth of coefficients /// </summary> private bool encode_one_block(savable_state state, short[] block, int last_dc_val, c_derived_tbl dctbl, c_derived_tbl actbl) { /* Encode the DC coefficient difference per section F.1.2.1 */ int temp = block[0] - last_dc_val; int temp2 = temp; if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* For a negative input, want temp2 = bitwise complement of abs(input) */ /* This code assumes we are on a two's complement machine */ temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ int nbits = 0; while (temp != 0) { nbits++; temp >>= 1; } /* Check for out-of-range coefficient values. * Since we're encoding a difference, the range limit is twice as much. */ if (nbits > MAX_HUFFMAN_COEF_BITS + 1) m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_DCT_COEF); /* Emit the Huffman-coded symbol for the number of bits */ if (!emit_bits(state, dctbl.ehufco[nbits], dctbl.ehufsi[nbits])) return false; /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (nbits != 0) { /* emit_bits rejects calls with size 0 */ if (!emit_bits(state, temp2, nbits)) return false; } /* Encode the AC coefficients per section F.1.2.2 */ int r = 0; /* r = run length of zeros */ for (int k = 1; k < JpegConstants.DCTSIZE2; k++) { temp = block[JpegUtils.jpeg_natural_order[k]]; if (temp == 0) { r++; } else { /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { if (!emit_bits(state, actbl.ehufco[0xF0], actbl.ehufsi[0xF0])) return false; r -= 16; } temp2 = temp; if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* This code assumes we are on a two's complement machine */ temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ 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_HUFFMAN_COEF_BITS) m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_DCT_COEF); /* Emit Huffman symbol for run length / number of bits */ int i = (r << 4) + nbits; if (!emit_bits(state, actbl.ehufco[i], actbl.ehufsi[i])) return false; /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (!emit_bits(state, temp2, nbits)) return false; r = 0; } } /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) { if (!emit_bits(state, actbl.ehufco[0], actbl.ehufsi[0])) return false; } return true; }
/// <summary> /// Finish up at the end of a Huffman-compressed scan. /// </summary> private void finish_pass_huff() { /* Load up working state ... flush_bits needs it */ savable_state state; state = m_saved; /* Flush out the last data */ if (!flush_bits(state)) m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CANT_SUSPEND); /* Update state */ m_saved = state; }
/// <summary> /// Encode and output one MCU's worth of Huffman-compressed coefficients. /// </summary> private bool encode_mcu_huff(JBLOCK[][] MCU_data) { /* Load up working state */ savable_state state; state = m_saved; /* Emit restart marker if needed */ if (m_cinfo.m_restart_interval != 0) { if (m_restarts_to_go == 0) { if (!emit_restart(state, m_next_restart_num)) return false; } } /* Encode the MCU data blocks */ for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++) { int ci = m_cinfo.m_MCU_membership[blkn]; if (!encode_one_block(state, MCU_data[blkn][0].data, state.last_dc_val[ci], m_dc_derived_tbls[m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]].Dc_tbl_no], m_ac_derived_tbls[m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]].Ac_tbl_no])) { return false; } /* Update last_dc_val */ state.last_dc_val[ci] = MCU_data[blkn][0][0]; } /* Completed MCU, so update state */ m_saved = state; /* 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; }
public int[] last_dc_val = new int[JpegConstants.MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ public void Assign(savable_state ss) { Buffer.BlockCopy(ss.last_dc_val, 0, last_dc_val, 0, last_dc_val.Length * sizeof(int)); }
public int[] last_dc_val = new int[JpegConstants.MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ #endregion Fields #region Methods public void Assign(savable_state ss) { Buffer.BlockCopy(ss.last_dc_val, 0, last_dc_val, 0, last_dc_val.Length * sizeof(int)); }
/// <summary> /// Encode a single block's worth of coefficients /// </summary> private bool encode_one_block(savable_state state, short[] block, int last_dc_val, c_derived_tbl dctbl, c_derived_tbl actbl) { /* Encode the DC coefficient difference per section F.1.2.1 */ int temp = block[0] - last_dc_val; int temp2 = temp; if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* For a negative input, want temp2 = bitwise complement of abs(input) */ /* This code assumes we are on a two's complement machine */ temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ int nbits = 0; while (temp != 0) { nbits++; temp >>= 1; } /* Check for out-of-range coefficient values. * Since we're encoding a difference, the range limit is twice as much. */ if (nbits > MAX_HUFFMAN_COEF_BITS + 1) { m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_DCT_COEF); } /* Emit the Huffman-coded symbol for the number of bits */ if (!emit_bits(state, dctbl.ehufco[nbits], dctbl.ehufsi[nbits])) { return(false); } /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (nbits != 0) { /* emit_bits rejects calls with size 0 */ if (!emit_bits(state, temp2, nbits)) { return(false); } } /* Encode the AC coefficients per section F.1.2.2 */ int r = 0; /* r = run length of zeros */ for (int k = 1; k < JpegConstants.DCTSIZE2; k++) { temp = block[JpegUtils.jpeg_natural_order[k]]; if (temp == 0) { r++; } else { /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { if (!emit_bits(state, actbl.ehufco[0xF0], actbl.ehufsi[0xF0])) { return(false); } r -= 16; } temp2 = temp; if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* This code assumes we are on a two's complement machine */ temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ 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_HUFFMAN_COEF_BITS) { m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_DCT_COEF); } /* Emit Huffman symbol for run length / number of bits */ int i = (r << 4) + nbits; if (!emit_bits(state, actbl.ehufco[i], actbl.ehufsi[i])) { return(false); } /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (!emit_bits(state, temp2, nbits)) { return(false); } r = 0; } } /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) { if (!emit_bits(state, actbl.ehufco[0], actbl.ehufsi[0])) { return(false); } } 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); }
private bool flush_bits(savable_state state) { if (!emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ return false; state.put_buffer = 0; /* and reset bit-buffer to empty */ state.put_bits = 0; 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; }
/// <summary> /// Emit a restart marker and resynchronize predictions. /// </summary> private bool emit_restart(savable_state state, int restart_num) { if (!flush_bits(state)) return false; if (!emit_byte(0xFF)) return false; if (!emit_byte((int)(JPEG_MARKER.RST0 + restart_num))) return false; /* Re-initialize DC predictions to 0 */ for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++) state.last_dc_val[ci] = 0; /* The restart counter is not updated until we successfully write the MCU. */ 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); }
/// <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; }
/// <summary> /// Finish up at the end of a Huffman-compressed scan. /// </summary> private void finish_pass_huff() { if (m_cinfo.m_progressive_mode) { /* Flush out any buffered data */ emit_eobrun(); flush_bits_e(); } else { /* Load up working state ... flush_bits needs it */ savable_state state = new savable_state(); state.ASSIGN_STATE(m_saved); /* Flush out the last data */ if (!flush_bits_s(state)) m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CANT_SUSPEND); /* Update state */ m_saved.ASSIGN_STATE(state); } }