/* * jdmcu.c * * Copyright (C) 1991, 1992, 1993, 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 MCU disassembly and IDCT control routines. * These routines are invoked via the disassemble_MCU, reverse_DCT, and * disassemble_init/term methods. */ #include "jinclude.h" /* * Fetch one MCU row from entropy_decode, build coefficient array. * This version is used for noninterleaved (single-component) scans. */ METHODDEF void disassemble_noninterleaved_MCU (decompress_info_ptr cinfo, JBLOCKIMAGE image_data) { JBLOCKROW MCU_data[1]; long mcuindex; /* this is pretty easy since there is one component and one block per MCU */ /* Pre-zero the target area to speed up entropy decoder */ /* (we assume wholesale zeroing is faster than retail) */ jzero_far((void FAR *) image_data[0][0], (size_t) (cinfo->MCUs_per_row * SIZEOF(JBLOCK))); for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) { /* Point to the proper spot in the image array for this MCU */ MCU_data[0] = image_data[0][0] + mcuindex; /* Fetch the coefficient data */ (*cinfo->methods->entropy_decode) (cinfo, MCU_data); } } /* * Fetch one MCU row from entropy_decode, build coefficient array. * This version is used for interleaved (multi-component) scans. */ METHODDEF void disassemble_interleaved_MCU (decompress_info_ptr cinfo, JBLOCKIMAGE image_data) { JBLOCKROW MCU_data[MAX_BLOCKS_IN_MCU]; long mcuindex; short blkn, ci, xpos, ypos; jpeg_component_info * compptr; JBLOCKROW image_ptr; /* Pre-zero the target area to speed up entropy decoder */ /* (we assume wholesale zeroing is faster than retail) */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; for (ypos = 0; ypos < compptr->MCU_height; ypos++) { jzero_far((void FAR *) image_data[ci][ypos], (size_t) (cinfo->MCUs_per_row * compptr->MCU_width * SIZEOF(JBLOCK))); } } for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) { /* Point to the proper spots in the image array for this MCU */ blkn = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; for (ypos = 0; ypos < compptr->MCU_height; ypos++) { image_ptr = image_data[ci][ypos] + (mcuindex * compptr->MCU_width); for (xpos = 0; xpos < compptr->MCU_width; xpos++) { MCU_data[blkn] = image_ptr; image_ptr++; blkn++; } } } /* Fetch the coefficient data */ (*cinfo->methods->entropy_decode) (cinfo, MCU_data); } } /* * Perform inverse DCT on each block in an MCU row's worth of data; * output the results into a sample array starting at row start_row. * NB: start_row can only be nonzero when dealing with a single-component * scan; otherwise we'd have to pass different offsets for different * components, since the heights of interleaved MCU rows can vary. * But the pipeline controller logic is such that this is not necessary. */ METHODDEF void reverse_DCT (decompress_info_ptr cinfo, JBLOCKIMAGE coeff_data, JSAMPIMAGE output_data, int start_row) { DCTBLOCK block; JBLOCKROW browptr; JSAMPARRAY srowptr; jpeg_component_info * compptr; long blocksperrow, bi; short numrows, ri; short ci; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* don't bother to IDCT an uninteresting component */ if (! compptr->component_needed) continue; /* calculate size of an MCU row in this component */ blocksperrow = compptr->downsampled_width / DCTSIZE; numrows = compptr->MCU_height; /* iterate through all blocks in MCU row */ for (ri = 0; ri < numrows; ri++) { browptr = coeff_data[ci][ri]; srowptr = output_data[ci] + (ri * DCTSIZE + start_row); for (bi = 0; bi < blocksperrow; bi++) { /* copy the data into a local DCTBLOCK. This allows for change of * representation (if DCTELEM != JCOEF). On 80x86 machines it also * brings the data back from FAR storage to NEAR storage. */ { register JCOEFPTR elemptr = browptr[bi]; register DCTELEM *localblkptr = block; register int elem = DCTSIZE2; while (--elem >= 0) *localblkptr++ = (DCTELEM) *elemptr++; } j_rev_dct(block); /* perform inverse DCT */ /* Output the data into the sample array. * Note change from signed to unsigned representation: * DCT calculation works with values +-CENTERJSAMPLE, * but sample arrays always hold 0..MAXJSAMPLE. * We have to do range-limiting because of quantization errors in the * DCT/IDCT phase. We use the sample_range_limit[] table to do this * quickly; the CENTERJSAMPLE offset is folded into table indexing. */ { register JSAMPROW elemptr; register DCTELEM *localblkptr = block; register JSAMPLE *range_limit = cinfo->sample_range_limit + CENTERJSAMPLE; #if DCTSIZE != 8 register int elemc; #endif register int elemr; for (elemr = 0; elemr < DCTSIZE; elemr++) { elemptr = srowptr[elemr] + (bi * DCTSIZE); #if DCTSIZE == 8 /* unroll the inner loop */ *elemptr++ = range_limit[*localblkptr++]; *elemptr++ = range_limit[*localblkptr++]; *elemptr++ = range_limit[*localblkptr++]; *elemptr++ = range_limit[*localblkptr++]; *elemptr++ = range_limit[*localblkptr++]; *elemptr++ = range_limit[*localblkptr++]; *elemptr++ = range_limit[*localblkptr++]; *elemptr++ = range_limit[*localblkptr++]; #else for (elemc = DCTSIZE; elemc > 0; elemc--) { *elemptr++ = range_limit[*localblkptr++]; } #endif } } } } } } /* * Initialize for processing a scan. */ METHODDEF void disassemble_init (decompress_info_ptr cinfo) { /* no work for now */ } /* * Clean up after a scan. */ METHODDEF void disassemble_term (decompress_info_ptr cinfo) { /* no work for now */ } /* * The method selection routine for MCU disassembly. */ GLOBAL void jseldmcu (decompress_info_ptr cinfo) { if (cinfo->comps_in_scan == 1) cinfo->methods->disassemble_MCU = disassemble_noninterleaved_MCU; else cinfo->methods->disassemble_MCU = disassemble_interleaved_MCU; cinfo->methods->reverse_DCT = reverse_DCT; cinfo->methods->disassemble_init = disassemble_init; cinfo->methods->disassemble_term = disassemble_term; }