// Initialize for a Huffman-compressed scan. static void start_pass_huff_decoder(jpeg_decompress cinfo) { jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef; shuff_entropy_decoder entropy = (shuff_entropy_decoder)lossyd.entropy_private; // Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. // This ought to be an error condition, but we make it a warning because // there are some baseline files out there with all zeroes in these bytes. if (cinfo.Ss != 0 || cinfo.Se != DCTSIZE2 - 1 || cinfo.Ah != 0 || cinfo.Al != 0) { WARNMS(cinfo, J_MESSAGE_CODE.JWRN_NOT_SEQUENTIAL); } for (int ci = 0; ci < cinfo.comps_in_scan; ci++) { jpeg_component_info compptr = cinfo.cur_comp_info[ci]; int dctbl = compptr.dc_tbl_no; int actbl = compptr.ac_tbl_no; // Compute derived values for Huffman tables // We may do this more than once for a table, but it's not expensive jpeg_make_d_derived_tbl(cinfo, true, dctbl, ref entropy.dc_derived_tbls[dctbl]); jpeg_make_d_derived_tbl(cinfo, false, actbl, ref entropy.ac_derived_tbls[actbl]); // Initialize DC predictions to 0 entropy.saved.last_dc_val[ci] = 0; } // Precalculate decoding info for each block in an MCU of this scan for (int blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++) { int ci = cinfo.MCU_membership[blkn]; jpeg_component_info compptr = cinfo.cur_comp_info[ci]; // Precalculate which table to use for each block entropy.dc_cur_tbls[blkn] = entropy.dc_derived_tbls[compptr.dc_tbl_no]; entropy.ac_cur_tbls[blkn] = entropy.ac_derived_tbls[compptr.ac_tbl_no]; // Decide whether we really care about the coefficient values if (compptr.component_needed) { entropy.dc_needed[blkn] = true; // we don't need the ACs if producing a 1/8th-size image entropy.ac_needed[blkn] = (compptr.DCT_scaled_size > 1); } else { entropy.dc_needed[blkn] = entropy.ac_needed[blkn] = false; } } // Initialize bitread state variables entropy.bitstate.bits_left = 0; entropy.bitstate.get_buffer = 0; // unnecessary, but keeps Purify quiet entropy.insufficient_data = false; // Initialize restart counter entropy.restarts_to_go = cinfo.restart_interval; }
// Module initialization routine for Huffman entropy decoding. public static void jinit_shuff_decoder(jpeg_decompress cinfo) { jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef; shuff_entropy_decoder entropy = null; try { entropy = new shuff_entropy_decoder(); entropy.saved.last_dc_val = new int[MAX_COMPS_IN_SCAN]; } catch { ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4); } lossyd.entropy_private = entropy; lossyd.entropy_start_pass = start_pass_huff_decoder; lossyd.entropy_decode_mcu = decode_mcu; // Mark tables unallocated for (int i = 0; i < NUM_HUFF_TBLS; i++) { entropy.dc_derived_tbls[i] = entropy.ac_derived_tbls[i] = null; } }
//#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) // Check for a restart marker & resynchronize decoder. // Returns false if must suspend. static bool process_restart_dshuff(jpeg_decompress cinfo) { jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef; shuff_entropy_decoder entropy = (shuff_entropy_decoder)lossyd.entropy_private; // Throw away any unused bits remaining in bit buffer; // include any full bytes in next_marker's count of discarded bytes cinfo.marker.discarded_bytes += (uint)(entropy.bitstate.bits_left / 8); entropy.bitstate.bits_left = 0; // Advance past the RSTn marker if (!cinfo.marker.read_restart_marker(cinfo)) { return(false); } // Re-initialize DC predictions to 0 for (int ci = 0; ci < cinfo.comps_in_scan; ci++) { entropy.saved.last_dc_val[ci] = 0; } // Reset restart counter entropy.restarts_to_go = cinfo.restart_interval; // Reset out-of-data flag, unless read_restart_marker left us smack up // against a marker. In that case we will end up treating the next data // segment as empty, and we can avoid producing bogus output pixels by // leaving the flag set. if (cinfo.unread_marker == 0) { entropy.insufficient_data = false; } return(true); }
// Module initialization routine for Huffman entropy decoding. public static void jinit_shuff_decoder(jpeg_decompress cinfo) { jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef; shuff_entropy_decoder entropy=null; try { entropy=new shuff_entropy_decoder(); entropy.saved.last_dc_val=new int[MAX_COMPS_IN_SCAN]; } catch { ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4); } lossyd.entropy_private=entropy; lossyd.entropy_start_pass=start_pass_huff_decoder; lossyd.entropy_decode_mcu=decode_mcu; // Mark tables unallocated for(int i=0; i<NUM_HUFF_TBLS; i++) entropy.dc_derived_tbls[i]=entropy.ac_derived_tbls[i]=null; }
// 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.) static bool decode_mcu(jpeg_decompress cinfo, short[][] MCU_data) { jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef; shuff_entropy_decoder entropy = (shuff_entropy_decoder)lossyd.entropy_private; // Process restart marker if needed; may have to suspend if (cinfo.restart_interval != 0) { if (entropy.restarts_to_go == 0) { if (!process_restart_dshuff(cinfo)) { 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 (!entropy.insufficient_data) { bitread_working_state br_state = new bitread_working_state(); savable_state_sq state; state.last_dc_val = new int[MAX_COMPS_IN_SCAN]; // Load up working state //was BITREAD_STATE_VARS; //was BITREAD_LOAD_STATE(cinfo, entropy.bitstate); br_state.cinfo = cinfo; br_state.input_bytes = cinfo.src.input_bytes; br_state.next_input_byte = cinfo.src.next_input_byte; br_state.bytes_in_buffer = cinfo.src.bytes_in_buffer; ulong get_buffer = entropy.bitstate.get_buffer; int bits_left = entropy.bitstate.bits_left; //was state=entropy.saved; entropy.saved.last_dc_val.CopyTo(state.last_dc_val, 0); // Outer loop handles each block in the MCU for (int blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++) { short[] block = MCU_data[blkn]; d_derived_tbl dctbl = entropy.dc_cur_tbls[blkn]; d_derived_tbl actbl = entropy.ac_cur_tbls[blkn]; int s = 0, k, r; // Decode a single block's worth of coefficients // Section F.2.2.1: decode the DC coefficient difference //was HUFF_DECODE(s, br_state, dctbl, return false, label1); { int nb, look; bool label = false; if (bits_left < HUFF_LOOKAHEAD) { if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0)) { return(false); } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; if (bits_left < HUFF_LOOKAHEAD) { nb = 1; label = true; if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, dctbl, nb)) < 0) { return(false); } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } } if (!label) { //was look=PEEK_BITS(HUFF_LOOKAHEAD); look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1); if ((nb = dctbl.look_nbits[look]) != 0) { //was DROP_BITS(nb); bits_left -= nb; s = dctbl.look_sym[look]; } else { nb = HUFF_LOOKAHEAD + 1; if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, dctbl, nb)) < 0) { return(false); } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } } } if (s != 0) { //was CHECK_BIT_BUFFER(br_state, s, return false); if (bits_left < s) { if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s)) { return(false); } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } //was r = GET_BITS(s); r = ((int)(get_buffer >> (bits_left -= s))) & ((1 << s) - 1); //was s=HUFF_EXTEND(r, s); s = (r < (1 << (s - 1))?r + (((-1) << s) + 1):r); } if (entropy.dc_needed[blkn]) { // Convert DC difference to actual value, update last_dc_val int ci = cinfo.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) block[0] = (short)s; } if (entropy.ac_needed[blkn]) { // Section F.2.2.2: decode the AC coefficients // Since zeroes are skipped, output area must be cleared beforehand for (k = 1; k < DCTSIZE2; k++) { //was HUFF_DECODE(s, br_state, actbl, return false, label2); { int nb, look; bool label = false; if (bits_left < HUFF_LOOKAHEAD) { if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0)) { return(false); } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; if (bits_left < HUFF_LOOKAHEAD) { nb = 1; label = true; if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb)) < 0) { return(false); } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } } if (!label) { //was look=PEEK_BITS(HUFF_LOOKAHEAD); look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1); if ((nb = actbl.look_nbits[look]) != 0) { //was DROP_BITS(nb); bits_left -= nb; s = actbl.look_sym[look]; } else { nb = HUFF_LOOKAHEAD + 1; if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb)) < 0) { return(false); } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } } } r = s >> 4; s &= 15; if (s != 0) { k += r; //was CHECK_BIT_BUFFER(br_state, s, return false); if (bits_left < s) { if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s)) { return(false); } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } //was r = GET_BITS(s); r = ((int)(get_buffer >> (bits_left -= s))) & ((1 << s) - 1); //was s=HUFF_EXTEND(r, s); s = (r < (1 << (s - 1))?r + (((-1) << s) + 1):r); // 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. block[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 (k = 1; k < DCTSIZE2; k++) { //was HUFF_DECODE(s, br_state, actbl, return false, label3); { int nb, look; bool label = false; if (bits_left < HUFF_LOOKAHEAD) { if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0)) { return(false); } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; if (bits_left < HUFF_LOOKAHEAD) { nb = 1; label = true; if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb)) < 0) { return(false); } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } } if (!label) { //was look=PEEK_BITS(HUFF_LOOKAHEAD); look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1); if ((nb = actbl.look_nbits[look]) != 0) { //was DROP_BITS(nb); bits_left -= nb; s = actbl.look_sym[look]; } else { nb = HUFF_LOOKAHEAD + 1; if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb)) < 0) { return(false); } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } } } r = s >> 4; s &= 15; if (s != 0) { k += r; //was CHECK_BIT_BUFFER(br_state, s, return false); if (bits_left < s) { if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s)) { return(false); } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } //was DROP_BITS(s); bits_left -= s; } else { if (r != 15) { break; } k += 15; } } } } // Completed MCU, so update state //was BITREAD_SAVE_STATE(cinfo, entropy.bitstate); cinfo.src.input_bytes = br_state.input_bytes; cinfo.src.next_input_byte = br_state.next_input_byte; cinfo.src.bytes_in_buffer = br_state.bytes_in_buffer; entropy.bitstate.get_buffer = get_buffer; entropy.bitstate.bits_left = bits_left; //was entropy.saved=state; state.last_dc_val.CopyTo(entropy.saved.last_dc_val, 0); } // Account for restart interval (no-op if not using restarts) entropy.restarts_to_go--; return(true); }