home *** CD-ROM | disk | FTP | other *** search
- /*
- * jdmcu.c
- *
- * Copyright (C) 1991, 1992, 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;
- long blocksperrow, bi;
- short numrows, ri;
- short ci;
-
- for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
- /* calculate size of an MCU row in this component */
- blocksperrow = cinfo->cur_comp_info[ci]->downsampled_width / DCTSIZE;
- numrows = cinfo->cur_comp_info[ci]->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;
- }
-