diff options
Diffstat (limited to 'media/libjpeg/jdapistd.c')
-rw-r--r-- | media/libjpeg/jdapistd.c | 194 |
1 files changed, 130 insertions, 64 deletions
diff --git a/media/libjpeg/jdapistd.c b/media/libjpeg/jdapistd.c index 37afc8448b..8827d8abf5 100644 --- a/media/libjpeg/jdapistd.c +++ b/media/libjpeg/jdapistd.c @@ -4,7 +4,7 @@ * 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-2016, D. R. Commander. + * Copyright (C) 2010, 2015-2020, 2022, D. R. Commander. * Copyright (C) 2015, Google, Inc. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -21,11 +21,13 @@ #include "jinclude.h" #include "jdmainct.h" #include "jdcoefct.h" +#include "jdmaster.h" +#include "jdmerge.h" #include "jdsample.h" #include "jmemsys.h" /* Forward declarations */ -LOCAL(boolean) output_pass_setup (j_decompress_ptr cinfo); +LOCAL(boolean) output_pass_setup(j_decompress_ptr cinfo); /* @@ -40,7 +42,7 @@ LOCAL(boolean) output_pass_setup (j_decompress_ptr cinfo); */ GLOBAL(boolean) -jpeg_start_decompress (j_decompress_ptr cinfo) +jpeg_start_decompress(j_decompress_ptr cinfo) { if (cinfo->global_state == DSTATE_READY) { /* First call: initialize master control, select active modules */ @@ -60,7 +62,7 @@ jpeg_start_decompress (j_decompress_ptr cinfo) int retcode; /* Call progress monitor hook if present */ if (cinfo->progress != NULL) - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo); /* Absorb some more input */ retcode = (*cinfo->inputctl->consume_input) (cinfo); if (retcode == JPEG_SUSPENDED) @@ -72,7 +74,7 @@ jpeg_start_decompress (j_decompress_ptr cinfo) (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; + cinfo->progress->pass_limit += (long)cinfo->total_iMCU_rows; } } } @@ -97,7 +99,7 @@ jpeg_start_decompress (j_decompress_ptr cinfo) */ LOCAL(boolean) -output_pass_setup (j_decompress_ptr cinfo) +output_pass_setup(j_decompress_ptr cinfo) { if (cinfo->global_state != DSTATE_PRESCAN) { /* First call: do pass setup */ @@ -113,14 +115,14 @@ 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->main->process_data) (cinfo, (JSAMPARRAY)NULL, + &cinfo->output_scanline, (JDIMENSION)0); if (cinfo->output_scanline == last_scanline) return FALSE; /* No progress made, must suspend */ } @@ -150,13 +152,14 @@ output_pass_setup (j_decompress_ptr cinfo) */ GLOBAL(void) -jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset, - JDIMENSION *width) +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; + my_master_ptr master = (my_master_ptr)cinfo->master; if (cinfo->global_state != DSTATE_SCANNING || cinfo->output_scanline != 0) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); @@ -190,7 +193,10 @@ jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset, * 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; + if (cinfo->comps_in_scan == 1 && cinfo->num_components == 1) + align = cinfo->_min_DCT_scaled_size; + else + align = cinfo->_min_DCT_scaled_size * cinfo->max_h_samp_factor; /* Adjust xoffset to the nearest iMCU boundary <= the requested value */ input_xoffset = *xoffset; @@ -203,24 +209,31 @@ jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset, */ *width = *width + input_xoffset - *xoffset; cinfo->output_width = *width; + if (master->using_merged_upsample && cinfo->max_v_samp_factor == 2) { + my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; + upsample->out_row_width = + cinfo->output_width * cinfo->out_color_components; + } /* 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->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; + (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++) { + int hsf = (cinfo->comps_in_scan == 1 && cinfo->num_components == 1) ? + 1 : compptr->h_samp_factor; + /* 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); + (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; @@ -228,12 +241,10 @@ jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset, * values will be used in multi-scan decompressions. */ cinfo->master->first_MCU_col[ci] = - (JDIMENSION) (long) (*xoffset * compptr->h_samp_factor) / - (long) align; + (JDIMENSION)(long)(*xoffset * hsf) / (long)align; cinfo->master->last_MCU_col[ci] = - (JDIMENSION) jdiv_round_up((long) ((*xoffset + cinfo->output_width) * - compptr->h_samp_factor), - (long) align) - 1; + (JDIMENSION)jdiv_round_up((long)((*xoffset + cinfo->output_width) * hsf), + (long)align) - 1; } if (reinit_upsampler) { @@ -258,8 +269,8 @@ jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset, */ GLOBAL(JDIMENSION) -jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, - JDIMENSION max_lines) +jpeg_read_scanlines(j_decompress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION max_lines) { JDIMENSION row_ctr; @@ -272,9 +283,9 @@ jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, /* 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 */ @@ -287,8 +298,16 @@ 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) +noop_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, + JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +{ +} + + +/* Dummy quantize function used by jpeg_skip_scanlines() */ +LOCAL(void) +noop_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) { } @@ -302,20 +321,46 @@ noop_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ LOCAL(void) -read_and_discard_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines) +read_and_discard_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) { JDIMENSION n; + my_master_ptr master = (my_master_ptr)cinfo->master; + JSAMPLE dummy_sample[1] = { 0 }; + JSAMPROW dummy_row = dummy_sample; + JSAMPARRAY scanlines = NULL; void (*color_convert) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, - int num_rows); + int num_rows) = NULL; + void (*color_quantize) (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) = NULL; + + if (cinfo->cconvert && cinfo->cconvert->color_convert) { + color_convert = cinfo->cconvert->color_convert; + cinfo->cconvert->color_convert = noop_convert; + /* This just prevents UBSan from complaining about adding 0 to a NULL + * pointer. The pointer isn't actually used. + */ + scanlines = &dummy_row; + } + + if (cinfo->cquantize && cinfo->cquantize->color_quantize) { + color_quantize = cinfo->cquantize->color_quantize; + cinfo->cquantize->color_quantize = noop_quantize; + } - color_convert = cinfo->cconvert->color_convert; - cinfo->cconvert->color_convert = noop_convert; + if (master->using_merged_upsample && cinfo->max_v_samp_factor == 2) { + my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; + scanlines = &upsample->spare_row; + } for (n = 0; n < num_lines; n++) - jpeg_read_scanlines(cinfo, NULL, 1); + jpeg_read_scanlines(cinfo, scanlines, 1); - cinfo->cconvert->color_convert = color_convert; + if (color_convert) + cinfo->cconvert->color_convert = color_convert; + + if (color_quantize) + cinfo->cquantize->color_quantize = color_quantize; } @@ -325,10 +370,16 @@ read_and_discard_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines) */ LOCAL(void) -increment_simple_rowgroup_ctr (j_decompress_ptr cinfo, JDIMENSION rows) +increment_simple_rowgroup_ctr(j_decompress_ptr cinfo, JDIMENSION rows) { JDIMENSION rows_left; - my_main_ptr main_ptr = (my_main_ptr) cinfo->main; + my_main_ptr main_ptr = (my_main_ptr)cinfo->main; + my_master_ptr master = (my_master_ptr)cinfo->master; + + if (master->using_merged_upsample && cinfo->max_v_samp_factor == 2) { + read_and_discard_scanlines(cinfo, rows); + return; + } /* Increment the counter to the next row group after the skipped rows. */ main_ptr->rowgroup_ctr += rows / cinfo->max_v_samp_factor; @@ -354,23 +405,31 @@ increment_simple_rowgroup_ctr (j_decompress_ptr cinfo, JDIMENSION rows) */ GLOBAL(JDIMENSION) -jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines) +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; + my_main_ptr main_ptr = (my_main_ptr)cinfo->main; + my_coef_ptr coef = (my_coef_ptr)cinfo->coef; + my_master_ptr master = (my_master_ptr)cinfo->master; + 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; + /* Two-pass color quantization is not supported. */ + if (cinfo->quantize_colors && cinfo->two_pass_quantize) + ERREXIT(cinfo, JERR_NOTIMPL); + 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) { + num_lines = cinfo->output_height - cinfo->output_scanline; cinfo->output_scanline = cinfo->output_height; - return cinfo->output_height - cinfo->output_scanline; + (*cinfo->inputctl->finish_input_pass) (cinfo); + cinfo->inputctl->eoi_reached = TRUE; + return num_lines; } if (num_lines == 0) @@ -419,8 +478,10 @@ jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines) 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; + if (!master->using_merged_upsample) { + 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. */ @@ -432,8 +493,10 @@ jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines) 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; + if (!master->using_merged_upsample) { + upsample->next_row_out = cinfo->max_v_samp_factor; + upsample->rows_to_go = cinfo->output_height - cinfo->output_scanline; + } } } @@ -458,7 +521,7 @@ jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines) 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; + 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. */ @@ -468,7 +531,8 @@ jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines) 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; + if (!master->using_merged_upsample) + upsample->rows_to_go = cinfo->output_height - cinfo->output_scanline; return num_lines; } @@ -480,6 +544,8 @@ jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines) * decoded coefficients. This is ~5% faster for large subsets, but * it's tough to tell a difference for smaller images. */ + if (!cinfo->entropy->insufficient_data) + cinfo->master->last_good_iMCU_row = cinfo->input_iMCU_row; (*cinfo->entropy->decode_mcu) (cinfo, NULL); } } @@ -509,7 +575,8 @@ jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines) * 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; + if (!master->using_merged_upsample) + upsample->rows_to_go = cinfo->output_height - cinfo->output_scanline; /* Always skip the requested number of lines. */ return num_lines; @@ -521,8 +588,8 @@ 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) +jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION max_lines) { JDIMENSION lines_per_iMCU_row; @@ -535,9 +602,9 @@ jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, /* 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); } /* Verify that at least one iMCU row can be returned. */ @@ -546,7 +613,7 @@ jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, ERREXIT(cinfo, JERR_BUFFER_SIZE); /* Decompress directly into user's buffer. */ - if (! (*cinfo->coef->decompress_data) (cinfo, data)) + if (!(*cinfo->coef->decompress_data) (cinfo, data)) return 0; /* suspension forced, can do nothing more */ /* OK, we processed one iMCU row. */ @@ -564,7 +631,7 @@ jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, */ GLOBAL(boolean) -jpeg_start_output (j_decompress_ptr cinfo, int scan_number) +jpeg_start_output(j_decompress_ptr cinfo, int scan_number) { if (cinfo->global_state != DSTATE_BUFIMAGE && cinfo->global_state != DSTATE_PRESCAN) @@ -572,8 +639,7 @@ jpeg_start_output (j_decompress_ptr cinfo, int scan_number) /* Limit scan number to valid range */ if (scan_number <= 0) scan_number = 1; - if (cinfo->inputctl->eoi_reached && - scan_number > cinfo->input_scan_number) + if (cinfo->inputctl->eoi_reached && scan_number > cinfo->input_scan_number) scan_number = cinfo->input_scan_number; cinfo->output_scan_number = scan_number; /* Perform any dummy output passes, and set up for the real pass */ @@ -589,7 +655,7 @@ jpeg_start_output (j_decompress_ptr cinfo, int scan_number) */ GLOBAL(boolean) -jpeg_finish_output (j_decompress_ptr cinfo) +jpeg_finish_output(j_decompress_ptr cinfo) { if ((cinfo->global_state == DSTATE_SCANNING || cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { @@ -603,7 +669,7 @@ 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 */ } |