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
=====
* 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.
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
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);
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 */
/* 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();
&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;
/* Start decompressor */
(void) jpeg_start_decompress(&cinfo);
- /* Write output file header */
- (*dest_mgr->start_output) (&cinfo, dest_mgr);
+ /* Stripe decode */
+ if (stripe) {
+ JDIMENSION tmp;
+
+ /* 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);
+ }
- /* 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);
+ /* 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
* 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
* 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);
}
+/* 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.
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;
}
*
* 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
/* 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];
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 */
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;
}
}
* 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.
*
* 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
#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.
*/
--- /dev/null
+/*
+ * 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;
+}
* 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.
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;
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 */
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;
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);
* 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"
/*
*/
-/* 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,
}
-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
--- /dev/null
+/*
+ * 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];
+ }
+ }
+}
* 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.
--- /dev/null
+/*
+ * 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;
* 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.
/* 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 */
* 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.
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. */
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.
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
-----------------------------------------------