// Initialize the marker writer module. static void jinit_marker_writer(jpeg_compress cinfo) { my_marker_writer marker=null; try { // Create the subobject marker=new my_marker_writer(); } catch { ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4); } cinfo.marker=marker; // Initialize method pointers marker.write_file_header=write_file_header; marker.write_frame_header=write_frame_header; marker.write_scan_header=write_scan_header; marker.write_file_trailer=write_file_trailer; marker.write_tables_only=write_tables_only; marker.write_marker_header=write_marker_header; marker.write_marker_byte=write_marker_byte; // Initialize private state marker.last_restart_interval=0; }
// Write scan header. // This consists of DHT or DAC markers, optional DRI, and SOS. // Compressed data will be written following the SOS. static void write_scan_header(jpeg_compress cinfo) { if(cinfo.arith_code) { // Emit arith conditioning info. We may have some duplication // if the file has multiple scans, but it's so small it's hardly // worth worrying about. emit_dac(cinfo); } else { // Emit Huffman tables. // Note that emit_dht() suppresses any duplicate tables. for(int i=0; i<cinfo.comps_in_scan; i++) { jpeg_component_info compptr=cinfo.cur_comp_info[i]; if(cinfo.process==J_CODEC_PROCESS.JPROC_PROGRESSIVE) { // Progressive mode: only DC or only AC tables are used in one scan if(cinfo.Ss==0) { if(cinfo.Ah==0) emit_dht(cinfo, compptr.dc_tbl_no, false); // DC needs no table for refinement scan } else { emit_dht(cinfo, compptr.ac_tbl_no, true); } } else if(cinfo.process==J_CODEC_PROCESS.JPROC_LOSSLESS) { // Lossless mode: only DC tables are used emit_dht(cinfo, compptr.dc_tbl_no, false); } else { // Sequential mode: need both DC and AC tables emit_dht(cinfo, compptr.dc_tbl_no, false); emit_dht(cinfo, compptr.ac_tbl_no, true); } } } my_marker_writer marker=(my_marker_writer)cinfo.marker; // Emit DRI if required --- note that DRI value could change for each scan. // We avoid wasting space with unnecessary DRIs, however. if(cinfo.restart_interval!=marker.last_restart_interval) { emit_dri(cinfo); marker.last_restart_interval=cinfo.restart_interval; } emit_sos(cinfo); }
// Write datastream header. // This consists of an SOI and optional APPn markers. // We recommend use of the JFIF marker, but not the Adobe marker, // when using YCbCr or grayscale data. The JFIF marker should NOT // be used for any other JPEG colorspace. The Adobe marker is helpful // to distinguish RGB, CMYK, and YCCK colorspaces. // Note that an application can write additional header markers after // jpeg_start_compress returns. static void write_file_header(jpeg_compress cinfo) { my_marker_writer marker=(my_marker_writer)cinfo.marker; emit_marker(cinfo, JPEG_MARKER.M_SOI); // first the SOI // SOI is defined to reset restart interval to 0 marker.last_restart_interval=0; if(cinfo.write_JFIF_header) emit_jfif_app0(cinfo); // next an optional JFIF APP0 if(cinfo.exif!=null&&cinfo.exif.HasData) emit_exif_app1(cinfo); // next an optional EXIF APP1 if(cinfo.write_Adobe_marker) emit_adobe_app14(cinfo); // next an optional Adobe APP14 }