Add a new libjpeg API function (jpeg_skip_scanlines()) to allow for partially decoding a JPEG image.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@1582 632fc199-4ca6-4c93-a231-07263d6284db
This commit is contained in:
@@ -8,6 +8,9 @@ to the compiler vs. x86, it was still possible to speed up compression by about
|
|||||||
3-4x and decompression by about 2-2.5x (relative to libjpeg v6b) through the
|
3-4x and decompression by about 2-2.5x (relative to libjpeg v6b) through the
|
||||||
use of AltiVec instructions.
|
use of AltiVec instructions.
|
||||||
|
|
||||||
|
[2] Added a new libjpeg API function (jpeg_skip_scanlines()) that can be used
|
||||||
|
to partially decode a JPEG image. See libjpeg.txt for more details.
|
||||||
|
|
||||||
|
|
||||||
1.4.1
|
1.4.1
|
||||||
=====
|
=====
|
||||||
|
|||||||
64
djpeg.c
64
djpeg.c
@@ -4,7 +4,8 @@
|
|||||||
* This file was part of the Independent JPEG Group's software:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2010-2011, 2013-2014, D. R. Commander.
|
* Copyright (C) 2010-2011, 2013-2015, D. R. Commander.
|
||||||
|
* Copyright (C) 2015, Google, Inc.
|
||||||
* For conditions of distribution and use, see the accompanying README file.
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
*
|
*
|
||||||
* This file contains a command-line user interface for the JPEG decompressor.
|
* This file contains a command-line user interface for the JPEG decompressor.
|
||||||
@@ -88,6 +89,8 @@ static IMAGE_FORMATS requested_fmt;
|
|||||||
static const char * progname; /* program name for error messages */
|
static const char * progname; /* program name for error messages */
|
||||||
static char * outfilename; /* for -outfile switch */
|
static char * outfilename; /* for -outfile switch */
|
||||||
boolean memsrc; /* for -memsrc switch */
|
boolean memsrc; /* for -memsrc switch */
|
||||||
|
boolean stripe;
|
||||||
|
JDIMENSION startY, endY;
|
||||||
#define INPUT_BUF_SIZE 4096
|
#define INPUT_BUF_SIZE 4096
|
||||||
|
|
||||||
|
|
||||||
@@ -164,6 +167,7 @@ usage (void)
|
|||||||
fprintf(stderr, " -memsrc Load input file into memory before decompressing\n");
|
fprintf(stderr, " -memsrc Load input file into memory before decompressing\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
fprintf(stderr, " -stripe Y0,Y1 Decode a horizontal stripe of the image [Y0, Y1)\n");
|
||||||
fprintf(stderr, " -verbose or -debug Emit debug output\n");
|
fprintf(stderr, " -verbose or -debug Emit debug output\n");
|
||||||
fprintf(stderr, " -version Print version information and exit\n");
|
fprintf(stderr, " -version Print version information and exit\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@@ -189,6 +193,7 @@ parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
|
|||||||
requested_fmt = DEFAULT_FMT; /* set default output file format */
|
requested_fmt = DEFAULT_FMT; /* set default output file format */
|
||||||
outfilename = NULL;
|
outfilename = NULL;
|
||||||
memsrc = FALSE;
|
memsrc = FALSE;
|
||||||
|
stripe = FALSE;
|
||||||
cinfo->err->trace_level = 0;
|
cinfo->err->trace_level = 0;
|
||||||
|
|
||||||
/* Scan command line options, adjust parameters */
|
/* Scan command line options, adjust parameters */
|
||||||
@@ -361,7 +366,7 @@ parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
|
|||||||
/* RLE output format. */
|
/* RLE output format. */
|
||||||
requested_fmt = FMT_RLE;
|
requested_fmt = FMT_RLE;
|
||||||
|
|
||||||
} else if (keymatch(arg, "scale", 1)) {
|
} else if (keymatch(arg, "scale", 2)) {
|
||||||
/* Scale the output image by a fraction M/N. */
|
/* Scale the output image by a fraction M/N. */
|
||||||
if (++argn >= argc) /* advance to next argument */
|
if (++argn >= argc) /* advance to next argument */
|
||||||
usage();
|
usage();
|
||||||
@@ -369,6 +374,13 @@ parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
|
|||||||
&cinfo->scale_num, &cinfo->scale_denom) != 2)
|
&cinfo->scale_num, &cinfo->scale_denom) != 2)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "stripe", 2)) {
|
||||||
|
if (++argn >= argc)
|
||||||
|
usage();
|
||||||
|
if (sscanf(argv[argn], "%d,%d", &startY, &endY) != 2 || startY > endY)
|
||||||
|
usage();
|
||||||
|
stripe = TRUE;
|
||||||
|
|
||||||
} else if (keymatch(arg, "targa", 1)) {
|
} else if (keymatch(arg, "targa", 1)) {
|
||||||
/* Targa output format. */
|
/* Targa output format. */
|
||||||
requested_fmt = FMT_TARGA;
|
requested_fmt = FMT_TARGA;
|
||||||
@@ -634,14 +646,48 @@ main (int argc, char **argv)
|
|||||||
/* Start decompressor */
|
/* Start decompressor */
|
||||||
(void) jpeg_start_decompress(&cinfo);
|
(void) jpeg_start_decompress(&cinfo);
|
||||||
|
|
||||||
/* Write output file header */
|
/* Stripe decode */
|
||||||
(*dest_mgr->start_output) (&cinfo, dest_mgr);
|
if (stripe) {
|
||||||
|
JDIMENSION tmp;
|
||||||
|
|
||||||
/* Process data */
|
/* Check for valid endY. We cannot check this value until after
|
||||||
while (cinfo.output_scanline < cinfo.output_height) {
|
* jpeg_start_decompress() is called. Note that we have already verified
|
||||||
num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
|
* that startY <= endY.
|
||||||
dest_mgr->buffer_height);
|
*/
|
||||||
(*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
|
if (endY > cinfo.output_height) {
|
||||||
|
fprintf(stderr, "%s: stripe %d-%d exceeds image height %d\n", progname,
|
||||||
|
startY, endY, cinfo.output_height);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write output file header. This is a hack to ensure that the destination
|
||||||
|
* manager creates an image of the proper size for the partial decode.
|
||||||
|
*/
|
||||||
|
tmp = cinfo.output_height;
|
||||||
|
cinfo.output_height = endY - startY;
|
||||||
|
(*dest_mgr->start_output) (&cinfo, dest_mgr);
|
||||||
|
cinfo.output_height = tmp;
|
||||||
|
|
||||||
|
/* Process data */
|
||||||
|
(void) jpeg_skip_scanlines(&cinfo, startY);
|
||||||
|
while (cinfo.output_scanline < endY) {
|
||||||
|
num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
|
||||||
|
dest_mgr->buffer_height);
|
||||||
|
(*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
|
||||||
|
}
|
||||||
|
(void) jpeg_skip_scanlines(&cinfo, cinfo.output_height - endY);
|
||||||
|
|
||||||
|
/* Normal full image decode */
|
||||||
|
} else {
|
||||||
|
/* Write output file header */
|
||||||
|
(*dest_mgr->start_output) (&cinfo, dest_mgr);
|
||||||
|
|
||||||
|
/* Process data */
|
||||||
|
while (cinfo.output_scanline < cinfo.output_height) {
|
||||||
|
num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
|
||||||
|
dest_mgr->buffer_height);
|
||||||
|
(*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PROGRESS_REPORT
|
#ifdef PROGRESS_REPORT
|
||||||
|
|||||||
255
jdapistd.c
255
jdapistd.c
@@ -4,7 +4,8 @@
|
|||||||
* This file was part of the Independent JPEG Group's software:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1994-1996, Thomas G. Lane.
|
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2010, D. R. Commander.
|
* Copyright (C) 2010, 2015, D. R. Commander.
|
||||||
|
* Copyright (C) 2015, Google, Inc.
|
||||||
* For conditions of distribution and use, see the accompanying README file.
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
*
|
*
|
||||||
* This file contains application interface code for the decompression half
|
* This file contains application interface code for the decompression half
|
||||||
@@ -16,11 +17,10 @@
|
|||||||
* whole decompression library into a transcoder.
|
* whole decompression library into a transcoder.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define JPEG_INTERNALS
|
#include "jdmainct.h"
|
||||||
#include "jinclude.h"
|
#include "jdcoefct.h"
|
||||||
#include "jpeglib.h"
|
#include "jdsample.h"
|
||||||
#include "jpegcomp.h"
|
#include "jmemsys.h"
|
||||||
|
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
LOCAL(boolean) output_pass_setup (j_decompress_ptr cinfo);
|
LOCAL(boolean) output_pass_setup (j_decompress_ptr cinfo);
|
||||||
@@ -179,6 +179,242 @@ jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Prepare temporary row buffer */
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
dummy_buffer_setup (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
int nc;
|
||||||
|
|
||||||
|
if (!cinfo->master || cinfo->master->dummy_row_buffer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nc = (cinfo->out_color_space == JCS_RGB565) ?
|
||||||
|
2 : cinfo->out_color_components;
|
||||||
|
cinfo->master->dummy_row_buffer =
|
||||||
|
jpeg_get_small((j_common_ptr) cinfo,
|
||||||
|
cinfo->output_width * nc * sizeof(JSAMPLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called by jpeg_skip_scanlines(). This partially skips a decompress block by
|
||||||
|
* incrementing the rowgroup counter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
increment_simple_rowgroup_ctr (j_decompress_ptr cinfo, JDIMENSION rows)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
JDIMENSION rows_left;
|
||||||
|
my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
|
||||||
|
|
||||||
|
/* Increment the counter to the next row group after the skipped rows. */
|
||||||
|
main_ptr->rowgroup_ctr += rows / cinfo->max_v_samp_factor;
|
||||||
|
|
||||||
|
/* Partially skipping a row group would involve modifying the internal state
|
||||||
|
* of the upsampler, so read the remaining rows into a dummy buffer instead.
|
||||||
|
*/
|
||||||
|
rows_left = rows % cinfo->max_v_samp_factor;
|
||||||
|
cinfo->output_scanline += rows - rows_left;
|
||||||
|
|
||||||
|
dummy_buffer_setup(cinfo);
|
||||||
|
for (i = 0; i < rows_left; i++)
|
||||||
|
jpeg_read_scanlines(cinfo, &(cinfo->master->dummy_row_buffer), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called by jpeg_skip_scanlines(). When we skip iMCU rows, we must update the
|
||||||
|
* iMCU row counter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
increment_iMCU_ctr (j_decompress_ptr cinfo, JDIMENSION iMCU_rows)
|
||||||
|
{
|
||||||
|
my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
|
||||||
|
if (main_ptr->iMCU_row_ctr == 0 && iMCU_rows > 0)
|
||||||
|
set_wraparound_pointers(cinfo);
|
||||||
|
main_ptr->iMCU_row_ctr += iMCU_rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skips some scanlines of data from the JPEG decompressor.
|
||||||
|
*
|
||||||
|
* The return value will be the number of lines actually skipped. If skipping
|
||||||
|
* num_lines would move beyond the end of the image, then the actual number of
|
||||||
|
* lines remaining in the image is returned. Otherwise, the return value will
|
||||||
|
* be equal to num_lines.
|
||||||
|
*
|
||||||
|
* Refer to libjpeg.txt for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(JDIMENSION)
|
||||||
|
jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
|
||||||
|
{
|
||||||
|
my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
|
||||||
|
int i, y, x;
|
||||||
|
JDIMENSION lines_per_iMCU_row, lines_left_in_iMCU_row, lines_after_iMCU_row;
|
||||||
|
JDIMENSION lines_to_skip, lines_to_read;
|
||||||
|
|
||||||
|
if (cinfo->global_state != DSTATE_SCANNING)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
|
||||||
|
/* Do not skip past the bottom of the image. */
|
||||||
|
if (cinfo->output_scanline + num_lines >= cinfo->output_height) {
|
||||||
|
cinfo->output_scanline = cinfo->output_height;
|
||||||
|
return cinfo->output_height - cinfo->output_scanline;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_lines == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
lines_per_iMCU_row = cinfo->_min_DCT_scaled_size * cinfo->max_v_samp_factor;
|
||||||
|
lines_left_in_iMCU_row =
|
||||||
|
(lines_per_iMCU_row - (cinfo->output_scanline % lines_per_iMCU_row)) %
|
||||||
|
lines_per_iMCU_row;
|
||||||
|
lines_after_iMCU_row = num_lines - lines_left_in_iMCU_row;
|
||||||
|
|
||||||
|
/* Skip the lines remaining in the current iMCU row. When upsampling
|
||||||
|
* requires context rows, we need the previous and next rows in order to read
|
||||||
|
* the current row. This adds some complexity.
|
||||||
|
*/
|
||||||
|
if (cinfo->upsample->need_context_rows) {
|
||||||
|
/* If the skipped lines would not move us past the current iMCU row, we
|
||||||
|
* read the lines and ignore them. There might be a faster way of doing
|
||||||
|
* this, but we are facing increasing complexity for diminishing returns.
|
||||||
|
* The increasing complexity would be a by-product of meddling with the
|
||||||
|
* state machine used to skip context rows. Near the end of an iMCU row,
|
||||||
|
* the next iMCU row may have already been entropy-decoded. In this unique
|
||||||
|
* case, we will read the next iMCU row if we cannot skip past it as well.
|
||||||
|
*/
|
||||||
|
if ((num_lines < lines_left_in_iMCU_row + 1) ||
|
||||||
|
(lines_left_in_iMCU_row <= 1 && main_ptr->buffer_full &&
|
||||||
|
lines_after_iMCU_row < lines_per_iMCU_row + 1)) {
|
||||||
|
dummy_buffer_setup(cinfo);
|
||||||
|
for (i = 0; i < num_lines; i++)
|
||||||
|
jpeg_read_scanlines(cinfo, &(cinfo->master->dummy_row_buffer), 1);
|
||||||
|
return num_lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the next iMCU row has already been entropy-decoded, make sure that
|
||||||
|
* we do not skip too far.
|
||||||
|
*/
|
||||||
|
if (lines_left_in_iMCU_row <= 1 && main_ptr->buffer_full) {
|
||||||
|
cinfo->output_scanline += lines_left_in_iMCU_row + lines_per_iMCU_row;
|
||||||
|
lines_after_iMCU_row -= lines_per_iMCU_row;
|
||||||
|
} else {
|
||||||
|
cinfo->output_scanline += lines_left_in_iMCU_row;
|
||||||
|
}
|
||||||
|
main_ptr->buffer_full = FALSE;
|
||||||
|
main_ptr->rowgroup_ctr = 0;
|
||||||
|
main_ptr->context_state = CTX_PREPARE_FOR_IMCU;
|
||||||
|
upsample->next_row_out = cinfo->max_v_samp_factor;
|
||||||
|
upsample->rows_to_go = cinfo->output_height - cinfo->output_scanline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skipping is much simpler when context rows are not required. */
|
||||||
|
else {
|
||||||
|
if (num_lines < lines_left_in_iMCU_row) {
|
||||||
|
increment_simple_rowgroup_ctr(cinfo, num_lines);
|
||||||
|
return num_lines;
|
||||||
|
} else {
|
||||||
|
cinfo->output_scanline += lines_left_in_iMCU_row;
|
||||||
|
main_ptr->buffer_full = FALSE;
|
||||||
|
main_ptr->rowgroup_ctr = 0;
|
||||||
|
upsample->next_row_out = cinfo->max_v_samp_factor;
|
||||||
|
upsample->rows_to_go = cinfo->output_height - cinfo->output_scanline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate how many full iMCU rows we can skip. */
|
||||||
|
if (cinfo->upsample->need_context_rows)
|
||||||
|
lines_to_skip = ((lines_after_iMCU_row - 1) / lines_per_iMCU_row) *
|
||||||
|
lines_per_iMCU_row;
|
||||||
|
else
|
||||||
|
lines_to_skip = (lines_after_iMCU_row / lines_per_iMCU_row) *
|
||||||
|
lines_per_iMCU_row;
|
||||||
|
/* Calculate the number of lines that remain to be skipped after skipping all
|
||||||
|
* of the full iMCU rows that we can. We will not read these lines unless we
|
||||||
|
* have to.
|
||||||
|
*/
|
||||||
|
lines_to_read = lines_after_iMCU_row - lines_to_skip;
|
||||||
|
|
||||||
|
/* For images requiring multiple scans (progressive, non-interleaved, etc.),
|
||||||
|
* all of the entropy decoding occurs in jpeg_start_decompress(), assuming
|
||||||
|
* that the input data source is non-suspending. This makes skipping easy.
|
||||||
|
*/
|
||||||
|
if (cinfo->inputctl->has_multiple_scans) {
|
||||||
|
if (cinfo->upsample->need_context_rows) {
|
||||||
|
cinfo->output_scanline += lines_to_skip;
|
||||||
|
cinfo->output_iMCU_row += lines_to_skip / lines_per_iMCU_row;
|
||||||
|
increment_iMCU_ctr(cinfo, lines_after_iMCU_row / lines_per_iMCU_row);
|
||||||
|
/* It is complex to properly move to the middle of a context block, so
|
||||||
|
* read the remaining lines instead of skipping them.
|
||||||
|
*/
|
||||||
|
dummy_buffer_setup(cinfo);
|
||||||
|
for (i = 0; i < lines_to_read; i++)
|
||||||
|
jpeg_read_scanlines(cinfo, &(cinfo->master->dummy_row_buffer), 1);
|
||||||
|
} else {
|
||||||
|
cinfo->output_scanline += lines_to_skip;
|
||||||
|
cinfo->output_iMCU_row += lines_to_skip / lines_per_iMCU_row;
|
||||||
|
increment_simple_rowgroup_ctr(cinfo, lines_to_read);
|
||||||
|
}
|
||||||
|
upsample->rows_to_go = cinfo->output_height - cinfo->output_scanline;
|
||||||
|
return num_lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip the iMCU rows that we can safely skip. */
|
||||||
|
for (i = 0; i < lines_to_skip; i += lines_per_iMCU_row) {
|
||||||
|
for (y = 0; y < coef->MCU_rows_per_iMCU_row; y++) {
|
||||||
|
for (x = 0; x < cinfo->MCUs_per_row; x++) {
|
||||||
|
/* Calling decode_mcu() with a NULL pointer causes it to discard the
|
||||||
|
* decoded coefficients. This is ~5% faster for large subsets, but
|
||||||
|
* it's tough to tell a difference for smaller images. Another
|
||||||
|
* advantage of discarding coefficients is that it allows us to avoid
|
||||||
|
* accessing the private field cinfo->coef->MCU_buffer (which would
|
||||||
|
* normally be a parameter to decode_mcu().)
|
||||||
|
*/
|
||||||
|
(*cinfo->entropy->decode_mcu) (cinfo, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cinfo->input_iMCU_row++;
|
||||||
|
cinfo->output_iMCU_row++;
|
||||||
|
if (cinfo->input_iMCU_row < cinfo->total_iMCU_rows)
|
||||||
|
start_iMCU_row(cinfo);
|
||||||
|
else
|
||||||
|
(*cinfo->inputctl->finish_input_pass) (cinfo);
|
||||||
|
}
|
||||||
|
cinfo->output_scanline += lines_to_skip;
|
||||||
|
|
||||||
|
if (cinfo->upsample->need_context_rows) {
|
||||||
|
/* Context-based upsampling keeps track of iMCU rows. */
|
||||||
|
increment_iMCU_ctr(cinfo, lines_to_skip / lines_per_iMCU_row);
|
||||||
|
|
||||||
|
/* It is complex to properly move to the middle of a context block, so
|
||||||
|
* read the remaining lines instead of skipping them.
|
||||||
|
*/
|
||||||
|
dummy_buffer_setup(cinfo);
|
||||||
|
for (i = 0; i < lines_to_read; i++)
|
||||||
|
jpeg_read_scanlines(cinfo, &(cinfo->master->dummy_row_buffer), 1);
|
||||||
|
} else {
|
||||||
|
increment_simple_rowgroup_ctr(cinfo, lines_to_read);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Since skipping lines involves skipping the upsampling step, the value of
|
||||||
|
* "rows_to_go" will become invalid unless we set it here. NOTE: This is a
|
||||||
|
* bit odd, since "rows_to_go" seems to be redundantly keeping track of
|
||||||
|
* output_scanline.
|
||||||
|
*/
|
||||||
|
upsample->rows_to_go = cinfo->output_height - cinfo->output_scanline;
|
||||||
|
|
||||||
|
/* Always skip the requested number of lines. */
|
||||||
|
return num_lines;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Alternate entry point to read raw data.
|
* Alternate entry point to read raw data.
|
||||||
* Processes exactly one iMCU row per call, unless suspended.
|
* Processes exactly one iMCU row per call, unless suspended.
|
||||||
@@ -271,6 +507,13 @@ jpeg_finish_output (j_decompress_ptr cinfo)
|
|||||||
if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
|
if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
|
||||||
return FALSE; /* Suspend, come back later */
|
return FALSE; /* Suspend, come back later */
|
||||||
}
|
}
|
||||||
|
/* Clean up row buffer */
|
||||||
|
if (cinfo->master->dummy_row_buffer) {
|
||||||
|
int nc = (cinfo->out_color_space == JCS_RGB565) ?
|
||||||
|
2 : cinfo->out_color_components;
|
||||||
|
jpeg_free_small((j_common_ptr) cinfo, cinfo->master->dummy_row_buffer,
|
||||||
|
cinfo->output_width * nc * sizeof(JSAMPLE));
|
||||||
|
}
|
||||||
cinfo->global_state = DSTATE_BUFIMAGE;
|
cinfo->global_state = DSTATE_BUFIMAGE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|||||||
12
jdarith.c
12
jdarith.c
@@ -3,8 +3,8 @@
|
|||||||
*
|
*
|
||||||
* This file was part of the Independent JPEG Group's software:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Developed 1997-2009 by Guido Vollbeding.
|
* Developed 1997-2009 by Guido Vollbeding.
|
||||||
* It was modified by The libjpeg-turbo Project to include only code relevant
|
* libjpeg-turbo Modifications:
|
||||||
* to libjpeg-turbo.
|
* Copyright (C) 2015, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README file.
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
*
|
*
|
||||||
* This file contains portable arithmetic entropy decoding routines for JPEG
|
* This file contains portable arithmetic entropy decoding routines for JPEG
|
||||||
@@ -516,7 +516,7 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
|||||||
/* Outer loop handles each block in the MCU */
|
/* Outer loop handles each block in the MCU */
|
||||||
|
|
||||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||||
block = MCU_data[blkn];
|
block = MCU_data ? MCU_data[blkn] : NULL;
|
||||||
ci = cinfo->MCU_membership[blkn];
|
ci = cinfo->MCU_membership[blkn];
|
||||||
compptr = cinfo->cur_comp_info[ci];
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
|
||||||
@@ -563,7 +563,8 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
|||||||
entropy->last_dc_val[ci] += v;
|
entropy->last_dc_val[ci] += v;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*block)[0] = (JCOEF) entropy->last_dc_val[ci];
|
if (block)
|
||||||
|
(*block)[0] = (JCOEF) entropy->last_dc_val[ci];
|
||||||
|
|
||||||
/* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */
|
/* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */
|
||||||
|
|
||||||
@@ -607,7 +608,8 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
|||||||
while (m >>= 1)
|
while (m >>= 1)
|
||||||
if (arith_decode(cinfo, st)) v |= m;
|
if (arith_decode(cinfo, st)) v |= m;
|
||||||
v += 1; if (sign) v = -v;
|
v += 1; if (sign) v = -v;
|
||||||
(*block)[jpeg_natural_order[k]] = (JCOEF) v;
|
if (block)
|
||||||
|
(*block)[jpeg_natural_order[k]] = (JCOEF) v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
71
jdcoefct.c
71
jdcoefct.c
@@ -4,6 +4,7 @@
|
|||||||
* This file was part of the Independent JPEG Group's software:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
|
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
|
||||||
* Copyright (C) 2010, D. R. Commander.
|
* Copyright (C) 2010, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README file.
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
*
|
*
|
||||||
@@ -16,53 +17,9 @@
|
|||||||
* Also, the input side (only) is used when reading a file for transcoding.
|
* Also, the input side (only) is used when reading a file for transcoding.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define JPEG_INTERNALS
|
#include "jdcoefct.h"
|
||||||
#include "jinclude.h"
|
|
||||||
#include "jpeglib.h"
|
|
||||||
#include "jpegcomp.h"
|
#include "jpegcomp.h"
|
||||||
|
|
||||||
/* Block smoothing is only applicable for progressive JPEG, so: */
|
|
||||||
#ifndef D_PROGRESSIVE_SUPPORTED
|
|
||||||
#undef BLOCK_SMOOTHING_SUPPORTED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Private buffer controller object */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
struct jpeg_d_coef_controller pub; /* public fields */
|
|
||||||
|
|
||||||
/* These variables keep track of the current location of the input side. */
|
|
||||||
/* cinfo->input_iMCU_row is also used for this. */
|
|
||||||
JDIMENSION MCU_ctr; /* counts MCUs processed in current row */
|
|
||||||
int MCU_vert_offset; /* counts MCU rows within iMCU row */
|
|
||||||
int MCU_rows_per_iMCU_row; /* number of such rows needed */
|
|
||||||
|
|
||||||
/* The output side's location is represented by cinfo->output_iMCU_row. */
|
|
||||||
|
|
||||||
/* In single-pass modes, it's sufficient to buffer just one MCU.
|
|
||||||
* We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks,
|
|
||||||
* and let the entropy decoder write into that workspace each time.
|
|
||||||
* In multi-pass modes, this array points to the current MCU's blocks
|
|
||||||
* within the virtual arrays; it is used only by the input side.
|
|
||||||
*/
|
|
||||||
JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU];
|
|
||||||
|
|
||||||
/* Temporary workspace for one MCU */
|
|
||||||
JCOEF * workspace;
|
|
||||||
|
|
||||||
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
|
||||||
/* In multi-pass modes, we need a virtual block array for each component. */
|
|
||||||
jvirt_barray_ptr whole_image[MAX_COMPONENTS];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
|
||||||
/* When doing block smoothing, we latch coefficient Al values here */
|
|
||||||
int * coef_bits_latch;
|
|
||||||
#define SAVED_COEFS 6 /* we save coef_bits[0..5] */
|
|
||||||
#endif
|
|
||||||
} my_coef_controller;
|
|
||||||
|
|
||||||
typedef my_coef_controller * my_coef_ptr;
|
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
METHODDEF(int) decompress_onepass
|
METHODDEF(int) decompress_onepass
|
||||||
@@ -78,30 +35,6 @@ METHODDEF(int) decompress_smooth_data
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
LOCAL(void)
|
|
||||||
start_iMCU_row (j_decompress_ptr cinfo)
|
|
||||||
/* Reset within-iMCU-row counters for a new row (input side) */
|
|
||||||
{
|
|
||||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
|
||||||
|
|
||||||
/* In an interleaved scan, an MCU row is the same as an iMCU row.
|
|
||||||
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
|
|
||||||
* But at the bottom of the image, process only what's left.
|
|
||||||
*/
|
|
||||||
if (cinfo->comps_in_scan > 1) {
|
|
||||||
coef->MCU_rows_per_iMCU_row = 1;
|
|
||||||
} else {
|
|
||||||
if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
|
|
||||||
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
|
|
||||||
else
|
|
||||||
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
coef->MCU_ctr = 0;
|
|
||||||
coef->MCU_vert_offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize for an input processing pass.
|
* Initialize for an input processing pass.
|
||||||
*/
|
*/
|
||||||
|
|||||||
82
jdcoefct.h
Normal file
82
jdcoefct.h
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* jdcoefct.h
|
||||||
|
*
|
||||||
|
* This file was part of the Independent JPEG Group's software:
|
||||||
|
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||||
|
* libjpeg-turbo Modifications:
|
||||||
|
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Block smoothing is only applicable for progressive JPEG, so: */
|
||||||
|
#ifndef D_PROGRESSIVE_SUPPORTED
|
||||||
|
#undef BLOCK_SMOOTHING_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Private buffer controller object */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_d_coef_controller pub; /* public fields */
|
||||||
|
|
||||||
|
/* These variables keep track of the current location of the input side. */
|
||||||
|
/* cinfo->input_iMCU_row is also used for this. */
|
||||||
|
JDIMENSION MCU_ctr; /* counts MCUs processed in current row */
|
||||||
|
int MCU_vert_offset; /* counts MCU rows within iMCU row */
|
||||||
|
int MCU_rows_per_iMCU_row; /* number of such rows needed */
|
||||||
|
|
||||||
|
/* The output side's location is represented by cinfo->output_iMCU_row. */
|
||||||
|
|
||||||
|
/* In single-pass modes, it's sufficient to buffer just one MCU.
|
||||||
|
* We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks,
|
||||||
|
* and let the entropy decoder write into that workspace each time.
|
||||||
|
* In multi-pass modes, this array points to the current MCU's blocks
|
||||||
|
* within the virtual arrays; it is used only by the input side.
|
||||||
|
*/
|
||||||
|
JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU];
|
||||||
|
|
||||||
|
/* Temporary workspace for one MCU */
|
||||||
|
JCOEF * workspace;
|
||||||
|
|
||||||
|
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||||
|
/* In multi-pass modes, we need a virtual block array for each component. */
|
||||||
|
jvirt_barray_ptr whole_image[MAX_COMPONENTS];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||||
|
/* When doing block smoothing, we latch coefficient Al values here */
|
||||||
|
int * coef_bits_latch;
|
||||||
|
#define SAVED_COEFS 6 /* we save coef_bits[0..5] */
|
||||||
|
#endif
|
||||||
|
} my_coef_controller;
|
||||||
|
|
||||||
|
typedef my_coef_controller * my_coef_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
start_iMCU_row (j_decompress_ptr cinfo)
|
||||||
|
/* Reset within-iMCU-row counters for a new row (input side) */
|
||||||
|
{
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
|
||||||
|
/* In an interleaved scan, an MCU row is the same as an iMCU row.
|
||||||
|
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
|
||||||
|
* But at the bottom of the image, process only what's left.
|
||||||
|
*/
|
||||||
|
if (cinfo->comps_in_scan > 1) {
|
||||||
|
coef->MCU_rows_per_iMCU_row = 1;
|
||||||
|
} else {
|
||||||
|
if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
|
||||||
|
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
|
||||||
|
else
|
||||||
|
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
coef->MCU_ctr = 0;
|
||||||
|
coef->MCU_vert_offset = 0;
|
||||||
|
}
|
||||||
19
jdhuff.c
19
jdhuff.c
@@ -4,7 +4,7 @@
|
|||||||
* This file was part of the Independent JPEG Group's software:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2009-2011, D. R. Commander.
|
* Copyright (C) 2009-2011, 2015, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README file.
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
*
|
*
|
||||||
* This file contains Huffman entropy decoding routines.
|
* This file contains Huffman entropy decoding routines.
|
||||||
@@ -562,7 +562,7 @@ decode_mcu_slow (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
|||||||
ASSIGN_STATE(state, entropy->saved);
|
ASSIGN_STATE(state, entropy->saved);
|
||||||
|
|
||||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||||
JBLOCKROW block = MCU_data[blkn];
|
JBLOCKROW block = MCU_data ? MCU_data[blkn] : NULL;
|
||||||
d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn];
|
d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn];
|
||||||
d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn];
|
d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn];
|
||||||
register int s, k, r;
|
register int s, k, r;
|
||||||
@@ -582,11 +582,13 @@ decode_mcu_slow (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
|||||||
int ci = cinfo->MCU_membership[blkn];
|
int ci = cinfo->MCU_membership[blkn];
|
||||||
s += state.last_dc_val[ci];
|
s += state.last_dc_val[ci];
|
||||||
state.last_dc_val[ci] = s;
|
state.last_dc_val[ci] = s;
|
||||||
/* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
|
if (block) {
|
||||||
(*block)[0] = (JCOEF) s;
|
/* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
|
||||||
|
(*block)[0] = (JCOEF) s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entropy->ac_needed[blkn]) {
|
if (entropy->ac_needed[blkn] && block) {
|
||||||
|
|
||||||
/* Section F.2.2.2: decode the AC coefficients */
|
/* Section F.2.2.2: decode the AC coefficients */
|
||||||
/* Since zeroes are skipped, output area must be cleared beforehand */
|
/* Since zeroes are skipped, output area must be cleared beforehand */
|
||||||
@@ -659,7 +661,7 @@ decode_mcu_fast (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
|||||||
ASSIGN_STATE(state, entropy->saved);
|
ASSIGN_STATE(state, entropy->saved);
|
||||||
|
|
||||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||||
JBLOCKROW block = MCU_data[blkn];
|
JBLOCKROW block = MCU_data ? MCU_data[blkn] : NULL;
|
||||||
d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn];
|
d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn];
|
||||||
d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn];
|
d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn];
|
||||||
register int s, k, r, l;
|
register int s, k, r, l;
|
||||||
@@ -675,10 +677,11 @@ decode_mcu_fast (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
|||||||
int ci = cinfo->MCU_membership[blkn];
|
int ci = cinfo->MCU_membership[blkn];
|
||||||
s += state.last_dc_val[ci];
|
s += state.last_dc_val[ci];
|
||||||
state.last_dc_val[ci] = s;
|
state.last_dc_val[ci] = s;
|
||||||
(*block)[0] = (JCOEF) s;
|
if (block)
|
||||||
|
(*block)[0] = (JCOEF) s;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entropy->ac_needed[blkn]) {
|
if (entropy->ac_needed[blkn] && block) {
|
||||||
|
|
||||||
for (k = 1; k < DCTSIZE2; k++) {
|
for (k = 1; k < DCTSIZE2; k++) {
|
||||||
HUFF_DECODE_FAST(s, l, actbl);
|
HUFF_DECODE_FAST(s, l, actbl);
|
||||||
|
|||||||
63
jdmainct.c
63
jdmainct.c
@@ -15,10 +15,7 @@
|
|||||||
* supplies the equivalent of the main buffer in that case.
|
* supplies the equivalent of the main buffer in that case.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define JPEG_INTERNALS
|
#include "jdmainct.h"
|
||||||
#include "jinclude.h"
|
|
||||||
#include "jpeglib.h"
|
|
||||||
#include "jpegcomp.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -112,36 +109,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* Private buffer controller object */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
struct jpeg_d_main_controller pub; /* public fields */
|
|
||||||
|
|
||||||
/* Pointer to allocated workspace (M or M+2 row groups). */
|
|
||||||
JSAMPARRAY buffer[MAX_COMPONENTS];
|
|
||||||
|
|
||||||
boolean buffer_full; /* Have we gotten an iMCU row from decoder? */
|
|
||||||
JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */
|
|
||||||
|
|
||||||
/* Remaining fields are only used in the context case. */
|
|
||||||
|
|
||||||
/* These are the master pointers to the funny-order pointer lists. */
|
|
||||||
JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */
|
|
||||||
|
|
||||||
int whichptr; /* indicates which pointer set is now in use */
|
|
||||||
int context_state; /* process_data state machine status */
|
|
||||||
JDIMENSION rowgroups_avail; /* row groups available to postprocessor */
|
|
||||||
JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */
|
|
||||||
} my_main_controller;
|
|
||||||
|
|
||||||
typedef my_main_controller * my_main_ptr;
|
|
||||||
|
|
||||||
/* context_state values: */
|
|
||||||
#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */
|
|
||||||
#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */
|
|
||||||
#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */
|
|
||||||
|
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
METHODDEF(void) process_data_simple_main
|
METHODDEF(void) process_data_simple_main
|
||||||
(j_decompress_ptr cinfo, JSAMPARRAY output_buf,
|
(j_decompress_ptr cinfo, JSAMPARRAY output_buf,
|
||||||
@@ -237,34 +204,6 @@ make_funny_pointers (j_decompress_ptr cinfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LOCAL(void)
|
|
||||||
set_wraparound_pointers (j_decompress_ptr cinfo)
|
|
||||||
/* Set up the "wraparound" pointers at top and bottom of the pointer lists.
|
|
||||||
* This changes the pointer list state from top-of-image to the normal state.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
|
|
||||||
int ci, i, rgroup;
|
|
||||||
int M = cinfo->_min_DCT_scaled_size;
|
|
||||||
jpeg_component_info *compptr;
|
|
||||||
JSAMPARRAY xbuf0, xbuf1;
|
|
||||||
|
|
||||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
|
||||||
ci++, compptr++) {
|
|
||||||
rgroup = (compptr->v_samp_factor * compptr->_DCT_scaled_size) /
|
|
||||||
cinfo->_min_DCT_scaled_size; /* height of a row group of component */
|
|
||||||
xbuf0 = main_ptr->xbuffer[0][ci];
|
|
||||||
xbuf1 = main_ptr->xbuffer[1][ci];
|
|
||||||
for (i = 0; i < rgroup; i++) {
|
|
||||||
xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i];
|
|
||||||
xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i];
|
|
||||||
xbuf0[rgroup*(M+2) + i] = xbuf0[i];
|
|
||||||
xbuf1[rgroup*(M+2) + i] = xbuf1[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LOCAL(void)
|
LOCAL(void)
|
||||||
set_bottom_pointers (j_decompress_ptr cinfo)
|
set_bottom_pointers (j_decompress_ptr cinfo)
|
||||||
/* Change the pointer lists to duplicate the last sample row at the bottom
|
/* Change the pointer lists to duplicate the last sample row at the bottom
|
||||||
|
|||||||
71
jdmainct.h
Normal file
71
jdmainct.h
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* jdmainct.h
|
||||||
|
*
|
||||||
|
* This file was part of the Independent JPEG Group's software:
|
||||||
|
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
#include "jpegcomp.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Private buffer controller object */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_d_main_controller pub; /* public fields */
|
||||||
|
|
||||||
|
/* Pointer to allocated workspace (M or M+2 row groups). */
|
||||||
|
JSAMPARRAY buffer[MAX_COMPONENTS];
|
||||||
|
|
||||||
|
boolean buffer_full; /* Have we gotten an iMCU row from decoder? */
|
||||||
|
JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */
|
||||||
|
|
||||||
|
/* Remaining fields are only used in the context case. */
|
||||||
|
|
||||||
|
/* These are the master pointers to the funny-order pointer lists. */
|
||||||
|
JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */
|
||||||
|
|
||||||
|
int whichptr; /* indicates which pointer set is now in use */
|
||||||
|
int context_state; /* process_data state machine status */
|
||||||
|
JDIMENSION rowgroups_avail; /* row groups available to postprocessor */
|
||||||
|
JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */
|
||||||
|
} my_main_controller;
|
||||||
|
|
||||||
|
typedef my_main_controller * my_main_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* context_state values: */
|
||||||
|
#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */
|
||||||
|
#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */
|
||||||
|
#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
set_wraparound_pointers (j_decompress_ptr cinfo)
|
||||||
|
/* Set up the "wraparound" pointers at top and bottom of the pointer lists.
|
||||||
|
* This changes the pointer list state from top-of-image to the normal state.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
|
||||||
|
int ci, i, rgroup;
|
||||||
|
int M = cinfo->_min_DCT_scaled_size;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
JSAMPARRAY xbuf0, xbuf1;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
rgroup = (compptr->v_samp_factor * compptr->_DCT_scaled_size) /
|
||||||
|
cinfo->_min_DCT_scaled_size; /* height of a row group of component */
|
||||||
|
xbuf0 = main_ptr->xbuffer[0][ci];
|
||||||
|
xbuf1 = main_ptr->xbuffer[1][ci];
|
||||||
|
for (i = 0; i < rgroup; i++) {
|
||||||
|
xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i];
|
||||||
|
xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i];
|
||||||
|
xbuf0[rgroup*(M+2) + i] = xbuf0[i];
|
||||||
|
xbuf1[rgroup*(M+2) + i] = xbuf1[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
jdsample.c
42
jdsample.c
@@ -22,51 +22,11 @@
|
|||||||
* Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
|
* Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define JPEG_INTERNALS
|
#include "jdsample.h"
|
||||||
#include "jinclude.h"
|
|
||||||
#include "jpeglib.h"
|
|
||||||
#include "jsimd.h"
|
#include "jsimd.h"
|
||||||
#include "jpegcomp.h"
|
#include "jpegcomp.h"
|
||||||
|
|
||||||
|
|
||||||
/* Pointer to routine to upsample a single component */
|
|
||||||
typedef void (*upsample1_ptr) (j_decompress_ptr cinfo,
|
|
||||||
jpeg_component_info * compptr,
|
|
||||||
JSAMPARRAY input_data,
|
|
||||||
JSAMPARRAY * output_data_ptr);
|
|
||||||
|
|
||||||
/* Private subobject */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
struct jpeg_upsampler pub; /* public fields */
|
|
||||||
|
|
||||||
/* Color conversion buffer. When using separate upsampling and color
|
|
||||||
* conversion steps, this buffer holds one upsampled row group until it
|
|
||||||
* has been color converted and output.
|
|
||||||
* Note: we do not allocate any storage for component(s) which are full-size,
|
|
||||||
* ie do not need rescaling. The corresponding entry of color_buf[] is
|
|
||||||
* simply set to point to the input data array, thereby avoiding copying.
|
|
||||||
*/
|
|
||||||
JSAMPARRAY color_buf[MAX_COMPONENTS];
|
|
||||||
|
|
||||||
/* Per-component upsampling method pointers */
|
|
||||||
upsample1_ptr methods[MAX_COMPONENTS];
|
|
||||||
|
|
||||||
int next_row_out; /* counts rows emitted from color_buf */
|
|
||||||
JDIMENSION rows_to_go; /* counts rows remaining in image */
|
|
||||||
|
|
||||||
/* Height of an input row group for each component. */
|
|
||||||
int rowgroup_height[MAX_COMPONENTS];
|
|
||||||
|
|
||||||
/* These arrays save pixel expansion factors so that int_expand need not
|
|
||||||
* recompute them each time. They are unused for other upsampling methods.
|
|
||||||
*/
|
|
||||||
UINT8 h_expand[MAX_COMPONENTS];
|
|
||||||
UINT8 v_expand[MAX_COMPONENTS];
|
|
||||||
} my_upsampler;
|
|
||||||
|
|
||||||
typedef my_upsampler * my_upsample_ptr;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize for an upsampling pass.
|
* Initialize for an upsampling pass.
|
||||||
|
|||||||
50
jdsample.h
Normal file
50
jdsample.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* jdsample.h
|
||||||
|
*
|
||||||
|
* This file was part of the Independent JPEG Group's software:
|
||||||
|
* Copyright (C) 1991-1996, Thomas G. Lane.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Pointer to routine to upsample a single component */
|
||||||
|
typedef void (*upsample1_ptr) (j_decompress_ptr cinfo,
|
||||||
|
jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data,
|
||||||
|
JSAMPARRAY * output_data_ptr);
|
||||||
|
|
||||||
|
/* Private subobject */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_upsampler pub; /* public fields */
|
||||||
|
|
||||||
|
/* Color conversion buffer. When using separate upsampling and color
|
||||||
|
* conversion steps, this buffer holds one upsampled row group until it
|
||||||
|
* has been color converted and output.
|
||||||
|
* Note: we do not allocate any storage for component(s) which are full-size,
|
||||||
|
* ie do not need rescaling. The corresponding entry of color_buf[] is
|
||||||
|
* simply set to point to the input data array, thereby avoiding copying.
|
||||||
|
*/
|
||||||
|
JSAMPARRAY color_buf[MAX_COMPONENTS];
|
||||||
|
|
||||||
|
/* Per-component upsampling method pointers */
|
||||||
|
upsample1_ptr methods[MAX_COMPONENTS];
|
||||||
|
|
||||||
|
int next_row_out; /* counts rows emitted from color_buf */
|
||||||
|
JDIMENSION rows_to_go; /* counts rows remaining in image */
|
||||||
|
|
||||||
|
/* Height of an input row group for each component. */
|
||||||
|
int rowgroup_height[MAX_COMPONENTS];
|
||||||
|
|
||||||
|
/* These arrays save pixel expansion factors so that int_expand need not
|
||||||
|
* recompute them each time. They are unused for other upsampling methods.
|
||||||
|
*/
|
||||||
|
UINT8 h_expand[MAX_COMPONENTS];
|
||||||
|
UINT8 v_expand[MAX_COMPONENTS];
|
||||||
|
} my_upsampler;
|
||||||
|
|
||||||
|
typedef my_upsampler * my_upsample_ptr;
|
||||||
10
jpegint.h
10
jpegint.h
@@ -4,8 +4,8 @@
|
|||||||
* This file was part of the Independent JPEG Group's software:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
* Modified 1997-2009 by Guido Vollbeding.
|
* Modified 1997-2009 by Guido Vollbeding.
|
||||||
* It was modified by The libjpeg-turbo Project to include only code relevant
|
* libjpeg-turbo Modifications:
|
||||||
* to libjpeg-turbo.
|
* Copyright (C) 2015, Google, Inc.
|
||||||
* For conditions of distribution and use, see the accompanying README file.
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
*
|
*
|
||||||
* This file provides common declarations for the various JPEG modules.
|
* This file provides common declarations for the various JPEG modules.
|
||||||
@@ -137,6 +137,12 @@ struct jpeg_decomp_master {
|
|||||||
|
|
||||||
/* State variables made visible to other modules */
|
/* State variables made visible to other modules */
|
||||||
boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */
|
boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */
|
||||||
|
|
||||||
|
/* Buffer large enough to store an output row. This is used when
|
||||||
|
* jpeg_skip_scanlines() chooses to "skip" a row by reading it into this
|
||||||
|
* dummy buffer.
|
||||||
|
*/
|
||||||
|
JSAMPROW dummy_row_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Input control module */
|
/* Input control module */
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
* Modified 2002-2009 by Guido Vollbeding.
|
* Modified 2002-2009 by Guido Vollbeding.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2009-2011, 2013-2014, D. R. Commander.
|
* Copyright (C) 2009-2011, 2013-2014, D. R. Commander.
|
||||||
|
* Copyright (C) 2015, Google, Inc.
|
||||||
* For conditions of distribution and use, see the accompanying README file.
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
*
|
*
|
||||||
* This file defines the application interface for the JPEG library.
|
* This file defines the application interface for the JPEG library.
|
||||||
@@ -990,6 +991,8 @@ EXTERN(boolean) jpeg_start_decompress (j_decompress_ptr cinfo);
|
|||||||
EXTERN(JDIMENSION) jpeg_read_scanlines (j_decompress_ptr cinfo,
|
EXTERN(JDIMENSION) jpeg_read_scanlines (j_decompress_ptr cinfo,
|
||||||
JSAMPARRAY scanlines,
|
JSAMPARRAY scanlines,
|
||||||
JDIMENSION max_lines);
|
JDIMENSION max_lines);
|
||||||
|
EXTERN(JDIMENSION) jpeg_skip_scanlines (j_decompress_ptr cinfo,
|
||||||
|
JDIMENSION num_lines);
|
||||||
EXTERN(boolean) jpeg_finish_decompress (j_decompress_ptr cinfo);
|
EXTERN(boolean) jpeg_finish_decompress (j_decompress_ptr cinfo);
|
||||||
|
|
||||||
/* Replaces jpeg_read_scanlines when reading raw downsampled data. */
|
/* Replaces jpeg_read_scanlines when reading raw downsampled data. */
|
||||||
|
|||||||
46
libjpeg.txt
46
libjpeg.txt
@@ -3,7 +3,8 @@ USING THE IJG JPEG LIBRARY
|
|||||||
This file was part of the Independent JPEG Group's software:
|
This file was part of the Independent JPEG Group's software:
|
||||||
Copyright (C) 1994-2011, Thomas G. Lane, Guido Vollbeding.
|
Copyright (C) 1994-2011, Thomas G. Lane, Guido Vollbeding.
|
||||||
libjpeg-turbo Modifications:
|
libjpeg-turbo Modifications:
|
||||||
Copyright (C) 2010, 2014, D. R. Commander.
|
Copyright (C) 2010, 2014, 2015, D. R. Commander.
|
||||||
|
Copyright (C) 2015, Google, Inc.
|
||||||
For conditions of distribution and use, see the accompanying README file.
|
For conditions of distribution and use, see the accompanying README file.
|
||||||
|
|
||||||
|
|
||||||
@@ -729,6 +730,49 @@ jpeg_abort_decompress() or jpeg_abort() if you want to reuse the object.
|
|||||||
The previous discussion of aborting compression cycles applies here too.
|
The previous discussion of aborting compression cycles applies here too.
|
||||||
|
|
||||||
|
|
||||||
|
Skipping rows when decompressing
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines);
|
||||||
|
|
||||||
|
This function provides application programmers with the ability to skip over
|
||||||
|
multiple rows in the JPEG image, thus decoding only a subset of the image data.
|
||||||
|
This is convenient for performance-critical applications that wish to view only
|
||||||
|
a portion of a large JPEG image without decompressing the whole thing. It it
|
||||||
|
also useful in memory-constrained environments (such as on mobile devices.)
|
||||||
|
|
||||||
|
Suspending data sources are not supported by this function. Calling
|
||||||
|
jpeg_skip_scanlines() with a suspending data source will result in undefined
|
||||||
|
behavior.
|
||||||
|
|
||||||
|
jpeg_skip_scanlines() will not allow skipping past the bottom of the image. If
|
||||||
|
the value of num_lines is large enough to skip past the bottom of the image,
|
||||||
|
then the function will skip to the end of the image instead.
|
||||||
|
|
||||||
|
If the value of num_lines is valid, then jpeg_skip_scanlines() will always
|
||||||
|
skip all of the input rows requested. There is no need to inspect the return
|
||||||
|
value of the function in that case.
|
||||||
|
|
||||||
|
Best results will be achieved by calling jpeg_skip_scanlines() for large chunks
|
||||||
|
of rows. The function should be viewed as a way to quickly jump to a
|
||||||
|
particular vertical offset in the JPEG image in order to decode a subset of the
|
||||||
|
image. Used in this manner, it will provide significant performance
|
||||||
|
improvements.
|
||||||
|
|
||||||
|
Calling jpeg_skip_scanlines() for small values of num_lines has several
|
||||||
|
potential drawbacks:
|
||||||
|
1) JPEG decompression occurs in blocks, so if jpeg_skip_scanlines() is
|
||||||
|
called from the middle of a decompression block, then it is likely that
|
||||||
|
much of the decompression work has already been done for the first
|
||||||
|
couple of rows that need to be skipped.
|
||||||
|
2) When this function returns, it must leave the decompressor in a state
|
||||||
|
such that it is ready to read the next line. This may involve
|
||||||
|
decompressing a block that must be partially skipped.
|
||||||
|
These issues are especially tricky for cases in which upsampling requires
|
||||||
|
context rows. In the worst case, jpeg_skip_scanlines() will perform similarly
|
||||||
|
to jpeg_read_scanlines() (since it will actually call jpeg_read_scanlines().)
|
||||||
|
|
||||||
|
|
||||||
Mechanics of usage: include files, linking, etc
|
Mechanics of usage: include files, linking, etc
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user