| /* |
| * jdlossy.c |
| * |
| * This file was part of the Independent JPEG Group's software: |
| * Copyright (C) 1998, Thomas G. Lane. |
| * Lossless JPEG Modifications: |
| * Copyright (C) 1999, Ken Murchison. |
| * For conditions of distribution and use, see the accompanying README file. |
| * |
| * This file contains the control logic for the lossy JPEG decompressor. |
| */ |
| |
| #define JPEG_INTERNALS |
| #include "jinclude.h" |
| #include "jpeglib.h" |
| #include "jlossy.h" |
| |
| |
| /* |
| * Compute output image dimensions and related values. |
| */ |
| |
| METHODDEF(void) |
| calc_output_dimensions (j_decompress_ptr cinfo) |
| { |
| #ifdef IDCT_SCALING_SUPPORTED |
| int ci; |
| jpeg_component_info *compptr; |
| |
| /* Compute actual output image dimensions and DCT scaling choices. */ |
| if (cinfo->scale_num * 8 <= cinfo->scale_denom) { |
| /* Provide 1/8 scaling */ |
| cinfo->output_width = (JDIMENSION) |
| jdiv_round_up((long) cinfo->image_width, 8L); |
| cinfo->output_height = (JDIMENSION) |
| jdiv_round_up((long) cinfo->image_height, 8L); |
| cinfo->min_codec_data_unit = 1; |
| } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { |
| /* Provide 1/4 scaling */ |
| cinfo->output_width = (JDIMENSION) |
| jdiv_round_up((long) cinfo->image_width, 4L); |
| cinfo->output_height = (JDIMENSION) |
| jdiv_round_up((long) cinfo->image_height, 4L); |
| cinfo->min_codec_data_unit = 2; |
| } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { |
| /* Provide 1/2 scaling */ |
| cinfo->output_width = (JDIMENSION) |
| jdiv_round_up((long) cinfo->image_width, 2L); |
| cinfo->output_height = (JDIMENSION) |
| jdiv_round_up((long) cinfo->image_height, 2L); |
| cinfo->min_codec_data_unit = 4; |
| } else { |
| /* Provide 1/1 scaling */ |
| cinfo->output_width = cinfo->image_width; |
| cinfo->output_height = cinfo->image_height; |
| cinfo->min_codec_data_unit = DCTSIZE; |
| } |
| /* In selecting the actual DCT scaling for each component, we try to |
| * scale up the chroma components via IDCT scaling rather than upsampling. |
| * This saves time if the upsampler gets to use 1:1 scaling. |
| * Note this code assumes that the supported DCT scalings are powers of 2. |
| */ |
| for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; |
| ci++, compptr++) { |
| int ssize = cinfo->min_codec_data_unit; |
| while (ssize < DCTSIZE && |
| (compptr->h_samp_factor * ssize * 2 <= |
| cinfo->max_h_samp_factor * cinfo->min_codec_data_unit) && |
| (compptr->v_samp_factor * ssize * 2 <= |
| cinfo->max_v_samp_factor * cinfo->min_codec_data_unit)) { |
| ssize = ssize * 2; |
| } |
| compptr->codec_data_unit = ssize; |
| } |
| |
| /* Recompute downsampled dimensions of components; |
| * application needs to know these if using raw downsampled data. |
| */ |
| for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; |
| ci++, compptr++) { |
| /* Size in samples, after IDCT scaling */ |
| compptr->downsampled_width = (JDIMENSION) |
| jdiv_round_up((long) cinfo->image_width * |
| (long) (compptr->h_samp_factor * compptr->codec_data_unit), |
| (long) (cinfo->max_h_samp_factor * DCTSIZE)); |
| compptr->downsampled_height = (JDIMENSION) |
| jdiv_round_up((long) cinfo->image_height * |
| (long) (compptr->v_samp_factor * compptr->codec_data_unit), |
| (long) (cinfo->max_v_samp_factor * DCTSIZE)); |
| } |
| |
| #else /* !IDCT_SCALING_SUPPORTED */ |
| |
| /* Hardwire it to "no scaling" */ |
| cinfo->output_width = cinfo->image_width; |
| cinfo->output_height = cinfo->image_height; |
| /* jdinput.c has already initialized codec_data_unit to DCTSIZE, |
| * and has computed unscaled downsampled_width and downsampled_height. |
| */ |
| |
| #endif /* IDCT_SCALING_SUPPORTED */ |
| } |
| |
| |
| /* |
| * Save away a copy of the Q-table referenced by each component present |
| * in the current scan, unless already saved during a prior scan. |
| * |
| * In a multiple-scan JPEG file, the encoder could assign different components |
| * the same Q-table slot number, but change table definitions between scans |
| * so that each component uses a different Q-table. (The IJG encoder is not |
| * currently capable of doing this, but other encoders might.) Since we want |
| * to be able to dequantize all the components at the end of the file, this |
| * means that we have to save away the table actually used for each component. |
| * We do this by copying the table at the start of the first scan containing |
| * the component. |
| * The JPEG spec prohibits the encoder from changing the contents of a Q-table |
| * slot between scans of a component using that slot. If the encoder does so |
| * anyway, this decoder will simply use the Q-table values that were current |
| * at the start of the first scan for the component. |
| * |
| * The decompressor output side looks only at the saved quant tables, |
| * not at the current Q-table slots. |
| */ |
| |
| LOCAL(void) |
| latch_quant_tables (j_decompress_ptr cinfo) |
| { |
| int ci, qtblno; |
| jpeg_component_info *compptr; |
| JQUANT_TBL * qtbl; |
| |
| for (ci = 0; ci < cinfo->comps_in_scan; ci++) { |
| compptr = cinfo->cur_comp_info[ci]; |
| /* No work if we already saved Q-table for this component */ |
| if (compptr->quant_table != NULL) |
| continue; |
| /* Make sure specified quantization table is present */ |
| qtblno = compptr->quant_tbl_no; |
| if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || |
| cinfo->quant_tbl_ptrs[qtblno] == NULL) |
| ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); |
| /* OK, save away the quantization table */ |
| qtbl = (JQUANT_TBL *) |
| (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
| SIZEOF(JQUANT_TBL)); |
| MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); |
| compptr->quant_table = qtbl; |
| } |
| } |
| |
| |
| /* |
| * Initialize for an input processing pass. |
| */ |
| |
| METHODDEF(void) |
| start_input_pass (j_decompress_ptr cinfo) |
| { |
| j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; |
| |
| latch_quant_tables(cinfo); |
| (*lossyd->entropy_start_pass) (cinfo); |
| (*lossyd->coef_start_input_pass) (cinfo); |
| } |
| |
| |
| /* |
| * Initialize for an output processing pass. |
| */ |
| |
| METHODDEF(void) |
| start_output_pass (j_decompress_ptr cinfo) |
| { |
| j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; |
| |
| (*lossyd->idct_start_pass) (cinfo); |
| (*lossyd->coef_start_output_pass) (cinfo); |
| } |
| |
| /* |
| * Initialize the lossy decompression codec. |
| * This is called only once, during master selection. |
| */ |
| |
| GLOBAL(void) |
| jinit_lossy_d_codec (j_decompress_ptr cinfo) |
| { |
| j_lossy_d_ptr lossyd; |
| boolean use_c_buffer; |
| |
| /* Create subobject in permanent pool */ |
| lossyd = (j_lossy_d_ptr) |
| (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, |
| SIZEOF(jpeg_lossy_d_codec)); |
| cinfo->codec = (struct jpeg_d_codec *) lossyd; |
| |
| /* Initialize sub-modules */ |
| |
| /* 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->process == JPROC_PROGRESSIVE) { |
| #ifdef D_PROGRESSIVE_SUPPORTED |
| jinit_phuff_decoder(cinfo); |
| #else |
| ERREXIT(cinfo, JERR_NOT_COMPILED); |
| #endif |
| } else |
| jinit_shuff_decoder(cinfo); |
| } |
| |
| use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; |
| jinit_d_coef_controller(cinfo, use_c_buffer); |
| |
| /* Initialize method pointers. |
| * |
| * Note: consume_data and decompress_data are assigned in jdcoefct.c. |
| */ |
| lossyd->pub.calc_output_dimensions = calc_output_dimensions; |
| lossyd->pub.start_input_pass = start_input_pass; |
| lossyd->pub.start_output_pass = start_output_pass; |
| } |
| |
| |
| |
| |