/// <summary> /// Tunes decompressor /// </summary> /// <param name="jpeg">Stream with input compressed JPEG data</param> private void beforeDecompress(Stream jpeg) { m_decompressor.jpeg_stdio_src(jpeg); /* Read file header, set default decompression parameters */ m_decompressor.jpeg_read_header(true); applyParameters(m_decompressionParameters); m_decompressor.jpeg_calc_output_dimensions(); }
private int cur_output_row; /* next row# to write to virtual array */ public bmp_dest_struct(jpeg_decompress_struct cinfo, bool is_os2) { this.cinfo = cinfo; this.is_os2 = is_os2; if (cinfo.Out_color_space == J_COLOR_SPACE.JCS_GRAYSCALE) { m_putGrayRows = true; } else if (cinfo.Out_color_space == J_COLOR_SPACE.JCS_RGB) { if (cinfo.Quantize_colors) { m_putGrayRows = true; } else { m_putGrayRows = false; } } else { cinfo.ERREXIT((int)ADDON_MESSAGE_CODE.JERR_BMP_COLORSPACE); } /* Calculate output image dimensions so we can allocate space */ cinfo.jpeg_calc_output_dimensions(); /* Determine width of rows in the BMP file (padded to 4-byte boundary). */ row_width = cinfo.Output_width * cinfo.Output_components; data_width = row_width; while ((row_width & 3) != 0) { row_width++; } pad_bytes = row_width - data_width; /* Allocate space for inversion array, prepare for write pass */ whole_image = jpeg_common_struct.CreateSamplesArray(row_width, cinfo.Output_height); whole_image.ErrorProcessor = cinfo; cur_output_row = 0; if (cinfo.Progress != null) { cdjpeg_progress_mgr progress = cinfo.Progress as cdjpeg_progress_mgr; if (progress != null) { /* count file input as separate pass */ progress.total_extra_passes++; } } /* Create decompressor output buffer. */ buffer = jpeg_common_struct.AllocJpegSamples(row_width, 1); buffer_height = 1; }
/// <summary> /// Master selection of decompression modules. /// This is done once at jpeg_start_decompress time. We determine /// which modules will be used and give them appropriate initialization calls. /// We also initialize the decompressor input side to begin consuming data. /// /// Since jpeg_read_header has finished, we know what is in the SOF /// and (first) SOS markers. We also have all the application parameter /// settings. /// </summary> private void master_selection() { /* Initialize dimensions and other stuff */ m_cinfo.jpeg_calc_output_dimensions(); prepare_range_limit_table(); /* Width of an output scanline must be representable as int. */ long samplesperrow = m_cinfo.m_output_width * m_cinfo.m_out_color_components; int jd_samplesperrow = (int)samplesperrow; if ((long)jd_samplesperrow != samplesperrow) { m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_WIDTH_OVERFLOW); } /* Initialize my private state */ m_pass_number = 0; m_using_merged_upsample = m_cinfo.use_merged_upsample(); /* Color quantizer selection */ m_quantizer_1pass = null; m_quantizer_2pass = null; /* No mode changes if not using buffered-image mode. */ if (!m_cinfo.m_quantize_colors || !m_cinfo.m_buffered_image) { m_cinfo.m_enable_1pass_quant = false; m_cinfo.m_enable_external_quant = false; m_cinfo.m_enable_2pass_quant = false; } if (m_cinfo.m_quantize_colors) { if (m_cinfo.m_raw_data_out) { m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_NOTIMPL); } /* 2-pass quantizer only works in 3-component color space. */ if (m_cinfo.m_out_color_components != 3) { m_cinfo.m_enable_1pass_quant = true; m_cinfo.m_enable_external_quant = false; m_cinfo.m_enable_2pass_quant = false; m_cinfo.m_colormap = null; } else if (m_cinfo.m_colormap != null) { m_cinfo.m_enable_external_quant = true; } else if (m_cinfo.m_two_pass_quantize) { m_cinfo.m_enable_2pass_quant = true; } else { m_cinfo.m_enable_1pass_quant = true; } if (m_cinfo.m_enable_1pass_quant) { m_cinfo.m_cquantize = new my_1pass_cquantizer(m_cinfo); m_quantizer_1pass = m_cinfo.m_cquantize; } /* We use the 2-pass code to map to external colormaps. */ if (m_cinfo.m_enable_2pass_quant || m_cinfo.m_enable_external_quant) { m_cinfo.m_cquantize = new my_2pass_cquantizer(m_cinfo); m_quantizer_2pass = m_cinfo.m_cquantize; } /* If both quantizers are initialized, the 2-pass one is left active; * this is necessary for starting with quantization to an external map. */ } /* Post-processing: in particular, color conversion first */ if (!m_cinfo.m_raw_data_out) { if (m_using_merged_upsample) { /* does color conversion too */ m_cinfo.m_upsample = new my_merged_upsampler(m_cinfo); } else { m_cinfo.m_cconvert = new jpeg_color_deconverter(m_cinfo); m_cinfo.m_upsample = new my_upsampler(m_cinfo); } m_cinfo.m_post = new jpeg_d_post_controller(m_cinfo, m_cinfo.m_enable_2pass_quant); } /* Inverse DCT */ m_cinfo.m_idct = new jpeg_inverse_dct(m_cinfo); if (m_cinfo.m_progressive_mode) { m_cinfo.m_entropy = new phuff_entropy_decoder(m_cinfo); } else { m_cinfo.m_entropy = new huff_entropy_decoder(m_cinfo); } /* Initialize principal buffer controllers. */ bool use_c_buffer = m_cinfo.m_inputctl.HasMultipleScans() || m_cinfo.m_buffered_image; m_cinfo.m_coef = new jpeg_d_coef_controller(m_cinfo, use_c_buffer); if (!m_cinfo.m_raw_data_out) { m_cinfo.m_main = new jpeg_d_main_controller(m_cinfo); } /* Initialize input side of decompressor to consume first scan. */ m_cinfo.m_inputctl.start_input_pass(); /* If jpeg_start_decompress will read the whole file, initialize * progress monitoring appropriately. The input step is counted * as one pass. */ if (m_cinfo.m_progress != null && !m_cinfo.m_buffered_image && m_cinfo.m_inputctl.HasMultipleScans()) { /* Estimate number of scans to set pass_limit. */ int nscans; if (m_cinfo.m_progressive_mode) { /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ nscans = 2 + 3 * m_cinfo.m_num_components; } else { /* For a non progressive multiscan file, estimate 1 scan per component. */ nscans = m_cinfo.m_num_components; } m_cinfo.m_progress.Pass_counter = 0; m_cinfo.m_progress.Pass_limit = m_cinfo.m_total_iMCU_rows * nscans; m_cinfo.m_progress.Completed_passes = 0; m_cinfo.m_progress.Total_passes = (m_cinfo.m_enable_2pass_quant ? 3 : 2); /* Count the input pass as done */ m_pass_number++; } }