Path: blob/master/thirdparty/libjpeg-turbo/src/jdmarker.c
9904 views
/*1* jdmarker.c2*3* This file was part of the Independent JPEG Group's software:4* Copyright (C) 1991-1998, Thomas G. Lane.5* Lossless JPEG Modifications:6* Copyright (C) 1999, Ken Murchison.7* libjpeg-turbo Modifications:8* Copyright (C) 2012, 2015, 2022, 2024, D. R. Commander.9* For conditions of distribution and use, see the accompanying README.ijg10* file.11*12* This file contains routines to decode JPEG datastream markers.13* Most of the complexity arises from our desire to support input14* suspension: if not all of the data for a marker is available,15* we must exit back to the application. On resumption, we reprocess16* the marker.17*/1819#define JPEG_INTERNALS20#include "jinclude.h"21#include "jpeglib.h"222324typedef enum { /* JPEG marker codes */25M_SOF0 = 0xc0,26M_SOF1 = 0xc1,27M_SOF2 = 0xc2,28M_SOF3 = 0xc3,2930M_SOF5 = 0xc5,31M_SOF6 = 0xc6,32M_SOF7 = 0xc7,3334M_JPG = 0xc8,35M_SOF9 = 0xc9,36M_SOF10 = 0xca,37M_SOF11 = 0xcb,3839M_SOF13 = 0xcd,40M_SOF14 = 0xce,41M_SOF15 = 0xcf,4243M_DHT = 0xc4,4445M_DAC = 0xcc,4647M_RST0 = 0xd0,48M_RST1 = 0xd1,49M_RST2 = 0xd2,50M_RST3 = 0xd3,51M_RST4 = 0xd4,52M_RST5 = 0xd5,53M_RST6 = 0xd6,54M_RST7 = 0xd7,5556M_SOI = 0xd8,57M_EOI = 0xd9,58M_SOS = 0xda,59M_DQT = 0xdb,60M_DNL = 0xdc,61M_DRI = 0xdd,62M_DHP = 0xde,63M_EXP = 0xdf,6465M_APP0 = 0xe0,66M_APP1 = 0xe1,67M_APP2 = 0xe2,68M_APP3 = 0xe3,69M_APP4 = 0xe4,70M_APP5 = 0xe5,71M_APP6 = 0xe6,72M_APP7 = 0xe7,73M_APP8 = 0xe8,74M_APP9 = 0xe9,75M_APP10 = 0xea,76M_APP11 = 0xeb,77M_APP12 = 0xec,78M_APP13 = 0xed,79M_APP14 = 0xee,80M_APP15 = 0xef,8182M_JPG0 = 0xf0,83M_JPG13 = 0xfd,84M_COM = 0xfe,8586M_TEM = 0x01,8788M_ERROR = 0x10089} JPEG_MARKER;909192/* Private state */9394typedef struct {95struct jpeg_marker_reader pub; /* public fields */9697/* Application-overridable marker processing methods */98jpeg_marker_parser_method process_COM;99jpeg_marker_parser_method process_APPn[16];100101/* Limit on marker data length to save for each marker type */102unsigned int length_limit_COM;103unsigned int length_limit_APPn[16];104105/* Status of COM/APPn marker saving */106jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */107unsigned int bytes_read; /* data bytes read so far in marker */108/* Note: cur_marker is not linked into marker_list until it's all read. */109} my_marker_reader;110111typedef my_marker_reader *my_marker_ptr;112113114/*115* Macros for fetching data from the data source module.116*117* At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect118* the current restart point; we update them only when we have reached a119* suitable place to restart if a suspension occurs.120*/121122/* Declare and initialize local copies of input pointer/count */123#define INPUT_VARS(cinfo) \124struct jpeg_source_mgr *datasrc = (cinfo)->src; \125const JOCTET *next_input_byte = datasrc->next_input_byte; \126size_t bytes_in_buffer = datasrc->bytes_in_buffer127128/* Unload the local copies --- do this only at a restart boundary */129#define INPUT_SYNC(cinfo) \130( datasrc->next_input_byte = next_input_byte, \131datasrc->bytes_in_buffer = bytes_in_buffer )132133/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */134#define INPUT_RELOAD(cinfo) \135( next_input_byte = datasrc->next_input_byte, \136bytes_in_buffer = datasrc->bytes_in_buffer )137138/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available.139* Note we do *not* do INPUT_SYNC before calling fill_input_buffer,140* but we must reload the local copies after a successful fill.141*/142#define MAKE_BYTE_AVAIL(cinfo, action) \143if (bytes_in_buffer == 0) { \144if (!(*datasrc->fill_input_buffer) (cinfo)) \145{ action; } \146INPUT_RELOAD(cinfo); \147}148149/* Read a byte into variable V.150* If must suspend, take the specified action (typically "return FALSE").151*/152#define INPUT_BYTE(cinfo, V, action) \153MAKESTMT( MAKE_BYTE_AVAIL(cinfo, action); \154bytes_in_buffer--; \155V = *next_input_byte++; )156157/* As above, but read two bytes interpreted as an unsigned 16-bit integer.158* V should be declared unsigned int or perhaps JLONG.159*/160#define INPUT_2BYTES(cinfo, V, action) \161MAKESTMT( MAKE_BYTE_AVAIL(cinfo, action); \162bytes_in_buffer--; \163V = ((unsigned int)(*next_input_byte++)) << 8; \164MAKE_BYTE_AVAIL(cinfo, action); \165bytes_in_buffer--; \166V += *next_input_byte++; )167168169/*170* Routines to process JPEG markers.171*172* Entry condition: JPEG marker itself has been read and its code saved173* in cinfo->unread_marker; input restart point is just after the marker.174*175* Exit: if return TRUE, have read and processed any parameters, and have176* updated the restart point to point after the parameters.177* If return FALSE, was forced to suspend before reaching end of178* marker parameters; restart point has not been moved. Same routine179* will be called again after application supplies more input data.180*181* This approach to suspension assumes that all of a marker's parameters182* can fit into a single input bufferload. This should hold for "normal"183* markers. Some COM/APPn markers might have large parameter segments184* that might not fit. If we are simply dropping such a marker, we use185* skip_input_data to get past it, and thereby put the problem on the186* source manager's shoulders. If we are saving the marker's contents187* into memory, we use a slightly different convention: when forced to188* suspend, the marker processor updates the restart point to the end of189* what it's consumed (ie, the end of the buffer) before returning FALSE.190* On resumption, cinfo->unread_marker still contains the marker code,191* but the data source will point to the next chunk of marker data.192* The marker processor must retain internal state to deal with this.193*194* Note that we don't bother to avoid duplicate trace messages if a195* suspension occurs within marker parameters. Other side effects196* require more care.197*/198199200LOCAL(boolean)201get_soi(j_decompress_ptr cinfo)202/* Process an SOI marker */203{204int i;205206TRACEMS(cinfo, 1, JTRC_SOI);207208if (cinfo->marker->saw_SOI)209ERREXIT(cinfo, JERR_SOI_DUPLICATE);210211/* Reset all parameters that are defined to be reset by SOI */212213for (i = 0; i < NUM_ARITH_TBLS; i++) {214cinfo->arith_dc_L[i] = 0;215cinfo->arith_dc_U[i] = 1;216cinfo->arith_ac_K[i] = 5;217}218cinfo->restart_interval = 0;219220/* Set initial assumptions for colorspace etc */221222cinfo->jpeg_color_space = JCS_UNKNOWN;223cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */224225cinfo->saw_JFIF_marker = FALSE;226cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */227cinfo->JFIF_minor_version = 1;228cinfo->density_unit = 0;229cinfo->X_density = 1;230cinfo->Y_density = 1;231cinfo->saw_Adobe_marker = FALSE;232cinfo->Adobe_transform = 0;233234cinfo->marker->saw_SOI = TRUE;235236return TRUE;237}238239240LOCAL(boolean)241get_sof(j_decompress_ptr cinfo, boolean is_prog, boolean is_lossless,242boolean is_arith)243/* Process a SOFn marker */244{245JLONG length;246int c, ci;247jpeg_component_info *compptr;248INPUT_VARS(cinfo);249250if (cinfo->marker->saw_SOF)251ERREXIT(cinfo, JERR_SOF_DUPLICATE);252253cinfo->progressive_mode = is_prog;254cinfo->master->lossless = is_lossless;255cinfo->arith_code = is_arith;256257INPUT_2BYTES(cinfo, length, return FALSE);258259INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE);260INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE);261INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE);262INPUT_BYTE(cinfo, cinfo->num_components, return FALSE);263264length -= 8;265266TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker,267(int)cinfo->image_width, (int)cinfo->image_height,268cinfo->num_components);269270/* We don't support files in which the image height is initially specified */271/* as 0 and is later redefined by DNL. As long as we have to check that, */272/* might as well have a general sanity check. */273if (cinfo->image_height <= 0 || cinfo->image_width <= 0 ||274cinfo->num_components <= 0)275ERREXIT(cinfo, JERR_EMPTY_IMAGE);276277if (length != (cinfo->num_components * 3))278ERREXIT(cinfo, JERR_BAD_LENGTH);279280if (cinfo->comp_info == NULL) /* do only once, even if suspend */281cinfo->comp_info = (jpeg_component_info *)(*cinfo->mem->alloc_small)282((j_common_ptr)cinfo, JPOOL_IMAGE,283cinfo->num_components * sizeof(jpeg_component_info));284285for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;286ci++, compptr++) {287compptr->component_index = ci;288INPUT_BYTE(cinfo, compptr->component_id, return FALSE);289INPUT_BYTE(cinfo, c, return FALSE);290compptr->h_samp_factor = (c >> 4) & 15;291compptr->v_samp_factor = (c ) & 15;292INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE);293294TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT,295compptr->component_id, compptr->h_samp_factor,296compptr->v_samp_factor, compptr->quant_tbl_no);297}298299cinfo->marker->saw_SOF = TRUE;300301INPUT_SYNC(cinfo);302return TRUE;303}304305306LOCAL(boolean)307get_sos(j_decompress_ptr cinfo)308/* Process a SOS marker */309{310JLONG length;311int i, ci, n, c, cc, pi;312jpeg_component_info *compptr;313INPUT_VARS(cinfo);314315if (!cinfo->marker->saw_SOF)316ERREXIT(cinfo, JERR_SOS_NO_SOF);317318INPUT_2BYTES(cinfo, length, return FALSE);319320INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */321322TRACEMS1(cinfo, 1, JTRC_SOS, n);323324if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN)325ERREXIT(cinfo, JERR_BAD_LENGTH);326327cinfo->comps_in_scan = n;328329/* Collect the component-spec parameters */330331for (i = 0; i < MAX_COMPS_IN_SCAN; i++)332cinfo->cur_comp_info[i] = NULL;333334for (i = 0; i < n; i++) {335INPUT_BYTE(cinfo, cc, return FALSE);336INPUT_BYTE(cinfo, c, return FALSE);337338for (ci = 0, compptr = cinfo->comp_info;339ci < cinfo->num_components && ci < MAX_COMPS_IN_SCAN;340ci++, compptr++) {341if (cc == compptr->component_id && !cinfo->cur_comp_info[ci])342goto id_found;343}344345ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);346347id_found:348349cinfo->cur_comp_info[i] = compptr;350compptr->dc_tbl_no = (c >> 4) & 15;351compptr->ac_tbl_no = (c ) & 15;352353TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc,354compptr->dc_tbl_no, compptr->ac_tbl_no);355356/* This CSi (cc) should differ from the previous CSi */357for (pi = 0; pi < i; pi++) {358if (cinfo->cur_comp_info[pi] == compptr) {359ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);360}361}362}363364/* Collect the additional scan parameters Ss, Se, Ah/Al. */365INPUT_BYTE(cinfo, c, return FALSE);366cinfo->Ss = c;367INPUT_BYTE(cinfo, c, return FALSE);368cinfo->Se = c;369INPUT_BYTE(cinfo, c, return FALSE);370cinfo->Ah = (c >> 4) & 15;371cinfo->Al = (c ) & 15;372373TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se,374cinfo->Ah, cinfo->Al);375376/* Prepare to scan data & restart markers */377cinfo->marker->next_restart_num = 0;378379/* Count another SOS marker */380cinfo->input_scan_number++;381382INPUT_SYNC(cinfo);383return TRUE;384}385386387#ifdef D_ARITH_CODING_SUPPORTED388389LOCAL(boolean)390get_dac(j_decompress_ptr cinfo)391/* Process a DAC marker */392{393JLONG length;394int index, val;395INPUT_VARS(cinfo);396397INPUT_2BYTES(cinfo, length, return FALSE);398length -= 2;399400while (length > 0) {401INPUT_BYTE(cinfo, index, return FALSE);402INPUT_BYTE(cinfo, val, return FALSE);403404length -= 2;405406TRACEMS2(cinfo, 1, JTRC_DAC, index, val);407408if (index < 0 || index >= (2 * NUM_ARITH_TBLS))409ERREXIT1(cinfo, JERR_DAC_INDEX, index);410411if (index >= NUM_ARITH_TBLS) { /* define AC table */412cinfo->arith_ac_K[index - NUM_ARITH_TBLS] = (UINT8)val;413} else { /* define DC table */414cinfo->arith_dc_L[index] = (UINT8)(val & 0x0F);415cinfo->arith_dc_U[index] = (UINT8)(val >> 4);416if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])417ERREXIT1(cinfo, JERR_DAC_VALUE, val);418}419}420421if (length != 0)422ERREXIT(cinfo, JERR_BAD_LENGTH);423424INPUT_SYNC(cinfo);425return TRUE;426}427428#else /* !D_ARITH_CODING_SUPPORTED */429430#define get_dac(cinfo) skip_variable(cinfo)431432#endif /* D_ARITH_CODING_SUPPORTED */433434435LOCAL(boolean)436get_dht(j_decompress_ptr cinfo)437/* Process a DHT marker */438{439JLONG length;440UINT8 bits[17];441UINT8 huffval[256];442int i, index, count;443JHUFF_TBL **htblptr;444INPUT_VARS(cinfo);445446INPUT_2BYTES(cinfo, length, return FALSE);447length -= 2;448449while (length > 16) {450INPUT_BYTE(cinfo, index, return FALSE);451452TRACEMS1(cinfo, 1, JTRC_DHT, index);453454bits[0] = 0;455count = 0;456for (i = 1; i <= 16; i++) {457INPUT_BYTE(cinfo, bits[i], return FALSE);458count += bits[i];459}460461length -= 1 + 16;462463TRACEMS8(cinfo, 2, JTRC_HUFFBITS,464bits[1], bits[2], bits[3], bits[4],465bits[5], bits[6], bits[7], bits[8]);466TRACEMS8(cinfo, 2, JTRC_HUFFBITS,467bits[9], bits[10], bits[11], bits[12],468bits[13], bits[14], bits[15], bits[16]);469470/* Here we just do minimal validation of the counts to avoid walking471* off the end of our table space. jdhuff.c will check more carefully.472*/473if (count > 256 || ((JLONG)count) > length)474ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);475476for (i = 0; i < count; i++)477INPUT_BYTE(cinfo, huffval[i], return FALSE);478479memset(&huffval[count], 0, (256 - count) * sizeof(UINT8));480481length -= count;482483if (index & 0x10) { /* AC table definition */484index -= 0x10;485if (index < 0 || index >= NUM_HUFF_TBLS)486ERREXIT1(cinfo, JERR_DHT_INDEX, index);487htblptr = &cinfo->ac_huff_tbl_ptrs[index];488} else { /* DC table definition */489if (index < 0 || index >= NUM_HUFF_TBLS)490ERREXIT1(cinfo, JERR_DHT_INDEX, index);491htblptr = &cinfo->dc_huff_tbl_ptrs[index];492}493494if (*htblptr == NULL)495*htblptr = jpeg_alloc_huff_table((j_common_ptr)cinfo);496497memcpy((*htblptr)->bits, bits, sizeof((*htblptr)->bits));498memcpy((*htblptr)->huffval, huffval, sizeof((*htblptr)->huffval));499}500501if (length != 0)502ERREXIT(cinfo, JERR_BAD_LENGTH);503504INPUT_SYNC(cinfo);505return TRUE;506}507508509LOCAL(boolean)510get_dqt(j_decompress_ptr cinfo)511/* Process a DQT marker */512{513JLONG length;514int n, i, prec;515unsigned int tmp;516JQUANT_TBL *quant_ptr;517INPUT_VARS(cinfo);518519INPUT_2BYTES(cinfo, length, return FALSE);520length -= 2;521522while (length > 0) {523INPUT_BYTE(cinfo, n, return FALSE);524prec = n >> 4;525n &= 0x0F;526527TRACEMS2(cinfo, 1, JTRC_DQT, n, prec);528529if (n >= NUM_QUANT_TBLS)530ERREXIT1(cinfo, JERR_DQT_INDEX, n);531532if (cinfo->quant_tbl_ptrs[n] == NULL)533cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr)cinfo);534quant_ptr = cinfo->quant_tbl_ptrs[n];535536for (i = 0; i < DCTSIZE2; i++) {537if (prec)538INPUT_2BYTES(cinfo, tmp, return FALSE);539else540INPUT_BYTE(cinfo, tmp, return FALSE);541/* We convert the zigzag-order table to natural array order. */542quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16)tmp;543}544545if (cinfo->err->trace_level >= 2) {546for (i = 0; i < DCTSIZE2; i += 8) {547TRACEMS8(cinfo, 2, JTRC_QUANTVALS,548quant_ptr->quantval[i], quant_ptr->quantval[i + 1],549quant_ptr->quantval[i + 2], quant_ptr->quantval[i + 3],550quant_ptr->quantval[i + 4], quant_ptr->quantval[i + 5],551quant_ptr->quantval[i + 6], quant_ptr->quantval[i + 7]);552}553}554555length -= DCTSIZE2 + 1;556if (prec) length -= DCTSIZE2;557}558559if (length != 0)560ERREXIT(cinfo, JERR_BAD_LENGTH);561562INPUT_SYNC(cinfo);563return TRUE;564}565566567LOCAL(boolean)568get_dri(j_decompress_ptr cinfo)569/* Process a DRI marker */570{571JLONG length;572unsigned int tmp;573INPUT_VARS(cinfo);574575INPUT_2BYTES(cinfo, length, return FALSE);576577if (length != 4)578ERREXIT(cinfo, JERR_BAD_LENGTH);579580INPUT_2BYTES(cinfo, tmp, return FALSE);581582TRACEMS1(cinfo, 1, JTRC_DRI, tmp);583584cinfo->restart_interval = tmp;585586INPUT_SYNC(cinfo);587return TRUE;588}589590591/*592* Routines for processing APPn and COM markers.593* These are either saved in memory or discarded, per application request.594* APP0 and APP14 are specially checked to see if they are595* JFIF and Adobe markers, respectively.596*/597598#define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */599#define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */600#define APPN_DATA_LEN 14 /* Must be the largest of the above!! */601602603LOCAL(void)604examine_app0(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,605JLONG remaining)606/* Examine first few bytes from an APP0.607* Take appropriate action if it is a JFIF marker.608* datalen is # of bytes at data[], remaining is length of rest of marker data.609*/610{611JLONG totallen = (JLONG)datalen + remaining;612613if (datalen >= APP0_DATA_LEN &&614data[0] == 0x4A &&615data[1] == 0x46 &&616data[2] == 0x49 &&617data[3] == 0x46 &&618data[4] == 0) {619/* Found JFIF APP0 marker: save info */620cinfo->saw_JFIF_marker = TRUE;621cinfo->JFIF_major_version = data[5];622cinfo->JFIF_minor_version = data[6];623cinfo->density_unit = data[7];624cinfo->X_density = (data[8] << 8) + data[9];625cinfo->Y_density = (data[10] << 8) + data[11];626/* Check version.627* Major version must be 1, anything else signals an incompatible change.628* (We used to treat this as an error, but now it's a nonfatal warning,629* because some bozo at Hijaak couldn't read the spec.)630* Minor version should be 0..2, but process anyway if newer.631*/632if (cinfo->JFIF_major_version != 1)633WARNMS2(cinfo, JWRN_JFIF_MAJOR,634cinfo->JFIF_major_version, cinfo->JFIF_minor_version);635/* Generate trace messages */636TRACEMS5(cinfo, 1, JTRC_JFIF,637cinfo->JFIF_major_version, cinfo->JFIF_minor_version,638cinfo->X_density, cinfo->Y_density, cinfo->density_unit);639/* Validate thumbnail dimensions and issue appropriate messages */640if (data[12] | data[13])641TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, data[12], data[13]);642totallen -= APP0_DATA_LEN;643if (totallen != ((JLONG)data[12] * (JLONG)data[13] * (JLONG)3))644TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int)totallen);645} else if (datalen >= 6 &&646data[0] == 0x4A &&647data[1] == 0x46 &&648data[2] == 0x58 &&649data[3] == 0x58 &&650data[4] == 0) {651/* Found JFIF "JFXX" extension APP0 marker */652/* The library doesn't actually do anything with these,653* but we try to produce a helpful trace message.654*/655switch (data[5]) {656case 0x10:657TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int)totallen);658break;659case 0x11:660TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int)totallen);661break;662case 0x13:663TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int)totallen);664break;665default:666TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, data[5], (int)totallen);667break;668}669} else {670/* Start of APP0 does not match "JFIF" or "JFXX", or too short */671TRACEMS1(cinfo, 1, JTRC_APP0, (int)totallen);672}673}674675676LOCAL(void)677examine_app14(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,678JLONG remaining)679/* Examine first few bytes from an APP14.680* Take appropriate action if it is an Adobe marker.681* datalen is # of bytes at data[], remaining is length of rest of marker data.682*/683{684unsigned int version, flags0, flags1, transform;685686if (datalen >= APP14_DATA_LEN &&687data[0] == 0x41 &&688data[1] == 0x64 &&689data[2] == 0x6F &&690data[3] == 0x62 &&691data[4] == 0x65) {692/* Found Adobe APP14 marker */693version = (data[5] << 8) + data[6];694flags0 = (data[7] << 8) + data[8];695flags1 = (data[9] << 8) + data[10];696transform = data[11];697TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform);698cinfo->saw_Adobe_marker = TRUE;699cinfo->Adobe_transform = (UINT8)transform;700} else {701/* Start of APP14 does not match "Adobe", or too short */702TRACEMS1(cinfo, 1, JTRC_APP14, (int)(datalen + remaining));703}704}705706707METHODDEF(boolean)708get_interesting_appn(j_decompress_ptr cinfo)709/* Process an APP0 or APP14 marker without saving it */710{711JLONG length;712JOCTET b[APPN_DATA_LEN];713unsigned int i, numtoread;714INPUT_VARS(cinfo);715716INPUT_2BYTES(cinfo, length, return FALSE);717length -= 2;718719/* get the interesting part of the marker data */720if (length >= APPN_DATA_LEN)721numtoread = APPN_DATA_LEN;722else if (length > 0)723numtoread = (unsigned int)length;724else725numtoread = 0;726for (i = 0; i < numtoread; i++)727INPUT_BYTE(cinfo, b[i], return FALSE);728length -= numtoread;729730/* process it */731switch (cinfo->unread_marker) {732case M_APP0:733examine_app0(cinfo, (JOCTET *)b, numtoread, length);734break;735case M_APP14:736examine_app14(cinfo, (JOCTET *)b, numtoread, length);737break;738default:739/* can't get here unless jpeg_save_markers chooses wrong processor */740ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker);741break;742}743744/* skip any remaining data -- could be lots */745INPUT_SYNC(cinfo);746if (length > 0)747(*cinfo->src->skip_input_data) (cinfo, (long)length);748749return TRUE;750}751752753#ifdef SAVE_MARKERS_SUPPORTED754755METHODDEF(boolean)756save_marker(j_decompress_ptr cinfo)757/* Save an APPn or COM marker into the marker list */758{759my_marker_ptr marker = (my_marker_ptr)cinfo->marker;760jpeg_saved_marker_ptr cur_marker = marker->cur_marker;761unsigned int bytes_read, data_length;762JOCTET *data;763JLONG length = 0;764INPUT_VARS(cinfo);765766if (cur_marker == NULL) {767/* begin reading a marker */768INPUT_2BYTES(cinfo, length, return FALSE);769length -= 2;770if (length >= 0) { /* watch out for bogus length word */771/* figure out how much we want to save */772unsigned int limit;773if (cinfo->unread_marker == (int)M_COM)774limit = marker->length_limit_COM;775else776limit = marker->length_limit_APPn[cinfo->unread_marker - (int)M_APP0];777if ((unsigned int)length < limit)778limit = (unsigned int)length;779/* allocate and initialize the marker item */780cur_marker = (jpeg_saved_marker_ptr)781(*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE,782sizeof(struct jpeg_marker_struct) + limit);783cur_marker->next = NULL;784cur_marker->marker = (UINT8)cinfo->unread_marker;785cur_marker->original_length = (unsigned int)length;786cur_marker->data_length = limit;787/* data area is just beyond the jpeg_marker_struct */788data = cur_marker->data = (JOCTET *)(cur_marker + 1);789marker->cur_marker = cur_marker;790marker->bytes_read = 0;791bytes_read = 0;792data_length = limit;793} else {794/* deal with bogus length word */795bytes_read = data_length = 0;796data = NULL;797}798} else {799/* resume reading a marker */800bytes_read = marker->bytes_read;801data_length = cur_marker->data_length;802data = cur_marker->data + bytes_read;803}804805while (bytes_read < data_length) {806INPUT_SYNC(cinfo); /* move the restart point to here */807marker->bytes_read = bytes_read;808/* If there's not at least one byte in buffer, suspend */809MAKE_BYTE_AVAIL(cinfo, return FALSE);810/* Copy bytes with reasonable rapidity */811while (bytes_read < data_length && bytes_in_buffer > 0) {812*data++ = *next_input_byte++;813bytes_in_buffer--;814bytes_read++;815}816}817818/* Done reading what we want to read */819if (cur_marker != NULL) { /* will be NULL if bogus length word */820/* Add new marker to end of list */821if (cinfo->marker_list == NULL || cinfo->master->marker_list_end == NULL) {822cinfo->marker_list = cinfo->master->marker_list_end = cur_marker;823} else {824cinfo->master->marker_list_end->next = cur_marker;825cinfo->master->marker_list_end = cur_marker;826}827/* Reset pointer & calc remaining data length */828data = cur_marker->data;829length = cur_marker->original_length - data_length;830}831/* Reset to initial state for next marker */832marker->cur_marker = NULL;833834/* Process the marker if interesting; else just make a generic trace msg */835switch (cinfo->unread_marker) {836case M_APP0:837examine_app0(cinfo, data, data_length, length);838break;839case M_APP14:840examine_app14(cinfo, data, data_length, length);841break;842default:843TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker,844(int)(data_length + length));845break;846}847848/* skip any remaining data -- could be lots */849INPUT_SYNC(cinfo); /* do before skip_input_data */850if (length > 0)851(*cinfo->src->skip_input_data) (cinfo, (long)length);852853return TRUE;854}855856#endif /* SAVE_MARKERS_SUPPORTED */857858859METHODDEF(boolean)860skip_variable(j_decompress_ptr cinfo)861/* Skip over an unknown or uninteresting variable-length marker */862{863JLONG length;864INPUT_VARS(cinfo);865866INPUT_2BYTES(cinfo, length, return FALSE);867length -= 2;868869TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int)length);870871INPUT_SYNC(cinfo); /* do before skip_input_data */872if (length > 0)873(*cinfo->src->skip_input_data) (cinfo, (long)length);874875return TRUE;876}877878879/*880* Find the next JPEG marker, save it in cinfo->unread_marker.881* Returns FALSE if had to suspend before reaching a marker;882* in that case cinfo->unread_marker is unchanged.883*884* Note that the result might not be a valid marker code,885* but it will never be 0 or FF.886*/887888LOCAL(boolean)889next_marker(j_decompress_ptr cinfo)890{891int c;892INPUT_VARS(cinfo);893894for (;;) {895INPUT_BYTE(cinfo, c, return FALSE);896/* Skip any non-FF bytes.897* This may look a bit inefficient, but it will not occur in a valid file.898* We sync after each discarded byte so that a suspending data source899* can discard the byte from its buffer.900*/901while (c != 0xFF) {902cinfo->marker->discarded_bytes++;903INPUT_SYNC(cinfo);904INPUT_BYTE(cinfo, c, return FALSE);905}906/* This loop swallows any duplicate FF bytes. Extra FFs are legal as907* pad bytes, so don't count them in discarded_bytes. We assume there908* will not be so many consecutive FF bytes as to overflow a suspending909* data source's input buffer.910*/911do {912INPUT_BYTE(cinfo, c, return FALSE);913} while (c == 0xFF);914if (c != 0)915break; /* found a valid marker, exit loop */916/* Reach here if we found a stuffed-zero data sequence (FF/00).917* Discard it and loop back to try again.918*/919cinfo->marker->discarded_bytes += 2;920INPUT_SYNC(cinfo);921}922923if (cinfo->marker->discarded_bytes != 0) {924WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c);925cinfo->marker->discarded_bytes = 0;926}927928cinfo->unread_marker = c;929930INPUT_SYNC(cinfo);931return TRUE;932}933934935LOCAL(boolean)936first_marker(j_decompress_ptr cinfo)937/* Like next_marker, but used to obtain the initial SOI marker. */938/* For this marker, we do not allow preceding garbage or fill; otherwise,939* we might well scan an entire input file before realizing it ain't JPEG.940* If an application wants to process non-JFIF files, it must seek to the941* SOI before calling the JPEG library.942*/943{944int c, c2;945INPUT_VARS(cinfo);946947INPUT_BYTE(cinfo, c, return FALSE);948INPUT_BYTE(cinfo, c2, return FALSE);949if (c != 0xFF || c2 != (int)M_SOI)950ERREXIT2(cinfo, JERR_NO_SOI, c, c2);951952cinfo->unread_marker = c2;953954INPUT_SYNC(cinfo);955return TRUE;956}957958959/*960* Read markers until SOS or EOI.961*962* Returns same codes as are defined for jpeg_consume_input:963* JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.964*/965966METHODDEF(int)967read_markers(j_decompress_ptr cinfo)968{969/* Outer loop repeats once for each marker. */970for (;;) {971/* Collect the marker proper, unless we already did. */972/* NB: first_marker() enforces the requirement that SOI appear first. */973if (cinfo->unread_marker == 0) {974if (!cinfo->marker->saw_SOI) {975if (!first_marker(cinfo))976return JPEG_SUSPENDED;977} else {978if (!next_marker(cinfo))979return JPEG_SUSPENDED;980}981}982/* At this point cinfo->unread_marker contains the marker code and the983* input point is just past the marker proper, but before any parameters.984* A suspension will cause us to return with this state still true.985*/986switch (cinfo->unread_marker) {987case M_SOI:988if (!get_soi(cinfo))989return JPEG_SUSPENDED;990break;991992case M_SOF0: /* Baseline */993case M_SOF1: /* Extended sequential, Huffman */994if (!get_sof(cinfo, FALSE, FALSE, FALSE))995return JPEG_SUSPENDED;996break;997998case M_SOF2: /* Progressive, Huffman */999if (!get_sof(cinfo, TRUE, FALSE, FALSE))1000return JPEG_SUSPENDED;1001break;10021003case M_SOF3: /* Lossless, Huffman */1004if (!get_sof(cinfo, FALSE, TRUE, FALSE))1005return JPEG_SUSPENDED;1006break;10071008case M_SOF9: /* Extended sequential, arithmetic */1009if (!get_sof(cinfo, FALSE, FALSE, TRUE))1010return JPEG_SUSPENDED;1011break;10121013case M_SOF10: /* Progressive, arithmetic */1014if (!get_sof(cinfo, TRUE, FALSE, TRUE))1015return JPEG_SUSPENDED;1016break;10171018case M_SOF11: /* Lossless, arithmetic */1019if (!get_sof(cinfo, FALSE, TRUE, TRUE))1020return JPEG_SUSPENDED;1021break;10221023/* Currently unsupported SOFn types */1024case M_SOF5: /* Differential sequential, Huffman */1025case M_SOF6: /* Differential progressive, Huffman */1026case M_SOF7: /* Differential lossless, Huffman */1027case M_JPG: /* Reserved for JPEG extensions */1028case M_SOF13: /* Differential sequential, arithmetic */1029case M_SOF14: /* Differential progressive, arithmetic */1030case M_SOF15: /* Differential lossless, arithmetic */1031ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker);1032break;10331034case M_SOS:1035if (!get_sos(cinfo))1036return JPEG_SUSPENDED;1037cinfo->unread_marker = 0; /* processed the marker */1038return JPEG_REACHED_SOS;10391040case M_EOI:1041TRACEMS(cinfo, 1, JTRC_EOI);1042cinfo->unread_marker = 0; /* processed the marker */1043return JPEG_REACHED_EOI;10441045case M_DAC:1046if (!get_dac(cinfo))1047return JPEG_SUSPENDED;1048break;10491050case M_DHT:1051if (!get_dht(cinfo))1052return JPEG_SUSPENDED;1053break;10541055case M_DQT:1056if (!get_dqt(cinfo))1057return JPEG_SUSPENDED;1058break;10591060case M_DRI:1061if (!get_dri(cinfo))1062return JPEG_SUSPENDED;1063break;10641065case M_APP0:1066case M_APP1:1067case M_APP2:1068case M_APP3:1069case M_APP4:1070case M_APP5:1071case M_APP6:1072case M_APP7:1073case M_APP8:1074case M_APP9:1075case M_APP10:1076case M_APP11:1077case M_APP12:1078case M_APP13:1079case M_APP14:1080case M_APP15:1081if (!(*((my_marker_ptr)cinfo->marker)->process_APPn[1082cinfo->unread_marker - (int)M_APP0]) (cinfo))1083return JPEG_SUSPENDED;1084break;10851086case M_COM:1087if (!(*((my_marker_ptr)cinfo->marker)->process_COM) (cinfo))1088return JPEG_SUSPENDED;1089break;10901091case M_RST0: /* these are all parameterless */1092case M_RST1:1093case M_RST2:1094case M_RST3:1095case M_RST4:1096case M_RST5:1097case M_RST6:1098case M_RST7:1099case M_TEM:1100TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker);1101break;11021103case M_DNL: /* Ignore DNL ... perhaps the wrong thing */1104if (!skip_variable(cinfo))1105return JPEG_SUSPENDED;1106break;11071108default: /* must be DHP, EXP, JPGn, or RESn */1109/* For now, we treat the reserved markers as fatal errors since they are1110* likely to be used to signal incompatible JPEG Part 3 extensions.1111* Once the JPEG 3 version-number marker is well defined, this code1112* ought to change!1113*/1114ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker);1115break;1116}1117/* Successfully processed marker, so reset state variable */1118cinfo->unread_marker = 0;1119} /* end loop */1120}112111221123/*1124* Read a restart marker, which is expected to appear next in the datastream;1125* if the marker is not there, take appropriate recovery action.1126* Returns FALSE if suspension is required.1127*1128* This is called by the entropy decoder after it has read an appropriate1129* number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder1130* has already read a marker from the data source. Under normal conditions1131* cinfo->unread_marker will be reset to 0 before returning; if not reset,1132* it holds a marker which the decoder will be unable to read past.1133*/11341135METHODDEF(boolean)1136read_restart_marker(j_decompress_ptr cinfo)1137{1138/* Obtain a marker unless we already did. */1139/* Note that next_marker will complain if it skips any data. */1140if (cinfo->unread_marker == 0) {1141if (!next_marker(cinfo))1142return FALSE;1143}11441145if (cinfo->unread_marker ==1146((int)M_RST0 + cinfo->marker->next_restart_num)) {1147/* Normal case --- swallow the marker and let entropy decoder continue */1148TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num);1149cinfo->unread_marker = 0;1150} else {1151/* Uh-oh, the restart markers have been messed up. */1152/* Let the data source manager determine how to resync. */1153if (!(*cinfo->src->resync_to_restart) (cinfo,1154cinfo->marker->next_restart_num))1155return FALSE;1156}11571158/* Update next-restart state */1159cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7;11601161return TRUE;1162}116311641165/*1166* This is the default resync_to_restart method for data source managers1167* to use if they don't have any better approach. Some data source managers1168* may be able to back up, or may have additional knowledge about the data1169* which permits a more intelligent recovery strategy; such managers would1170* presumably supply their own resync method.1171*1172* read_restart_marker calls resync_to_restart if it finds a marker other than1173* the restart marker it was expecting. (This code is *not* used unless1174* a nonzero restart interval has been declared.) cinfo->unread_marker is1175* the marker code actually found (might be anything, except 0 or FF).1176* The desired restart marker number (0..7) is passed as a parameter.1177* This routine is supposed to apply whatever error recovery strategy seems1178* appropriate in order to position the input stream to the next data segment.1179* Note that cinfo->unread_marker is treated as a marker appearing before1180* the current data-source input point; usually it should be reset to zero1181* before returning.1182* Returns FALSE if suspension is required.1183*1184* This implementation is substantially constrained by wanting to treat the1185* input as a data stream; this means we can't back up. Therefore, we have1186* only the following actions to work with:1187* 1. Simply discard the marker and let the entropy decoder resume at next1188* byte of file.1189* 2. Read forward until we find another marker, discarding intervening1190* data. (In theory we could look ahead within the current bufferload,1191* without having to discard data if we don't find the desired marker.1192* This idea is not implemented here, in part because it makes behavior1193* dependent on buffer size and chance buffer-boundary positions.)1194* 3. Leave the marker unread (by failing to zero cinfo->unread_marker).1195* This will cause the entropy decoder to process an empty data segment,1196* inserting dummy zeroes, and then we will reprocess the marker.1197*1198* #2 is appropriate if we think the desired marker lies ahead, while #3 is1199* appropriate if the found marker is a future restart marker (indicating1200* that we have missed the desired restart marker, probably because it got1201* corrupted).1202* We apply #2 or #3 if the found marker is a restart marker no more than1203* two counts behind or ahead of the expected one. We also apply #2 if the1204* found marker is not a legal JPEG marker code (it's certainly bogus data).1205* If the found marker is a restart marker more than 2 counts away, we do #11206* (too much risk that the marker is erroneous; with luck we will be able to1207* resync at some future point).1208* For any valid non-restart JPEG marker, we apply #3. This keeps us from1209* overrunning the end of a scan. An implementation limited to single-scan1210* files might find it better to apply #2 for markers other than EOI, since1211* any other marker would have to be bogus data in that case.1212*/12131214GLOBAL(boolean)1215jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired)1216{1217int marker = cinfo->unread_marker;1218int action = 1;12191220/* Always put up a warning. */1221WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired);12221223/* Outer loop handles repeated decision after scanning forward. */1224for (;;) {1225if (marker < (int)M_SOF0)1226action = 2; /* invalid marker */1227else if (marker < (int)M_RST0 || marker > (int)M_RST7)1228action = 3; /* valid non-restart marker */1229else {1230if (marker == ((int)M_RST0 + ((desired + 1) & 7)) ||1231marker == ((int)M_RST0 + ((desired + 2) & 7)))1232action = 3; /* one of the next two expected restarts */1233else if (marker == ((int)M_RST0 + ((desired - 1) & 7)) ||1234marker == ((int)M_RST0 + ((desired - 2) & 7)))1235action = 2; /* a prior restart, so advance */1236else1237action = 1; /* desired restart or too far away */1238}1239TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action);1240switch (action) {1241case 1:1242/* Discard marker and let entropy decoder resume processing. */1243cinfo->unread_marker = 0;1244return TRUE;1245case 2:1246/* Scan to the next marker, and repeat the decision loop. */1247if (!next_marker(cinfo))1248return FALSE;1249marker = cinfo->unread_marker;1250break;1251case 3:1252/* Return without advancing past this marker. */1253/* Entropy decoder will be forced to process an empty segment. */1254return TRUE;1255}1256} /* end loop */1257}125812591260/*1261* Reset marker processing state to begin a fresh datastream.1262*/12631264METHODDEF(void)1265reset_marker_reader(j_decompress_ptr cinfo)1266{1267my_marker_ptr marker = (my_marker_ptr)cinfo->marker;12681269cinfo->comp_info = NULL; /* until allocated by get_sof */1270cinfo->input_scan_number = 0; /* no SOS seen yet */1271cinfo->unread_marker = 0; /* no pending marker */1272marker->pub.saw_SOI = FALSE; /* set internal state too */1273marker->pub.saw_SOF = FALSE;1274marker->pub.discarded_bytes = 0;1275marker->cur_marker = NULL;1276}127712781279/*1280* Initialize the marker reader module.1281* This is called only once, when the decompression object is created.1282*/12831284GLOBAL(void)1285jinit_marker_reader(j_decompress_ptr cinfo)1286{1287my_marker_ptr marker;1288int i;12891290/* Create subobject in permanent pool */1291marker = (my_marker_ptr)1292(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,1293sizeof(my_marker_reader));1294cinfo->marker = (struct jpeg_marker_reader *)marker;1295/* Initialize public method pointers */1296marker->pub.reset_marker_reader = reset_marker_reader;1297marker->pub.read_markers = read_markers;1298marker->pub.read_restart_marker = read_restart_marker;1299/* Initialize COM/APPn processing.1300* By default, we examine and then discard APP0 and APP14,1301* but simply discard COM and all other APPn.1302*/1303marker->process_COM = skip_variable;1304marker->length_limit_COM = 0;1305for (i = 0; i < 16; i++) {1306marker->process_APPn[i] = skip_variable;1307marker->length_limit_APPn[i] = 0;1308}1309marker->process_APPn[0] = get_interesting_appn;1310marker->process_APPn[14] = get_interesting_appn;1311/* Reset marker processing state */1312reset_marker_reader(cinfo);1313}131413151316/*1317* Control saving of COM and APPn markers into marker_list.1318*/13191320#ifdef SAVE_MARKERS_SUPPORTED13211322GLOBAL(void)1323jpeg_save_markers(j_decompress_ptr cinfo, int marker_code,1324unsigned int length_limit)1325{1326my_marker_ptr marker = (my_marker_ptr)cinfo->marker;1327long maxlength;1328jpeg_marker_parser_method processor;13291330/* Length limit mustn't be larger than what we can allocate1331* (should only be a concern in a 16-bit environment).1332*/1333maxlength = cinfo->mem->max_alloc_chunk - sizeof(struct jpeg_marker_struct);1334if (((long)length_limit) > maxlength)1335length_limit = (unsigned int)maxlength;13361337/* Choose processor routine to use.1338* APP0/APP14 have special requirements.1339*/1340if (length_limit) {1341processor = save_marker;1342/* If saving APP0/APP14, save at least enough for our internal use. */1343if (marker_code == (int)M_APP0 && length_limit < APP0_DATA_LEN)1344length_limit = APP0_DATA_LEN;1345else if (marker_code == (int)M_APP14 && length_limit < APP14_DATA_LEN)1346length_limit = APP14_DATA_LEN;1347} else {1348processor = skip_variable;1349/* If discarding APP0/APP14, use our regular on-the-fly processor. */1350if (marker_code == (int)M_APP0 || marker_code == (int)M_APP14)1351processor = get_interesting_appn;1352}13531354if (marker_code == (int)M_COM) {1355marker->process_COM = processor;1356marker->length_limit_COM = length_limit;1357} else if (marker_code >= (int)M_APP0 && marker_code <= (int)M_APP15) {1358marker->process_APPn[marker_code - (int)M_APP0] = processor;1359marker->length_limit_APPn[marker_code - (int)M_APP0] = length_limit;1360} else1361ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);1362}13631364#endif /* SAVE_MARKERS_SUPPORTED */136513661367/*1368* Install a special processing method for COM or APPn markers.1369*/13701371GLOBAL(void)1372jpeg_set_marker_processor(j_decompress_ptr cinfo, int marker_code,1373jpeg_marker_parser_method routine)1374{1375my_marker_ptr marker = (my_marker_ptr)cinfo->marker;13761377if (marker_code == (int)M_COM)1378marker->process_COM = routine;1379else if (marker_code >= (int)M_APP0 && marker_code <= (int)M_APP15)1380marker->process_APPn[marker_code - (int)M_APP0] = routine;1381else1382ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);1383}138413851386