// Emit a restart marker & resynchronize predictions. static bool emit_restart(ref working_state_sq state, int restart_num) { if (!flush_bits(ref state)) { return(false); } //was emit_byte(state, 0xFF, return false); state.output_bytes[state.next_output_byte++] = 0xFF; state.free_in_buffer--; if (state.free_in_buffer == 0) { if (!dump_buffer(ref state)) { return(false); } } //was emit_byte(state, JPEG_RST0 + restart_num, return false); state.output_bytes[state.next_output_byte++] = (byte)(JPEG_RST0 + restart_num); state.free_in_buffer--; if (state.free_in_buffer == 0) { if (!dump_buffer(ref state)) { return(false); } } // Re-initialize DC predictions to 0 for (int ci = 0; ci < state.cinfo.comps_in_scan; ci++) { state.cur.last_dc_val[ci] = 0; } // The restart counter is not updated until we successfully write the MCU. return(true); }
// Emit a restart marker & resynchronize predictions. static bool emit_restart(ref working_state_sq state, int restart_num) { if(!flush_bits(ref state)) return false; //was emit_byte(state, 0xFF, return false); state.output_bytes[state.next_output_byte++]=0xFF; state.free_in_buffer--; if(state.free_in_buffer==0) { if(!dump_buffer(ref state)) return false; } //was emit_byte(state, JPEG_RST0 + restart_num, return false); state.output_bytes[state.next_output_byte++]=(byte)(JPEG_RST0+restart_num); state.free_in_buffer--; if(state.free_in_buffer==0) { if(!dump_buffer(ref state)) return false; } // Re-initialize DC predictions to 0 for(int ci=0; ci<state.cinfo.comps_in_scan; ci++) state.cur.last_dc_val[ci]=0; // The restart counter is not updated until we successfully write the MCU. return true; }
// Encode a single block's worth of coefficients static bool encode_one_block(ref working_state_sq 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_COEF_BITS+1) ERREXIT(state.cinfo, J_MESSAGE_CODE.JERR_BAD_DCT_COEF); // Emit the Huffman-coded symbol for the number of bits if(!emit_bits(ref 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(ref state, (uint)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<DCTSIZE2; k++) { temp=block[jpeg_natural_order[k]]; if(temp==0) { r++; continue; } // if run length > 15, must emit special run-length-16 codes (0xF0) while(r>15) { if(!emit_bits(ref 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_COEF_BITS) ERREXIT(state.cinfo, J_MESSAGE_CODE.JERR_BAD_DCT_COEF); // Emit Huffman symbol for run length / number of bits int i=(r<<4)+nbits; if(!emit_bits(ref 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(ref state, (uint)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(ref state, actbl.ehufco[0], actbl.ehufsi[0])) return false; } return true; }
static bool flush_bits(ref working_state_sq state) { if(!emit_bits(ref state, 0x7F, 7)) return false; // fill any partial byte with ones state.cur.put_buffer=0; // and reset bit-buffer to empty state.cur.put_bits=0; return true; }
// Outputting bits to the file // 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. // Emit some bits; return true if successful, false if must suspend static bool emit_bits(ref working_state_sq state, uint code, int size) { // This routine is heavily used, so it's worth coding tightly. int put_buffer=(int)code; int put_bits=state.cur.put_bits; // if size is 0, caller used an invalid Huffman table entry if(size==0) ERREXIT(state.cinfo, 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.cur.put_buffer; // and merge with old buffer contents while(put_bits>=8) { byte c=(byte)((put_buffer>>16)&0xFF); //was emit_byte(state, c, return false); state.output_bytes[state.next_output_byte++]=c; state.free_in_buffer--; if(state.free_in_buffer==0) { if(!dump_buffer(ref state)) return false; } if(c==0xFF) { // need to stuff a zero byte? //was emit_byte(state, 0, return false); state.output_bytes[state.next_output_byte++]=0; state.free_in_buffer--; if(state.free_in_buffer==0) { if(!dump_buffer(ref state)) return false; } } put_buffer<<=8; put_bits-=8; } state.cur.put_buffer=put_buffer; // update state variables state.cur.put_bits=put_bits; return true; }
// Outputting bytes to the file // Empty the output buffer; return true if successful, false if must suspend static bool dump_buffer(ref working_state_sq state) { jpeg_destination_mgr dest=state.cinfo.dest; if(!dest.empty_output_buffer(state.cinfo)) return false; // After a successful buffer dump, must reset buffer pointers state.output_bytes=dest.output_bytes; state.next_output_byte=dest.next_output_byte; state.free_in_buffer=dest.free_in_buffer; return true; }
// Encode a single block's worth of coefficients static bool encode_one_block(ref working_state_sq 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_COEF_BITS + 1) { ERREXIT(state.cinfo, J_MESSAGE_CODE.JERR_BAD_DCT_COEF); } // Emit the Huffman-coded symbol for the number of bits if (!emit_bits(ref 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(ref state, (uint)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 < DCTSIZE2; k++) { temp = block[jpeg_natural_order[k]]; if (temp == 0) { r++; continue; } // if run length > 15, must emit special run-length-16 codes (0xF0) while (r > 15) { if (!emit_bits(ref 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_COEF_BITS) { ERREXIT(state.cinfo, J_MESSAGE_CODE.JERR_BAD_DCT_COEF); } // Emit Huffman symbol for run length / number of bits int i = (r << 4) + nbits; if (!emit_bits(ref 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(ref state, (uint)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(ref state, actbl.ehufco[0], actbl.ehufsi[0])) { return(false); } } return(true); }