Revision control
++ /*
++ * jdapimin.c
++ *
++ * This file was part of the Independent JPEG Group's software:
++ * Copyright (C) 1994-1998, Thomas G. Lane.
++ * Lossless JPEG Modifications:
++ * Copyright (C) 1999, Ken Murchison.
++ * libjpeg-turbo Modifications:
++ * Copyright (C) 2016, 2022, 2024-2025, D. R. Commander.
++ * 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 "minimum" API routines that may be
++ * needed in either the normal full-decompression case or the
++ * transcoding-only case.
++ *
++ * Most of the routines intended to be called directly by an application
++ * are in this file or in jdapistd.c. But also see jcomapi.c for routines
++ * shared by compression and decompression, and jdtrans.c for the transcoding
++ * case.
++ */
++
++ #define JPEG_INTERNALS
++ #include "jinclude.h"
++ #include "jpeglib.h"
++ #include "jdmaster.h"
++ #ifdef WITH_SIMD
++ #include "../simd/jsimdconst.h"
++ #endif
++
++
++ /*
++ * Initialization of a JPEG decompression object.
++ * The error manager must already be set up (in case memory manager fails).
++ */
++
++ GLOBAL(void)
++ jpeg_CreateDecompress(j_decompress_ptr cinfo, int version, size_t structsize)
++ {
++ int i;
++
++ /* Guard against version mismatches between library and caller. */
++ cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
++ if (version != JPEG_LIB_VERSION)
++ ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
++ if (structsize != sizeof(struct jpeg_decompress_struct))
++ ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
++ (int)sizeof(struct jpeg_decompress_struct), (int)structsize);
++
++ /* For debugging purposes, we zero the whole master structure.
++ * But the application has already set the err pointer, and may have set
++ * client_data, so we have to save and restore those fields.
++ * Note: if application hasn't set client_data, tools like Purify may
++ * complain here.
++ */
++ {
++ struct jpeg_error_mgr *err = cinfo->err;
++ void *client_data = cinfo->client_data; /* ignore Purify complaint here */
++ memset(cinfo, 0, sizeof(struct jpeg_decompress_struct));
++ cinfo->err = err;
++ cinfo->client_data = client_data;
++ }
++ cinfo->is_decompressor = TRUE;
++
++ /* Initialize a memory manager instance for this object */
++ jinit_memory_mgr((j_common_ptr)cinfo);
++
++ /* Zero out pointers to permanent structures. */
++ cinfo->progress = NULL;
++ cinfo->src = NULL;
++
++ for (i = 0; i < NUM_QUANT_TBLS; i++)
++ cinfo->quant_tbl_ptrs[i] = NULL;
++
++ for (i = 0; i < NUM_HUFF_TBLS; i++) {
++ cinfo->dc_huff_tbl_ptrs[i] = NULL;
++ cinfo->ac_huff_tbl_ptrs[i] = NULL;
++ }
++
++ /* Initialize marker processor so application can override methods
++ * for COM, APPn markers before calling jpeg_read_header.
++ */
++ cinfo->marker_list = NULL;
++ jinit_marker_reader(cinfo);
++
++ /* And initialize the overall input controller. */
++ jinit_input_controller(cinfo);
++
++ cinfo->data_precision = BITS_IN_JSAMPLE;
++
++ /* OK, I'm ready */
++ cinfo->global_state = DSTATE_START;
++
++ /* The master struct is used to store extension parameters, so we allocate it
++ * here.
++ */
++ cinfo->master = (struct jpeg_decomp_master *)
++ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
++ sizeof(my_decomp_master));
++ memset(cinfo->master, 0, sizeof(my_decomp_master));
++ #ifdef WITH_SIMD
++ cinfo->master->simd_support = JSIMD_UNDEFINED;
++ cinfo->master->simd_huffman = 1;
++ #endif
++ }
++
++
++ /*
++ * Destruction of a JPEG decompression object
++ */
++
++ GLOBAL(void)
++ jpeg_destroy_decompress(j_decompress_ptr cinfo)
++ {
++ jpeg_destroy((j_common_ptr)cinfo); /* use common routine */
++ }
++
++
++ /*
++ * Abort processing of a JPEG decompression operation,
++ * but don't destroy the object itself.
++ */
++
++ GLOBAL(void)
++ jpeg_abort_decompress(j_decompress_ptr cinfo)
++ {
++ jpeg_abort((j_common_ptr)cinfo); /* use common routine */
++ }
++
++
++ /*
++ * Set default decompression parameters.
++ */
++
++ LOCAL(void)
++ default_decompress_parms(j_decompress_ptr cinfo)
++ {
++ /* Guess the input colorspace, and set output colorspace accordingly. */
++ /* (Wish JPEG committee had provided a real way to specify this...) */
++ /* Note application may override our guesses. */
++ switch (cinfo->num_components) {
++ case 1:
++ cinfo->jpeg_color_space = JCS_GRAYSCALE;
++ cinfo->out_color_space = JCS_GRAYSCALE;
++ break;
++
++ case 3:
++ if (cinfo->saw_JFIF_marker) {
++ cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */
++ } else if (cinfo->saw_Adobe_marker) {
++ switch (cinfo->Adobe_transform) {
++ case 0:
++ cinfo->jpeg_color_space = JCS_RGB;
++ break;
++ case 1:
++ cinfo->jpeg_color_space = JCS_YCbCr;
++ break;
++ default:
++ WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
++ cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
++ break;
++ }
++ } else {
++ /* Saw no special markers, try to guess from the component IDs */
++ int cid0 = cinfo->comp_info[0].component_id;
++ int cid1 = cinfo->comp_info[1].component_id;
++ int cid2 = cinfo->comp_info[2].component_id;
++
++ if (cid0 == 1 && cid1 == 2 && cid2 == 3) {
++ #ifdef D_LOSSLESS_SUPPORTED
++ if (cinfo->master->lossless)
++ cinfo->jpeg_color_space = JCS_RGB; /* assume RGB w/out marker */
++ else
++ #endif
++ cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */
++ } else if (cid0 == 82 && cid1 == 71 && cid2 == 66)
++ cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
++ else {
++ TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2);
++ #ifdef D_LOSSLESS_SUPPORTED
++ if (cinfo->master->lossless)
++ cinfo->jpeg_color_space = JCS_RGB; /* assume it's RGB */
++ else
++ #endif
++ cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
++ }
++ }
++ /* Always guess RGB is proper output colorspace. */
++ cinfo->out_color_space = JCS_RGB;
++ break;
++
++ case 4:
++ if (cinfo->saw_Adobe_marker) {
++ switch (cinfo->Adobe_transform) {
++ case 0:
++ cinfo->jpeg_color_space = JCS_CMYK;
++ break;
++ case 2:
++ cinfo->jpeg_color_space = JCS_YCCK;
++ break;
++ default:
++ WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
++ cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */
++ break;
++ }
++ } else {
++ /* No special markers, assume straight CMYK. */
++ cinfo->jpeg_color_space = JCS_CMYK;
++ }
++ cinfo->out_color_space = JCS_CMYK;
++ break;
++
++ default:
++ cinfo->jpeg_color_space = JCS_UNKNOWN;
++ cinfo->out_color_space = JCS_UNKNOWN;
++ break;
++ }
++
++ /* Set defaults for other decompression parameters. */
++ cinfo->scale_num = 1; /* 1:1 scaling */
++ cinfo->scale_denom = 1;
++ cinfo->output_gamma = 1.0;
++ cinfo->buffered_image = FALSE;
++ cinfo->raw_data_out = FALSE;
++ cinfo->dct_method = JDCT_DEFAULT;
++ cinfo->do_fancy_upsampling = TRUE;
++ cinfo->do_block_smoothing = TRUE;
++ cinfo->quantize_colors = FALSE;
++ /* We set these in case application only sets quantize_colors. */
++ cinfo->dither_mode = JDITHER_FS;
++ #ifdef QUANT_2PASS_SUPPORTED
++ cinfo->two_pass_quantize = TRUE;
++ #else
++ cinfo->two_pass_quantize = FALSE;
++ #endif
++ cinfo->desired_number_of_colors = 256;
++ cinfo->colormap = NULL;
++ /* Initialize for no mode change in buffered-image mode. */
++ cinfo->enable_1pass_quant = FALSE;
++ cinfo->enable_external_quant = FALSE;
++ cinfo->enable_2pass_quant = FALSE;
++ }
++
++
++ /*
++ * Decompression startup: read start of JPEG datastream to see what's there.
++ * Need only initialize JPEG object and supply a data source before calling.
++ *
++ * This routine will read as far as the first SOS marker (ie, actual start of
++ * compressed data), and will save all tables and parameters in the JPEG
++ * object. It will also initialize the decompression parameters to default
++ * values, and finally return JPEG_HEADER_OK. On return, the application may
++ * adjust the decompression parameters and then call jpeg_start_decompress.
++ * (Or, if the application only wanted to determine the image parameters,
++ * the data need not be decompressed. In that case, call jpeg_abort or
++ * jpeg_destroy to release any temporary space.)
++ * If an abbreviated (tables only) datastream is presented, the routine will
++ * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then
++ * re-use the JPEG object to read the abbreviated image datastream(s).
++ * It is unnecessary (but OK) to call jpeg_abort in this case.
++ * The JPEG_SUSPENDED return code only occurs if the data source module
++ * requests suspension of the decompressor. In this case the application
++ * should load more source data and then re-call jpeg_read_header to resume
++ * processing.
++ * If a non-suspending data source is used and require_image is TRUE, then the
++ * return code need not be inspected since only JPEG_HEADER_OK is possible.
++ *
++ * This routine is now just a front end to jpeg_consume_input, with some
++ * extra error checking.
++ */
++
++ GLOBAL(int)
++ jpeg_read_header(j_decompress_ptr cinfo, boolean require_image)
++ {
++ int retcode;
++
++ if (cinfo->global_state != DSTATE_START &&
++ cinfo->global_state != DSTATE_INHEADER)
++ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
++
++ retcode = jpeg_consume_input(cinfo);
++
++ switch (retcode) {
++ case JPEG_REACHED_SOS:
++ retcode = JPEG_HEADER_OK;
++ break;
++ case JPEG_REACHED_EOI:
++ if (require_image) /* Complain if application wanted an image */
++ ERREXIT(cinfo, JERR_NO_IMAGE);
++ /* Reset to start state; it would be safer to require the application to
++ * call jpeg_abort, but we can't change it now for compatibility reasons.
++ * A side effect is to free any temporary memory (there shouldn't be any).
++ */
++ jpeg_abort((j_common_ptr)cinfo); /* sets state = DSTATE_START */
++ retcode = JPEG_HEADER_TABLES_ONLY;
++ break;
++ case JPEG_SUSPENDED:
++ /* no work */
++ break;
++ }
++
++ return retcode;
++ }
++
++
++ /*
++ * Consume data in advance of what the decompressor requires.
++ * This can be called at any time once the decompressor object has
++ * been created and a data source has been set up.
++ *
++ * This routine is essentially a state machine that handles a couple
++ * of critical state-transition actions, namely initial setup and
++ * transition from header scanning to ready-for-start_decompress.
++ * All the actual input is done via the input controller's consume_input
++ * method.
++ */
++
++ GLOBAL(int)
++ jpeg_consume_input(j_decompress_ptr cinfo)
++ {
++ int retcode = JPEG_SUSPENDED;
++
++ /* NB: every possible DSTATE value should be listed in this switch */
++ switch (cinfo->global_state) {
++ case DSTATE_START:
++ /* Start-of-datastream actions: reset appropriate modules */
++ (*cinfo->inputctl->reset_input_controller) (cinfo);
++ /* Initialize application's data source module */
++ (*cinfo->src->init_source) (cinfo);
++ cinfo->global_state = DSTATE_INHEADER;
++ FALLTHROUGH /*FALLTHROUGH*/
++ case DSTATE_INHEADER:
++ retcode = (*cinfo->inputctl->consume_input) (cinfo);
++ if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */
++ /* Set up default parameters based on header data */
++ default_decompress_parms(cinfo);
++ /* Set global state: ready for start_decompress */
++ cinfo->global_state = DSTATE_READY;
++ }
++ break;
++ case DSTATE_READY:
++ /* Can't advance past first SOS until start_decompress is called */
++ retcode = JPEG_REACHED_SOS;
++ break;
++ case DSTATE_PRELOAD:
++ case DSTATE_PRESCAN:
++ case DSTATE_SCANNING:
++ case DSTATE_RAW_OK:
++ case DSTATE_BUFIMAGE:
++ case DSTATE_BUFPOST:
++ case DSTATE_STOPPING:
++ retcode = (*cinfo->inputctl->consume_input) (cinfo);
++ break;
++ default:
++ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
++ }
++ return retcode;
++ }
++
++
++ /*
++ * Have we finished reading the input file?
++ */
++
++ GLOBAL(boolean)
++ jpeg_input_complete(j_decompress_ptr cinfo)
++ {
++ /* Check for valid jpeg object */
++ if (cinfo->global_state < DSTATE_START ||
++ cinfo->global_state > DSTATE_STOPPING)
++ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
++ return cinfo->inputctl->eoi_reached;
++ }
++
++
++ /*
++ * Is there more than one scan?
++ */
++
++ GLOBAL(boolean)
++ jpeg_has_multiple_scans(j_decompress_ptr cinfo)
++ {
++ /* Only valid after jpeg_read_header completes */
++ if (cinfo->global_state < DSTATE_READY ||
++ cinfo->global_state > DSTATE_STOPPING)
++ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
++ return cinfo->inputctl->has_multiple_scans;
++ }
++
++
++ /*
++ * Finish JPEG decompression.
++ *
++ * This will normally just verify the file trailer and release temp storage.
++ *
++ * Returns FALSE if suspended. The return value need be inspected only if
++ * a suspending data source is used.
++ */
++
++ GLOBAL(boolean)
++ jpeg_finish_decompress(j_decompress_ptr cinfo)
++ {
++ if ((cinfo->global_state == DSTATE_SCANNING ||
++ cinfo->global_state == DSTATE_RAW_OK) && !cinfo->buffered_image) {
++ /* Terminate final pass of non-buffered mode */
++ if (cinfo->output_scanline < cinfo->output_height)
++ ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
++ (*cinfo->master->finish_output_pass) (cinfo);
++ cinfo->global_state = DSTATE_STOPPING;
++ } else if (cinfo->global_state == DSTATE_BUFIMAGE) {
++ /* Finishing after a buffered-image operation */
++ cinfo->global_state = DSTATE_STOPPING;
++ } else if (cinfo->global_state != DSTATE_STOPPING) {
++ /* STOPPING = repeat call after a suspension, anything else is error */
++ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
++ }
++ /* Read until EOI */
++ while (!cinfo->inputctl->eoi_reached) {
++ if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
++ return FALSE; /* Suspend, come back later */
++ }
++ /* Do final cleanup */
++ (*cinfo->src->term_source) (cinfo);
++ /* We can use jpeg_abort to release memory and reset global_state */
++ jpeg_abort((j_common_ptr)cinfo);
++ return TRUE;
++ }