// Out-of-line code for Huffman code decoding. static int jpeg_huff_decode(ref bitread_working_state state, ulong get_buffer, int bits_left, d_derived_tbl htbl, int min_bits) { int l = min_bits; // HUFF_DECODE has determined that the code is at least min_bits // bits long, so fetch that many bits in one swoop. //was CHECK_BIT_BUFFER(*state, l, return -1); if (bits_left < l) { if (!jpeg_fill_bit_buffer(ref state, get_buffer, bits_left, l)) { return(-1); } get_buffer = state.get_buffer; bits_left = state.bits_left; } //was code = GET_BITS(l); int code = ((int)(get_buffer >> (bits_left -= l))) & ((1 << l) - 1); // Collect the rest of the Huffman code one bit at a time. // This is per Figure F.16 in the JPEG spec. while (code > htbl.maxcode[l]) { code <<= 1; //was CHECK_BIT_BUFFER(*state, 1, return -1); if (bits_left < 1) { if (!jpeg_fill_bit_buffer(ref state, get_buffer, bits_left, 1)) { return(-1); } get_buffer = state.get_buffer; bits_left = state.bits_left; } //was code |= GET_BITS(1); code |= ((int)(get_buffer >> (bits_left -= 1))) & 1; l++; } // Unload the local registers state.get_buffer = get_buffer; state.bits_left = bits_left; // With garbage input we may reach the sentinel value l = 17. if (l > 16) { WARNMS(state.cinfo, J_MESSAGE_CODE.JWRN_HUFF_BAD_CODE); return(0); // fake a zero as the safest result } return(htbl.pub.huffval[(int)(code + htbl.valoffset[l])]); }
// 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; }
// Out-of-line code for Huffman code decoding. static int jpeg_huff_decode(ref bitread_working_state state, ulong get_buffer, int bits_left, d_derived_tbl htbl, int min_bits) { int l=min_bits; // HUFF_DECODE has determined that the code is at least min_bits // bits long, so fetch that many bits in one swoop. //was CHECK_BIT_BUFFER(*state, l, return -1); if(bits_left<l) { if(!jpeg_fill_bit_buffer(ref state, get_buffer, bits_left, l)) return -1; get_buffer=state.get_buffer; bits_left=state.bits_left; } //was code = GET_BITS(l); int code=((int)(get_buffer>>(bits_left-=l)))&((1<<l)-1); // Collect the rest of the Huffman code one bit at a time. // This is per Figure F.16 in the JPEG spec. while(code>htbl.maxcode[l]) { code<<=1; //was CHECK_BIT_BUFFER(*state, 1, return -1); if(bits_left<1) { if(!jpeg_fill_bit_buffer(ref state, get_buffer, bits_left, 1)) return -1; get_buffer=state.get_buffer; bits_left=state.bits_left; } //was code |= GET_BITS(1); code|=((int)(get_buffer>>(bits_left-=1)))&1; l++; } // Unload the local registers state.get_buffer=get_buffer; state.bits_left=bits_left; // With garbage input we may reach the sentinel value l = 17. if(l>16) { WARNMS(state.cinfo, J_MESSAGE_CODE.JWRN_HUFF_BAD_CODE); return 0; // fake a zero as the safest result } return htbl.pub.huffval[(int)(code+htbl.valoffset[l])]; }
// Macros to declare and load/save bitread local variables. //#define BITREAD_STATE_VARS \ // ulong get_buffer; \ // int bits_left; \ // bitread_working_state br_state //#define BITREAD_LOAD_STATE(cinfop, permstate) \ // br_state.cinfo=cinfop; \ // br_state.next_input_byte=cinfop.src.next_input_byte; \ // br_state.bytes_in_buffer=cinfop.src.bytes_in_buffer; \ // get_buffer=permstate.get_buffer; \ // bits_left=permstate.bits_left; //#define BITREAD_SAVE_STATE(cinfop, permstate) \ // cinfop.src.next_input_byte=br_state.next_input_byte; \ // cinfop.src.bytes_in_buffer=br_state.bytes_in_buffer; \ // permstate.get_buffer=get_buffer; \ // permstate.bits_left=bits_left // These macros provide the in-line portion of bit fetching. // Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer // before using GET_BITS, PEEK_BITS, or DROP_BITS. // The variables get_buffer and bits_left are assumed to be locals, // but the state struct might not be (jpeg_huff_decode needs this). // CHECK_BIT_BUFFER(state,n,action); // Ensure there are N bits in get_buffer; if suspend, take action. // val = GET_BITS(n); // Fetch next N bits. // val = PEEK_BITS(n); // Fetch next N bits without removing them from the buffer. // DROP_BITS(n); // Discard next N bits. // The value N should be a simple variable, not an expression, because it // is evaluated multiple times. //#define CHECK_BIT_BUFFER(state, nbits, action) \ // { if(bits_left<(nbits)) { \ // if(!jpeg_fill_bit_buffer(&(state), get_buffer, bits_left, nbits)) { action; } \ // get_buffer=(state).get_buffer; bits_left=(state).bits_left; } } //#define GET_BITS(nbits) (((int)(get_buffer>>(bits_left-=(nbits))))&((1<<(nbits))-1)) //#define PEEK_BITS(nbits) (((int)(get_buffer>>(bits_left-(nbits))))&((1<<(nbits))-1)) //#define DROP_BITS(nbits) (bits_left-=(nbits)) // Load up the bit buffer to a depth of at least nbits // Out-of-line code for bit fetching. // Note: current values of get_buffer and bits_left are passed as parameters, // but are returned in the corresponding fields of the state struct. // On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width // of get_buffer to be used. (On machines with wider words, an even larger // buffer could be used.) However, on some machines 32-bit shifts are // quite slow and take time proportional to the number of places shifted. // (This is true with most PC compilers, for instance.) In this case it may // be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the // average shift distance at the cost of more calls to jpeg_fill_bit_buffer. static bool jpeg_fill_bit_buffer(ref bitread_working_state state, ulong get_buffer, int bits_left, int nbits) { int MIN_GET_BITS=57; // Copy heavily used state fields into locals (hopefully registers) byte[] input_bytes=state.input_bytes; int next_input_byte=state.next_input_byte; uint bytes_in_buffer=state.bytes_in_buffer; jpeg_decompress cinfo=state.cinfo; // Attempt to load at least MIN_GET_BITS bits into get_buffer. // (It is assumed that no request will be for more than that many bits.) // We fail to do so only if we hit a marker or are forced to suspend. if(cinfo.unread_marker==0) { // cannot advance past a marker while(bits_left<MIN_GET_BITS) { // Attempt to read a byte if(bytes_in_buffer==0) { if(!cinfo.src.fill_input_buffer(cinfo)) return false; input_bytes=cinfo.src.input_bytes; next_input_byte=cinfo.src.next_input_byte; bytes_in_buffer=cinfo.src.bytes_in_buffer; } bytes_in_buffer--; int c=input_bytes[next_input_byte++]; // If it's 0xFF, check and discard stuffed zero byte if(c==0xFF) { // Loop here to discard any padding FF's on terminating marker, // so that we can save a valid unread_marker value. NOTE: we will // accept multiple FF's followed by a 0 as meaning a single FF data // byte. This data pattern is not valid according to the standard. do { if(bytes_in_buffer==0) { if(!cinfo.src.fill_input_buffer(cinfo)) return false; input_bytes=cinfo.src.input_bytes; next_input_byte=cinfo.src.next_input_byte; bytes_in_buffer=cinfo.src.bytes_in_buffer; } bytes_in_buffer--; c=input_bytes[next_input_byte++]; } while(c==0xFF); if(c==0) { // Found FF/00, which represents an FF data byte c=0xFF; } else { // Oops, it's actually a marker indicating end of compressed data. // Save the marker code for later use. // Fine point: it might appear that we should save the marker into // bitread working state, not straight into permanent state. But // once we have hit a marker, we cannot need to suspend within the // current MCU, because we will read no more bytes from the data // source. So it is OK to update permanent state right away. cinfo.unread_marker=c; // See if we need to insert some fake zero bits. break; } } // OK, load c into get_buffer get_buffer*=256; get_buffer|=(uint)c; bits_left+=8; } // end while } if(cinfo.unread_marker!=0) { // We get here if we've read the marker that terminates the compressed // data segment. There should be enough bits in the buffer register // to satisfy the request; if so, no problem. if(nbits>bits_left) { // Uh-oh. Report corrupted data to user and stuff zeroes into // the data stream, so that we can produce some kind of image. // We use a nonvolatile flag to ensure that only one warning message // appears per data segment. jpeg_entropy_decoder huffd; #if D_LOSSLESS_SUPPORTED if(cinfo.process==J_CODEC_PROCESS.JPROC_LOSSLESS) huffd=(jpeg_entropy_decoder)((jpeg_lossless_d_codec)cinfo.coef).entropy_private; else #endif huffd=(jpeg_entropy_decoder)((jpeg_lossy_d_codec)cinfo.coef).entropy_private; if(!huffd.insufficient_data) { WARNMS(cinfo, J_MESSAGE_CODE.JWRN_HIT_MARKER); huffd.insufficient_data=true; } // Fill the buffer with zero bits get_buffer<<=MIN_GET_BITS-bits_left; bits_left=MIN_GET_BITS; } } // Unload the local registers state.input_bytes=input_bytes; state.next_input_byte=next_input_byte; state.bytes_in_buffer=bytes_in_buffer; state.get_buffer=get_buffer; state.bits_left=bits_left; return true; }
// MCU decoding for AC successive approximation refinement scan. static bool decode_mcu_AC_refine(jpeg_decompress cinfo, short[][] MCU_data) { jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef; phuff_entropy_decoder entropy=(phuff_entropy_decoder)lossyd.entropy_private; int Se=cinfo.Se; short p1=(short)(1<<cinfo.Al); // 1 in the bit position being coded short m1=(short)((-1)<<cinfo.Al); // -1 in the bit position being coded short[] block=null; // 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[DCTSIZE2]; // Process restart marker if needed; may have to suspend if(cinfo.restart_interval!=0) { if(entropy.restarts_to_go==0) if(!process_restart_dphuff(cinfo)) return false; } // If we've run out of data, don't modify the MCU. if(!entropy.insufficient_data) { // Load up working state //was BITREAD_STATE_VARS; bitread_working_state br_state=new bitread_working_state(); //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; uint EOBRUN=entropy.saved.EOBRUN; // only part of saved state we need // There is always only one block per MCU block=MCU_data[0]; d_derived_tbl tbl=entropy.ac_derived_tbl; // initialize coefficient loop counter to start of band int k=cinfo.Ss; if(EOBRUN==0) { for(; k<=Se; k++) { int s=0, r; //was HUFF_DECODE(s, br_state, tbl, goto undoit, 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)) goto undoit; 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, tbl, nb))<0) goto undoit; 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=tbl.look_nbits[look])!=0) { //was DROP_BITS(nb); bits_left-=nb; s=tbl.look_sym[look]; } else { nb=HUFF_LOOKAHEAD+1; if((s=jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb))<0) goto undoit; get_buffer=br_state.get_buffer; bits_left=br_state.bits_left; } } } r=s>>4; s&=15; if(s!=0) { if(s!=1) WARNMS(cinfo, J_MESSAGE_CODE.JWRN_HUFF_BAD_CODE); // size of new coef should always be 1 //was CHECK_BIT_BUFFER(br_state, 1, goto undoit); if(bits_left<1) { if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1)) goto undoit; get_buffer=br_state.get_buffer; bits_left=br_state.bits_left; } //was if (GET_BITS(1)) if((((int)(get_buffer>>(bits_left-=1)))&1)!=0) s=p1; // newly nonzero coef is positive else s=m1; // newly nonzero coef is negative } else { if(r!=15) { EOBRUN=(uint)(1<<r); // EOBr, run length is 2^r + appended bits if(r!=0) { //was CHECK_BIT_BUFFER(br_state, r, goto undoit); if(bits_left<r) { if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, r)) goto undoit; get_buffer=br_state.get_buffer; bits_left=br_state.bits_left; } //was r = GET_BITS(r); r=((int)(get_buffer>>(bits_left-=r)))&((1<<r)-1); 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 thiscoef=jpeg_natural_order[k]; if(block[thiscoef]!=0) { //was CHECK_BIT_BUFFER(br_state, 1, goto undoit); if(bits_left<1) { if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1)) goto undoit; get_buffer=br_state.get_buffer; bits_left=br_state.bits_left; } //was if (GET_BITS(1)) if((((int)(get_buffer>>(bits_left-=1)))&1)!=0) { if((block[thiscoef]&p1)==0) { // do nothing if already set it if(block[thiscoef]>=0) block[thiscoef]+=p1; else block[thiscoef]+=m1; } } } else { if(--r<0) break; // reached target zero coefficient } k++; } while(k<=Se); if(s!=0) { int pos=jpeg_natural_order[k]; // Output newly nonzero coefficient block[pos]=(short)s; // Remember its position in case we have to suspend newnz_pos[num_newnz++]=pos; } } } 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. for(; k<=Se; k++) { int thiscoef=jpeg_natural_order[k]; if(block[thiscoef]!=0) { //was CHECK_BIT_BUFFER(br_state, 1, goto undoit); if(bits_left<1) { if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1)) goto undoit; get_buffer=br_state.get_buffer; bits_left=br_state.bits_left; } //was if (GET_BITS(1)) if((((int)(get_buffer>>(bits_left-=1)))&1)!=0) { if((block[thiscoef]&p1)==0) { // do nothing if already changed it if(block[thiscoef]>=0) block[thiscoef]+=p1; else block[thiscoef]+=m1; } } } } // Count one block completed in EOB run EOBRUN--; } // 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; entropy.saved.EOBRUN=EOBRUN; // only part of saved state we need } // Account for restart interval (no-op if not using restarts) entropy.restarts_to_go--; return true; undoit: // Re-zero any output coefficients that we made newly nonzero while(num_newnz>0) block[newnz_pos[--num_newnz]]=0; return false; }
// MCU decoding for DC successive approximation refinement scan. // Note: we assume such scans can be multi-component, although the spec // is not very clear on the point. static bool decode_mcu_DC_refine(jpeg_decompress cinfo, short[][] MCU_data) { jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef; phuff_entropy_decoder entropy=(phuff_entropy_decoder)lossyd.entropy_private; short p1=(short)(1<<cinfo.Al); // 1 in the bit position being coded // Process restart marker if needed; may have to suspend if(cinfo.restart_interval!=0) { if(entropy.restarts_to_go==0) if(!process_restart_dphuff(cinfo)) return false; } // Not worth the cycles to check insufficient_data here, // since we will not change the data anyway if we read zeroes. // Load up working state //was BITREAD_STATE_VARS; bitread_working_state br_state=new bitread_working_state(); //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; // Outer loop handles each block in the MCU for(int blkn=0; blkn<cinfo.blocks_in_MCU; blkn++) { short[] block=MCU_data[blkn]; // Encoded data is simply the next bit of the two's-complement DC value //was CHECK_BIT_BUFFER(br_state, 1, return false); if(bits_left<1) { if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1)) return false; get_buffer=br_state.get_buffer; bits_left=br_state.bits_left; } //was if(GET_BITS(1)) if((((int)(get_buffer>>(bits_left-=1)))&1)!=0) block[0]|=p1; // Note: since we use |=, repeating the assignment later is safe } // 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; // Account for restart interval (no-op if not using restarts) entropy.restarts_to_go--; return true; }
// MCU decoding for AC initial scan (either spectral selection, // or first pass of successive approximation). static bool decode_mcu_AC_first(jpeg_decompress cinfo, short[][] MCU_data) { jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef; phuff_entropy_decoder entropy=(phuff_entropy_decoder)lossyd.entropy_private; int Se=cinfo.Se; int Al=cinfo.Al; // Process restart marker if needed; may have to suspend if(cinfo.restart_interval!=0) { if(entropy.restarts_to_go==0) if(!process_restart_dphuff(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) { // Load up working state. // We can avoid loading/saving bitread state if in an EOB run. uint EOBRUN=entropy.saved.EOBRUN; // only part of saved state we need // There is always only one block per MCU if(EOBRUN>0) EOBRUN--; // if it's a band of zeroes... ...process it now (we do nothing) else { //was BITREAD_STATE_VARS; bitread_working_state br_state=new bitread_working_state(); //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; short[] block=MCU_data[0]; d_derived_tbl tbl=entropy.ac_derived_tbl; for(int k=cinfo.Ss; k<=Se; k++) { int s=0, r; //was HUFF_DECODE(s, br_state, tbl, 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, tbl, 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=tbl.look_nbits[look])!=0) { //was DROP_BITS(nb); bits_left-=nb; s=tbl.look_sym[look]; } else { nb=HUFF_LOOKAHEAD+1; if((s=jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, 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); // Scale and output coefficient in natural (dezigzagged) order block[jpeg_natural_order[k]]=(short)(s<<Al); } else { if(r==15) { // ZRL k+=15; // skip 15 zeroes in band } else { // EOBr, run length is 2^r + appended bits EOBRUN=(uint)(1<<r); if(r!=0) { // EOBr, r > 0 //was CHECK_BIT_BUFFER(br_state, r, return false); if(bits_left<r) { if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, r)) return false; get_buffer=br_state.get_buffer; bits_left=br_state.bits_left; } //was r = GET_BITS(r); r=((int)(get_buffer>>(bits_left-=r)))&((1<<r)-1); EOBRUN+=(uint)r; } EOBRUN--; // this band is processed at this moment break; // force end-of-band } } } //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; } // Completed MCU, so update state entropy.saved.EOBRUN=EOBRUN; // only part of saved state we need } // Account for restart interval (no-op if not using restarts) entropy.restarts_to_go--; 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.) // MCU decoding for DC initial scan (either spectral selection, // or first pass of successive approximation). static bool decode_mcu_DC_first(jpeg_decompress cinfo, short[][] MCU_data) { jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef; phuff_entropy_decoder entropy=(phuff_entropy_decoder)lossyd.entropy_private; int Al=cinfo.Al; // Process restart marker if needed; may have to suspend if(cinfo.restart_interval!=0) { if(entropy.restarts_to_go==0) if(!process_restart_dphuff(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) { // Load up working state //was BITREAD_STATE_VARS; bitread_working_state br_state=new bitread_working_state(); savable_state state; state.last_dc_val=new int[MAX_COMPS_IN_SCAN]; //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; state.EOBRUN=entropy.saved.EOBRUN; 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]; int ci=cinfo.MCU_membership[blkn]; jpeg_component_info compptr=cinfo.cur_comp_info[ci]; d_derived_tbl tbl=entropy.derived_tbls[compptr.dc_tbl_no]; int s=0; // Decode a single block's worth of coefficients // Section F.2.2.1: decode the DC coefficient difference //was HUFF_DECODE(s, br_state, tbl, 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, tbl, 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=tbl.look_nbits[look])!=0) { //was DROP_BITS(nb); bits_left-=nb; s=tbl.look_sym[look]; } else { nb=HUFF_LOOKAHEAD+1; if((s=jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, 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); int 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); } // 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) block[0]=(short)(s<<Al); } // 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; entropy.saved.EOBRUN=state.EOBRUN; 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; }
// Decode and return nMCU's worth of Huffman-compressed differences. // Each MCU is also disassembled and placed accordingly in diff_buf. // // MCU_col_num specifies the column of the first MCU being requested within // the MCU-row. This tells us where to position the output row pointers in // diff_buf. // // Returns the number of MCUs decoded. This may be less than nMCU if data // source requested suspension. In that case no changes have been made to // permanent state. (Exception: some output differences may already have // been assigned. This is harmless for this module, since we'll just // re-assign them on the next call.) static uint decode_mcus_dlhuff(jpeg_decompress cinfo, int[][][] diff_buf, uint MCU_row_num, uint MCU_col_num, uint nMCU) { jpeg_lossless_d_codec losslsd = (jpeg_lossless_d_codec)cinfo.coef; lhuff_entropy_decoder entropy = (lhuff_entropy_decoder)losslsd.entropy_private; // Set output pointer locations based on MCU_col_num for (int ptrn = 0; ptrn < entropy.num_output_ptrs; ptrn++) { int ci = entropy.output_ptr_info[ptrn].ci; int yoffset = entropy.output_ptr_info[ptrn].yoffset; int MCU_width = entropy.output_ptr_info[ptrn].MCU_width; entropy.output_ptr[ptrn] = diff_buf[ci][MCU_row_num + yoffset]; entropy.output_ptr_ind[ptrn] = (int)(MCU_col_num * MCU_width); } // If we've run out of data, zero out the buffers and return. // By resetting the undifferencer, the output samples will be CENTERJSAMPLE. // // NB: We should find a way to do this without interacting with the // undifferencer module directly. if (entropy.insufficient_data) { for (int ptrn = 0; ptrn < entropy.num_output_ptrs; ptrn++) { for (int i = 0; i < nMCU * entropy.output_ptr_info[ptrn].MCU_width; i++) { entropy.output_ptr[ptrn][entropy.output_ptr_ind[ptrn] + i] = 0; } } losslsd.predict_process_restart(cinfo); } else { // Load up working state //was BITREAD_STATE_VARS; bitread_working_state br_state = new bitread_working_state(); //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; // Outer loop handles the number of MCU requested for (uint mcu_num = 0; mcu_num < nMCU; mcu_num++) { // Inner loop handles the samples in the MCU for (int sampn = 0; sampn < cinfo.blocks_in_MCU; sampn++) { d_derived_tbl dctbl = entropy.cur_tbls[sampn]; int s = 0, r; // Section H.2.2: decode the sample difference //was HUFF_DECODE(s, br_state, dctbl, return mcu_num, 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(mcu_num); } 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(mcu_num); } 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(mcu_num); } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } } } if (s != 0) { if (s == 16) { s = 32768; // special case: always output 32768 } else { // normal case: fetch subsequent bits //was CHECK_BIT_BUFFER(br_state, s, return mcu_num); if (bits_left < s) { if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s)) { return(mcu_num); } 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 the sample difference int ind = entropy.output_ptr_index[sampn]; entropy.output_ptr[ind][entropy.output_ptr_ind[ind]++] = (int)s; } // 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; } } return(nMCU); }
// Macros to declare and load/save bitread local variables. //#define BITREAD_STATE_VARS \ // ulong get_buffer; \ // int bits_left; \ // bitread_working_state br_state //#define BITREAD_LOAD_STATE(cinfop, permstate) \ // br_state.cinfo=cinfop; \ // br_state.next_input_byte=cinfop.src.next_input_byte; \ // br_state.bytes_in_buffer=cinfop.src.bytes_in_buffer; \ // get_buffer=permstate.get_buffer; \ // bits_left=permstate.bits_left; //#define BITREAD_SAVE_STATE(cinfop, permstate) \ // cinfop.src.next_input_byte=br_state.next_input_byte; \ // cinfop.src.bytes_in_buffer=br_state.bytes_in_buffer; \ // permstate.get_buffer=get_buffer; \ // permstate.bits_left=bits_left // These macros provide the in-line portion of bit fetching. // Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer // before using GET_BITS, PEEK_BITS, or DROP_BITS. // The variables get_buffer and bits_left are assumed to be locals, // but the state struct might not be (jpeg_huff_decode needs this). // CHECK_BIT_BUFFER(state,n,action); // Ensure there are N bits in get_buffer; if suspend, take action. // val = GET_BITS(n); // Fetch next N bits. // val = PEEK_BITS(n); // Fetch next N bits without removing them from the buffer. // DROP_BITS(n); // Discard next N bits. // The value N should be a simple variable, not an expression, because it // is evaluated multiple times. //#define CHECK_BIT_BUFFER(state, nbits, action) \ // { if(bits_left<(nbits)) { \ // if(!jpeg_fill_bit_buffer(&(state), get_buffer, bits_left, nbits)) { action; } \ // get_buffer=(state).get_buffer; bits_left=(state).bits_left; } } //#define GET_BITS(nbits) (((int)(get_buffer>>(bits_left-=(nbits))))&((1<<(nbits))-1)) //#define PEEK_BITS(nbits) (((int)(get_buffer>>(bits_left-(nbits))))&((1<<(nbits))-1)) //#define DROP_BITS(nbits) (bits_left-=(nbits)) // Load up the bit buffer to a depth of at least nbits // Out-of-line code for bit fetching. // Note: current values of get_buffer and bits_left are passed as parameters, // but are returned in the corresponding fields of the state struct. // On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width // of get_buffer to be used. (On machines with wider words, an even larger // buffer could be used.) However, on some machines 32-bit shifts are // quite slow and take time proportional to the number of places shifted. // (This is true with most PC compilers, for instance.) In this case it may // be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the // average shift distance at the cost of more calls to jpeg_fill_bit_buffer. static bool jpeg_fill_bit_buffer(ref bitread_working_state state, ulong get_buffer, int bits_left, int nbits) { int MIN_GET_BITS = 57; // Copy heavily used state fields into locals (hopefully registers) byte[] input_bytes = state.input_bytes; int next_input_byte = state.next_input_byte; uint bytes_in_buffer = state.bytes_in_buffer; jpeg_decompress cinfo = state.cinfo; // Attempt to load at least MIN_GET_BITS bits into get_buffer. // (It is assumed that no request will be for more than that many bits.) // We fail to do so only if we hit a marker or are forced to suspend. if (cinfo.unread_marker == 0) { // cannot advance past a marker while (bits_left < MIN_GET_BITS) { // Attempt to read a byte if (bytes_in_buffer == 0) { if (!cinfo.src.fill_input_buffer(cinfo)) { return(false); } input_bytes = cinfo.src.input_bytes; next_input_byte = cinfo.src.next_input_byte; bytes_in_buffer = cinfo.src.bytes_in_buffer; } bytes_in_buffer--; int c = input_bytes[next_input_byte++]; // If it's 0xFF, check and discard stuffed zero byte if (c == 0xFF) { // Loop here to discard any padding FF's on terminating marker, // so that we can save a valid unread_marker value. NOTE: we will // accept multiple FF's followed by a 0 as meaning a single FF data // byte. This data pattern is not valid according to the standard. do { if (bytes_in_buffer == 0) { if (!cinfo.src.fill_input_buffer(cinfo)) { return(false); } input_bytes = cinfo.src.input_bytes; next_input_byte = cinfo.src.next_input_byte; bytes_in_buffer = cinfo.src.bytes_in_buffer; } bytes_in_buffer--; c = input_bytes[next_input_byte++]; } while(c == 0xFF); if (c == 0) { // Found FF/00, which represents an FF data byte c = 0xFF; } else { // Oops, it's actually a marker indicating end of compressed data. // Save the marker code for later use. // Fine point: it might appear that we should save the marker into // bitread working state, not straight into permanent state. But // once we have hit a marker, we cannot need to suspend within the // current MCU, because we will read no more bytes from the data // source. So it is OK to update permanent state right away. cinfo.unread_marker = c; // See if we need to insert some fake zero bits. break; } } // OK, load c into get_buffer get_buffer *= 256; get_buffer |= (uint)c; bits_left += 8; } // end while } if (cinfo.unread_marker != 0) { // We get here if we've read the marker that terminates the compressed // data segment. There should be enough bits in the buffer register // to satisfy the request; if so, no problem. if (nbits > bits_left) { // Uh-oh. Report corrupted data to user and stuff zeroes into // the data stream, so that we can produce some kind of image. // We use a nonvolatile flag to ensure that only one warning message // appears per data segment. jpeg_entropy_decoder huffd; #if D_LOSSLESS_SUPPORTED if (cinfo.process == J_CODEC_PROCESS.JPROC_LOSSLESS) { huffd = (jpeg_entropy_decoder)((jpeg_lossless_d_codec)cinfo.coef).entropy_private; } else #endif huffd = (jpeg_entropy_decoder)((jpeg_lossy_d_codec)cinfo.coef).entropy_private; if (!huffd.insufficient_data) { WARNMS(cinfo, J_MESSAGE_CODE.JWRN_HIT_MARKER); huffd.insufficient_data = true; } // Fill the buffer with zero bits get_buffer <<= MIN_GET_BITS - bits_left; bits_left = MIN_GET_BITS; } } // Unload the local registers state.input_bytes = input_bytes; state.next_input_byte = next_input_byte; state.bytes_in_buffer = bytes_in_buffer; state.get_buffer = get_buffer; state.bits_left = bits_left; return(true); }
// 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); }
// MCU decoding for AC successive approximation refinement scan. static bool decode_mcu_AC_refine(jpeg_decompress cinfo, short[][] MCU_data) { jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef; phuff_entropy_decoder entropy = (phuff_entropy_decoder)lossyd.entropy_private; int Se = cinfo.Se; short p1 = (short)(1 << cinfo.Al); // 1 in the bit position being coded short m1 = (short)((-1) << cinfo.Al); // -1 in the bit position being coded short[] block = null; // 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[DCTSIZE2]; // Process restart marker if needed; may have to suspend if (cinfo.restart_interval != 0) { if (entropy.restarts_to_go == 0) { if (!process_restart_dphuff(cinfo)) { return(false); } } } // If we've run out of data, don't modify the MCU. if (!entropy.insufficient_data) { // Load up working state //was BITREAD_STATE_VARS; bitread_working_state br_state = new bitread_working_state(); //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; uint EOBRUN = entropy.saved.EOBRUN; // only part of saved state we need // There is always only one block per MCU block = MCU_data[0]; d_derived_tbl tbl = entropy.ac_derived_tbl; // initialize coefficient loop counter to start of band int k = cinfo.Ss; if (EOBRUN == 0) { for (; k <= Se; k++) { int s = 0, r; //was HUFF_DECODE(s, br_state, tbl, goto undoit, 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)) { goto undoit; } 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, tbl, nb)) < 0) { goto undoit; } 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 = tbl.look_nbits[look]) != 0) { //was DROP_BITS(nb); bits_left -= nb; s = tbl.look_sym[look]; } else { nb = HUFF_LOOKAHEAD + 1; if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb)) < 0) { goto undoit; } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } } } r = s >> 4; s &= 15; if (s != 0) { if (s != 1) { WARNMS(cinfo, J_MESSAGE_CODE.JWRN_HUFF_BAD_CODE); // size of new coef should always be 1 } //was CHECK_BIT_BUFFER(br_state, 1, goto undoit); if (bits_left < 1) { if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1)) { goto undoit; } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } //was if (GET_BITS(1)) if ((((int)(get_buffer >> (bits_left -= 1))) & 1) != 0) { s = p1; // newly nonzero coef is positive } else { s = m1; // newly nonzero coef is negative } } else { if (r != 15) { EOBRUN = (uint)(1 << r); // EOBr, run length is 2^r + appended bits if (r != 0) { //was CHECK_BIT_BUFFER(br_state, r, goto undoit); if (bits_left < r) { if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, r)) { goto undoit; } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } //was r = GET_BITS(r); r = ((int)(get_buffer >> (bits_left -= r))) & ((1 << r) - 1); 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 thiscoef = jpeg_natural_order[k]; if (block[thiscoef] != 0) { //was CHECK_BIT_BUFFER(br_state, 1, goto undoit); if (bits_left < 1) { if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1)) { goto undoit; } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } //was if (GET_BITS(1)) if ((((int)(get_buffer >> (bits_left -= 1))) & 1) != 0) { if ((block[thiscoef] & p1) == 0) { // do nothing if already set it if (block[thiscoef] >= 0) { block[thiscoef] += p1; } else { block[thiscoef] += m1; } } } } else { if (--r < 0) { break; // reached target zero coefficient } } k++; } while(k <= Se); if (s != 0) { int pos = jpeg_natural_order[k]; // Output newly nonzero coefficient block[pos] = (short)s; // Remember its position in case we have to suspend newnz_pos[num_newnz++] = pos; } } } 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. for (; k <= Se; k++) { int thiscoef = jpeg_natural_order[k]; if (block[thiscoef] != 0) { //was CHECK_BIT_BUFFER(br_state, 1, goto undoit); if (bits_left < 1) { if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1)) { goto undoit; } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } //was if (GET_BITS(1)) if ((((int)(get_buffer >> (bits_left -= 1))) & 1) != 0) { if ((block[thiscoef] & p1) == 0) { // do nothing if already changed it if (block[thiscoef] >= 0) { block[thiscoef] += p1; } else { block[thiscoef] += m1; } } } } } // Count one block completed in EOB run EOBRUN--; } // 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; entropy.saved.EOBRUN = EOBRUN; // only part of saved state we need } // Account for restart interval (no-op if not using restarts) entropy.restarts_to_go--; return(true); undoit: // Re-zero any output coefficients that we made newly nonzero while (num_newnz > 0) { block[newnz_pos[--num_newnz]] = 0; } return(false); }
// MCU decoding for DC successive approximation refinement scan. // Note: we assume such scans can be multi-component, although the spec // is not very clear on the point. static bool decode_mcu_DC_refine(jpeg_decompress cinfo, short[][] MCU_data) { jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef; phuff_entropy_decoder entropy = (phuff_entropy_decoder)lossyd.entropy_private; short p1 = (short)(1 << cinfo.Al); // 1 in the bit position being coded // Process restart marker if needed; may have to suspend if (cinfo.restart_interval != 0) { if (entropy.restarts_to_go == 0) { if (!process_restart_dphuff(cinfo)) { return(false); } } } // Not worth the cycles to check insufficient_data here, // since we will not change the data anyway if we read zeroes. // Load up working state //was BITREAD_STATE_VARS; bitread_working_state br_state = new bitread_working_state(); //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; // Outer loop handles each block in the MCU for (int blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++) { short[] block = MCU_data[blkn]; // Encoded data is simply the next bit of the two's-complement DC value //was CHECK_BIT_BUFFER(br_state, 1, return false); if (bits_left < 1) { if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1)) { return(false); } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } //was if(GET_BITS(1)) if ((((int)(get_buffer >> (bits_left -= 1))) & 1) != 0) { block[0] |= p1; } // Note: since we use |=, repeating the assignment later is safe } // 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; // Account for restart interval (no-op if not using restarts) entropy.restarts_to_go--; return(true); }
// MCU decoding for AC initial scan (either spectral selection, // or first pass of successive approximation). static bool decode_mcu_AC_first(jpeg_decompress cinfo, short[][] MCU_data) { jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef; phuff_entropy_decoder entropy = (phuff_entropy_decoder)lossyd.entropy_private; int Se = cinfo.Se; int Al = cinfo.Al; // Process restart marker if needed; may have to suspend if (cinfo.restart_interval != 0) { if (entropy.restarts_to_go == 0) { if (!process_restart_dphuff(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) { // Load up working state. // We can avoid loading/saving bitread state if in an EOB run. uint EOBRUN = entropy.saved.EOBRUN; // only part of saved state we need // There is always only one block per MCU if (EOBRUN > 0) { EOBRUN--; // if it's a band of zeroes... ...process it now (we do nothing) } else { //was BITREAD_STATE_VARS; bitread_working_state br_state = new bitread_working_state(); //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; short[] block = MCU_data[0]; d_derived_tbl tbl = entropy.ac_derived_tbl; for (int k = cinfo.Ss; k <= Se; k++) { int s = 0, r; //was HUFF_DECODE(s, br_state, tbl, 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, tbl, 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 = tbl.look_nbits[look]) != 0) { //was DROP_BITS(nb); bits_left -= nb; s = tbl.look_sym[look]; } else { nb = HUFF_LOOKAHEAD + 1; if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, 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); // Scale and output coefficient in natural (dezigzagged) order block[jpeg_natural_order[k]] = (short)(s << Al); } else { if (r == 15) { // ZRL k += 15; // skip 15 zeroes in band } else { // EOBr, run length is 2^r + appended bits EOBRUN = (uint)(1 << r); if (r != 0) { // EOBr, r > 0 //was CHECK_BIT_BUFFER(br_state, r, return false); if (bits_left < r) { if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, r)) { return(false); } get_buffer = br_state.get_buffer; bits_left = br_state.bits_left; } //was r = GET_BITS(r); r = ((int)(get_buffer >> (bits_left -= r))) & ((1 << r) - 1); EOBRUN += (uint)r; } EOBRUN--; // this band is processed at this moment break; // force end-of-band } } } //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; } // Completed MCU, so update state entropy.saved.EOBRUN = EOBRUN; // only part of saved state we need } // Account for restart interval (no-op if not using restarts) entropy.restarts_to_go--; 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.) // MCU decoding for DC initial scan (either spectral selection, // or first pass of successive approximation). static bool decode_mcu_DC_first(jpeg_decompress cinfo, short[][] MCU_data) { jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef; phuff_entropy_decoder entropy = (phuff_entropy_decoder)lossyd.entropy_private; int Al = cinfo.Al; // Process restart marker if needed; may have to suspend if (cinfo.restart_interval != 0) { if (entropy.restarts_to_go == 0) { if (!process_restart_dphuff(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) { // Load up working state //was BITREAD_STATE_VARS; bitread_working_state br_state = new bitread_working_state(); savable_state state; state.last_dc_val = new int[MAX_COMPS_IN_SCAN]; //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; state.EOBRUN = entropy.saved.EOBRUN; 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]; int ci = cinfo.MCU_membership[blkn]; jpeg_component_info compptr = cinfo.cur_comp_info[ci]; d_derived_tbl tbl = entropy.derived_tbls[compptr.dc_tbl_no]; int s = 0; // Decode a single block's worth of coefficients // Section F.2.2.1: decode the DC coefficient difference //was HUFF_DECODE(s, br_state, tbl, 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, tbl, 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 = tbl.look_nbits[look]) != 0) { //was DROP_BITS(nb); bits_left -= nb; s = tbl.look_sym[look]; } else { nb = HUFF_LOOKAHEAD + 1; if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, 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); int 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); } // 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) block[0] = (short)(s << Al); } // 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; entropy.saved.EOBRUN = state.EOBRUN; 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); }