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:
DRC
2015-06-25 03:44:36 +00:00
parent 691cd93383
commit eb32cc1e6d
14 changed files with 588 additions and 203 deletions

View File

@@ -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
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
=====

64
djpeg.c
View File

@@ -4,7 +4,8 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* 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.
*
* 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 char * outfilename; /* for -outfile switch */
boolean memsrc; /* for -memsrc switch */
boolean stripe;
JDIMENSION startY, endY;
#define INPUT_BUF_SIZE 4096
@@ -164,6 +167,7 @@ usage (void)
fprintf(stderr, " -memsrc Load input file into memory before decompressing\n");
#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, " -version Print version information and exit\n");
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 */
outfilename = NULL;
memsrc = FALSE;
stripe = FALSE;
cinfo->err->trace_level = 0;
/* Scan command line options, adjust parameters */
@@ -361,7 +366,7 @@ parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
/* RLE output format. */
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. */
if (++argn >= argc) /* advance to next argument */
usage();
@@ -369,6 +374,13 @@ parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
&cinfo->scale_num, &cinfo->scale_denom) != 2)
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)) {
/* Targa output format. */
requested_fmt = FMT_TARGA;
@@ -634,14 +646,48 @@ main (int argc, char **argv)
/* Start decompressor */
(void) jpeg_start_decompress(&cinfo);
/* Write output file header */
(*dest_mgr->start_output) (&cinfo, dest_mgr);
/* Stripe decode */
if (stripe) {
JDIMENSION tmp;
/* 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);
/* Check for valid endY. We cannot check this value until after
* jpeg_start_decompress() is called. Note that we have already verified
* that startY <= endY.
*/
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

View File

@@ -4,7 +4,8 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1994-1996, Thomas G. Lane.
* 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.
*
* This file contains application interface code for the decompression half
@@ -16,11 +17,10 @@
* whole decompression library into a transcoder.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jpegcomp.h"
#include "jdmainct.h"
#include "jdcoefct.h"
#include "jdsample.h"
#include "jmemsys.h"
/* Forward declarations */
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.
* 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)
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;
return TRUE;
}

View File

@@ -3,8 +3,8 @@
*
* This file was part of the Independent JPEG Group's software:
* Developed 1997-2009 by Guido Vollbeding.
* It was modified by The libjpeg-turbo Project to include only code relevant
* to libjpeg-turbo.
* libjpeg-turbo Modifications:
* Copyright (C) 2015, D. R. Commander.
* For conditions of distribution and use, see the accompanying README file.
*
* 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 */
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];
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;
}
(*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 */
@@ -607,7 +608,8 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
while (m >>= 1)
if (arith_decode(cinfo, st)) v |= m;
v += 1; if (sign) v = -v;
(*block)[jpeg_natural_order[k]] = (JCOEF) v;
if (block)
(*block)[jpeg_natural_order[k]] = (JCOEF) v;
}
}

View File

@@ -4,6 +4,7 @@
* 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
* Copyright (C) 2010, D. R. Commander.
* 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.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdcoefct.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 */
METHODDEF(int) decompress_onepass
@@ -78,30 +35,6 @@ METHODDEF(int) decompress_smooth_data
#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.
*/

82
jdcoefct.h Normal file
View 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;
}

View File

@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* 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.
*
* 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);
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 * actbl = entropy->ac_cur_tbls[blkn];
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];
s += state.last_dc_val[ci];
state.last_dc_val[ci] = s;
/* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
(*block)[0] = (JCOEF) s;
if (block) {
/* 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 */
/* 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);
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 * actbl = entropy->ac_cur_tbls[blkn];
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];
s += state.last_dc_val[ci];
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++) {
HUFF_DECODE_FAST(s, l, actbl);

View File

@@ -15,10 +15,7 @@
* supplies the equivalent of the main buffer in that case.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jpegcomp.h"
#include "jdmainct.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 */
METHODDEF(void) process_data_simple_main
(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)
set_bottom_pointers (j_decompress_ptr cinfo)
/* Change the pointer lists to duplicate the last sample row at the bottom

71
jdmainct.h Normal file
View 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];
}
}
}

View File

@@ -22,51 +22,11 @@
* Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdsample.h"
#include "jsimd.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.

50
jdsample.h Normal file
View 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;

View File

@@ -4,8 +4,8 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* Modified 1997-2009 by Guido Vollbeding.
* It was modified by The libjpeg-turbo Project to include only code relevant
* to libjpeg-turbo.
* libjpeg-turbo Modifications:
* Copyright (C) 2015, Google, Inc.
* For conditions of distribution and use, see the accompanying README file.
*
* 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 */
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 */

View File

@@ -6,6 +6,7 @@
* Modified 2002-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
* 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.
*
* 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,
JSAMPARRAY scanlines,
JDIMENSION max_lines);
EXTERN(JDIMENSION) jpeg_skip_scanlines (j_decompress_ptr cinfo,
JDIMENSION num_lines);
EXTERN(boolean) jpeg_finish_decompress (j_decompress_ptr cinfo);
/* Replaces jpeg_read_scanlines when reading raw downsampled data. */

View File

@@ -3,7 +3,8 @@ USING THE IJG JPEG LIBRARY
This file was part of the Independent JPEG Group's software:
Copyright (C) 1994-2011, Thomas G. Lane, Guido Vollbeding.
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.
@@ -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.
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
-----------------------------------------------