Hash :
cc7150e2
Author :
Date :
1993-02-18T00:00:00
The Independent JPEG Group's JPEG software v4a
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
/*
* 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;
}