diff options
Diffstat (limited to 'src/3rdparty/libjpeg/src/jcmaster.c')
-rw-r--r-- | src/3rdparty/libjpeg/src/jcmaster.c | 312 |
1 files changed, 231 insertions, 81 deletions
diff --git a/src/3rdparty/libjpeg/src/jcmaster.c b/src/3rdparty/libjpeg/src/jcmaster.c index c2b2600031..161019763d 100644 --- a/src/3rdparty/libjpeg/src/jcmaster.c +++ b/src/3rdparty/libjpeg/src/jcmaster.c @@ -4,8 +4,10 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2003-2010 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2010, 2016, 2018, D. R. Commander. + * Copyright (C) 2010, 2016, 2018, 2022-2024, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -18,40 +20,8 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jpegcomp.h" -#include "jconfigint.h" - - -/* Private state */ - -typedef enum { - main_pass, /* input data, also do first output step */ - huff_opt_pass, /* Huffman code optimization pass */ - output_pass /* data output pass */ -} c_pass_type; - -typedef struct { - struct jpeg_comp_master pub; /* public fields */ - - c_pass_type pass_type; /* the type of the current pass */ - - int pass_number; /* # of passes completed */ - int total_passes; /* total # of passes needed */ - - int scan_number; /* current index in scan_info[] */ - - /* - * This is here so we can add libjpeg-turbo version/build information to the - * global string table without introducing a new global symbol. Adding this - * information to the global string table allows one to examine a binary - * object and determine which version of libjpeg-turbo it was built from or - * linked against. - */ - const char *jpeg_version; - -} my_comp_master; - -typedef my_comp_master *my_master_ptr; +#include "jpegapicomp.h" +#include "jcmaster.h" /* @@ -69,15 +39,124 @@ GLOBAL(void) jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo) /* Do computations that are needed before master selection phase */ { + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + /* Hardwire it to "no scaling" */ cinfo->jpeg_width = cinfo->image_width; cinfo->jpeg_height = cinfo->image_height; - cinfo->min_DCT_h_scaled_size = DCTSIZE; - cinfo->min_DCT_v_scaled_size = DCTSIZE; + cinfo->min_DCT_h_scaled_size = data_unit; + cinfo->min_DCT_v_scaled_size = data_unit; } #endif +LOCAL(boolean) +using_std_huff_tables(j_compress_ptr cinfo) +{ + int i; + + static const UINT8 bits_dc_luminance[17] = { + /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 + }; + static const UINT8 val_dc_luminance[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 + }; + + static const UINT8 bits_dc_chrominance[17] = { + /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 + }; + static const UINT8 val_dc_chrominance[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 + }; + + static const UINT8 bits_ac_luminance[17] = { + /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d + }; + static const UINT8 val_ac_luminance[] = { + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa + }; + + static const UINT8 bits_ac_chrominance[17] = { + /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 + }; + static const UINT8 val_ac_chrominance[] = { + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa + }; + + if (cinfo->dc_huff_tbl_ptrs[0] == NULL || + cinfo->ac_huff_tbl_ptrs[0] == NULL || + cinfo->dc_huff_tbl_ptrs[1] == NULL || + cinfo->ac_huff_tbl_ptrs[1] == NULL) + return FALSE; + + for (i = 2; i < NUM_HUFF_TBLS; i++) { + if (cinfo->dc_huff_tbl_ptrs[i] != NULL || + cinfo->ac_huff_tbl_ptrs[i] != NULL) + return FALSE; + } + + if (memcmp(cinfo->dc_huff_tbl_ptrs[0]->bits, bits_dc_luminance, + sizeof(bits_dc_luminance)) || + memcmp(cinfo->dc_huff_tbl_ptrs[0]->huffval, val_dc_luminance, + sizeof(val_dc_luminance)) || + memcmp(cinfo->ac_huff_tbl_ptrs[0]->bits, bits_ac_luminance, + sizeof(bits_ac_luminance)) || + memcmp(cinfo->ac_huff_tbl_ptrs[0]->huffval, val_ac_luminance, + sizeof(val_ac_luminance)) || + memcmp(cinfo->dc_huff_tbl_ptrs[1]->bits, bits_dc_chrominance, + sizeof(bits_dc_chrominance)) || + memcmp(cinfo->dc_huff_tbl_ptrs[1]->huffval, val_dc_chrominance, + sizeof(val_dc_chrominance)) || + memcmp(cinfo->ac_huff_tbl_ptrs[1]->bits, bits_ac_chrominance, + sizeof(bits_ac_chrominance)) || + memcmp(cinfo->ac_huff_tbl_ptrs[1]->huffval, val_ac_chrominance, + sizeof(val_ac_chrominance))) + return FALSE; + + return TRUE; +} + + LOCAL(void) initial_setup(j_compress_ptr cinfo, boolean transcode_only) /* Do computations that are needed before master selection phase */ @@ -86,6 +165,7 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only) jpeg_component_info *compptr; long samplesperrow; JDIMENSION jd_samplesperrow; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; #if JPEG_LIB_VERSION >= 70 #if JPEG_LIB_VERSION >= 80 @@ -110,8 +190,12 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only) if ((long)jd_samplesperrow != samplesperrow) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - /* For now, precision must match compiled-in value... */ - if (cinfo->data_precision != BITS_IN_JSAMPLE) +#ifdef C_LOSSLESS_SUPPORTED + if (cinfo->data_precision != 8 && cinfo->data_precision != 12 && + cinfo->data_precision != 16) +#else + if (cinfo->data_precision != 8 && cinfo->data_precision != 12) +#endif ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ @@ -142,17 +226,17 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only) compptr->component_index = ci; /* For compression, we never do DCT scaling. */ #if JPEG_LIB_VERSION >= 70 - compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = DCTSIZE; + compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = data_unit; #else - compptr->DCT_scaled_size = DCTSIZE; + compptr->DCT_scaled_size = data_unit; #endif - /* Size in DCT blocks */ + /* Size in data units */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor, - (long)(cinfo->max_h_samp_factor * DCTSIZE)); + (long)(cinfo->max_h_samp_factor * data_unit)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_height * (long)compptr->v_samp_factor, - (long)(cinfo->max_v_samp_factor * DCTSIZE)); + (long)(cinfo->max_v_samp_factor * data_unit)); /* Size in samples */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor, @@ -165,15 +249,19 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only) } /* Compute number of fully interleaved MCU rows (number of times that - * main controller will call coefficient controller). + * main controller will call coefficient or difference controller). */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_height, - (long)(cinfo->max_v_samp_factor * DCTSIZE)); + (long)(cinfo->max_v_samp_factor * data_unit)); } -#ifdef C_MULTISCAN_FILES_SUPPORTED +#if defined(C_MULTISCAN_FILES_SUPPORTED) || defined(C_LOSSLESS_SUPPORTED) +#define NEED_SCAN_SCRIPT +#endif + +#ifdef NEED_SCAN_SCRIPT LOCAL(void) validate_script(j_compress_ptr cinfo) @@ -194,13 +282,29 @@ validate_script(j_compress_ptr cinfo) if (cinfo->num_scans <= 0) ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); +#ifndef C_MULTISCAN_FILES_SUPPORTED + if (cinfo->num_scans > 1) + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + + scanptr = cinfo->scan_info; + if (scanptr->Ss != 0 && scanptr->Se == 0) { +#ifdef C_LOSSLESS_SUPPORTED + cinfo->master->lossless = TRUE; + cinfo->progressive_mode = FALSE; + for (ci = 0; ci < cinfo->num_components; ci++) + component_sent[ci] = FALSE; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; * for progressive JPEG, no scan can have this. */ - scanptr = cinfo->scan_info; - if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2 - 1) { + else if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2 - 1) { #ifdef C_PROGRESSIVE_SUPPORTED cinfo->progressive_mode = TRUE; + cinfo->master->lossless = FALSE; last_bitpos_ptr = &last_bitpos[0][0]; for (ci = 0; ci < cinfo->num_components; ci++) for (coefi = 0; coefi < DCTSIZE2; coefi++) @@ -209,7 +313,7 @@ validate_script(j_compress_ptr cinfo) ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { - cinfo->progressive_mode = FALSE; + cinfo->progressive_mode = cinfo->master->lossless = FALSE; for (ci = 0; ci < cinfo->num_components; ci++) component_sent[ci] = FALSE; } @@ -241,13 +345,10 @@ validate_script(j_compress_ptr cinfo) * out-of-range reconstructed DC values during the first DC scan, * which might cause problems for some decoders. */ -#if BITS_IN_JSAMPLE == 8 -#define MAX_AH_AL 10 -#else -#define MAX_AH_AL 13 -#endif + int max_Ah_Al = cinfo->data_precision == 12 ? 13 : 10; + if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || - Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) + Ah < 0 || Ah > max_Ah_Al || Al < 0 || Al > max_Ah_Al) ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); if (Ss == 0) { if (Se != 0) /* DC and AC together not OK */ @@ -275,9 +376,25 @@ validate_script(j_compress_ptr cinfo) } #endif } else { - /* For sequential JPEG, all progression parameters must be these: */ - if (Ss != 0 || Se != DCTSIZE2 - 1 || Ah != 0 || Al != 0) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); +#ifdef C_LOSSLESS_SUPPORTED + if (cinfo->master->lossless) { + /* The JPEG spec simply gives the range 0..15 for Al (Pt), but that + * seems wrong: the upper bound ought to depend on data precision. + * Perhaps they really meant 0..N-1 for N-bit precision, which is what + * we allow here. Values greater than or equal to the data precision + * will result in a blank image. + */ + if (Ss < 1 || Ss > 7 || /* predictor selection value */ + Se != 0 || Ah != 0 || + Al < 0 || Al >= cinfo->data_precision) /* point transform */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else +#endif + { + /* For sequential JPEG, all progression parameters must be these: */ + if (Ss != 0 || Se != DCTSIZE2 - 1 || Ah != 0 || Al != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } /* Make sure components are not sent twice */ for (ci = 0; ci < ncomps; ci++) { thisi = scanptr->component_index[ci]; @@ -309,7 +426,7 @@ validate_script(j_compress_ptr cinfo) } } -#endif /* C_MULTISCAN_FILES_SUPPORTED */ +#endif /* NEED_SCAN_SCRIPT */ LOCAL(void) @@ -318,7 +435,7 @@ select_scan_parameters(j_compress_ptr cinfo) { int ci; -#ifdef C_MULTISCAN_FILES_SUPPORTED +#ifdef NEED_SCAN_SCRIPT if (cinfo->scan_info != NULL) { /* Prepare for current scan --- the script is already validated */ my_master_ptr master = (my_master_ptr)cinfo->master; @@ -344,10 +461,12 @@ select_scan_parameters(j_compress_ptr cinfo) for (ci = 0; ci < cinfo->num_components; ci++) { cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; } - cinfo->Ss = 0; - cinfo->Se = DCTSIZE2 - 1; - cinfo->Ah = 0; - cinfo->Al = 0; + if (!cinfo->master->lossless) { + cinfo->Ss = 0; + cinfo->Se = DCTSIZE2 - 1; + cinfo->Ah = 0; + cinfo->Al = 0; + } } } @@ -359,6 +478,7 @@ per_scan_setup(j_compress_ptr cinfo) { int ci, mcublks, tmp; jpeg_component_info *compptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; if (cinfo->comps_in_scan == 1) { @@ -373,7 +493,7 @@ per_scan_setup(j_compress_ptr cinfo) compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; - compptr->MCU_sample_width = DCTSIZE; + compptr->MCU_sample_width = data_unit; compptr->last_col_width = 1; /* For noninterleaved scans, it is convenient to define last_row_height * as the number of block rows present in the last iMCU row. @@ -396,10 +516,10 @@ per_scan_setup(j_compress_ptr cinfo) /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_width, - (long)(cinfo->max_h_samp_factor * DCTSIZE)); + (long)(cinfo->max_h_samp_factor * data_unit)); cinfo->MCU_rows_in_scan = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_height, - (long)(cinfo->max_v_samp_factor * DCTSIZE)); + (long)(cinfo->max_v_samp_factor * data_unit)); cinfo->blocks_in_MCU = 0; @@ -409,7 +529,7 @@ per_scan_setup(j_compress_ptr cinfo) compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; - compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; + compptr->MCU_sample_width = compptr->MCU_width * data_unit; /* Figure number of non-dummy blocks in last MCU column & row */ tmp = (int)(compptr->width_in_blocks % compptr->MCU_width); if (tmp == 0) tmp = compptr->MCU_width; @@ -481,7 +601,8 @@ prepare_for_pass(j_compress_ptr cinfo) /* Do Huffman optimization for a scan after the first one. */ select_scan_parameters(cinfo); per_scan_setup(cinfo); - if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) { + if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code || + cinfo->master->lossless) { (*cinfo->entropy->start_pass) (cinfo, TRUE); (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); master->pub.call_pass_startup = FALSE; @@ -590,22 +711,17 @@ finish_pass_master(j_compress_ptr cinfo) GLOBAL(void) jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only) { - my_master_ptr master; + my_master_ptr master = (my_master_ptr)cinfo->master; + boolean empty_huff_tables = TRUE; + int i; - master = (my_master_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - sizeof(my_comp_master)); - cinfo->master = (struct jpeg_comp_master *)master; master->pub.prepare_for_pass = prepare_for_pass; master->pub.pass_startup = pass_startup; master->pub.finish_pass = finish_pass_master; master->pub.is_last_pass = FALSE; - /* Validate parameters, determine derived values */ - initial_setup(cinfo, transcode_only); - if (cinfo->scan_info != NULL) { -#ifdef C_MULTISCAN_FILES_SUPPORTED +#ifdef NEED_SCAN_SCRIPT validate_script(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); @@ -615,8 +731,42 @@ jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only) cinfo->num_scans = 1; } - if (cinfo->progressive_mode && !cinfo->arith_code) /* TEMPORARY HACK ??? */ - cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */ + /* Disable smoothing and subsampling in lossless mode, since those are lossy + * algorithms. Set the JPEG colorspace to the input colorspace. Disable raw + * (downsampled) data input, because it isn't particularly useful without + * subsampling and has not been tested in lossless mode. + */ + if (cinfo->master->lossless) { + int ci; + jpeg_component_info *compptr; + + cinfo->raw_data_in = FALSE; + cinfo->smoothing_factor = 0; + jpeg_default_colorspace(cinfo); + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) + compptr->h_samp_factor = compptr->v_samp_factor = 1; + } + + /* Validate parameters, determine derived values */ + initial_setup(cinfo, transcode_only); + + if (cinfo->master->lossless || /* TEMPORARY HACK ??? */ + (cinfo->progressive_mode && !cinfo->arith_code)) + cinfo->optimize_coding = TRUE; /* assume default tables no good for + progressive mode or lossless mode */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if (cinfo->dc_huff_tbl_ptrs[i] != NULL || + cinfo->ac_huff_tbl_ptrs[i] != NULL) { + empty_huff_tables = FALSE; + break; + } + } + if (cinfo->data_precision == 12 && !cinfo->arith_code && + !cinfo->optimize_coding && + (empty_huff_tables || using_std_huff_tables(cinfo))) + cinfo->optimize_coding = TRUE; /* assume default tables no good for 12-bit + data precision */ /* Initialize my private state */ if (transcode_only) { |