/* * jdlossy.c * * Copyright (C) 1998, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * 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) { #ifdef WITH_ARITHMETIC_PATCH jinit_arith_decoder(cinfo); #else ERREXIT(cinfo, JERR_ARITH_NOTIMPL); #endif } 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; }