jpeg_init_read_tile_scanline(j_decompress_ptr cinfo, huffman_index *index, int *start_x, int *start_y, int *width, int *height) { int lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE; int lines_per_iMCU_col = cinfo->max_h_samp_factor * DCTSIZE; int row_offset = *start_y / lines_per_iMCU_row; int col_left_boundary = ((*start_x / lines_per_iMCU_col) / index->MCU_sample_size) * index->MCU_sample_size; int col_right_boundary = jdiv_round_up(*start_x + *width, lines_per_iMCU_col); cinfo->coef->MCU_columns_to_skip = *start_x / lines_per_iMCU_col - col_left_boundary; *height = (*start_y - row_offset * lines_per_iMCU_row) + *height; *start_x = col_left_boundary * lines_per_iMCU_col; *start_y = row_offset * lines_per_iMCU_row; cinfo->image_width = jmin(cinfo->original_image_width, col_right_boundary * lines_per_iMCU_col) - col_left_boundary * lines_per_iMCU_col; cinfo->input_iMCU_row = row_offset; cinfo->output_iMCU_row = row_offset; jinit_color_deconverter(cinfo); jpeg_calc_output_dimensions(cinfo); jinit_upsampler(cinfo); (*cinfo->master->prepare_for_output_pass) (cinfo); if (cinfo->progressive_mode) (*cinfo->entropy->start_pass) (cinfo); else jpeg_decompress_per_scan_setup(cinfo); int sample_size = DCTSIZE / cinfo->min_DCT_scaled_size; *height = jdiv_round_up(*height, sample_size); *width = cinfo->output_width; cinfo->output_scanline = lines_per_iMCU_row * row_offset / sample_size; cinfo->inputctl->consume_input = cinfo->coef->consume_data; cinfo->inputctl->consume_input_build_huffman_index = cinfo->coef->consume_data_build_huffman_index; cinfo->entropy->index = index; cinfo->input_iMCU_row = row_offset; cinfo->output_iMCU_row = row_offset; cinfo->coef->MCU_column_left_boundary = col_left_boundary; cinfo->coef->MCU_column_right_boundary = col_right_boundary; cinfo->coef->column_left_boundary = col_left_boundary / index->MCU_sample_size; cinfo->coef->column_right_boundary = jdiv_round_up(col_right_boundary, index->MCU_sample_size); }
LOCAL void master_selection (j_decompress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; boolean use_c_buffer; long samplesperrow; JDIMENSION jd_samplesperrow; /* Initialize dimensions and other stuff */ jpeg_calc_output_dimensions(cinfo); prepare_range_limit_table(cinfo); /* Width of an output scanline must be representable as JDIMENSION. */ samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; jd_samplesperrow = (JDIMENSION) samplesperrow; if ((long) jd_samplesperrow != samplesperrow) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); /* Initialize my private state */ master->pass_number = 0; master->using_merged_upsample = use_merged_upsample(cinfo); /* Color quantizer selection */ master->quantizer_1pass = NULL; master->quantizer_2pass = NULL; /* No mode changes if not using buffered-image mode. */ if (! cinfo->quantize_colors || ! cinfo->buffered_image) { cinfo->enable_1pass_quant = FALSE; cinfo->enable_external_quant = FALSE; cinfo->enable_2pass_quant = FALSE; } if (cinfo->quantize_colors) { if (cinfo->raw_data_out) ERREXIT(cinfo, JERR_NOTIMPL); /* 2-pass quantizer only works in 3-component color space. */ if (cinfo->out_color_components != 3) { cinfo->enable_1pass_quant = TRUE; cinfo->enable_external_quant = FALSE; cinfo->enable_2pass_quant = FALSE; cinfo->colormap = NULL; } else if (cinfo->colormap != NULL) { cinfo->enable_external_quant = TRUE; } else if (cinfo->two_pass_quantize) { cinfo->enable_2pass_quant = TRUE; } else { cinfo->enable_1pass_quant = TRUE; } if (cinfo->enable_1pass_quant) { #ifdef QUANT_1PASS_SUPPORTED jinit_1pass_quantizer(cinfo); master->quantizer_1pass = cinfo->cquantize; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } /* We use the 2-pass code to map to external colormaps. */ if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { #ifdef QUANT_2PASS_SUPPORTED jinit_2pass_quantizer(cinfo); master->quantizer_2pass = cinfo->cquantize; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } /* 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 (! cinfo->raw_data_out) { if (master->using_merged_upsample) { #ifdef UPSAMPLE_MERGING_SUPPORTED jinit_merged_upsampler(cinfo); /* does color conversion too */ #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { jinit_color_deconverter(cinfo); jinit_upsampler(cinfo); } jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); } /* Inverse DCT */ jinit_inverse_dct(cinfo); /* Entropy decoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) { ERREXIT(cinfo, JERR_ARITH_NOTIMPL); } else { if (cinfo->progressive_mode) { #ifdef D_PROGRESSIVE_SUPPORTED jinit_phuff_decoder(cinfo); #else ERREXIT(cinfo, JERR_NO_PROGRESSIVE); #endif } else jinit_huff_decoder(cinfo); } /* Initialize principal buffer controllers. */ use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; jinit_d_coef_controller(cinfo, use_c_buffer); if (! cinfo->raw_data_out) jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); /* Initialize input side of decompressor to consume first scan. */ (*cinfo->inputctl->start_input_pass) (cinfo); #ifdef D_MULTISCAN_FILES_SUPPORTED /* If jpeg_start_decompress will read the whole file, initialize * progress monitoring appropriately. The input step is counted * as one pass. */ if (cinfo->progress != NULL && ! cinfo->buffered_image && cinfo->inputctl->has_multiple_scans) { int nscans; /* Estimate number of scans to set pass_limit. */ if (cinfo->progressive_mode) { /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ nscans = 2 + 3 * cinfo->num_components; } else { /* For a nonprogressive multiscan file, estimate 1 scan per component. */ nscans = cinfo->num_components; } cinfo->progress->pass_counter = 0L; cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; cinfo->progress->completed_passes = 0; cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); /* Count the input pass as done */ master->pass_number++; } #endif /* D_MULTISCAN_FILES_SUPPORTED */ }
jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset, JDIMENSION *width) { int ci, align, orig_downsampled_width; JDIMENSION input_xoffset; boolean reinit_upsampler = FALSE; jpeg_component_info *compptr; if (cinfo->global_state != DSTATE_SCANNING || cinfo->output_scanline != 0) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (!xoffset || !width) ERREXIT(cinfo, JERR_BAD_CROP_SPEC); /* xoffset and width must fall within the output image dimensions. */ if (*width == 0 || *xoffset + *width > cinfo->output_width) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); /* No need to do anything if the caller wants the entire width. */ if (*width == cinfo->output_width) return; /* Ensuring the proper alignment of xoffset is tricky. At minimum, it * must align with an MCU boundary, because: * * (1) The IDCT is performed in blocks, and it is not feasible to modify * the algorithm so that it can transform partial blocks. * (2) Because of the SIMD extensions, any input buffer passed to the * upsampling and color conversion routines must be aligned to the * SIMD word size (for instance, 128-bit in the case of SSE2.) The * easiest way to accomplish this without copying data is to ensure * that upsampling and color conversion begin at the start of the * first MCU column that will be inverse transformed. * * In practice, we actually impose a stricter alignment requirement. We * require that xoffset be a multiple of the maximum MCU column width of all * of the components (the "iMCU column width.") This is to simplify the * single-pass decompression case, allowing us to use the same MCU column * width for all of the components. */ align = cinfo->_min_DCT_scaled_size * cinfo->max_h_samp_factor; /* Adjust xoffset to the nearest iMCU boundary <= the requested value */ input_xoffset = *xoffset; *xoffset = (input_xoffset / align) * align; /* Adjust the width so that the right edge of the output image is as * requested (only the left edge is altered.) It is important that calling * programs check this value after this function returns, so that they can * allocate an output buffer with the appropriate size. */ *width = *width + input_xoffset - *xoffset; cinfo->output_width = *width; /* Set the first and last iMCU columns that we must decompress. These values * will be used in single-scan decompressions. */ cinfo->master->first_iMCU_col = (JDIMENSION) (long) (*xoffset) / (long) align; cinfo->master->last_iMCU_col = (JDIMENSION) jdiv_round_up((long) (*xoffset + cinfo->output_width), (long) align) - 1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Set downsampled_width to the new output width. */ orig_downsampled_width = compptr->downsampled_width; compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long) (cinfo->output_width * compptr->h_samp_factor), (long) cinfo->max_h_samp_factor); if (compptr->downsampled_width < 2 && orig_downsampled_width >= 2) reinit_upsampler = TRUE; /* Set the first and last iMCU columns that we must decompress. These * values will be used in multi-scan decompressions. */ cinfo->master->first_MCU_col[ci] = (JDIMENSION) (long) (*xoffset * compptr->h_samp_factor) / (long) align; cinfo->master->last_MCU_col[ci] = (JDIMENSION) jdiv_round_up((long) ((*xoffset + cinfo->output_width) * compptr->h_samp_factor), (long) align) - 1; } if (reinit_upsampler) { cinfo->master->jinit_upsampler_no_alloc = TRUE; jinit_upsampler(cinfo); cinfo->master->jinit_upsampler_no_alloc = FALSE; } }
static void master_selection (CJPegDecompress * cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; Word8 use_c_buffer; long samplesperrow; Word jd_samplesperrow; /* Initialize dimensions and other stuff */ jpeg_calc_output_dimensions(cinfo); prepare_range_limit_table(cinfo); /* Width of an output scanline must be representable as Word. */ samplesperrow = (long) cinfo->output_width * (long) cinfo->m_ColorComponents; jd_samplesperrow = (Word) samplesperrow; if ((long) jd_samplesperrow != samplesperrow) cinfo->FatalError(JPeg70::JERR_WIDTH_OVERFLOW); /* Initialize my private state */ master->pass_number = 0; master->using_merged_upsample = use_merged_upsample(cinfo); /* Color quantizer selection */ master->quantizer_1pass = NULL; master->quantizer_2pass = NULL; /* No mode changes if not using buffered-image mode. */ if (! cinfo->m_QuantizeColors || ! cinfo->buffered_image) { cinfo->enable_1pass_quant = FALSE; cinfo->enable_external_quant = FALSE; cinfo->enable_2pass_quant = FALSE; } if (cinfo->m_QuantizeColors) { if (cinfo->raw_data_out) cinfo->FatalError(JPeg70::JERR_NOTIMPL); /* 2-pass quantizer only works in 3-component color space. */ if (cinfo->m_ColorComponents != 3) { cinfo->enable_1pass_quant = TRUE; cinfo->enable_external_quant = FALSE; cinfo->enable_2pass_quant = FALSE; cinfo->colormap = 0; } else if (cinfo->colormap) { cinfo->enable_external_quant = TRUE; } else if (cinfo->two_pass_quantize) { cinfo->enable_2pass_quant = TRUE; } else { cinfo->enable_1pass_quant = TRUE; } if (cinfo->enable_1pass_quant) { cinfo->m_CQuantizePtr = new JPeg70::CColorQuantizer1Pass(cinfo); master->quantizer_1pass = cinfo->m_CQuantizePtr; } /* We use the 2-pass code to map to external colormaps. */ if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { cinfo->m_CQuantizePtr = new JPeg70::CColorQuantizer2Pass(cinfo); master->quantizer_2pass = cinfo->m_CQuantizePtr; } /* 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 (!cinfo->raw_data_out) { if (master->using_merged_upsample) { jinit_merged_upsampler(cinfo); /* does color conversion too */ } else { cinfo->m_ColorDeconverterPtr = new JPeg70::CColorDeconverter(cinfo); jinit_upsampler(cinfo); } jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); } /* Inverse DCT */ jinit_inverse_dct(cinfo); /* Entropy decoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) { cinfo->FatalError(JPeg70::JERR_ARITH_NOTIMPL); } else { if (cinfo->progressive_mode) { jinit_phuff_decoder(cinfo); } else jinit_huff_decoder(cinfo); } /* Initialize principal buffer controllers. */ use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; jinit_d_coef_controller(cinfo, use_c_buffer); if (!cinfo->raw_data_out) jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((JPeg70::CCommonManager *) cinfo); /* Initialize input side of decompressor to consume first scan. */ (*cinfo->inputctl->start_input_pass) (cinfo); /* If jpeg_start_decompress will read the whole file, initialize * progress monitoring appropriately. The input step is counted * as one pass. */ if (!cinfo->buffered_image && cinfo->inputctl->has_multiple_scans) { int nscans; /* Estimate number of scans to set pass_limit. */ if (cinfo->progressive_mode) { /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ nscans = 2 + 3 * cinfo->m_NumComponents; } else { /* For a nonprogressive multiscan file, estimate 1 scan per component. */ nscans = cinfo->m_NumComponents; } cinfo->m_PassCounter = 0; cinfo->m_PassLimit = (Word) cinfo->total_iMCU_rows * nscans; cinfo->m_CompletedPasses = 0; cinfo->m_TotalPasses = (cinfo->enable_2pass_quant ? 3U : 2U); /* Count the input pass as done */ master->pass_number++; } }