| Index: jdapistd.c
|
| diff --git a/jdapistd.c b/jdapistd.c
|
| index 056fa1d07bc9979ec93ca412dbee7baecbed91d4..37afc8448b93ea0cad5e744b0ef899a0b7c316ec 100644
|
| --- a/jdapistd.c
|
| +++ b/jdapistd.c
|
| @@ -4,9 +4,10 @@
|
| * This file was part of the Independent JPEG Group's software:
|
| * Copyright (C) 1994-1996, Thomas G. Lane.
|
| * libjpeg-turbo Modifications:
|
| - * Copyright (C) 2010, 2015, D. R. Commander.
|
| + * Copyright (C) 2010, 2015-2016, 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.ijg
|
| + * file.
|
| *
|
| * This file contains application interface code for the decompression half
|
| * of the JPEG library. These are the "standard" API routines that are
|
| @@ -17,14 +18,14 @@
|
| * whole decompression library into a transcoder.
|
| */
|
|
|
| +#include "jinclude.h"
|
| #include "jdmainct.h"
|
| #include "jdcoefct.h"
|
| #include "jdsample.h"
|
| #include "jmemsys.h"
|
|
|
| -
|
| /* Forward declarations */
|
| -LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo));
|
| +LOCAL(boolean) output_pass_setup (j_decompress_ptr cinfo);
|
|
|
|
|
| /*
|
| @@ -56,24 +57,24 @@ jpeg_start_decompress (j_decompress_ptr cinfo)
|
| if (cinfo->inputctl->has_multiple_scans) {
|
| #ifdef D_MULTISCAN_FILES_SUPPORTED
|
| for (;;) {
|
| - int retcode;
|
| - /* Call progress monitor hook if present */
|
| - if (cinfo->progress != NULL)
|
| - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
| - /* Absorb some more input */
|
| - retcode = (*cinfo->inputctl->consume_input) (cinfo);
|
| - if (retcode == JPEG_SUSPENDED)
|
| - return FALSE;
|
| - if (retcode == JPEG_REACHED_EOI)
|
| - break;
|
| - /* Advance progress counter if appropriate */
|
| - if (cinfo->progress != NULL &&
|
| - (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
|
| - if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
|
| - /* jdmaster underestimated number of scans; ratchet up one scan */
|
| - cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
|
| - }
|
| - }
|
| + int retcode;
|
| + /* Call progress monitor hook if present */
|
| + if (cinfo->progress != NULL)
|
| + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
| + /* Absorb some more input */
|
| + retcode = (*cinfo->inputctl->consume_input) (cinfo);
|
| + if (retcode == JPEG_SUSPENDED)
|
| + return FALSE;
|
| + if (retcode == JPEG_REACHED_EOI)
|
| + break;
|
| + /* Advance progress counter if appropriate */
|
| + if (cinfo->progress != NULL &&
|
| + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
|
| + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
|
| + /* jdmaster underestimated number of scans; ratchet up one scan */
|
| + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
|
| + }
|
| + }
|
| }
|
| #else
|
| ERREXIT(cinfo, JERR_NOT_COMPILED);
|
| @@ -112,16 +113,16 @@ output_pass_setup (j_decompress_ptr cinfo)
|
| JDIMENSION last_scanline;
|
| /* Call progress monitor hook if present */
|
| if (cinfo->progress != NULL) {
|
| - cinfo->progress->pass_counter = (long) cinfo->output_scanline;
|
| - cinfo->progress->pass_limit = (long) cinfo->output_height;
|
| - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
| + cinfo->progress->pass_counter = (long) cinfo->output_scanline;
|
| + cinfo->progress->pass_limit = (long) cinfo->output_height;
|
| + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
| }
|
| /* Process some data */
|
| last_scanline = cinfo->output_scanline;
|
| (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL,
|
| - &cinfo->output_scanline, (JDIMENSION) 0);
|
| + &cinfo->output_scanline, (JDIMENSION) 0);
|
| if (cinfo->output_scanline == last_scanline)
|
| - return FALSE; /* No progress made, must suspend */
|
| + return FALSE; /* No progress made, must suspend */
|
| }
|
| /* Finish up dummy pass, and set up for another one */
|
| (*cinfo->master->finish_output_pass) (cinfo);
|
| @@ -140,6 +141,110 @@ output_pass_setup (j_decompress_ptr cinfo)
|
|
|
|
|
| /*
|
| + * Enable partial scanline decompression
|
| + *
|
| + * Must be called after jpeg_start_decompress() and before any calls to
|
| + * jpeg_read_scanlines() or jpeg_skip_scanlines().
|
| + *
|
| + * Refer to libjpeg.txt for more information.
|
| + */
|
| +
|
| +GLOBAL(void)
|
| +jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
|
| + JDIMENSION *width)
|
| +{
|
| + int ci, align, orig_downsampled_width;
|
| + JDIMENSION input_xoffset;
|
| + boolean reinit_upsampler = FALSE;
|
| + jpeg_component_info *compptr;
|
| +
|
| + if (cinfo->global_state != DSTATE_SCANNING || cinfo->output_scanline != 0)
|
| + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
| +
|
| + if (!xoffset || !width)
|
| + ERREXIT(cinfo, JERR_BAD_CROP_SPEC);
|
| +
|
| + /* xoffset and width must fall within the output image dimensions. */
|
| + if (*width == 0 || *xoffset + *width > cinfo->output_width)
|
| + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
|
| +
|
| + /* No need to do anything if the caller wants the entire width. */
|
| + if (*width == cinfo->output_width)
|
| + return;
|
| +
|
| + /* Ensuring the proper alignment of xoffset is tricky. At minimum, it
|
| + * must align with an MCU boundary, because:
|
| + *
|
| + * (1) The IDCT is performed in blocks, and it is not feasible to modify
|
| + * the algorithm so that it can transform partial blocks.
|
| + * (2) Because of the SIMD extensions, any input buffer passed to the
|
| + * upsampling and color conversion routines must be aligned to the
|
| + * SIMD word size (for instance, 128-bit in the case of SSE2.) The
|
| + * easiest way to accomplish this without copying data is to ensure
|
| + * that upsampling and color conversion begin at the start of the
|
| + * first MCU column that will be inverse transformed.
|
| + *
|
| + * In practice, we actually impose a stricter alignment requirement. We
|
| + * require that xoffset be a multiple of the maximum MCU column width of all
|
| + * of the components (the "iMCU column width.") This is to simplify the
|
| + * single-pass decompression case, allowing us to use the same MCU column
|
| + * width for all of the components.
|
| + */
|
| + align = cinfo->_min_DCT_scaled_size * cinfo->max_h_samp_factor;
|
| +
|
| + /* Adjust xoffset to the nearest iMCU boundary <= the requested value */
|
| + input_xoffset = *xoffset;
|
| + *xoffset = (input_xoffset / align) * align;
|
| +
|
| + /* Adjust the width so that the right edge of the output image is as
|
| + * requested (only the left edge is altered.) It is important that calling
|
| + * programs check this value after this function returns, so that they can
|
| + * allocate an output buffer with the appropriate size.
|
| + */
|
| + *width = *width + input_xoffset - *xoffset;
|
| + cinfo->output_width = *width;
|
| +
|
| + /* Set the first and last iMCU columns that we must decompress. These values
|
| + * will be used in single-scan decompressions.
|
| + */
|
| + cinfo->master->first_iMCU_col =
|
| + (JDIMENSION) (long) (*xoffset) / (long) align;
|
| + cinfo->master->last_iMCU_col =
|
| + (JDIMENSION) jdiv_round_up((long) (*xoffset + cinfo->output_width),
|
| + (long) align) - 1;
|
| +
|
| + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
| + ci++, compptr++) {
|
| + /* Set downsampled_width to the new output width. */
|
| + orig_downsampled_width = compptr->downsampled_width;
|
| + compptr->downsampled_width =
|
| + (JDIMENSION) jdiv_round_up((long) (cinfo->output_width *
|
| + compptr->h_samp_factor),
|
| + (long) cinfo->max_h_samp_factor);
|
| + if (compptr->downsampled_width < 2 && orig_downsampled_width >= 2)
|
| + reinit_upsampler = TRUE;
|
| +
|
| + /* Set the first and last iMCU columns that we must decompress. These
|
| + * values will be used in multi-scan decompressions.
|
| + */
|
| + cinfo->master->first_MCU_col[ci] =
|
| + (JDIMENSION) (long) (*xoffset * compptr->h_samp_factor) /
|
| + (long) align;
|
| + cinfo->master->last_MCU_col[ci] =
|
| + (JDIMENSION) jdiv_round_up((long) ((*xoffset + cinfo->output_width) *
|
| + compptr->h_samp_factor),
|
| + (long) align) - 1;
|
| + }
|
| +
|
| + if (reinit_upsampler) {
|
| + cinfo->master->jinit_upsampler_no_alloc = TRUE;
|
| + jinit_upsampler(cinfo);
|
| + cinfo->master->jinit_upsampler_no_alloc = FALSE;
|
| + }
|
| +}
|
| +
|
| +
|
| +/*
|
| * Read some scanlines of data from the JPEG decompressor.
|
| *
|
| * The return value will be the number of lines actually read.
|
| @@ -154,7 +259,7 @@ output_pass_setup (j_decompress_ptr cinfo)
|
|
|
| GLOBAL(JDIMENSION)
|
| jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
|
| - JDIMENSION max_lines)
|
| + JDIMENSION max_lines)
|
| {
|
| JDIMENSION row_ctr;
|
|
|
| @@ -180,7 +285,6 @@ jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
|
| }
|
|
|
|
|
| -
|
| /* Dummy color convert function used by jpeg_skip_scanlines() */
|
| LOCAL(void)
|
| noop_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
| @@ -196,6 +300,7 @@ noop_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
| * we set up and tear down a dummy color converter in order to avoid valgrind
|
| * errors and to achieve the best possible performance.
|
| */
|
| +
|
| LOCAL(void)
|
| read_and_discard_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
|
| {
|
| @@ -213,6 +318,7 @@ read_and_discard_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
|
| cinfo->cconvert->color_convert = color_convert;
|
| }
|
|
|
| +
|
| /*
|
| * Called by jpeg_skip_scanlines(). This partially skips a decompress block by
|
| * incrementing the rowgroup counter.
|
| @@ -416,7 +522,7 @@ jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
|
|
|
| GLOBAL(JDIMENSION)
|
| jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
|
| - JDIMENSION max_lines)
|
| + JDIMENSION max_lines)
|
| {
|
| JDIMENSION lines_per_iMCU_row;
|
|
|
| @@ -441,7 +547,7 @@ jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
|
|
|
| /* Decompress directly into user's buffer. */
|
| if (! (*cinfo->coef->decompress_data) (cinfo, data))
|
| - return 0; /* suspension forced, can do nothing more */
|
| + return 0; /* suspension forced, can do nothing more */
|
|
|
| /* OK, we processed one iMCU row. */
|
| cinfo->output_scanline += lines_per_iMCU_row;
|
| @@ -497,9 +603,9 @@ jpeg_finish_output (j_decompress_ptr cinfo)
|
| }
|
| /* Read markers looking for SOS or EOI */
|
| while (cinfo->input_scan_number <= cinfo->output_scan_number &&
|
| - ! cinfo->inputctl->eoi_reached) {
|
| + ! cinfo->inputctl->eoi_reached) {
|
| if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
|
| - return FALSE; /* Suspend, come back later */
|
| + return FALSE; /* Suspend, come back later */
|
| }
|
| cinfo->global_state = DSTATE_BUFIMAGE;
|
| return TRUE;
|
|
|