📄 jdpipe.c
字号:
/* Expand the last row group with dummy below-context */
/* Note whichss points to last buffer side used */
expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width,
(short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
(short) (DCTSIZE-1));
/* and dump the remaining data (may be less than full height) */
emit_1pass (cinfo, (int) (cinfo->image_height - pixel_rows_output),
fullsize_data, (JSAMPARRAY) NULL);
/* Clean up after the scan */
(*cinfo->methods->disassemble_term) (cinfo);
(*cinfo->methods->upsample_term) (cinfo);
(*cinfo->methods->entropy_decode_term) (cinfo);
(*cinfo->methods->read_scan_trailer) (cinfo);
cinfo->completed_passes++;
/* Verify that we've seen the whole input file */
if ((*cinfo->methods->read_scan_header) (cinfo))
/* WARNMS(cinfo->emethods, "Didn't expect more than one scan"); */
send_command(ERR5);
/* Release working memory */
/* (no work -- we let free_all release what's needful) */
}
/*
* Decompression pipeline controller used for multiple-scan files
* and/or 2-pass color quantization.
*
* The current implementation places the "big" buffer at the stage of
* upsampled, non-color-processed data. This is the only place that
* makes sense when doing 2-pass quantization. For processing multiple-scan
* files without 2-pass quantization, it would be possible to develop another
* controller that buffers the downsampled data instead, thus reducing the size
* of the temp files (by about a factor of 2 in typical cases). However,
* our present upsampling logic is dependent on the assumption that
* upsampling occurs during a scan, so it's much easier to do the
* enlargement as the JPEG file is read. This also simplifies life for the
* memory manager, which would otherwise have to deal with overlapping
* access_big_sarray() requests.
* At present it appears that most JPEG files will be single-scan,
* so it doesn't seem worthwhile to worry about this optimization.
*/
#ifdef NEED_COMPLEX_CONTROLLER
METHODDEF void
complex_dcontroller (decompress_info_ptr cinfo)
{
long fullsize_width; /* # of samples per row in full-size buffers */
long cur_mcu_row; /* counts # of MCU rows processed */
long pixel_rows_output; /* # of pixel rows actually emitted */
int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */
/* Work buffer for dequantized coefficients (IDCT input) */
JBLOCKIMAGE coeff_data;
/* Work buffer for cross-block smoothing input */
#ifdef BLOCK_SMOOTHING_SUPPORTED
JBLOCKIMAGE bsmooth[3]; /* this is optional */
int whichb;
#endif
/* Work buffer for downsampled image data (see comments at head of file) */
JSAMPIMAGE sampled_data[2];
int whichss, ri;
short ci, i;
boolean single_scan;
/* Compute dimensions of full-size pixel buffers */
/* Note these are the same whether interleaved or not. */
rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
fullsize_width = jround_up(cinfo->image_width,
(long) (cinfo->max_h_samp_factor * DCTSIZE));
/* Allocate all working memory that doesn't depend on scan info */
/* output_workspace is the color-processed data */
output_workspace = alloc_sampimage(cinfo, (int) cinfo->final_out_comps,
(long) rows_in_mem, fullsize_width);
prepare_range_limit_table(cinfo);
/* Get a big image: fullsize_image is sample data after upsampling. */
fullsize_image = (big_sarray_ptr *) (*cinfo->emethods->alloc_small)
(cinfo->num_components * SIZEOF(big_sarray_ptr));
for (ci = 0; ci < cinfo->num_components; ci++) {
fullsize_image[ci] = (*cinfo->emethods->request_big_sarray)
(fullsize_width,
jround_up(cinfo->image_height, (long) rows_in_mem),
(long) rows_in_mem);
}
/* Also get an area for pointers to currently accessible chunks */
fullsize_ptrs = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
(cinfo->num_components * SIZEOF(JSAMPARRAY));
/* Tell the memory manager to instantiate big arrays */
(*cinfo->emethods->alloc_big_arrays)
/* extra sarray space is for downsampled-data buffers: */
((long) (fullsize_width /* max width in samples */
* cinfo->max_v_samp_factor*(DCTSIZE+2) /* max height */
* cinfo->num_components), /* max components per scan */
/* extra barray space is for MCU-row buffers: */
(long) ((fullsize_width / DCTSIZE) /* max width in blocks */
* cinfo->max_v_samp_factor /* max height */
* cinfo->num_components /* max components per scan */
* (cinfo->do_block_smoothing ? 4 : 1)),/* how many of these we need */
/* no extra "medium"-object space */
(long) 0);
/* NB: if quantizer needs any "medium" size objects, it must get them */
/* at color_quant_init time */
/* If file is single-scan, we can do color quantization prescan on-the-fly
* during the scan (we must be doing 2-pass quantization, else this method
* would not have been selected). If it is multiple scans, we have to make
* a separate pass after we've collected all the components. (We could save
* some I/O by doing CQ prescan during the last scan, but the extra logic
* doesn't seem worth the trouble.)
*/
single_scan = (cinfo->comps_in_scan == cinfo->num_components);
/* Account for passes needed (color quantizer adds its passes separately).
* If multiscan file, we guess that each component has its own scan,
* and increment completed_passes by the number of components in the scan.
*/
if (single_scan)
cinfo->total_passes++; /* the single scan */
else {
cinfo->total_passes += cinfo->num_components; /* guessed # of scans */
if (cinfo->two_pass_quantize)
cinfo->total_passes++; /* account for separate CQ prescan pass */
}
if (! cinfo->two_pass_quantize)
cinfo->total_passes++; /* count output pass unless quantizer does it */
/* Loop over scans in file */
do {
/* Prepare for this scan */
if (cinfo->comps_in_scan == 1) {
noninterleaved_scan_setup(cinfo);
/* Need to read Vk MCU rows to obtain Vk block rows */
mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
} else {
interleaved_scan_setup(cinfo);
/* in an interleaved scan, one MCU row provides Vk block rows */
mcu_rows_per_loop = 1;
}
/* Allocate scan-local working memory */
/* coeff_data holds a single MCU row of coefficient blocks */
coeff_data = alloc_MCU_row(cinfo);
/* if doing cross-block smoothing, need extra space for its input */
#ifdef BLOCK_SMOOTHING_SUPPORTED
if (cinfo->do_block_smoothing) {
bsmooth[0] = alloc_MCU_row(cinfo);
bsmooth[1] = alloc_MCU_row(cinfo);
bsmooth[2] = alloc_MCU_row(cinfo);
}
#endif
/* sampled_data is sample data before upsampling */
alloc_sampling_buffer(cinfo, sampled_data);
/* line up the big buffers for components in this scan */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
fullsize_ptrs[ci] = (*cinfo->emethods->access_big_sarray)
(fullsize_image[cinfo->cur_comp_info[ci]->component_index],
(long) 0, TRUE);
}
/* Initialize to read scan data */
(*cinfo->methods->entropy_decode_init) (cinfo);
(*cinfo->methods->upsample_init) (cinfo);
(*cinfo->methods->disassemble_init) (cinfo);
/* Loop over scan's data: rows_in_mem pixel rows are processed per loop */
pixel_rows_output = 0;
whichss = 1; /* arrange to start with sampled_data[0] */
for (cur_mcu_row = 0; cur_mcu_row < cinfo->MCU_rows_in_scan;
cur_mcu_row += mcu_rows_per_loop) {
(*cinfo->methods->progress_monitor) (cinfo, cur_mcu_row,
cinfo->MCU_rows_in_scan);
whichss ^= 1; /* switch to other downsampled-data buffer */
/* Obtain v_samp_factor block rows of each component in the scan. */
/* This is a single MCU row if interleaved, multiple MCU rows if not. */
/* In the noninterleaved case there might be fewer than v_samp_factor */
/* block rows remaining; if so, pad with copies of the last pixel row */
/* so that upsampling doesn't have to treat it as a special case. */
for (ri = 0; ri < mcu_rows_per_loop; ri++) {
if (cur_mcu_row + ri < cinfo->MCU_rows_in_scan) {
/* OK to actually read an MCU row. */
#ifdef BLOCK_SMOOTHING_SUPPORTED
if (cinfo->do_block_smoothing)
get_smoothed_row(cinfo, coeff_data,
bsmooth, &whichb, cur_mcu_row + ri);
else
#endif
(*cinfo->methods->disassemble_MCU) (cinfo, coeff_data);
(*cinfo->methods->reverse_DCT) (cinfo, coeff_data,
sampled_data[whichss],
ri * DCTSIZE);
} else {
/* Need to pad out with copies of the last downsampled row. */
/* This can only happen if there is just one component. */
duplicate_row(sampled_data[whichss][0],
cinfo->cur_comp_info[0]->downsampled_width,
ri * DCTSIZE - 1, DCTSIZE);
}
}
/* Upsample the data */
/* First time through is a special case */
if (cur_mcu_row) {
/* Expand last row group of previous set */
expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width,
(short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
(short) (DCTSIZE-1));
/* If single scan, can do color quantization prescan on-the-fly */
if (single_scan)
(*cinfo->methods->color_quant_prescan) (cinfo, rows_in_mem,
fullsize_ptrs,
output_workspace[0]);
/* Realign the big buffers */
pixel_rows_output += rows_in_mem;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
fullsize_ptrs[ci] = (*cinfo->emethods->access_big_sarray)
(fullsize_image[cinfo->cur_comp_info[ci]->component_index],
pixel_rows_output, TRUE);
}
/* Expand first row group of this set */
expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width,
(short) (DCTSIZE+1), (short) 0, (short) 1,
(short) 0);
} else {
/* Expand first row group with dummy above-context */
expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width,
(short) (-1), (short) 0, (short) 1,
(short) 0);
}
/* Expand second through next-to-last row groups of this set */
for (i = 1; i <= DCTSIZE-2; i++) {
expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width,
(short) (i-1), (short) i, (short) (i+1),
(short) i);
}
} /* end of loop over scan's data */
/* Expand the last row group with dummy below-context */
/* Note whichss points to last buffer side used */
expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width,
(short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
(short) (DCTSIZE-1));
/* If single scan, finish on-the-fly color quantization prescan */
if (single_scan)
(*cinfo->methods->color_quant_prescan) (cinfo,
(int) (cinfo->image_height - pixel_rows_output),
fullsize_ptrs, output_workspace[0]);
/* Clean up after the scan */
(*cinfo->methods->disassemble_term) (cinfo);
(*cinfo->methods->upsample_term) (cinfo);
(*cinfo->methods->entropy_decode_term) (cinfo);
(*cinfo->methods->read_scan_trailer) (cinfo);
if (single_scan)
cinfo->completed_passes++;
else
cinfo->completed_passes += cinfo->comps_in_scan;
/* Release scan-local working memory */
free_MCU_row(cinfo, coeff_data);
#ifdef BLOCK_SMOOTHING_SUPPORTED
if (cinfo->do_block_smoothing) {
free_MCU_row(cinfo, bsmooth[0]);
free_MCU_row(cinfo, bsmooth[1]);
free_MCU_row(cinfo, bsmooth[2]);
}
#endif
free_sampling_buffer(cinfo, sampled_data);
/* Repeat if there is another scan */
} while ((!single_scan) && (*cinfo->methods->read_scan_header) (cinfo));
if (single_scan) {
/* If we expected just one scan, make SURE there's just one */
if ((*cinfo->methods->read_scan_header) (cinfo))
/* WARNMS(cinfo->emethods, "Didn't expect more than one scan"); */
send_command(ERR5);
/* We did the CQ prescan on-the-fly, so we are all set. */
} else {
/* For multiple-scan file, do the CQ prescan as a separate pass. */
/* The main reason why prescan is passed the output_workspace is */
/* so that we can use scan_big_image to call it... */
if (cinfo->two_pass_quantize)
scan_big_image(cinfo, cinfo->methods->color_quant_prescan);
}
/* Now that we've collected the data, do color processing and output */
if (cinfo->two_pass_quantize)
(*cinfo->methods->color_quant_doit) (cinfo, scan_big_image);
else
scan_big_image(cinfo, emit_1pass);
/* Release working memory */
/* (no work -- we let free_all release what's needful) */
}
#endif /* NEED_COMPLEX_CONTROLLER */
/*
* The method selection routine for decompression pipeline controllers.
* Note that at this point we've already read the JPEG header and first SOS,
* so we can tell whether the input is one scan or not.
*/
GLOBAL void
jseldpipeline (decompress_info_ptr cinfo)
{
/* simplify subsequent tests on color quantization */
if (! cinfo->quantize_colors)
cinfo->two_pass_quantize = FALSE;
if (cinfo->comps_in_scan == cinfo->num_components) {
/* It's a single-scan file */
if (cinfo->two_pass_quantize) {
#ifdef NEED_COMPLEX_CONTROLLER
cinfo->methods->d_pipeline_controller = complex_dcontroller;
#else
/* ERREXIT(cinfo->emethods, "2-pass quantization support was not compiled"); */
send_command(ERR7);
receive_command();
exit();
#endif
} else
cinfo->methods->d_pipeline_controller = simple_dcontroller;
} else {
/* It's a multiple-scan file */
#ifdef NEED_COMPLEX_CONTROLLER
cinfo->methods->d_pipeline_controller = complex_dcontroller;
#else
/* ERREXIT(cinfo->emethods, "Multiple-scan support was not compiled"); */
send_command(ERR7);
receive_command();
exit();
#endif
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -