Index: jdapistd.c |
diff --git a/jdapistd.c b/jdapistd.c |
index a50fda528bc5ad444337c83889f8d94a26d14a8c..056fa1d07bc9979ec93ca412dbee7baecbed91d4 100644 |
--- a/jdapistd.c |
+++ b/jdapistd.c |
@@ -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,10 +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 */ |
@@ -179,6 +180,235 @@ 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, |
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) |
+{ |
+} |
+ |
+ |
+/* |
+ * In some cases, it is best to call jpeg_read_scanlines() and discard the |
+ * output, rather than skipping the scanlines, because this allows us to |
+ * maintain the internal state of the context-based upsampler. In these cases, |
+ * 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) |
+{ |
+ JDIMENSION n; |
+ void (*color_convert) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, |
+ JDIMENSION input_row, JSAMPARRAY output_buf, |
+ int num_rows); |
+ |
+ color_convert = cinfo->cconvert->color_convert; |
+ cinfo->cconvert->color_convert = noop_convert; |
+ |
+ for (n = 0; n < num_lines; n++) |
+ jpeg_read_scanlines(cinfo, NULL, 1); |
+ |
+ cinfo->cconvert->color_convert = color_convert; |
+} |
+ |
+/* |
+ * 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) |
+{ |
+ 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; |
+ |
+ read_and_discard_scanlines(cinfo, rows_left); |
+} |
+ |
+/* |
+ * 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; |
+ JDIMENSION i, x; |
+ int y; |
+ 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)) { |
+ read_and_discard_scanlines(cinfo, num_lines); |
+ 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; |
+ } |
+ |
+ /* If we have just completed the first block, adjust the buffer pointers */ |
+ if (main_ptr->iMCU_row_ctr == 0 || |
+ (main_ptr->iMCU_row_ctr == 1 && lines_left_in_iMCU_row > 2)) |
+ set_wraparound_pointers(cinfo); |
+ 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; |
+ main_ptr->iMCU_row_ctr += 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. |
+ */ |
+ read_and_discard_scanlines(cinfo, lines_to_read); |
+ } 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. |
+ */ |
+ (*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. */ |
+ main_ptr->iMCU_row_ctr += 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. |
+ */ |
+ read_and_discard_scanlines(cinfo, lines_to_read); |
+ } 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. |