// Set up the scan parameters for the current scan static void select_scan_parameters(jpeg_compress cinfo) { #if NEED_SCAN_SCRIPT if (cinfo.scan_info != null) { // Prepare for current scan --- the script is already validated my_comp_master master = (my_comp_master)cinfo.master; jpeg_scan_info scanptr = cinfo.scan_info[master.scan_number]; cinfo.comps_in_scan = scanptr.comps_in_scan; for (int ci = 0; ci < scanptr.comps_in_scan; ci++) { cinfo.cur_comp_info[ci] = cinfo.comp_info[scanptr.component_index[ci]]; } cinfo.Ss = scanptr.Ss; cinfo.Se = scanptr.Se; cinfo.Ah = scanptr.Ah; cinfo.Al = scanptr.Al; } else #endif { // Prepare for single sequential-JPEG scan containing all components if (cinfo.num_components > MAX_COMPS_IN_SCAN) { ERREXIT2(cinfo, J_MESSAGE_CODE.JERR_COMPONENT_COUNT, cinfo.num_components, MAX_COMPS_IN_SCAN); } cinfo.comps_in_scan = cinfo.num_components; for (int ci = 0; ci < cinfo.num_components; ci++) { cinfo.cur_comp_info[ci] = cinfo.comp_info[ci]; } if (cinfo.lossless) { #if C_LOSSLESS_SUPPORTED // If we fall through to here, the user specified lossless, but did not // provide a scan script. ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NO_LOSSLESS_SCRIPT); #endif } else { cinfo.process = J_CODEC_PROCESS.JPROC_SEQUENTIAL; cinfo.Ss = 0; cinfo.Se = DCTSIZE2 - 1; cinfo.Ah = 0; cinfo.Al = 0; } } }
// Finish up at end of pass. static void finish_pass_master(jpeg_compress cinfo) { my_comp_master master = (my_comp_master)cinfo.master; // The entropy coder always needs an end-of-pass call, // either to analyze statistics or to flush its output buffer. cinfo.coef.entropy_finish_pass(cinfo); // Update state for next pass switch (master.pass_type) { case c_pass_type.main_pass: // next pass is either output of scan 0 (after optimization) // or output of scan 1 (if no optimization). master.pass_type = c_pass_type.output_pass; if (!cinfo.optimize_coding) { master.scan_number++; } break; case c_pass_type.huff_opt_pass: // next pass is always output of current scan master.pass_type = c_pass_type.output_pass; break; case c_pass_type.output_pass: // next pass is either optimization or output of next scan if (cinfo.optimize_coding) { master.pass_type = c_pass_type.huff_opt_pass; } master.scan_number++; break; } master.pass_number++; }
// Initialize master compression control. static void jinit_c_master_control(jpeg_compress cinfo, bool transcode_only) { my_comp_master master=null; try { master=new my_comp_master(); } catch { ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4); } cinfo.master=master; master.prepare_for_pass=prepare_for_pass; master.pass_startup=pass_startup; master.finish_pass=finish_pass_master; master.is_last_pass=false; cinfo.DCT_size=cinfo.lossless?1:(uint)DCTSIZE; // Validate parameters, determine derived values initial_setup(cinfo); if(cinfo.scan_info!=null) { #if NEED_SCAN_SCRIPT validate_script(cinfo); #else ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED); #endif } else { cinfo.process=J_CODEC_PROCESS.JPROC_SEQUENTIAL; cinfo.num_scans=1; } if((cinfo.process==J_CODEC_PROCESS.JPROC_PROGRESSIVE||cinfo.process==J_CODEC_PROCESS.JPROC_LOSSLESS)&&!cinfo.arith_code) cinfo.optimize_coding=true; // assume default tables no good for progressive mode or lossless mode; but only in Huffman case! // Initialize my private state if(transcode_only) { // no main pass in transcoding if(cinfo.optimize_coding) master.pass_type=c_pass_type.huff_opt_pass; else master.pass_type=c_pass_type.output_pass; } else { // for normal compression, first pass is always this type: master.pass_type=c_pass_type.main_pass; } master.scan_number=master.pass_number=0; if(cinfo.optimize_coding) master.total_passes=cinfo.num_scans*2; else master.total_passes=cinfo.num_scans; }
// Initialize master compression control. static void jinit_c_master_control(jpeg_compress cinfo, bool transcode_only) { my_comp_master master = null; try { master = new my_comp_master(); } catch { ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4); } cinfo.master = master; master.prepare_for_pass = prepare_for_pass; master.pass_startup = pass_startup; master.finish_pass = finish_pass_master; master.is_last_pass = false; cinfo.DCT_size = cinfo.lossless?1:(uint)DCTSIZE; // Validate parameters, determine derived values initial_setup(cinfo); if (cinfo.scan_info != null) { #if NEED_SCAN_SCRIPT validate_script(cinfo); #else ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED); #endif } else { cinfo.process = J_CODEC_PROCESS.JPROC_SEQUENTIAL; cinfo.num_scans = 1; } if ((cinfo.process == J_CODEC_PROCESS.JPROC_PROGRESSIVE || cinfo.process == J_CODEC_PROCESS.JPROC_LOSSLESS) && !cinfo.arith_code) { cinfo.optimize_coding = true; // assume default tables no good for progressive mode or lossless mode; but only in Huffman case! } // Initialize my private state if (transcode_only) { // no main pass in transcoding if (cinfo.optimize_coding) { master.pass_type = c_pass_type.huff_opt_pass; } else { master.pass_type = c_pass_type.output_pass; } } else { // for normal compression, first pass is always this type: master.pass_type = c_pass_type.main_pass; } master.scan_number = master.pass_number = 0; if (cinfo.optimize_coding) { master.total_passes = cinfo.num_scans * 2; } else { master.total_passes = cinfo.num_scans; } }
// Per-pass setup. // This is called at the beginning of each pass. We determine which modules // will be active during this pass and give them appropriate start_pass calls. // We also set is_last_pass to indicate whether any more passes will be required. static void prepare_for_pass(jpeg_compress cinfo) { my_comp_master master = (my_comp_master)cinfo.master; switch (master.pass_type) { case c_pass_type.main_pass: // Initial pass: will collect input data, and do either Huffman // optimization or data output for the first scan. select_scan_parameters(cinfo); per_scan_setup(cinfo); if (!cinfo.raw_data_in) { cinfo.cconvert.start_pass(cinfo); cinfo.downsample.start_pass(cinfo); cinfo.prep.start_pass(cinfo, J_BUF_MODE.JBUF_PASS_THRU); } cinfo.coef.entropy_start_pass(cinfo, cinfo.optimize_coding); cinfo.coef.start_pass(cinfo, (master.total_passes > 1?J_BUF_MODE.JBUF_SAVE_AND_PASS:J_BUF_MODE.JBUF_PASS_THRU)); cinfo.main.start_pass(cinfo, J_BUF_MODE.JBUF_PASS_THRU); if (cinfo.optimize_coding) { // No immediate data output; postpone writing frame/scan headers master.call_pass_startup = false; } else { // Will write frame/scan headers at first jpeg_write_scanlines call master.call_pass_startup = true; } break; #if ENTROPY_OPT_SUPPORTED case c_pass_type.huff_opt_pass: // Do Huffman optimization for a scan after the first one. select_scan_parameters(cinfo); per_scan_setup(cinfo); if (cinfo.coef.need_optimization_pass(cinfo)) { cinfo.coef.entropy_start_pass(cinfo, true); cinfo.coef.start_pass(cinfo, J_BUF_MODE.JBUF_CRANK_DEST); master.call_pass_startup = false; break; } // Special case: Huffman DC refinement scans need no Huffman table // and therefore we can skip the optimization pass for them. master.pass_type = c_pass_type.output_pass; master.pass_number++; goto case c_pass_type.output_pass; // FALLTHROUGH #endif case c_pass_type.output_pass: // Do a data-output pass. // We need not repeat per-scan setup if prior optimization pass did it. if (!cinfo.optimize_coding) { select_scan_parameters(cinfo); per_scan_setup(cinfo); } cinfo.coef.entropy_start_pass(cinfo, false); cinfo.coef.start_pass(cinfo, J_BUF_MODE.JBUF_CRANK_DEST); // We emit frame/scan headers now if (master.scan_number == 0) { cinfo.marker.write_frame_header(cinfo); } cinfo.marker.write_scan_header(cinfo); master.call_pass_startup = false; break; default: ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED); break; } master.is_last_pass = (master.pass_number == master.total_passes - 1); // Set up progress monitor's pass info if present if (cinfo.progress != null) { cinfo.progress.completed_passes = master.pass_number; cinfo.progress.total_passes = master.total_passes; } }