1*dfc6aa5cSAndroid Build Coastguard Worker /*
2*dfc6aa5cSAndroid Build Coastguard Worker * jdmarker.c
3*dfc6aa5cSAndroid Build Coastguard Worker *
4*dfc6aa5cSAndroid Build Coastguard Worker * This file was part of the Independent JPEG Group's software:
5*dfc6aa5cSAndroid Build Coastguard Worker * Copyright (C) 1991-1998, Thomas G. Lane.
6*dfc6aa5cSAndroid Build Coastguard Worker * Lossless JPEG Modifications:
7*dfc6aa5cSAndroid Build Coastguard Worker * Copyright (C) 1999, Ken Murchison.
8*dfc6aa5cSAndroid Build Coastguard Worker * libjpeg-turbo Modifications:
9*dfc6aa5cSAndroid Build Coastguard Worker * Copyright (C) 2012, 2015, 2022, 2024, D. R. Commander.
10*dfc6aa5cSAndroid Build Coastguard Worker * For conditions of distribution and use, see the accompanying README.ijg
11*dfc6aa5cSAndroid Build Coastguard Worker * file.
12*dfc6aa5cSAndroid Build Coastguard Worker *
13*dfc6aa5cSAndroid Build Coastguard Worker * This file contains routines to decode JPEG datastream markers.
14*dfc6aa5cSAndroid Build Coastguard Worker * Most of the complexity arises from our desire to support input
15*dfc6aa5cSAndroid Build Coastguard Worker * suspension: if not all of the data for a marker is available,
16*dfc6aa5cSAndroid Build Coastguard Worker * we must exit back to the application. On resumption, we reprocess
17*dfc6aa5cSAndroid Build Coastguard Worker * the marker.
18*dfc6aa5cSAndroid Build Coastguard Worker */
19*dfc6aa5cSAndroid Build Coastguard Worker
20*dfc6aa5cSAndroid Build Coastguard Worker #define JPEG_INTERNALS
21*dfc6aa5cSAndroid Build Coastguard Worker #include "jinclude.h"
22*dfc6aa5cSAndroid Build Coastguard Worker #include "jpeglib.h"
23*dfc6aa5cSAndroid Build Coastguard Worker
24*dfc6aa5cSAndroid Build Coastguard Worker
25*dfc6aa5cSAndroid Build Coastguard Worker typedef enum { /* JPEG marker codes */
26*dfc6aa5cSAndroid Build Coastguard Worker M_SOF0 = 0xc0,
27*dfc6aa5cSAndroid Build Coastguard Worker M_SOF1 = 0xc1,
28*dfc6aa5cSAndroid Build Coastguard Worker M_SOF2 = 0xc2,
29*dfc6aa5cSAndroid Build Coastguard Worker M_SOF3 = 0xc3,
30*dfc6aa5cSAndroid Build Coastguard Worker
31*dfc6aa5cSAndroid Build Coastguard Worker M_SOF5 = 0xc5,
32*dfc6aa5cSAndroid Build Coastguard Worker M_SOF6 = 0xc6,
33*dfc6aa5cSAndroid Build Coastguard Worker M_SOF7 = 0xc7,
34*dfc6aa5cSAndroid Build Coastguard Worker
35*dfc6aa5cSAndroid Build Coastguard Worker M_JPG = 0xc8,
36*dfc6aa5cSAndroid Build Coastguard Worker M_SOF9 = 0xc9,
37*dfc6aa5cSAndroid Build Coastguard Worker M_SOF10 = 0xca,
38*dfc6aa5cSAndroid Build Coastguard Worker M_SOF11 = 0xcb,
39*dfc6aa5cSAndroid Build Coastguard Worker
40*dfc6aa5cSAndroid Build Coastguard Worker M_SOF13 = 0xcd,
41*dfc6aa5cSAndroid Build Coastguard Worker M_SOF14 = 0xce,
42*dfc6aa5cSAndroid Build Coastguard Worker M_SOF15 = 0xcf,
43*dfc6aa5cSAndroid Build Coastguard Worker
44*dfc6aa5cSAndroid Build Coastguard Worker M_DHT = 0xc4,
45*dfc6aa5cSAndroid Build Coastguard Worker
46*dfc6aa5cSAndroid Build Coastguard Worker M_DAC = 0xcc,
47*dfc6aa5cSAndroid Build Coastguard Worker
48*dfc6aa5cSAndroid Build Coastguard Worker M_RST0 = 0xd0,
49*dfc6aa5cSAndroid Build Coastguard Worker M_RST1 = 0xd1,
50*dfc6aa5cSAndroid Build Coastguard Worker M_RST2 = 0xd2,
51*dfc6aa5cSAndroid Build Coastguard Worker M_RST3 = 0xd3,
52*dfc6aa5cSAndroid Build Coastguard Worker M_RST4 = 0xd4,
53*dfc6aa5cSAndroid Build Coastguard Worker M_RST5 = 0xd5,
54*dfc6aa5cSAndroid Build Coastguard Worker M_RST6 = 0xd6,
55*dfc6aa5cSAndroid Build Coastguard Worker M_RST7 = 0xd7,
56*dfc6aa5cSAndroid Build Coastguard Worker
57*dfc6aa5cSAndroid Build Coastguard Worker M_SOI = 0xd8,
58*dfc6aa5cSAndroid Build Coastguard Worker M_EOI = 0xd9,
59*dfc6aa5cSAndroid Build Coastguard Worker M_SOS = 0xda,
60*dfc6aa5cSAndroid Build Coastguard Worker M_DQT = 0xdb,
61*dfc6aa5cSAndroid Build Coastguard Worker M_DNL = 0xdc,
62*dfc6aa5cSAndroid Build Coastguard Worker M_DRI = 0xdd,
63*dfc6aa5cSAndroid Build Coastguard Worker M_DHP = 0xde,
64*dfc6aa5cSAndroid Build Coastguard Worker M_EXP = 0xdf,
65*dfc6aa5cSAndroid Build Coastguard Worker
66*dfc6aa5cSAndroid Build Coastguard Worker M_APP0 = 0xe0,
67*dfc6aa5cSAndroid Build Coastguard Worker M_APP1 = 0xe1,
68*dfc6aa5cSAndroid Build Coastguard Worker M_APP2 = 0xe2,
69*dfc6aa5cSAndroid Build Coastguard Worker M_APP3 = 0xe3,
70*dfc6aa5cSAndroid Build Coastguard Worker M_APP4 = 0xe4,
71*dfc6aa5cSAndroid Build Coastguard Worker M_APP5 = 0xe5,
72*dfc6aa5cSAndroid Build Coastguard Worker M_APP6 = 0xe6,
73*dfc6aa5cSAndroid Build Coastguard Worker M_APP7 = 0xe7,
74*dfc6aa5cSAndroid Build Coastguard Worker M_APP8 = 0xe8,
75*dfc6aa5cSAndroid Build Coastguard Worker M_APP9 = 0xe9,
76*dfc6aa5cSAndroid Build Coastguard Worker M_APP10 = 0xea,
77*dfc6aa5cSAndroid Build Coastguard Worker M_APP11 = 0xeb,
78*dfc6aa5cSAndroid Build Coastguard Worker M_APP12 = 0xec,
79*dfc6aa5cSAndroid Build Coastguard Worker M_APP13 = 0xed,
80*dfc6aa5cSAndroid Build Coastguard Worker M_APP14 = 0xee,
81*dfc6aa5cSAndroid Build Coastguard Worker M_APP15 = 0xef,
82*dfc6aa5cSAndroid Build Coastguard Worker
83*dfc6aa5cSAndroid Build Coastguard Worker M_JPG0 = 0xf0,
84*dfc6aa5cSAndroid Build Coastguard Worker M_JPG13 = 0xfd,
85*dfc6aa5cSAndroid Build Coastguard Worker M_COM = 0xfe,
86*dfc6aa5cSAndroid Build Coastguard Worker
87*dfc6aa5cSAndroid Build Coastguard Worker M_TEM = 0x01,
88*dfc6aa5cSAndroid Build Coastguard Worker
89*dfc6aa5cSAndroid Build Coastguard Worker M_ERROR = 0x100
90*dfc6aa5cSAndroid Build Coastguard Worker } JPEG_MARKER;
91*dfc6aa5cSAndroid Build Coastguard Worker
92*dfc6aa5cSAndroid Build Coastguard Worker
93*dfc6aa5cSAndroid Build Coastguard Worker /* Private state */
94*dfc6aa5cSAndroid Build Coastguard Worker
95*dfc6aa5cSAndroid Build Coastguard Worker typedef struct {
96*dfc6aa5cSAndroid Build Coastguard Worker struct jpeg_marker_reader pub; /* public fields */
97*dfc6aa5cSAndroid Build Coastguard Worker
98*dfc6aa5cSAndroid Build Coastguard Worker /* Application-overridable marker processing methods */
99*dfc6aa5cSAndroid Build Coastguard Worker jpeg_marker_parser_method process_COM;
100*dfc6aa5cSAndroid Build Coastguard Worker jpeg_marker_parser_method process_APPn[16];
101*dfc6aa5cSAndroid Build Coastguard Worker
102*dfc6aa5cSAndroid Build Coastguard Worker /* Limit on marker data length to save for each marker type */
103*dfc6aa5cSAndroid Build Coastguard Worker unsigned int length_limit_COM;
104*dfc6aa5cSAndroid Build Coastguard Worker unsigned int length_limit_APPn[16];
105*dfc6aa5cSAndroid Build Coastguard Worker
106*dfc6aa5cSAndroid Build Coastguard Worker /* Status of COM/APPn marker saving */
107*dfc6aa5cSAndroid Build Coastguard Worker jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */
108*dfc6aa5cSAndroid Build Coastguard Worker unsigned int bytes_read; /* data bytes read so far in marker */
109*dfc6aa5cSAndroid Build Coastguard Worker /* Note: cur_marker is not linked into marker_list until it's all read. */
110*dfc6aa5cSAndroid Build Coastguard Worker } my_marker_reader;
111*dfc6aa5cSAndroid Build Coastguard Worker
112*dfc6aa5cSAndroid Build Coastguard Worker typedef my_marker_reader *my_marker_ptr;
113*dfc6aa5cSAndroid Build Coastguard Worker
114*dfc6aa5cSAndroid Build Coastguard Worker
115*dfc6aa5cSAndroid Build Coastguard Worker /*
116*dfc6aa5cSAndroid Build Coastguard Worker * Macros for fetching data from the data source module.
117*dfc6aa5cSAndroid Build Coastguard Worker *
118*dfc6aa5cSAndroid Build Coastguard Worker * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect
119*dfc6aa5cSAndroid Build Coastguard Worker * the current restart point; we update them only when we have reached a
120*dfc6aa5cSAndroid Build Coastguard Worker * suitable place to restart if a suspension occurs.
121*dfc6aa5cSAndroid Build Coastguard Worker */
122*dfc6aa5cSAndroid Build Coastguard Worker
123*dfc6aa5cSAndroid Build Coastguard Worker /* Declare and initialize local copies of input pointer/count */
124*dfc6aa5cSAndroid Build Coastguard Worker #define INPUT_VARS(cinfo) \
125*dfc6aa5cSAndroid Build Coastguard Worker struct jpeg_source_mgr *datasrc = (cinfo)->src; \
126*dfc6aa5cSAndroid Build Coastguard Worker const JOCTET *next_input_byte = datasrc->next_input_byte; \
127*dfc6aa5cSAndroid Build Coastguard Worker size_t bytes_in_buffer = datasrc->bytes_in_buffer
128*dfc6aa5cSAndroid Build Coastguard Worker
129*dfc6aa5cSAndroid Build Coastguard Worker /* Unload the local copies --- do this only at a restart boundary */
130*dfc6aa5cSAndroid Build Coastguard Worker #define INPUT_SYNC(cinfo) \
131*dfc6aa5cSAndroid Build Coastguard Worker ( datasrc->next_input_byte = next_input_byte, \
132*dfc6aa5cSAndroid Build Coastguard Worker datasrc->bytes_in_buffer = bytes_in_buffer )
133*dfc6aa5cSAndroid Build Coastguard Worker
134*dfc6aa5cSAndroid Build Coastguard Worker /* Reload the local copies --- used only in MAKE_BYTE_AVAIL */
135*dfc6aa5cSAndroid Build Coastguard Worker #define INPUT_RELOAD(cinfo) \
136*dfc6aa5cSAndroid Build Coastguard Worker ( next_input_byte = datasrc->next_input_byte, \
137*dfc6aa5cSAndroid Build Coastguard Worker bytes_in_buffer = datasrc->bytes_in_buffer )
138*dfc6aa5cSAndroid Build Coastguard Worker
139*dfc6aa5cSAndroid Build Coastguard Worker /* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available.
140*dfc6aa5cSAndroid Build Coastguard Worker * Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
141*dfc6aa5cSAndroid Build Coastguard Worker * but we must reload the local copies after a successful fill.
142*dfc6aa5cSAndroid Build Coastguard Worker */
143*dfc6aa5cSAndroid Build Coastguard Worker #define MAKE_BYTE_AVAIL(cinfo, action) \
144*dfc6aa5cSAndroid Build Coastguard Worker if (bytes_in_buffer == 0) { \
145*dfc6aa5cSAndroid Build Coastguard Worker if (!(*datasrc->fill_input_buffer) (cinfo)) \
146*dfc6aa5cSAndroid Build Coastguard Worker { action; } \
147*dfc6aa5cSAndroid Build Coastguard Worker INPUT_RELOAD(cinfo); \
148*dfc6aa5cSAndroid Build Coastguard Worker }
149*dfc6aa5cSAndroid Build Coastguard Worker
150*dfc6aa5cSAndroid Build Coastguard Worker /* Read a byte into variable V.
151*dfc6aa5cSAndroid Build Coastguard Worker * If must suspend, take the specified action (typically "return FALSE").
152*dfc6aa5cSAndroid Build Coastguard Worker */
153*dfc6aa5cSAndroid Build Coastguard Worker #define INPUT_BYTE(cinfo, V, action) \
154*dfc6aa5cSAndroid Build Coastguard Worker MAKESTMT( MAKE_BYTE_AVAIL(cinfo, action); \
155*dfc6aa5cSAndroid Build Coastguard Worker bytes_in_buffer--; \
156*dfc6aa5cSAndroid Build Coastguard Worker V = *next_input_byte++; )
157*dfc6aa5cSAndroid Build Coastguard Worker
158*dfc6aa5cSAndroid Build Coastguard Worker /* As above, but read two bytes interpreted as an unsigned 16-bit integer.
159*dfc6aa5cSAndroid Build Coastguard Worker * V should be declared unsigned int or perhaps JLONG.
160*dfc6aa5cSAndroid Build Coastguard Worker */
161*dfc6aa5cSAndroid Build Coastguard Worker #define INPUT_2BYTES(cinfo, V, action) \
162*dfc6aa5cSAndroid Build Coastguard Worker MAKESTMT( MAKE_BYTE_AVAIL(cinfo, action); \
163*dfc6aa5cSAndroid Build Coastguard Worker bytes_in_buffer--; \
164*dfc6aa5cSAndroid Build Coastguard Worker V = ((unsigned int)(*next_input_byte++)) << 8; \
165*dfc6aa5cSAndroid Build Coastguard Worker MAKE_BYTE_AVAIL(cinfo, action); \
166*dfc6aa5cSAndroid Build Coastguard Worker bytes_in_buffer--; \
167*dfc6aa5cSAndroid Build Coastguard Worker V += *next_input_byte++; )
168*dfc6aa5cSAndroid Build Coastguard Worker
169*dfc6aa5cSAndroid Build Coastguard Worker
170*dfc6aa5cSAndroid Build Coastguard Worker /*
171*dfc6aa5cSAndroid Build Coastguard Worker * Routines to process JPEG markers.
172*dfc6aa5cSAndroid Build Coastguard Worker *
173*dfc6aa5cSAndroid Build Coastguard Worker * Entry condition: JPEG marker itself has been read and its code saved
174*dfc6aa5cSAndroid Build Coastguard Worker * in cinfo->unread_marker; input restart point is just after the marker.
175*dfc6aa5cSAndroid Build Coastguard Worker *
176*dfc6aa5cSAndroid Build Coastguard Worker * Exit: if return TRUE, have read and processed any parameters, and have
177*dfc6aa5cSAndroid Build Coastguard Worker * updated the restart point to point after the parameters.
178*dfc6aa5cSAndroid Build Coastguard Worker * If return FALSE, was forced to suspend before reaching end of
179*dfc6aa5cSAndroid Build Coastguard Worker * marker parameters; restart point has not been moved. Same routine
180*dfc6aa5cSAndroid Build Coastguard Worker * will be called again after application supplies more input data.
181*dfc6aa5cSAndroid Build Coastguard Worker *
182*dfc6aa5cSAndroid Build Coastguard Worker * This approach to suspension assumes that all of a marker's parameters
183*dfc6aa5cSAndroid Build Coastguard Worker * can fit into a single input bufferload. This should hold for "normal"
184*dfc6aa5cSAndroid Build Coastguard Worker * markers. Some COM/APPn markers might have large parameter segments
185*dfc6aa5cSAndroid Build Coastguard Worker * that might not fit. If we are simply dropping such a marker, we use
186*dfc6aa5cSAndroid Build Coastguard Worker * skip_input_data to get past it, and thereby put the problem on the
187*dfc6aa5cSAndroid Build Coastguard Worker * source manager's shoulders. If we are saving the marker's contents
188*dfc6aa5cSAndroid Build Coastguard Worker * into memory, we use a slightly different convention: when forced to
189*dfc6aa5cSAndroid Build Coastguard Worker * suspend, the marker processor updates the restart point to the end of
190*dfc6aa5cSAndroid Build Coastguard Worker * what it's consumed (ie, the end of the buffer) before returning FALSE.
191*dfc6aa5cSAndroid Build Coastguard Worker * On resumption, cinfo->unread_marker still contains the marker code,
192*dfc6aa5cSAndroid Build Coastguard Worker * but the data source will point to the next chunk of marker data.
193*dfc6aa5cSAndroid Build Coastguard Worker * The marker processor must retain internal state to deal with this.
194*dfc6aa5cSAndroid Build Coastguard Worker *
195*dfc6aa5cSAndroid Build Coastguard Worker * Note that we don't bother to avoid duplicate trace messages if a
196*dfc6aa5cSAndroid Build Coastguard Worker * suspension occurs within marker parameters. Other side effects
197*dfc6aa5cSAndroid Build Coastguard Worker * require more care.
198*dfc6aa5cSAndroid Build Coastguard Worker */
199*dfc6aa5cSAndroid Build Coastguard Worker
200*dfc6aa5cSAndroid Build Coastguard Worker
201*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(boolean)
get_soi(j_decompress_ptr cinfo)202*dfc6aa5cSAndroid Build Coastguard Worker get_soi(j_decompress_ptr cinfo)
203*dfc6aa5cSAndroid Build Coastguard Worker /* Process an SOI marker */
204*dfc6aa5cSAndroid Build Coastguard Worker {
205*dfc6aa5cSAndroid Build Coastguard Worker int i;
206*dfc6aa5cSAndroid Build Coastguard Worker
207*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS(cinfo, 1, JTRC_SOI);
208*dfc6aa5cSAndroid Build Coastguard Worker
209*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->marker->saw_SOI)
210*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(cinfo, JERR_SOI_DUPLICATE);
211*dfc6aa5cSAndroid Build Coastguard Worker
212*dfc6aa5cSAndroid Build Coastguard Worker /* Reset all parameters that are defined to be reset by SOI */
213*dfc6aa5cSAndroid Build Coastguard Worker
214*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < NUM_ARITH_TBLS; i++) {
215*dfc6aa5cSAndroid Build Coastguard Worker cinfo->arith_dc_L[i] = 0;
216*dfc6aa5cSAndroid Build Coastguard Worker cinfo->arith_dc_U[i] = 1;
217*dfc6aa5cSAndroid Build Coastguard Worker cinfo->arith_ac_K[i] = 5;
218*dfc6aa5cSAndroid Build Coastguard Worker }
219*dfc6aa5cSAndroid Build Coastguard Worker cinfo->restart_interval = 0;
220*dfc6aa5cSAndroid Build Coastguard Worker
221*dfc6aa5cSAndroid Build Coastguard Worker /* Set initial assumptions for colorspace etc */
222*dfc6aa5cSAndroid Build Coastguard Worker
223*dfc6aa5cSAndroid Build Coastguard Worker cinfo->jpeg_color_space = JCS_UNKNOWN;
224*dfc6aa5cSAndroid Build Coastguard Worker cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */
225*dfc6aa5cSAndroid Build Coastguard Worker
226*dfc6aa5cSAndroid Build Coastguard Worker cinfo->saw_JFIF_marker = FALSE;
227*dfc6aa5cSAndroid Build Coastguard Worker cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */
228*dfc6aa5cSAndroid Build Coastguard Worker cinfo->JFIF_minor_version = 1;
229*dfc6aa5cSAndroid Build Coastguard Worker cinfo->density_unit = 0;
230*dfc6aa5cSAndroid Build Coastguard Worker cinfo->X_density = 1;
231*dfc6aa5cSAndroid Build Coastguard Worker cinfo->Y_density = 1;
232*dfc6aa5cSAndroid Build Coastguard Worker cinfo->saw_Adobe_marker = FALSE;
233*dfc6aa5cSAndroid Build Coastguard Worker cinfo->Adobe_transform = 0;
234*dfc6aa5cSAndroid Build Coastguard Worker
235*dfc6aa5cSAndroid Build Coastguard Worker cinfo->marker->saw_SOI = TRUE;
236*dfc6aa5cSAndroid Build Coastguard Worker
237*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
238*dfc6aa5cSAndroid Build Coastguard Worker }
239*dfc6aa5cSAndroid Build Coastguard Worker
240*dfc6aa5cSAndroid Build Coastguard Worker
241*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(boolean)
get_sof(j_decompress_ptr cinfo,boolean is_prog,boolean is_arith)242*dfc6aa5cSAndroid Build Coastguard Worker get_sof(j_decompress_ptr cinfo, boolean is_prog, boolean is_arith)
243*dfc6aa5cSAndroid Build Coastguard Worker /* Process a SOFn marker */
244*dfc6aa5cSAndroid Build Coastguard Worker {
245*dfc6aa5cSAndroid Build Coastguard Worker JLONG length;
246*dfc6aa5cSAndroid Build Coastguard Worker int c, ci;
247*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
248*dfc6aa5cSAndroid Build Coastguard Worker INPUT_VARS(cinfo);
249*dfc6aa5cSAndroid Build Coastguard Worker
250*dfc6aa5cSAndroid Build Coastguard Worker cinfo->progressive_mode = is_prog;
251*dfc6aa5cSAndroid Build Coastguard Worker cinfo->arith_code = is_arith;
252*dfc6aa5cSAndroid Build Coastguard Worker
253*dfc6aa5cSAndroid Build Coastguard Worker INPUT_2BYTES(cinfo, length, return FALSE);
254*dfc6aa5cSAndroid Build Coastguard Worker
255*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE);
256*dfc6aa5cSAndroid Build Coastguard Worker INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE);
257*dfc6aa5cSAndroid Build Coastguard Worker INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE);
258*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, cinfo->num_components, return FALSE);
259*dfc6aa5cSAndroid Build Coastguard Worker
260*dfc6aa5cSAndroid Build Coastguard Worker length -= 8;
261*dfc6aa5cSAndroid Build Coastguard Worker
262*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker,
263*dfc6aa5cSAndroid Build Coastguard Worker (int)cinfo->image_width, (int)cinfo->image_height,
264*dfc6aa5cSAndroid Build Coastguard Worker cinfo->num_components);
265*dfc6aa5cSAndroid Build Coastguard Worker
266*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->marker->saw_SOF)
267*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(cinfo, JERR_SOF_DUPLICATE);
268*dfc6aa5cSAndroid Build Coastguard Worker
269*dfc6aa5cSAndroid Build Coastguard Worker /* We don't support files in which the image height is initially specified */
270*dfc6aa5cSAndroid Build Coastguard Worker /* as 0 and is later redefined by DNL. As long as we have to check that, */
271*dfc6aa5cSAndroid Build Coastguard Worker /* might as well have a general sanity check. */
272*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->image_height <= 0 || cinfo->image_width <= 0 ||
273*dfc6aa5cSAndroid Build Coastguard Worker cinfo->num_components <= 0)
274*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(cinfo, JERR_EMPTY_IMAGE);
275*dfc6aa5cSAndroid Build Coastguard Worker
276*dfc6aa5cSAndroid Build Coastguard Worker if (length != (cinfo->num_components * 3))
277*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(cinfo, JERR_BAD_LENGTH);
278*dfc6aa5cSAndroid Build Coastguard Worker
279*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->comp_info == NULL) /* do only once, even if suspend */
280*dfc6aa5cSAndroid Build Coastguard Worker cinfo->comp_info = (jpeg_component_info *)(*cinfo->mem->alloc_small)
281*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)cinfo, JPOOL_IMAGE,
282*dfc6aa5cSAndroid Build Coastguard Worker cinfo->num_components * sizeof(jpeg_component_info));
283*dfc6aa5cSAndroid Build Coastguard Worker
284*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
285*dfc6aa5cSAndroid Build Coastguard Worker ci++, compptr++) {
286*dfc6aa5cSAndroid Build Coastguard Worker compptr->component_index = ci;
287*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, compptr->component_id, return FALSE);
288*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, c, return FALSE);
289*dfc6aa5cSAndroid Build Coastguard Worker compptr->h_samp_factor = (c >> 4) & 15;
290*dfc6aa5cSAndroid Build Coastguard Worker compptr->v_samp_factor = (c ) & 15;
291*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE);
292*dfc6aa5cSAndroid Build Coastguard Worker
293*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT,
294*dfc6aa5cSAndroid Build Coastguard Worker compptr->component_id, compptr->h_samp_factor,
295*dfc6aa5cSAndroid Build Coastguard Worker compptr->v_samp_factor, compptr->quant_tbl_no);
296*dfc6aa5cSAndroid Build Coastguard Worker }
297*dfc6aa5cSAndroid Build Coastguard Worker
298*dfc6aa5cSAndroid Build Coastguard Worker cinfo->marker->saw_SOF = TRUE;
299*dfc6aa5cSAndroid Build Coastguard Worker
300*dfc6aa5cSAndroid Build Coastguard Worker INPUT_SYNC(cinfo);
301*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
302*dfc6aa5cSAndroid Build Coastguard Worker }
303*dfc6aa5cSAndroid Build Coastguard Worker
304*dfc6aa5cSAndroid Build Coastguard Worker
305*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(boolean)
get_sos(j_decompress_ptr cinfo)306*dfc6aa5cSAndroid Build Coastguard Worker get_sos(j_decompress_ptr cinfo)
307*dfc6aa5cSAndroid Build Coastguard Worker /* Process a SOS marker */
308*dfc6aa5cSAndroid Build Coastguard Worker {
309*dfc6aa5cSAndroid Build Coastguard Worker JLONG length;
310*dfc6aa5cSAndroid Build Coastguard Worker int i, ci, n, c, cc, pi;
311*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
312*dfc6aa5cSAndroid Build Coastguard Worker INPUT_VARS(cinfo);
313*dfc6aa5cSAndroid Build Coastguard Worker
314*dfc6aa5cSAndroid Build Coastguard Worker if (!cinfo->marker->saw_SOF)
315*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(cinfo, JERR_SOS_NO_SOF);
316*dfc6aa5cSAndroid Build Coastguard Worker
317*dfc6aa5cSAndroid Build Coastguard Worker INPUT_2BYTES(cinfo, length, return FALSE);
318*dfc6aa5cSAndroid Build Coastguard Worker
319*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */
320*dfc6aa5cSAndroid Build Coastguard Worker
321*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS1(cinfo, 1, JTRC_SOS, n);
322*dfc6aa5cSAndroid Build Coastguard Worker
323*dfc6aa5cSAndroid Build Coastguard Worker if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN)
324*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(cinfo, JERR_BAD_LENGTH);
325*dfc6aa5cSAndroid Build Coastguard Worker
326*dfc6aa5cSAndroid Build Coastguard Worker cinfo->comps_in_scan = n;
327*dfc6aa5cSAndroid Build Coastguard Worker
328*dfc6aa5cSAndroid Build Coastguard Worker /* Collect the component-spec parameters */
329*dfc6aa5cSAndroid Build Coastguard Worker
330*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < MAX_COMPS_IN_SCAN; i++)
331*dfc6aa5cSAndroid Build Coastguard Worker cinfo->cur_comp_info[i] = NULL;
332*dfc6aa5cSAndroid Build Coastguard Worker
333*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < n; i++) {
334*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, cc, return FALSE);
335*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, c, return FALSE);
336*dfc6aa5cSAndroid Build Coastguard Worker
337*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0, compptr = cinfo->comp_info;
338*dfc6aa5cSAndroid Build Coastguard Worker ci < cinfo->num_components && ci < MAX_COMPS_IN_SCAN;
339*dfc6aa5cSAndroid Build Coastguard Worker ci++, compptr++) {
340*dfc6aa5cSAndroid Build Coastguard Worker if (cc == compptr->component_id && !cinfo->cur_comp_info[ci])
341*dfc6aa5cSAndroid Build Coastguard Worker goto id_found;
342*dfc6aa5cSAndroid Build Coastguard Worker }
343*dfc6aa5cSAndroid Build Coastguard Worker
344*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
345*dfc6aa5cSAndroid Build Coastguard Worker
346*dfc6aa5cSAndroid Build Coastguard Worker id_found:
347*dfc6aa5cSAndroid Build Coastguard Worker
348*dfc6aa5cSAndroid Build Coastguard Worker cinfo->cur_comp_info[i] = compptr;
349*dfc6aa5cSAndroid Build Coastguard Worker compptr->dc_tbl_no = (c >> 4) & 15;
350*dfc6aa5cSAndroid Build Coastguard Worker compptr->ac_tbl_no = (c ) & 15;
351*dfc6aa5cSAndroid Build Coastguard Worker
352*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc,
353*dfc6aa5cSAndroid Build Coastguard Worker compptr->dc_tbl_no, compptr->ac_tbl_no);
354*dfc6aa5cSAndroid Build Coastguard Worker
355*dfc6aa5cSAndroid Build Coastguard Worker /* This CSi (cc) should differ from the previous CSi */
356*dfc6aa5cSAndroid Build Coastguard Worker for (pi = 0; pi < i; pi++) {
357*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->cur_comp_info[pi] == compptr) {
358*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
359*dfc6aa5cSAndroid Build Coastguard Worker }
360*dfc6aa5cSAndroid Build Coastguard Worker }
361*dfc6aa5cSAndroid Build Coastguard Worker }
362*dfc6aa5cSAndroid Build Coastguard Worker
363*dfc6aa5cSAndroid Build Coastguard Worker /* Collect the additional scan parameters Ss, Se, Ah/Al. */
364*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, c, return FALSE);
365*dfc6aa5cSAndroid Build Coastguard Worker cinfo->Ss = c;
366*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, c, return FALSE);
367*dfc6aa5cSAndroid Build Coastguard Worker cinfo->Se = c;
368*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, c, return FALSE);
369*dfc6aa5cSAndroid Build Coastguard Worker cinfo->Ah = (c >> 4) & 15;
370*dfc6aa5cSAndroid Build Coastguard Worker cinfo->Al = (c ) & 15;
371*dfc6aa5cSAndroid Build Coastguard Worker
372*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se,
373*dfc6aa5cSAndroid Build Coastguard Worker cinfo->Ah, cinfo->Al);
374*dfc6aa5cSAndroid Build Coastguard Worker
375*dfc6aa5cSAndroid Build Coastguard Worker /* Prepare to scan data & restart markers */
376*dfc6aa5cSAndroid Build Coastguard Worker cinfo->marker->next_restart_num = 0;
377*dfc6aa5cSAndroid Build Coastguard Worker
378*dfc6aa5cSAndroid Build Coastguard Worker /* Count another SOS marker */
379*dfc6aa5cSAndroid Build Coastguard Worker cinfo->input_scan_number++;
380*dfc6aa5cSAndroid Build Coastguard Worker
381*dfc6aa5cSAndroid Build Coastguard Worker INPUT_SYNC(cinfo);
382*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
383*dfc6aa5cSAndroid Build Coastguard Worker }
384*dfc6aa5cSAndroid Build Coastguard Worker
385*dfc6aa5cSAndroid Build Coastguard Worker
386*dfc6aa5cSAndroid Build Coastguard Worker #ifdef D_ARITH_CODING_SUPPORTED
387*dfc6aa5cSAndroid Build Coastguard Worker
388*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(boolean)
get_dac(j_decompress_ptr cinfo)389*dfc6aa5cSAndroid Build Coastguard Worker get_dac(j_decompress_ptr cinfo)
390*dfc6aa5cSAndroid Build Coastguard Worker /* Process a DAC marker */
391*dfc6aa5cSAndroid Build Coastguard Worker {
392*dfc6aa5cSAndroid Build Coastguard Worker JLONG length;
393*dfc6aa5cSAndroid Build Coastguard Worker int index, val;
394*dfc6aa5cSAndroid Build Coastguard Worker INPUT_VARS(cinfo);
395*dfc6aa5cSAndroid Build Coastguard Worker
396*dfc6aa5cSAndroid Build Coastguard Worker INPUT_2BYTES(cinfo, length, return FALSE);
397*dfc6aa5cSAndroid Build Coastguard Worker length -= 2;
398*dfc6aa5cSAndroid Build Coastguard Worker
399*dfc6aa5cSAndroid Build Coastguard Worker while (length > 0) {
400*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, index, return FALSE);
401*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, val, return FALSE);
402*dfc6aa5cSAndroid Build Coastguard Worker
403*dfc6aa5cSAndroid Build Coastguard Worker length -= 2;
404*dfc6aa5cSAndroid Build Coastguard Worker
405*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS2(cinfo, 1, JTRC_DAC, index, val);
406*dfc6aa5cSAndroid Build Coastguard Worker
407*dfc6aa5cSAndroid Build Coastguard Worker if (index < 0 || index >= (2 * NUM_ARITH_TBLS))
408*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT1(cinfo, JERR_DAC_INDEX, index);
409*dfc6aa5cSAndroid Build Coastguard Worker
410*dfc6aa5cSAndroid Build Coastguard Worker if (index >= NUM_ARITH_TBLS) { /* define AC table */
411*dfc6aa5cSAndroid Build Coastguard Worker cinfo->arith_ac_K[index - NUM_ARITH_TBLS] = (UINT8)val;
412*dfc6aa5cSAndroid Build Coastguard Worker } else { /* define DC table */
413*dfc6aa5cSAndroid Build Coastguard Worker cinfo->arith_dc_L[index] = (UINT8)(val & 0x0F);
414*dfc6aa5cSAndroid Build Coastguard Worker cinfo->arith_dc_U[index] = (UINT8)(val >> 4);
415*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
416*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT1(cinfo, JERR_DAC_VALUE, val);
417*dfc6aa5cSAndroid Build Coastguard Worker }
418*dfc6aa5cSAndroid Build Coastguard Worker }
419*dfc6aa5cSAndroid Build Coastguard Worker
420*dfc6aa5cSAndroid Build Coastguard Worker if (length != 0)
421*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(cinfo, JERR_BAD_LENGTH);
422*dfc6aa5cSAndroid Build Coastguard Worker
423*dfc6aa5cSAndroid Build Coastguard Worker INPUT_SYNC(cinfo);
424*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
425*dfc6aa5cSAndroid Build Coastguard Worker }
426*dfc6aa5cSAndroid Build Coastguard Worker
427*dfc6aa5cSAndroid Build Coastguard Worker #else /* !D_ARITH_CODING_SUPPORTED */
428*dfc6aa5cSAndroid Build Coastguard Worker
429*dfc6aa5cSAndroid Build Coastguard Worker #define get_dac(cinfo) skip_variable(cinfo)
430*dfc6aa5cSAndroid Build Coastguard Worker
431*dfc6aa5cSAndroid Build Coastguard Worker #endif /* D_ARITH_CODING_SUPPORTED */
432*dfc6aa5cSAndroid Build Coastguard Worker
433*dfc6aa5cSAndroid Build Coastguard Worker
434*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(boolean)
get_dht(j_decompress_ptr cinfo)435*dfc6aa5cSAndroid Build Coastguard Worker get_dht(j_decompress_ptr cinfo)
436*dfc6aa5cSAndroid Build Coastguard Worker /* Process a DHT marker */
437*dfc6aa5cSAndroid Build Coastguard Worker {
438*dfc6aa5cSAndroid Build Coastguard Worker JLONG length;
439*dfc6aa5cSAndroid Build Coastguard Worker UINT8 bits[17];
440*dfc6aa5cSAndroid Build Coastguard Worker UINT8 huffval[256];
441*dfc6aa5cSAndroid Build Coastguard Worker int i, index, count;
442*dfc6aa5cSAndroid Build Coastguard Worker JHUFF_TBL **htblptr;
443*dfc6aa5cSAndroid Build Coastguard Worker INPUT_VARS(cinfo);
444*dfc6aa5cSAndroid Build Coastguard Worker
445*dfc6aa5cSAndroid Build Coastguard Worker INPUT_2BYTES(cinfo, length, return FALSE);
446*dfc6aa5cSAndroid Build Coastguard Worker length -= 2;
447*dfc6aa5cSAndroid Build Coastguard Worker
448*dfc6aa5cSAndroid Build Coastguard Worker while (length > 16) {
449*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, index, return FALSE);
450*dfc6aa5cSAndroid Build Coastguard Worker
451*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS1(cinfo, 1, JTRC_DHT, index);
452*dfc6aa5cSAndroid Build Coastguard Worker
453*dfc6aa5cSAndroid Build Coastguard Worker bits[0] = 0;
454*dfc6aa5cSAndroid Build Coastguard Worker count = 0;
455*dfc6aa5cSAndroid Build Coastguard Worker for (i = 1; i <= 16; i++) {
456*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, bits[i], return FALSE);
457*dfc6aa5cSAndroid Build Coastguard Worker count += bits[i];
458*dfc6aa5cSAndroid Build Coastguard Worker }
459*dfc6aa5cSAndroid Build Coastguard Worker
460*dfc6aa5cSAndroid Build Coastguard Worker length -= 1 + 16;
461*dfc6aa5cSAndroid Build Coastguard Worker
462*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
463*dfc6aa5cSAndroid Build Coastguard Worker bits[1], bits[2], bits[3], bits[4],
464*dfc6aa5cSAndroid Build Coastguard Worker bits[5], bits[6], bits[7], bits[8]);
465*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
466*dfc6aa5cSAndroid Build Coastguard Worker bits[9], bits[10], bits[11], bits[12],
467*dfc6aa5cSAndroid Build Coastguard Worker bits[13], bits[14], bits[15], bits[16]);
468*dfc6aa5cSAndroid Build Coastguard Worker
469*dfc6aa5cSAndroid Build Coastguard Worker /* Here we just do minimal validation of the counts to avoid walking
470*dfc6aa5cSAndroid Build Coastguard Worker * off the end of our table space. jdhuff.c will check more carefully.
471*dfc6aa5cSAndroid Build Coastguard Worker */
472*dfc6aa5cSAndroid Build Coastguard Worker if (count > 256 || ((JLONG)count) > length)
473*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
474*dfc6aa5cSAndroid Build Coastguard Worker
475*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < count; i++)
476*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, huffval[i], return FALSE);
477*dfc6aa5cSAndroid Build Coastguard Worker
478*dfc6aa5cSAndroid Build Coastguard Worker memset(&huffval[count], 0, (256 - count) * sizeof(UINT8));
479*dfc6aa5cSAndroid Build Coastguard Worker
480*dfc6aa5cSAndroid Build Coastguard Worker length -= count;
481*dfc6aa5cSAndroid Build Coastguard Worker
482*dfc6aa5cSAndroid Build Coastguard Worker if (index & 0x10) { /* AC table definition */
483*dfc6aa5cSAndroid Build Coastguard Worker index -= 0x10;
484*dfc6aa5cSAndroid Build Coastguard Worker if (index < 0 || index >= NUM_HUFF_TBLS)
485*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT1(cinfo, JERR_DHT_INDEX, index);
486*dfc6aa5cSAndroid Build Coastguard Worker htblptr = &cinfo->ac_huff_tbl_ptrs[index];
487*dfc6aa5cSAndroid Build Coastguard Worker } else { /* DC table definition */
488*dfc6aa5cSAndroid Build Coastguard Worker if (index < 0 || index >= NUM_HUFF_TBLS)
489*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT1(cinfo, JERR_DHT_INDEX, index);
490*dfc6aa5cSAndroid Build Coastguard Worker htblptr = &cinfo->dc_huff_tbl_ptrs[index];
491*dfc6aa5cSAndroid Build Coastguard Worker }
492*dfc6aa5cSAndroid Build Coastguard Worker
493*dfc6aa5cSAndroid Build Coastguard Worker if (*htblptr == NULL)
494*dfc6aa5cSAndroid Build Coastguard Worker *htblptr = jpeg_alloc_huff_table((j_common_ptr)cinfo);
495*dfc6aa5cSAndroid Build Coastguard Worker
496*dfc6aa5cSAndroid Build Coastguard Worker memcpy((*htblptr)->bits, bits, sizeof((*htblptr)->bits));
497*dfc6aa5cSAndroid Build Coastguard Worker memcpy((*htblptr)->huffval, huffval, sizeof((*htblptr)->huffval));
498*dfc6aa5cSAndroid Build Coastguard Worker }
499*dfc6aa5cSAndroid Build Coastguard Worker
500*dfc6aa5cSAndroid Build Coastguard Worker if (length != 0)
501*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(cinfo, JERR_BAD_LENGTH);
502*dfc6aa5cSAndroid Build Coastguard Worker
503*dfc6aa5cSAndroid Build Coastguard Worker INPUT_SYNC(cinfo);
504*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
505*dfc6aa5cSAndroid Build Coastguard Worker }
506*dfc6aa5cSAndroid Build Coastguard Worker
507*dfc6aa5cSAndroid Build Coastguard Worker
508*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(boolean)
get_dqt(j_decompress_ptr cinfo)509*dfc6aa5cSAndroid Build Coastguard Worker get_dqt(j_decompress_ptr cinfo)
510*dfc6aa5cSAndroid Build Coastguard Worker /* Process a DQT marker */
511*dfc6aa5cSAndroid Build Coastguard Worker {
512*dfc6aa5cSAndroid Build Coastguard Worker JLONG length;
513*dfc6aa5cSAndroid Build Coastguard Worker int n, i, prec;
514*dfc6aa5cSAndroid Build Coastguard Worker unsigned int tmp;
515*dfc6aa5cSAndroid Build Coastguard Worker JQUANT_TBL *quant_ptr;
516*dfc6aa5cSAndroid Build Coastguard Worker INPUT_VARS(cinfo);
517*dfc6aa5cSAndroid Build Coastguard Worker
518*dfc6aa5cSAndroid Build Coastguard Worker INPUT_2BYTES(cinfo, length, return FALSE);
519*dfc6aa5cSAndroid Build Coastguard Worker length -= 2;
520*dfc6aa5cSAndroid Build Coastguard Worker
521*dfc6aa5cSAndroid Build Coastguard Worker while (length > 0) {
522*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, n, return FALSE);
523*dfc6aa5cSAndroid Build Coastguard Worker prec = n >> 4;
524*dfc6aa5cSAndroid Build Coastguard Worker n &= 0x0F;
525*dfc6aa5cSAndroid Build Coastguard Worker
526*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS2(cinfo, 1, JTRC_DQT, n, prec);
527*dfc6aa5cSAndroid Build Coastguard Worker
528*dfc6aa5cSAndroid Build Coastguard Worker if (n >= NUM_QUANT_TBLS)
529*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT1(cinfo, JERR_DQT_INDEX, n);
530*dfc6aa5cSAndroid Build Coastguard Worker
531*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->quant_tbl_ptrs[n] == NULL)
532*dfc6aa5cSAndroid Build Coastguard Worker cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr)cinfo);
533*dfc6aa5cSAndroid Build Coastguard Worker quant_ptr = cinfo->quant_tbl_ptrs[n];
534*dfc6aa5cSAndroid Build Coastguard Worker
535*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE2; i++) {
536*dfc6aa5cSAndroid Build Coastguard Worker if (prec)
537*dfc6aa5cSAndroid Build Coastguard Worker INPUT_2BYTES(cinfo, tmp, return FALSE);
538*dfc6aa5cSAndroid Build Coastguard Worker else
539*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, tmp, return FALSE);
540*dfc6aa5cSAndroid Build Coastguard Worker /* We convert the zigzag-order table to natural array order. */
541*dfc6aa5cSAndroid Build Coastguard Worker quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16)tmp;
542*dfc6aa5cSAndroid Build Coastguard Worker }
543*dfc6aa5cSAndroid Build Coastguard Worker
544*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->err->trace_level >= 2) {
545*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE2; i += 8) {
546*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS8(cinfo, 2, JTRC_QUANTVALS,
547*dfc6aa5cSAndroid Build Coastguard Worker quant_ptr->quantval[i], quant_ptr->quantval[i + 1],
548*dfc6aa5cSAndroid Build Coastguard Worker quant_ptr->quantval[i + 2], quant_ptr->quantval[i + 3],
549*dfc6aa5cSAndroid Build Coastguard Worker quant_ptr->quantval[i + 4], quant_ptr->quantval[i + 5],
550*dfc6aa5cSAndroid Build Coastguard Worker quant_ptr->quantval[i + 6], quant_ptr->quantval[i + 7]);
551*dfc6aa5cSAndroid Build Coastguard Worker }
552*dfc6aa5cSAndroid Build Coastguard Worker }
553*dfc6aa5cSAndroid Build Coastguard Worker
554*dfc6aa5cSAndroid Build Coastguard Worker length -= DCTSIZE2 + 1;
555*dfc6aa5cSAndroid Build Coastguard Worker if (prec) length -= DCTSIZE2;
556*dfc6aa5cSAndroid Build Coastguard Worker }
557*dfc6aa5cSAndroid Build Coastguard Worker
558*dfc6aa5cSAndroid Build Coastguard Worker if (length != 0)
559*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(cinfo, JERR_BAD_LENGTH);
560*dfc6aa5cSAndroid Build Coastguard Worker
561*dfc6aa5cSAndroid Build Coastguard Worker INPUT_SYNC(cinfo);
562*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
563*dfc6aa5cSAndroid Build Coastguard Worker }
564*dfc6aa5cSAndroid Build Coastguard Worker
565*dfc6aa5cSAndroid Build Coastguard Worker
566*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(boolean)
get_dri(j_decompress_ptr cinfo)567*dfc6aa5cSAndroid Build Coastguard Worker get_dri(j_decompress_ptr cinfo)
568*dfc6aa5cSAndroid Build Coastguard Worker /* Process a DRI marker */
569*dfc6aa5cSAndroid Build Coastguard Worker {
570*dfc6aa5cSAndroid Build Coastguard Worker JLONG length;
571*dfc6aa5cSAndroid Build Coastguard Worker unsigned int tmp;
572*dfc6aa5cSAndroid Build Coastguard Worker INPUT_VARS(cinfo);
573*dfc6aa5cSAndroid Build Coastguard Worker
574*dfc6aa5cSAndroid Build Coastguard Worker INPUT_2BYTES(cinfo, length, return FALSE);
575*dfc6aa5cSAndroid Build Coastguard Worker
576*dfc6aa5cSAndroid Build Coastguard Worker if (length != 4)
577*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(cinfo, JERR_BAD_LENGTH);
578*dfc6aa5cSAndroid Build Coastguard Worker
579*dfc6aa5cSAndroid Build Coastguard Worker INPUT_2BYTES(cinfo, tmp, return FALSE);
580*dfc6aa5cSAndroid Build Coastguard Worker
581*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS1(cinfo, 1, JTRC_DRI, tmp);
582*dfc6aa5cSAndroid Build Coastguard Worker
583*dfc6aa5cSAndroid Build Coastguard Worker cinfo->restart_interval = tmp;
584*dfc6aa5cSAndroid Build Coastguard Worker
585*dfc6aa5cSAndroid Build Coastguard Worker INPUT_SYNC(cinfo);
586*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
587*dfc6aa5cSAndroid Build Coastguard Worker }
588*dfc6aa5cSAndroid Build Coastguard Worker
589*dfc6aa5cSAndroid Build Coastguard Worker
590*dfc6aa5cSAndroid Build Coastguard Worker /*
591*dfc6aa5cSAndroid Build Coastguard Worker * Routines for processing APPn and COM markers.
592*dfc6aa5cSAndroid Build Coastguard Worker * These are either saved in memory or discarded, per application request.
593*dfc6aa5cSAndroid Build Coastguard Worker * APP0 and APP14 are specially checked to see if they are
594*dfc6aa5cSAndroid Build Coastguard Worker * JFIF and Adobe markers, respectively.
595*dfc6aa5cSAndroid Build Coastguard Worker */
596*dfc6aa5cSAndroid Build Coastguard Worker
597*dfc6aa5cSAndroid Build Coastguard Worker #define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */
598*dfc6aa5cSAndroid Build Coastguard Worker #define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */
599*dfc6aa5cSAndroid Build Coastguard Worker #define APPN_DATA_LEN 14 /* Must be the largest of the above!! */
600*dfc6aa5cSAndroid Build Coastguard Worker
601*dfc6aa5cSAndroid Build Coastguard Worker
602*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
examine_app0(j_decompress_ptr cinfo,JOCTET * data,unsigned int datalen,JLONG remaining)603*dfc6aa5cSAndroid Build Coastguard Worker examine_app0(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,
604*dfc6aa5cSAndroid Build Coastguard Worker JLONG remaining)
605*dfc6aa5cSAndroid Build Coastguard Worker /* Examine first few bytes from an APP0.
606*dfc6aa5cSAndroid Build Coastguard Worker * Take appropriate action if it is a JFIF marker.
607*dfc6aa5cSAndroid Build Coastguard Worker * datalen is # of bytes at data[], remaining is length of rest of marker data.
608*dfc6aa5cSAndroid Build Coastguard Worker */
609*dfc6aa5cSAndroid Build Coastguard Worker {
610*dfc6aa5cSAndroid Build Coastguard Worker JLONG totallen = (JLONG)datalen + remaining;
611*dfc6aa5cSAndroid Build Coastguard Worker
612*dfc6aa5cSAndroid Build Coastguard Worker if (datalen >= APP0_DATA_LEN &&
613*dfc6aa5cSAndroid Build Coastguard Worker data[0] == 0x4A &&
614*dfc6aa5cSAndroid Build Coastguard Worker data[1] == 0x46 &&
615*dfc6aa5cSAndroid Build Coastguard Worker data[2] == 0x49 &&
616*dfc6aa5cSAndroid Build Coastguard Worker data[3] == 0x46 &&
617*dfc6aa5cSAndroid Build Coastguard Worker data[4] == 0) {
618*dfc6aa5cSAndroid Build Coastguard Worker /* Found JFIF APP0 marker: save info */
619*dfc6aa5cSAndroid Build Coastguard Worker cinfo->saw_JFIF_marker = TRUE;
620*dfc6aa5cSAndroid Build Coastguard Worker cinfo->JFIF_major_version = data[5];
621*dfc6aa5cSAndroid Build Coastguard Worker cinfo->JFIF_minor_version = data[6];
622*dfc6aa5cSAndroid Build Coastguard Worker cinfo->density_unit = data[7];
623*dfc6aa5cSAndroid Build Coastguard Worker cinfo->X_density = (data[8] << 8) + data[9];
624*dfc6aa5cSAndroid Build Coastguard Worker cinfo->Y_density = (data[10] << 8) + data[11];
625*dfc6aa5cSAndroid Build Coastguard Worker /* Check version.
626*dfc6aa5cSAndroid Build Coastguard Worker * Major version must be 1, anything else signals an incompatible change.
627*dfc6aa5cSAndroid Build Coastguard Worker * (We used to treat this as an error, but now it's a nonfatal warning,
628*dfc6aa5cSAndroid Build Coastguard Worker * because some bozo at Hijaak couldn't read the spec.)
629*dfc6aa5cSAndroid Build Coastguard Worker * Minor version should be 0..2, but process anyway if newer.
630*dfc6aa5cSAndroid Build Coastguard Worker */
631*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->JFIF_major_version != 1)
632*dfc6aa5cSAndroid Build Coastguard Worker WARNMS2(cinfo, JWRN_JFIF_MAJOR,
633*dfc6aa5cSAndroid Build Coastguard Worker cinfo->JFIF_major_version, cinfo->JFIF_minor_version);
634*dfc6aa5cSAndroid Build Coastguard Worker /* Generate trace messages */
635*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS5(cinfo, 1, JTRC_JFIF,
636*dfc6aa5cSAndroid Build Coastguard Worker cinfo->JFIF_major_version, cinfo->JFIF_minor_version,
637*dfc6aa5cSAndroid Build Coastguard Worker cinfo->X_density, cinfo->Y_density, cinfo->density_unit);
638*dfc6aa5cSAndroid Build Coastguard Worker /* Validate thumbnail dimensions and issue appropriate messages */
639*dfc6aa5cSAndroid Build Coastguard Worker if (data[12] | data[13])
640*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, data[12], data[13]);
641*dfc6aa5cSAndroid Build Coastguard Worker totallen -= APP0_DATA_LEN;
642*dfc6aa5cSAndroid Build Coastguard Worker if (totallen != ((JLONG)data[12] * (JLONG)data[13] * (JLONG)3))
643*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int)totallen);
644*dfc6aa5cSAndroid Build Coastguard Worker } else if (datalen >= 6 &&
645*dfc6aa5cSAndroid Build Coastguard Worker data[0] == 0x4A &&
646*dfc6aa5cSAndroid Build Coastguard Worker data[1] == 0x46 &&
647*dfc6aa5cSAndroid Build Coastguard Worker data[2] == 0x58 &&
648*dfc6aa5cSAndroid Build Coastguard Worker data[3] == 0x58 &&
649*dfc6aa5cSAndroid Build Coastguard Worker data[4] == 0) {
650*dfc6aa5cSAndroid Build Coastguard Worker /* Found JFIF "JFXX" extension APP0 marker */
651*dfc6aa5cSAndroid Build Coastguard Worker /* The library doesn't actually do anything with these,
652*dfc6aa5cSAndroid Build Coastguard Worker * but we try to produce a helpful trace message.
653*dfc6aa5cSAndroid Build Coastguard Worker */
654*dfc6aa5cSAndroid Build Coastguard Worker switch (data[5]) {
655*dfc6aa5cSAndroid Build Coastguard Worker case 0x10:
656*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int)totallen);
657*dfc6aa5cSAndroid Build Coastguard Worker break;
658*dfc6aa5cSAndroid Build Coastguard Worker case 0x11:
659*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int)totallen);
660*dfc6aa5cSAndroid Build Coastguard Worker break;
661*dfc6aa5cSAndroid Build Coastguard Worker case 0x13:
662*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int)totallen);
663*dfc6aa5cSAndroid Build Coastguard Worker break;
664*dfc6aa5cSAndroid Build Coastguard Worker default:
665*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, data[5], (int)totallen);
666*dfc6aa5cSAndroid Build Coastguard Worker break;
667*dfc6aa5cSAndroid Build Coastguard Worker }
668*dfc6aa5cSAndroid Build Coastguard Worker } else {
669*dfc6aa5cSAndroid Build Coastguard Worker /* Start of APP0 does not match "JFIF" or "JFXX", or too short */
670*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS1(cinfo, 1, JTRC_APP0, (int)totallen);
671*dfc6aa5cSAndroid Build Coastguard Worker }
672*dfc6aa5cSAndroid Build Coastguard Worker }
673*dfc6aa5cSAndroid Build Coastguard Worker
674*dfc6aa5cSAndroid Build Coastguard Worker
675*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
examine_app14(j_decompress_ptr cinfo,JOCTET * data,unsigned int datalen,JLONG remaining)676*dfc6aa5cSAndroid Build Coastguard Worker examine_app14(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,
677*dfc6aa5cSAndroid Build Coastguard Worker JLONG remaining)
678*dfc6aa5cSAndroid Build Coastguard Worker /* Examine first few bytes from an APP14.
679*dfc6aa5cSAndroid Build Coastguard Worker * Take appropriate action if it is an Adobe marker.
680*dfc6aa5cSAndroid Build Coastguard Worker * datalen is # of bytes at data[], remaining is length of rest of marker data.
681*dfc6aa5cSAndroid Build Coastguard Worker */
682*dfc6aa5cSAndroid Build Coastguard Worker {
683*dfc6aa5cSAndroid Build Coastguard Worker unsigned int version, flags0, flags1, transform;
684*dfc6aa5cSAndroid Build Coastguard Worker
685*dfc6aa5cSAndroid Build Coastguard Worker if (datalen >= APP14_DATA_LEN &&
686*dfc6aa5cSAndroid Build Coastguard Worker data[0] == 0x41 &&
687*dfc6aa5cSAndroid Build Coastguard Worker data[1] == 0x64 &&
688*dfc6aa5cSAndroid Build Coastguard Worker data[2] == 0x6F &&
689*dfc6aa5cSAndroid Build Coastguard Worker data[3] == 0x62 &&
690*dfc6aa5cSAndroid Build Coastguard Worker data[4] == 0x65) {
691*dfc6aa5cSAndroid Build Coastguard Worker /* Found Adobe APP14 marker */
692*dfc6aa5cSAndroid Build Coastguard Worker version = (data[5] << 8) + data[6];
693*dfc6aa5cSAndroid Build Coastguard Worker flags0 = (data[7] << 8) + data[8];
694*dfc6aa5cSAndroid Build Coastguard Worker flags1 = (data[9] << 8) + data[10];
695*dfc6aa5cSAndroid Build Coastguard Worker transform = data[11];
696*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform);
697*dfc6aa5cSAndroid Build Coastguard Worker cinfo->saw_Adobe_marker = TRUE;
698*dfc6aa5cSAndroid Build Coastguard Worker cinfo->Adobe_transform = (UINT8)transform;
699*dfc6aa5cSAndroid Build Coastguard Worker } else {
700*dfc6aa5cSAndroid Build Coastguard Worker /* Start of APP14 does not match "Adobe", or too short */
701*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS1(cinfo, 1, JTRC_APP14, (int)(datalen + remaining));
702*dfc6aa5cSAndroid Build Coastguard Worker }
703*dfc6aa5cSAndroid Build Coastguard Worker }
704*dfc6aa5cSAndroid Build Coastguard Worker
705*dfc6aa5cSAndroid Build Coastguard Worker
706*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(boolean)
get_interesting_appn(j_decompress_ptr cinfo)707*dfc6aa5cSAndroid Build Coastguard Worker get_interesting_appn(j_decompress_ptr cinfo)
708*dfc6aa5cSAndroid Build Coastguard Worker /* Process an APP0 or APP14 marker without saving it */
709*dfc6aa5cSAndroid Build Coastguard Worker {
710*dfc6aa5cSAndroid Build Coastguard Worker JLONG length;
711*dfc6aa5cSAndroid Build Coastguard Worker JOCTET b[APPN_DATA_LEN];
712*dfc6aa5cSAndroid Build Coastguard Worker unsigned int i, numtoread;
713*dfc6aa5cSAndroid Build Coastguard Worker INPUT_VARS(cinfo);
714*dfc6aa5cSAndroid Build Coastguard Worker
715*dfc6aa5cSAndroid Build Coastguard Worker INPUT_2BYTES(cinfo, length, return FALSE);
716*dfc6aa5cSAndroid Build Coastguard Worker length -= 2;
717*dfc6aa5cSAndroid Build Coastguard Worker
718*dfc6aa5cSAndroid Build Coastguard Worker /* get the interesting part of the marker data */
719*dfc6aa5cSAndroid Build Coastguard Worker if (length >= APPN_DATA_LEN)
720*dfc6aa5cSAndroid Build Coastguard Worker numtoread = APPN_DATA_LEN;
721*dfc6aa5cSAndroid Build Coastguard Worker else if (length > 0)
722*dfc6aa5cSAndroid Build Coastguard Worker numtoread = (unsigned int)length;
723*dfc6aa5cSAndroid Build Coastguard Worker else
724*dfc6aa5cSAndroid Build Coastguard Worker numtoread = 0;
725*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < numtoread; i++)
726*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, b[i], return FALSE);
727*dfc6aa5cSAndroid Build Coastguard Worker length -= numtoread;
728*dfc6aa5cSAndroid Build Coastguard Worker
729*dfc6aa5cSAndroid Build Coastguard Worker /* process it */
730*dfc6aa5cSAndroid Build Coastguard Worker switch (cinfo->unread_marker) {
731*dfc6aa5cSAndroid Build Coastguard Worker case M_APP0:
732*dfc6aa5cSAndroid Build Coastguard Worker examine_app0(cinfo, (JOCTET *)b, numtoread, length);
733*dfc6aa5cSAndroid Build Coastguard Worker break;
734*dfc6aa5cSAndroid Build Coastguard Worker case M_APP14:
735*dfc6aa5cSAndroid Build Coastguard Worker examine_app14(cinfo, (JOCTET *)b, numtoread, length);
736*dfc6aa5cSAndroid Build Coastguard Worker break;
737*dfc6aa5cSAndroid Build Coastguard Worker default:
738*dfc6aa5cSAndroid Build Coastguard Worker /* can't get here unless jpeg_save_markers chooses wrong processor */
739*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker);
740*dfc6aa5cSAndroid Build Coastguard Worker break;
741*dfc6aa5cSAndroid Build Coastguard Worker }
742*dfc6aa5cSAndroid Build Coastguard Worker
743*dfc6aa5cSAndroid Build Coastguard Worker /* skip any remaining data -- could be lots */
744*dfc6aa5cSAndroid Build Coastguard Worker INPUT_SYNC(cinfo);
745*dfc6aa5cSAndroid Build Coastguard Worker if (length > 0)
746*dfc6aa5cSAndroid Build Coastguard Worker (*cinfo->src->skip_input_data) (cinfo, (long)length);
747*dfc6aa5cSAndroid Build Coastguard Worker
748*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
749*dfc6aa5cSAndroid Build Coastguard Worker }
750*dfc6aa5cSAndroid Build Coastguard Worker
751*dfc6aa5cSAndroid Build Coastguard Worker
752*dfc6aa5cSAndroid Build Coastguard Worker #ifdef SAVE_MARKERS_SUPPORTED
753*dfc6aa5cSAndroid Build Coastguard Worker
754*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(boolean)
save_marker(j_decompress_ptr cinfo)755*dfc6aa5cSAndroid Build Coastguard Worker save_marker(j_decompress_ptr cinfo)
756*dfc6aa5cSAndroid Build Coastguard Worker /* Save an APPn or COM marker into the marker list */
757*dfc6aa5cSAndroid Build Coastguard Worker {
758*dfc6aa5cSAndroid Build Coastguard Worker my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
759*dfc6aa5cSAndroid Build Coastguard Worker jpeg_saved_marker_ptr cur_marker = marker->cur_marker;
760*dfc6aa5cSAndroid Build Coastguard Worker unsigned int bytes_read, data_length;
761*dfc6aa5cSAndroid Build Coastguard Worker JOCTET *data;
762*dfc6aa5cSAndroid Build Coastguard Worker JLONG length = 0;
763*dfc6aa5cSAndroid Build Coastguard Worker INPUT_VARS(cinfo);
764*dfc6aa5cSAndroid Build Coastguard Worker
765*dfc6aa5cSAndroid Build Coastguard Worker if (cur_marker == NULL) {
766*dfc6aa5cSAndroid Build Coastguard Worker /* begin reading a marker */
767*dfc6aa5cSAndroid Build Coastguard Worker INPUT_2BYTES(cinfo, length, return FALSE);
768*dfc6aa5cSAndroid Build Coastguard Worker length -= 2;
769*dfc6aa5cSAndroid Build Coastguard Worker if (length >= 0) { /* watch out for bogus length word */
770*dfc6aa5cSAndroid Build Coastguard Worker /* figure out how much we want to save */
771*dfc6aa5cSAndroid Build Coastguard Worker unsigned int limit;
772*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->unread_marker == (int)M_COM)
773*dfc6aa5cSAndroid Build Coastguard Worker limit = marker->length_limit_COM;
774*dfc6aa5cSAndroid Build Coastguard Worker else
775*dfc6aa5cSAndroid Build Coastguard Worker limit = marker->length_limit_APPn[cinfo->unread_marker - (int)M_APP0];
776*dfc6aa5cSAndroid Build Coastguard Worker if ((unsigned int)length < limit)
777*dfc6aa5cSAndroid Build Coastguard Worker limit = (unsigned int)length;
778*dfc6aa5cSAndroid Build Coastguard Worker /* allocate and initialize the marker item */
779*dfc6aa5cSAndroid Build Coastguard Worker cur_marker = (jpeg_saved_marker_ptr)
780*dfc6aa5cSAndroid Build Coastguard Worker (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE,
781*dfc6aa5cSAndroid Build Coastguard Worker sizeof(struct jpeg_marker_struct) + limit);
782*dfc6aa5cSAndroid Build Coastguard Worker cur_marker->next = NULL;
783*dfc6aa5cSAndroid Build Coastguard Worker cur_marker->marker = (UINT8)cinfo->unread_marker;
784*dfc6aa5cSAndroid Build Coastguard Worker cur_marker->original_length = (unsigned int)length;
785*dfc6aa5cSAndroid Build Coastguard Worker cur_marker->data_length = limit;
786*dfc6aa5cSAndroid Build Coastguard Worker /* data area is just beyond the jpeg_marker_struct */
787*dfc6aa5cSAndroid Build Coastguard Worker data = cur_marker->data = (JOCTET *)(cur_marker + 1);
788*dfc6aa5cSAndroid Build Coastguard Worker marker->cur_marker = cur_marker;
789*dfc6aa5cSAndroid Build Coastguard Worker marker->bytes_read = 0;
790*dfc6aa5cSAndroid Build Coastguard Worker bytes_read = 0;
791*dfc6aa5cSAndroid Build Coastguard Worker data_length = limit;
792*dfc6aa5cSAndroid Build Coastguard Worker } else {
793*dfc6aa5cSAndroid Build Coastguard Worker /* deal with bogus length word */
794*dfc6aa5cSAndroid Build Coastguard Worker bytes_read = data_length = 0;
795*dfc6aa5cSAndroid Build Coastguard Worker data = NULL;
796*dfc6aa5cSAndroid Build Coastguard Worker }
797*dfc6aa5cSAndroid Build Coastguard Worker } else {
798*dfc6aa5cSAndroid Build Coastguard Worker /* resume reading a marker */
799*dfc6aa5cSAndroid Build Coastguard Worker bytes_read = marker->bytes_read;
800*dfc6aa5cSAndroid Build Coastguard Worker data_length = cur_marker->data_length;
801*dfc6aa5cSAndroid Build Coastguard Worker data = cur_marker->data + bytes_read;
802*dfc6aa5cSAndroid Build Coastguard Worker }
803*dfc6aa5cSAndroid Build Coastguard Worker
804*dfc6aa5cSAndroid Build Coastguard Worker while (bytes_read < data_length) {
805*dfc6aa5cSAndroid Build Coastguard Worker INPUT_SYNC(cinfo); /* move the restart point to here */
806*dfc6aa5cSAndroid Build Coastguard Worker marker->bytes_read = bytes_read;
807*dfc6aa5cSAndroid Build Coastguard Worker /* If there's not at least one byte in buffer, suspend */
808*dfc6aa5cSAndroid Build Coastguard Worker MAKE_BYTE_AVAIL(cinfo, return FALSE);
809*dfc6aa5cSAndroid Build Coastguard Worker /* Copy bytes with reasonable rapidity */
810*dfc6aa5cSAndroid Build Coastguard Worker while (bytes_read < data_length && bytes_in_buffer > 0) {
811*dfc6aa5cSAndroid Build Coastguard Worker *data++ = *next_input_byte++;
812*dfc6aa5cSAndroid Build Coastguard Worker bytes_in_buffer--;
813*dfc6aa5cSAndroid Build Coastguard Worker bytes_read++;
814*dfc6aa5cSAndroid Build Coastguard Worker }
815*dfc6aa5cSAndroid Build Coastguard Worker }
816*dfc6aa5cSAndroid Build Coastguard Worker
817*dfc6aa5cSAndroid Build Coastguard Worker /* Done reading what we want to read */
818*dfc6aa5cSAndroid Build Coastguard Worker if (cur_marker != NULL) { /* will be NULL if bogus length word */
819*dfc6aa5cSAndroid Build Coastguard Worker /* Add new marker to end of list */
820*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->marker_list == NULL || cinfo->master->marker_list_end == NULL) {
821*dfc6aa5cSAndroid Build Coastguard Worker cinfo->marker_list = cinfo->master->marker_list_end = cur_marker;
822*dfc6aa5cSAndroid Build Coastguard Worker } else {
823*dfc6aa5cSAndroid Build Coastguard Worker cinfo->master->marker_list_end->next = cur_marker;
824*dfc6aa5cSAndroid Build Coastguard Worker cinfo->master->marker_list_end = cur_marker;
825*dfc6aa5cSAndroid Build Coastguard Worker }
826*dfc6aa5cSAndroid Build Coastguard Worker /* Reset pointer & calc remaining data length */
827*dfc6aa5cSAndroid Build Coastguard Worker data = cur_marker->data;
828*dfc6aa5cSAndroid Build Coastguard Worker length = cur_marker->original_length - data_length;
829*dfc6aa5cSAndroid Build Coastguard Worker }
830*dfc6aa5cSAndroid Build Coastguard Worker /* Reset to initial state for next marker */
831*dfc6aa5cSAndroid Build Coastguard Worker marker->cur_marker = NULL;
832*dfc6aa5cSAndroid Build Coastguard Worker
833*dfc6aa5cSAndroid Build Coastguard Worker /* Process the marker if interesting; else just make a generic trace msg */
834*dfc6aa5cSAndroid Build Coastguard Worker switch (cinfo->unread_marker) {
835*dfc6aa5cSAndroid Build Coastguard Worker case M_APP0:
836*dfc6aa5cSAndroid Build Coastguard Worker examine_app0(cinfo, data, data_length, length);
837*dfc6aa5cSAndroid Build Coastguard Worker break;
838*dfc6aa5cSAndroid Build Coastguard Worker case M_APP14:
839*dfc6aa5cSAndroid Build Coastguard Worker examine_app14(cinfo, data, data_length, length);
840*dfc6aa5cSAndroid Build Coastguard Worker break;
841*dfc6aa5cSAndroid Build Coastguard Worker default:
842*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker,
843*dfc6aa5cSAndroid Build Coastguard Worker (int)(data_length + length));
844*dfc6aa5cSAndroid Build Coastguard Worker break;
845*dfc6aa5cSAndroid Build Coastguard Worker }
846*dfc6aa5cSAndroid Build Coastguard Worker
847*dfc6aa5cSAndroid Build Coastguard Worker /* skip any remaining data -- could be lots */
848*dfc6aa5cSAndroid Build Coastguard Worker INPUT_SYNC(cinfo); /* do before skip_input_data */
849*dfc6aa5cSAndroid Build Coastguard Worker if (length > 0)
850*dfc6aa5cSAndroid Build Coastguard Worker (*cinfo->src->skip_input_data) (cinfo, (long)length);
851*dfc6aa5cSAndroid Build Coastguard Worker
852*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
853*dfc6aa5cSAndroid Build Coastguard Worker }
854*dfc6aa5cSAndroid Build Coastguard Worker
855*dfc6aa5cSAndroid Build Coastguard Worker #endif /* SAVE_MARKERS_SUPPORTED */
856*dfc6aa5cSAndroid Build Coastguard Worker
857*dfc6aa5cSAndroid Build Coastguard Worker
858*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(boolean)
skip_variable(j_decompress_ptr cinfo)859*dfc6aa5cSAndroid Build Coastguard Worker skip_variable(j_decompress_ptr cinfo)
860*dfc6aa5cSAndroid Build Coastguard Worker /* Skip over an unknown or uninteresting variable-length marker */
861*dfc6aa5cSAndroid Build Coastguard Worker {
862*dfc6aa5cSAndroid Build Coastguard Worker JLONG length;
863*dfc6aa5cSAndroid Build Coastguard Worker INPUT_VARS(cinfo);
864*dfc6aa5cSAndroid Build Coastguard Worker
865*dfc6aa5cSAndroid Build Coastguard Worker INPUT_2BYTES(cinfo, length, return FALSE);
866*dfc6aa5cSAndroid Build Coastguard Worker length -= 2;
867*dfc6aa5cSAndroid Build Coastguard Worker
868*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int)length);
869*dfc6aa5cSAndroid Build Coastguard Worker
870*dfc6aa5cSAndroid Build Coastguard Worker INPUT_SYNC(cinfo); /* do before skip_input_data */
871*dfc6aa5cSAndroid Build Coastguard Worker if (length > 0)
872*dfc6aa5cSAndroid Build Coastguard Worker (*cinfo->src->skip_input_data) (cinfo, (long)length);
873*dfc6aa5cSAndroid Build Coastguard Worker
874*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
875*dfc6aa5cSAndroid Build Coastguard Worker }
876*dfc6aa5cSAndroid Build Coastguard Worker
877*dfc6aa5cSAndroid Build Coastguard Worker
878*dfc6aa5cSAndroid Build Coastguard Worker /*
879*dfc6aa5cSAndroid Build Coastguard Worker * Find the next JPEG marker, save it in cinfo->unread_marker.
880*dfc6aa5cSAndroid Build Coastguard Worker * Returns FALSE if had to suspend before reaching a marker;
881*dfc6aa5cSAndroid Build Coastguard Worker * in that case cinfo->unread_marker is unchanged.
882*dfc6aa5cSAndroid Build Coastguard Worker *
883*dfc6aa5cSAndroid Build Coastguard Worker * Note that the result might not be a valid marker code,
884*dfc6aa5cSAndroid Build Coastguard Worker * but it will never be 0 or FF.
885*dfc6aa5cSAndroid Build Coastguard Worker */
886*dfc6aa5cSAndroid Build Coastguard Worker
887*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(boolean)
next_marker(j_decompress_ptr cinfo)888*dfc6aa5cSAndroid Build Coastguard Worker next_marker(j_decompress_ptr cinfo)
889*dfc6aa5cSAndroid Build Coastguard Worker {
890*dfc6aa5cSAndroid Build Coastguard Worker int c;
891*dfc6aa5cSAndroid Build Coastguard Worker INPUT_VARS(cinfo);
892*dfc6aa5cSAndroid Build Coastguard Worker
893*dfc6aa5cSAndroid Build Coastguard Worker for (;;) {
894*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, c, return FALSE);
895*dfc6aa5cSAndroid Build Coastguard Worker /* Skip any non-FF bytes.
896*dfc6aa5cSAndroid Build Coastguard Worker * This may look a bit inefficient, but it will not occur in a valid file.
897*dfc6aa5cSAndroid Build Coastguard Worker * We sync after each discarded byte so that a suspending data source
898*dfc6aa5cSAndroid Build Coastguard Worker * can discard the byte from its buffer.
899*dfc6aa5cSAndroid Build Coastguard Worker */
900*dfc6aa5cSAndroid Build Coastguard Worker while (c != 0xFF) {
901*dfc6aa5cSAndroid Build Coastguard Worker cinfo->marker->discarded_bytes++;
902*dfc6aa5cSAndroid Build Coastguard Worker INPUT_SYNC(cinfo);
903*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, c, return FALSE);
904*dfc6aa5cSAndroid Build Coastguard Worker }
905*dfc6aa5cSAndroid Build Coastguard Worker /* This loop swallows any duplicate FF bytes. Extra FFs are legal as
906*dfc6aa5cSAndroid Build Coastguard Worker * pad bytes, so don't count them in discarded_bytes. We assume there
907*dfc6aa5cSAndroid Build Coastguard Worker * will not be so many consecutive FF bytes as to overflow a suspending
908*dfc6aa5cSAndroid Build Coastguard Worker * data source's input buffer.
909*dfc6aa5cSAndroid Build Coastguard Worker */
910*dfc6aa5cSAndroid Build Coastguard Worker do {
911*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, c, return FALSE);
912*dfc6aa5cSAndroid Build Coastguard Worker } while (c == 0xFF);
913*dfc6aa5cSAndroid Build Coastguard Worker if (c != 0)
914*dfc6aa5cSAndroid Build Coastguard Worker break; /* found a valid marker, exit loop */
915*dfc6aa5cSAndroid Build Coastguard Worker /* Reach here if we found a stuffed-zero data sequence (FF/00).
916*dfc6aa5cSAndroid Build Coastguard Worker * Discard it and loop back to try again.
917*dfc6aa5cSAndroid Build Coastguard Worker */
918*dfc6aa5cSAndroid Build Coastguard Worker cinfo->marker->discarded_bytes += 2;
919*dfc6aa5cSAndroid Build Coastguard Worker INPUT_SYNC(cinfo);
920*dfc6aa5cSAndroid Build Coastguard Worker }
921*dfc6aa5cSAndroid Build Coastguard Worker
922*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->marker->discarded_bytes != 0) {
923*dfc6aa5cSAndroid Build Coastguard Worker WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c);
924*dfc6aa5cSAndroid Build Coastguard Worker cinfo->marker->discarded_bytes = 0;
925*dfc6aa5cSAndroid Build Coastguard Worker }
926*dfc6aa5cSAndroid Build Coastguard Worker
927*dfc6aa5cSAndroid Build Coastguard Worker cinfo->unread_marker = c;
928*dfc6aa5cSAndroid Build Coastguard Worker
929*dfc6aa5cSAndroid Build Coastguard Worker INPUT_SYNC(cinfo);
930*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
931*dfc6aa5cSAndroid Build Coastguard Worker }
932*dfc6aa5cSAndroid Build Coastguard Worker
933*dfc6aa5cSAndroid Build Coastguard Worker
934*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(boolean)
first_marker(j_decompress_ptr cinfo)935*dfc6aa5cSAndroid Build Coastguard Worker first_marker(j_decompress_ptr cinfo)
936*dfc6aa5cSAndroid Build Coastguard Worker /* Like next_marker, but used to obtain the initial SOI marker. */
937*dfc6aa5cSAndroid Build Coastguard Worker /* For this marker, we do not allow preceding garbage or fill; otherwise,
938*dfc6aa5cSAndroid Build Coastguard Worker * we might well scan an entire input file before realizing it ain't JPEG.
939*dfc6aa5cSAndroid Build Coastguard Worker * If an application wants to process non-JFIF files, it must seek to the
940*dfc6aa5cSAndroid Build Coastguard Worker * SOI before calling the JPEG library.
941*dfc6aa5cSAndroid Build Coastguard Worker */
942*dfc6aa5cSAndroid Build Coastguard Worker {
943*dfc6aa5cSAndroid Build Coastguard Worker int c, c2;
944*dfc6aa5cSAndroid Build Coastguard Worker INPUT_VARS(cinfo);
945*dfc6aa5cSAndroid Build Coastguard Worker
946*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, c, return FALSE);
947*dfc6aa5cSAndroid Build Coastguard Worker INPUT_BYTE(cinfo, c2, return FALSE);
948*dfc6aa5cSAndroid Build Coastguard Worker if (c != 0xFF || c2 != (int)M_SOI)
949*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT2(cinfo, JERR_NO_SOI, c, c2);
950*dfc6aa5cSAndroid Build Coastguard Worker
951*dfc6aa5cSAndroid Build Coastguard Worker cinfo->unread_marker = c2;
952*dfc6aa5cSAndroid Build Coastguard Worker
953*dfc6aa5cSAndroid Build Coastguard Worker INPUT_SYNC(cinfo);
954*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
955*dfc6aa5cSAndroid Build Coastguard Worker }
956*dfc6aa5cSAndroid Build Coastguard Worker
957*dfc6aa5cSAndroid Build Coastguard Worker
958*dfc6aa5cSAndroid Build Coastguard Worker /*
959*dfc6aa5cSAndroid Build Coastguard Worker * Read markers until SOS or EOI.
960*dfc6aa5cSAndroid Build Coastguard Worker *
961*dfc6aa5cSAndroid Build Coastguard Worker * Returns same codes as are defined for jpeg_consume_input:
962*dfc6aa5cSAndroid Build Coastguard Worker * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
963*dfc6aa5cSAndroid Build Coastguard Worker */
964*dfc6aa5cSAndroid Build Coastguard Worker
965*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(int)
read_markers(j_decompress_ptr cinfo)966*dfc6aa5cSAndroid Build Coastguard Worker read_markers(j_decompress_ptr cinfo)
967*dfc6aa5cSAndroid Build Coastguard Worker {
968*dfc6aa5cSAndroid Build Coastguard Worker /* Outer loop repeats once for each marker. */
969*dfc6aa5cSAndroid Build Coastguard Worker for (;;) {
970*dfc6aa5cSAndroid Build Coastguard Worker /* Collect the marker proper, unless we already did. */
971*dfc6aa5cSAndroid Build Coastguard Worker /* NB: first_marker() enforces the requirement that SOI appear first. */
972*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->unread_marker == 0) {
973*dfc6aa5cSAndroid Build Coastguard Worker if (!cinfo->marker->saw_SOI) {
974*dfc6aa5cSAndroid Build Coastguard Worker if (!first_marker(cinfo))
975*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_SUSPENDED;
976*dfc6aa5cSAndroid Build Coastguard Worker } else {
977*dfc6aa5cSAndroid Build Coastguard Worker if (!next_marker(cinfo))
978*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_SUSPENDED;
979*dfc6aa5cSAndroid Build Coastguard Worker }
980*dfc6aa5cSAndroid Build Coastguard Worker }
981*dfc6aa5cSAndroid Build Coastguard Worker /* At this point cinfo->unread_marker contains the marker code and the
982*dfc6aa5cSAndroid Build Coastguard Worker * input point is just past the marker proper, but before any parameters.
983*dfc6aa5cSAndroid Build Coastguard Worker * A suspension will cause us to return with this state still true.
984*dfc6aa5cSAndroid Build Coastguard Worker */
985*dfc6aa5cSAndroid Build Coastguard Worker switch (cinfo->unread_marker) {
986*dfc6aa5cSAndroid Build Coastguard Worker case M_SOI:
987*dfc6aa5cSAndroid Build Coastguard Worker if (!get_soi(cinfo))
988*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_SUSPENDED;
989*dfc6aa5cSAndroid Build Coastguard Worker break;
990*dfc6aa5cSAndroid Build Coastguard Worker
991*dfc6aa5cSAndroid Build Coastguard Worker case M_SOF0: /* Baseline */
992*dfc6aa5cSAndroid Build Coastguard Worker case M_SOF1: /* Extended sequential, Huffman */
993*dfc6aa5cSAndroid Build Coastguard Worker if (!get_sof(cinfo, FALSE, FALSE))
994*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_SUSPENDED;
995*dfc6aa5cSAndroid Build Coastguard Worker break;
996*dfc6aa5cSAndroid Build Coastguard Worker
997*dfc6aa5cSAndroid Build Coastguard Worker case M_SOF2: /* Progressive, Huffman */
998*dfc6aa5cSAndroid Build Coastguard Worker if (!get_sof(cinfo, TRUE, FALSE))
999*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_SUSPENDED;
1000*dfc6aa5cSAndroid Build Coastguard Worker break;
1001*dfc6aa5cSAndroid Build Coastguard Worker
1002*dfc6aa5cSAndroid Build Coastguard Worker case M_SOF9: /* Extended sequential, arithmetic */
1003*dfc6aa5cSAndroid Build Coastguard Worker if (!get_sof(cinfo, FALSE, TRUE))
1004*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_SUSPENDED;
1005*dfc6aa5cSAndroid Build Coastguard Worker break;
1006*dfc6aa5cSAndroid Build Coastguard Worker
1007*dfc6aa5cSAndroid Build Coastguard Worker case M_SOF10: /* Progressive, arithmetic */
1008*dfc6aa5cSAndroid Build Coastguard Worker if (!get_sof(cinfo, TRUE, TRUE))
1009*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_SUSPENDED;
1010*dfc6aa5cSAndroid Build Coastguard Worker break;
1011*dfc6aa5cSAndroid Build Coastguard Worker
1012*dfc6aa5cSAndroid Build Coastguard Worker /* Currently unsupported SOFn types */
1013*dfc6aa5cSAndroid Build Coastguard Worker case M_SOF3: /* Lossless, Huffman */
1014*dfc6aa5cSAndroid Build Coastguard Worker case M_SOF5: /* Differential sequential, Huffman */
1015*dfc6aa5cSAndroid Build Coastguard Worker case M_SOF6: /* Differential progressive, Huffman */
1016*dfc6aa5cSAndroid Build Coastguard Worker case M_SOF7: /* Differential lossless, Huffman */
1017*dfc6aa5cSAndroid Build Coastguard Worker case M_JPG: /* Reserved for JPEG extensions */
1018*dfc6aa5cSAndroid Build Coastguard Worker case M_SOF11: /* Lossless, arithmetic */
1019*dfc6aa5cSAndroid Build Coastguard Worker case M_SOF13: /* Differential sequential, arithmetic */
1020*dfc6aa5cSAndroid Build Coastguard Worker case M_SOF14: /* Differential progressive, arithmetic */
1021*dfc6aa5cSAndroid Build Coastguard Worker case M_SOF15: /* Differential lossless, arithmetic */
1022*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker);
1023*dfc6aa5cSAndroid Build Coastguard Worker break;
1024*dfc6aa5cSAndroid Build Coastguard Worker
1025*dfc6aa5cSAndroid Build Coastguard Worker case M_SOS:
1026*dfc6aa5cSAndroid Build Coastguard Worker if (!get_sos(cinfo))
1027*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_SUSPENDED;
1028*dfc6aa5cSAndroid Build Coastguard Worker cinfo->unread_marker = 0; /* processed the marker */
1029*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_REACHED_SOS;
1030*dfc6aa5cSAndroid Build Coastguard Worker
1031*dfc6aa5cSAndroid Build Coastguard Worker case M_EOI:
1032*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS(cinfo, 1, JTRC_EOI);
1033*dfc6aa5cSAndroid Build Coastguard Worker cinfo->unread_marker = 0; /* processed the marker */
1034*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_REACHED_EOI;
1035*dfc6aa5cSAndroid Build Coastguard Worker
1036*dfc6aa5cSAndroid Build Coastguard Worker case M_DAC:
1037*dfc6aa5cSAndroid Build Coastguard Worker if (!get_dac(cinfo))
1038*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_SUSPENDED;
1039*dfc6aa5cSAndroid Build Coastguard Worker break;
1040*dfc6aa5cSAndroid Build Coastguard Worker
1041*dfc6aa5cSAndroid Build Coastguard Worker case M_DHT:
1042*dfc6aa5cSAndroid Build Coastguard Worker if (!get_dht(cinfo))
1043*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_SUSPENDED;
1044*dfc6aa5cSAndroid Build Coastguard Worker break;
1045*dfc6aa5cSAndroid Build Coastguard Worker
1046*dfc6aa5cSAndroid Build Coastguard Worker case M_DQT:
1047*dfc6aa5cSAndroid Build Coastguard Worker if (!get_dqt(cinfo))
1048*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_SUSPENDED;
1049*dfc6aa5cSAndroid Build Coastguard Worker break;
1050*dfc6aa5cSAndroid Build Coastguard Worker
1051*dfc6aa5cSAndroid Build Coastguard Worker case M_DRI:
1052*dfc6aa5cSAndroid Build Coastguard Worker if (!get_dri(cinfo))
1053*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_SUSPENDED;
1054*dfc6aa5cSAndroid Build Coastguard Worker break;
1055*dfc6aa5cSAndroid Build Coastguard Worker
1056*dfc6aa5cSAndroid Build Coastguard Worker case M_APP0:
1057*dfc6aa5cSAndroid Build Coastguard Worker case M_APP1:
1058*dfc6aa5cSAndroid Build Coastguard Worker case M_APP2:
1059*dfc6aa5cSAndroid Build Coastguard Worker case M_APP3:
1060*dfc6aa5cSAndroid Build Coastguard Worker case M_APP4:
1061*dfc6aa5cSAndroid Build Coastguard Worker case M_APP5:
1062*dfc6aa5cSAndroid Build Coastguard Worker case M_APP6:
1063*dfc6aa5cSAndroid Build Coastguard Worker case M_APP7:
1064*dfc6aa5cSAndroid Build Coastguard Worker case M_APP8:
1065*dfc6aa5cSAndroid Build Coastguard Worker case M_APP9:
1066*dfc6aa5cSAndroid Build Coastguard Worker case M_APP10:
1067*dfc6aa5cSAndroid Build Coastguard Worker case M_APP11:
1068*dfc6aa5cSAndroid Build Coastguard Worker case M_APP12:
1069*dfc6aa5cSAndroid Build Coastguard Worker case M_APP13:
1070*dfc6aa5cSAndroid Build Coastguard Worker case M_APP14:
1071*dfc6aa5cSAndroid Build Coastguard Worker case M_APP15:
1072*dfc6aa5cSAndroid Build Coastguard Worker if (!(*((my_marker_ptr)cinfo->marker)->process_APPn[
1073*dfc6aa5cSAndroid Build Coastguard Worker cinfo->unread_marker - (int)M_APP0]) (cinfo))
1074*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_SUSPENDED;
1075*dfc6aa5cSAndroid Build Coastguard Worker break;
1076*dfc6aa5cSAndroid Build Coastguard Worker
1077*dfc6aa5cSAndroid Build Coastguard Worker case M_COM:
1078*dfc6aa5cSAndroid Build Coastguard Worker if (!(*((my_marker_ptr)cinfo->marker)->process_COM) (cinfo))
1079*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_SUSPENDED;
1080*dfc6aa5cSAndroid Build Coastguard Worker break;
1081*dfc6aa5cSAndroid Build Coastguard Worker
1082*dfc6aa5cSAndroid Build Coastguard Worker case M_RST0: /* these are all parameterless */
1083*dfc6aa5cSAndroid Build Coastguard Worker case M_RST1:
1084*dfc6aa5cSAndroid Build Coastguard Worker case M_RST2:
1085*dfc6aa5cSAndroid Build Coastguard Worker case M_RST3:
1086*dfc6aa5cSAndroid Build Coastguard Worker case M_RST4:
1087*dfc6aa5cSAndroid Build Coastguard Worker case M_RST5:
1088*dfc6aa5cSAndroid Build Coastguard Worker case M_RST6:
1089*dfc6aa5cSAndroid Build Coastguard Worker case M_RST7:
1090*dfc6aa5cSAndroid Build Coastguard Worker case M_TEM:
1091*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker);
1092*dfc6aa5cSAndroid Build Coastguard Worker break;
1093*dfc6aa5cSAndroid Build Coastguard Worker
1094*dfc6aa5cSAndroid Build Coastguard Worker case M_DNL: /* Ignore DNL ... perhaps the wrong thing */
1095*dfc6aa5cSAndroid Build Coastguard Worker if (!skip_variable(cinfo))
1096*dfc6aa5cSAndroid Build Coastguard Worker return JPEG_SUSPENDED;
1097*dfc6aa5cSAndroid Build Coastguard Worker break;
1098*dfc6aa5cSAndroid Build Coastguard Worker
1099*dfc6aa5cSAndroid Build Coastguard Worker default: /* must be DHP, EXP, JPGn, or RESn */
1100*dfc6aa5cSAndroid Build Coastguard Worker /* For now, we treat the reserved markers as fatal errors since they are
1101*dfc6aa5cSAndroid Build Coastguard Worker * likely to be used to signal incompatible JPEG Part 3 extensions.
1102*dfc6aa5cSAndroid Build Coastguard Worker * Once the JPEG 3 version-number marker is well defined, this code
1103*dfc6aa5cSAndroid Build Coastguard Worker * ought to change!
1104*dfc6aa5cSAndroid Build Coastguard Worker */
1105*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker);
1106*dfc6aa5cSAndroid Build Coastguard Worker break;
1107*dfc6aa5cSAndroid Build Coastguard Worker }
1108*dfc6aa5cSAndroid Build Coastguard Worker /* Successfully processed marker, so reset state variable */
1109*dfc6aa5cSAndroid Build Coastguard Worker cinfo->unread_marker = 0;
1110*dfc6aa5cSAndroid Build Coastguard Worker } /* end loop */
1111*dfc6aa5cSAndroid Build Coastguard Worker }
1112*dfc6aa5cSAndroid Build Coastguard Worker
1113*dfc6aa5cSAndroid Build Coastguard Worker
1114*dfc6aa5cSAndroid Build Coastguard Worker /*
1115*dfc6aa5cSAndroid Build Coastguard Worker * Read a restart marker, which is expected to appear next in the datastream;
1116*dfc6aa5cSAndroid Build Coastguard Worker * if the marker is not there, take appropriate recovery action.
1117*dfc6aa5cSAndroid Build Coastguard Worker * Returns FALSE if suspension is required.
1118*dfc6aa5cSAndroid Build Coastguard Worker *
1119*dfc6aa5cSAndroid Build Coastguard Worker * This is called by the entropy decoder after it has read an appropriate
1120*dfc6aa5cSAndroid Build Coastguard Worker * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder
1121*dfc6aa5cSAndroid Build Coastguard Worker * has already read a marker from the data source. Under normal conditions
1122*dfc6aa5cSAndroid Build Coastguard Worker * cinfo->unread_marker will be reset to 0 before returning; if not reset,
1123*dfc6aa5cSAndroid Build Coastguard Worker * it holds a marker which the decoder will be unable to read past.
1124*dfc6aa5cSAndroid Build Coastguard Worker */
1125*dfc6aa5cSAndroid Build Coastguard Worker
1126*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(boolean)
read_restart_marker(j_decompress_ptr cinfo)1127*dfc6aa5cSAndroid Build Coastguard Worker read_restart_marker(j_decompress_ptr cinfo)
1128*dfc6aa5cSAndroid Build Coastguard Worker {
1129*dfc6aa5cSAndroid Build Coastguard Worker /* Obtain a marker unless we already did. */
1130*dfc6aa5cSAndroid Build Coastguard Worker /* Note that next_marker will complain if it skips any data. */
1131*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->unread_marker == 0) {
1132*dfc6aa5cSAndroid Build Coastguard Worker if (!next_marker(cinfo))
1133*dfc6aa5cSAndroid Build Coastguard Worker return FALSE;
1134*dfc6aa5cSAndroid Build Coastguard Worker }
1135*dfc6aa5cSAndroid Build Coastguard Worker
1136*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->unread_marker ==
1137*dfc6aa5cSAndroid Build Coastguard Worker ((int)M_RST0 + cinfo->marker->next_restart_num)) {
1138*dfc6aa5cSAndroid Build Coastguard Worker /* Normal case --- swallow the marker and let entropy decoder continue */
1139*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num);
1140*dfc6aa5cSAndroid Build Coastguard Worker cinfo->unread_marker = 0;
1141*dfc6aa5cSAndroid Build Coastguard Worker } else {
1142*dfc6aa5cSAndroid Build Coastguard Worker /* Uh-oh, the restart markers have been messed up. */
1143*dfc6aa5cSAndroid Build Coastguard Worker /* Let the data source manager determine how to resync. */
1144*dfc6aa5cSAndroid Build Coastguard Worker if (!(*cinfo->src->resync_to_restart) (cinfo,
1145*dfc6aa5cSAndroid Build Coastguard Worker cinfo->marker->next_restart_num))
1146*dfc6aa5cSAndroid Build Coastguard Worker return FALSE;
1147*dfc6aa5cSAndroid Build Coastguard Worker }
1148*dfc6aa5cSAndroid Build Coastguard Worker
1149*dfc6aa5cSAndroid Build Coastguard Worker /* Update next-restart state */
1150*dfc6aa5cSAndroid Build Coastguard Worker cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7;
1151*dfc6aa5cSAndroid Build Coastguard Worker
1152*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
1153*dfc6aa5cSAndroid Build Coastguard Worker }
1154*dfc6aa5cSAndroid Build Coastguard Worker
1155*dfc6aa5cSAndroid Build Coastguard Worker
1156*dfc6aa5cSAndroid Build Coastguard Worker /*
1157*dfc6aa5cSAndroid Build Coastguard Worker * This is the default resync_to_restart method for data source managers
1158*dfc6aa5cSAndroid Build Coastguard Worker * to use if they don't have any better approach. Some data source managers
1159*dfc6aa5cSAndroid Build Coastguard Worker * may be able to back up, or may have additional knowledge about the data
1160*dfc6aa5cSAndroid Build Coastguard Worker * which permits a more intelligent recovery strategy; such managers would
1161*dfc6aa5cSAndroid Build Coastguard Worker * presumably supply their own resync method.
1162*dfc6aa5cSAndroid Build Coastguard Worker *
1163*dfc6aa5cSAndroid Build Coastguard Worker * read_restart_marker calls resync_to_restart if it finds a marker other than
1164*dfc6aa5cSAndroid Build Coastguard Worker * the restart marker it was expecting. (This code is *not* used unless
1165*dfc6aa5cSAndroid Build Coastguard Worker * a nonzero restart interval has been declared.) cinfo->unread_marker is
1166*dfc6aa5cSAndroid Build Coastguard Worker * the marker code actually found (might be anything, except 0 or FF).
1167*dfc6aa5cSAndroid Build Coastguard Worker * The desired restart marker number (0..7) is passed as a parameter.
1168*dfc6aa5cSAndroid Build Coastguard Worker * This routine is supposed to apply whatever error recovery strategy seems
1169*dfc6aa5cSAndroid Build Coastguard Worker * appropriate in order to position the input stream to the next data segment.
1170*dfc6aa5cSAndroid Build Coastguard Worker * Note that cinfo->unread_marker is treated as a marker appearing before
1171*dfc6aa5cSAndroid Build Coastguard Worker * the current data-source input point; usually it should be reset to zero
1172*dfc6aa5cSAndroid Build Coastguard Worker * before returning.
1173*dfc6aa5cSAndroid Build Coastguard Worker * Returns FALSE if suspension is required.
1174*dfc6aa5cSAndroid Build Coastguard Worker *
1175*dfc6aa5cSAndroid Build Coastguard Worker * This implementation is substantially constrained by wanting to treat the
1176*dfc6aa5cSAndroid Build Coastguard Worker * input as a data stream; this means we can't back up. Therefore, we have
1177*dfc6aa5cSAndroid Build Coastguard Worker * only the following actions to work with:
1178*dfc6aa5cSAndroid Build Coastguard Worker * 1. Simply discard the marker and let the entropy decoder resume at next
1179*dfc6aa5cSAndroid Build Coastguard Worker * byte of file.
1180*dfc6aa5cSAndroid Build Coastguard Worker * 2. Read forward until we find another marker, discarding intervening
1181*dfc6aa5cSAndroid Build Coastguard Worker * data. (In theory we could look ahead within the current bufferload,
1182*dfc6aa5cSAndroid Build Coastguard Worker * without having to discard data if we don't find the desired marker.
1183*dfc6aa5cSAndroid Build Coastguard Worker * This idea is not implemented here, in part because it makes behavior
1184*dfc6aa5cSAndroid Build Coastguard Worker * dependent on buffer size and chance buffer-boundary positions.)
1185*dfc6aa5cSAndroid Build Coastguard Worker * 3. Leave the marker unread (by failing to zero cinfo->unread_marker).
1186*dfc6aa5cSAndroid Build Coastguard Worker * This will cause the entropy decoder to process an empty data segment,
1187*dfc6aa5cSAndroid Build Coastguard Worker * inserting dummy zeroes, and then we will reprocess the marker.
1188*dfc6aa5cSAndroid Build Coastguard Worker *
1189*dfc6aa5cSAndroid Build Coastguard Worker * #2 is appropriate if we think the desired marker lies ahead, while #3 is
1190*dfc6aa5cSAndroid Build Coastguard Worker * appropriate if the found marker is a future restart marker (indicating
1191*dfc6aa5cSAndroid Build Coastguard Worker * that we have missed the desired restart marker, probably because it got
1192*dfc6aa5cSAndroid Build Coastguard Worker * corrupted).
1193*dfc6aa5cSAndroid Build Coastguard Worker * We apply #2 or #3 if the found marker is a restart marker no more than
1194*dfc6aa5cSAndroid Build Coastguard Worker * two counts behind or ahead of the expected one. We also apply #2 if the
1195*dfc6aa5cSAndroid Build Coastguard Worker * found marker is not a legal JPEG marker code (it's certainly bogus data).
1196*dfc6aa5cSAndroid Build Coastguard Worker * If the found marker is a restart marker more than 2 counts away, we do #1
1197*dfc6aa5cSAndroid Build Coastguard Worker * (too much risk that the marker is erroneous; with luck we will be able to
1198*dfc6aa5cSAndroid Build Coastguard Worker * resync at some future point).
1199*dfc6aa5cSAndroid Build Coastguard Worker * For any valid non-restart JPEG marker, we apply #3. This keeps us from
1200*dfc6aa5cSAndroid Build Coastguard Worker * overrunning the end of a scan. An implementation limited to single-scan
1201*dfc6aa5cSAndroid Build Coastguard Worker * files might find it better to apply #2 for markers other than EOI, since
1202*dfc6aa5cSAndroid Build Coastguard Worker * any other marker would have to be bogus data in that case.
1203*dfc6aa5cSAndroid Build Coastguard Worker */
1204*dfc6aa5cSAndroid Build Coastguard Worker
1205*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(boolean)
jpeg_resync_to_restart(j_decompress_ptr cinfo,int desired)1206*dfc6aa5cSAndroid Build Coastguard Worker jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired)
1207*dfc6aa5cSAndroid Build Coastguard Worker {
1208*dfc6aa5cSAndroid Build Coastguard Worker int marker = cinfo->unread_marker;
1209*dfc6aa5cSAndroid Build Coastguard Worker int action = 1;
1210*dfc6aa5cSAndroid Build Coastguard Worker
1211*dfc6aa5cSAndroid Build Coastguard Worker /* Always put up a warning. */
1212*dfc6aa5cSAndroid Build Coastguard Worker WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired);
1213*dfc6aa5cSAndroid Build Coastguard Worker
1214*dfc6aa5cSAndroid Build Coastguard Worker /* Outer loop handles repeated decision after scanning forward. */
1215*dfc6aa5cSAndroid Build Coastguard Worker for (;;) {
1216*dfc6aa5cSAndroid Build Coastguard Worker if (marker < (int)M_SOF0)
1217*dfc6aa5cSAndroid Build Coastguard Worker action = 2; /* invalid marker */
1218*dfc6aa5cSAndroid Build Coastguard Worker else if (marker < (int)M_RST0 || marker > (int)M_RST7)
1219*dfc6aa5cSAndroid Build Coastguard Worker action = 3; /* valid non-restart marker */
1220*dfc6aa5cSAndroid Build Coastguard Worker else {
1221*dfc6aa5cSAndroid Build Coastguard Worker if (marker == ((int)M_RST0 + ((desired + 1) & 7)) ||
1222*dfc6aa5cSAndroid Build Coastguard Worker marker == ((int)M_RST0 + ((desired + 2) & 7)))
1223*dfc6aa5cSAndroid Build Coastguard Worker action = 3; /* one of the next two expected restarts */
1224*dfc6aa5cSAndroid Build Coastguard Worker else if (marker == ((int)M_RST0 + ((desired - 1) & 7)) ||
1225*dfc6aa5cSAndroid Build Coastguard Worker marker == ((int)M_RST0 + ((desired - 2) & 7)))
1226*dfc6aa5cSAndroid Build Coastguard Worker action = 2; /* a prior restart, so advance */
1227*dfc6aa5cSAndroid Build Coastguard Worker else
1228*dfc6aa5cSAndroid Build Coastguard Worker action = 1; /* desired restart or too far away */
1229*dfc6aa5cSAndroid Build Coastguard Worker }
1230*dfc6aa5cSAndroid Build Coastguard Worker TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action);
1231*dfc6aa5cSAndroid Build Coastguard Worker switch (action) {
1232*dfc6aa5cSAndroid Build Coastguard Worker case 1:
1233*dfc6aa5cSAndroid Build Coastguard Worker /* Discard marker and let entropy decoder resume processing. */
1234*dfc6aa5cSAndroid Build Coastguard Worker cinfo->unread_marker = 0;
1235*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
1236*dfc6aa5cSAndroid Build Coastguard Worker case 2:
1237*dfc6aa5cSAndroid Build Coastguard Worker /* Scan to the next marker, and repeat the decision loop. */
1238*dfc6aa5cSAndroid Build Coastguard Worker if (!next_marker(cinfo))
1239*dfc6aa5cSAndroid Build Coastguard Worker return FALSE;
1240*dfc6aa5cSAndroid Build Coastguard Worker marker = cinfo->unread_marker;
1241*dfc6aa5cSAndroid Build Coastguard Worker break;
1242*dfc6aa5cSAndroid Build Coastguard Worker case 3:
1243*dfc6aa5cSAndroid Build Coastguard Worker /* Return without advancing past this marker. */
1244*dfc6aa5cSAndroid Build Coastguard Worker /* Entropy decoder will be forced to process an empty segment. */
1245*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
1246*dfc6aa5cSAndroid Build Coastguard Worker }
1247*dfc6aa5cSAndroid Build Coastguard Worker } /* end loop */
1248*dfc6aa5cSAndroid Build Coastguard Worker }
1249*dfc6aa5cSAndroid Build Coastguard Worker
1250*dfc6aa5cSAndroid Build Coastguard Worker
1251*dfc6aa5cSAndroid Build Coastguard Worker /*
1252*dfc6aa5cSAndroid Build Coastguard Worker * Reset marker processing state to begin a fresh datastream.
1253*dfc6aa5cSAndroid Build Coastguard Worker */
1254*dfc6aa5cSAndroid Build Coastguard Worker
1255*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
reset_marker_reader(j_decompress_ptr cinfo)1256*dfc6aa5cSAndroid Build Coastguard Worker reset_marker_reader(j_decompress_ptr cinfo)
1257*dfc6aa5cSAndroid Build Coastguard Worker {
1258*dfc6aa5cSAndroid Build Coastguard Worker my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
1259*dfc6aa5cSAndroid Build Coastguard Worker
1260*dfc6aa5cSAndroid Build Coastguard Worker cinfo->comp_info = NULL; /* until allocated by get_sof */
1261*dfc6aa5cSAndroid Build Coastguard Worker cinfo->input_scan_number = 0; /* no SOS seen yet */
1262*dfc6aa5cSAndroid Build Coastguard Worker cinfo->unread_marker = 0; /* no pending marker */
1263*dfc6aa5cSAndroid Build Coastguard Worker marker->pub.saw_SOI = FALSE; /* set internal state too */
1264*dfc6aa5cSAndroid Build Coastguard Worker marker->pub.saw_SOF = FALSE;
1265*dfc6aa5cSAndroid Build Coastguard Worker marker->pub.discarded_bytes = 0;
1266*dfc6aa5cSAndroid Build Coastguard Worker marker->cur_marker = NULL;
1267*dfc6aa5cSAndroid Build Coastguard Worker }
1268*dfc6aa5cSAndroid Build Coastguard Worker
1269*dfc6aa5cSAndroid Build Coastguard Worker
1270*dfc6aa5cSAndroid Build Coastguard Worker /*
1271*dfc6aa5cSAndroid Build Coastguard Worker * Initialize the marker reader module.
1272*dfc6aa5cSAndroid Build Coastguard Worker * This is called only once, when the decompression object is created.
1273*dfc6aa5cSAndroid Build Coastguard Worker */
1274*dfc6aa5cSAndroid Build Coastguard Worker
1275*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(void)
jinit_marker_reader(j_decompress_ptr cinfo)1276*dfc6aa5cSAndroid Build Coastguard Worker jinit_marker_reader(j_decompress_ptr cinfo)
1277*dfc6aa5cSAndroid Build Coastguard Worker {
1278*dfc6aa5cSAndroid Build Coastguard Worker my_marker_ptr marker;
1279*dfc6aa5cSAndroid Build Coastguard Worker int i;
1280*dfc6aa5cSAndroid Build Coastguard Worker
1281*dfc6aa5cSAndroid Build Coastguard Worker /* Create subobject in permanent pool */
1282*dfc6aa5cSAndroid Build Coastguard Worker marker = (my_marker_ptr)
1283*dfc6aa5cSAndroid Build Coastguard Worker (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
1284*dfc6aa5cSAndroid Build Coastguard Worker sizeof(my_marker_reader));
1285*dfc6aa5cSAndroid Build Coastguard Worker cinfo->marker = (struct jpeg_marker_reader *)marker;
1286*dfc6aa5cSAndroid Build Coastguard Worker /* Initialize public method pointers */
1287*dfc6aa5cSAndroid Build Coastguard Worker marker->pub.reset_marker_reader = reset_marker_reader;
1288*dfc6aa5cSAndroid Build Coastguard Worker marker->pub.read_markers = read_markers;
1289*dfc6aa5cSAndroid Build Coastguard Worker marker->pub.read_restart_marker = read_restart_marker;
1290*dfc6aa5cSAndroid Build Coastguard Worker /* Initialize COM/APPn processing.
1291*dfc6aa5cSAndroid Build Coastguard Worker * By default, we examine and then discard APP0 and APP14,
1292*dfc6aa5cSAndroid Build Coastguard Worker * but simply discard COM and all other APPn.
1293*dfc6aa5cSAndroid Build Coastguard Worker */
1294*dfc6aa5cSAndroid Build Coastguard Worker marker->process_COM = skip_variable;
1295*dfc6aa5cSAndroid Build Coastguard Worker marker->length_limit_COM = 0;
1296*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < 16; i++) {
1297*dfc6aa5cSAndroid Build Coastguard Worker marker->process_APPn[i] = skip_variable;
1298*dfc6aa5cSAndroid Build Coastguard Worker marker->length_limit_APPn[i] = 0;
1299*dfc6aa5cSAndroid Build Coastguard Worker }
1300*dfc6aa5cSAndroid Build Coastguard Worker marker->process_APPn[0] = get_interesting_appn;
1301*dfc6aa5cSAndroid Build Coastguard Worker marker->process_APPn[14] = get_interesting_appn;
1302*dfc6aa5cSAndroid Build Coastguard Worker /* Reset marker processing state */
1303*dfc6aa5cSAndroid Build Coastguard Worker reset_marker_reader(cinfo);
1304*dfc6aa5cSAndroid Build Coastguard Worker }
1305*dfc6aa5cSAndroid Build Coastguard Worker
1306*dfc6aa5cSAndroid Build Coastguard Worker
1307*dfc6aa5cSAndroid Build Coastguard Worker /*
1308*dfc6aa5cSAndroid Build Coastguard Worker * Control saving of COM and APPn markers into marker_list.
1309*dfc6aa5cSAndroid Build Coastguard Worker */
1310*dfc6aa5cSAndroid Build Coastguard Worker
1311*dfc6aa5cSAndroid Build Coastguard Worker #ifdef SAVE_MARKERS_SUPPORTED
1312*dfc6aa5cSAndroid Build Coastguard Worker
1313*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(void)
jpeg_save_markers(j_decompress_ptr cinfo,int marker_code,unsigned int length_limit)1314*dfc6aa5cSAndroid Build Coastguard Worker jpeg_save_markers(j_decompress_ptr cinfo, int marker_code,
1315*dfc6aa5cSAndroid Build Coastguard Worker unsigned int length_limit)
1316*dfc6aa5cSAndroid Build Coastguard Worker {
1317*dfc6aa5cSAndroid Build Coastguard Worker my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
1318*dfc6aa5cSAndroid Build Coastguard Worker long maxlength;
1319*dfc6aa5cSAndroid Build Coastguard Worker jpeg_marker_parser_method processor;
1320*dfc6aa5cSAndroid Build Coastguard Worker
1321*dfc6aa5cSAndroid Build Coastguard Worker /* Length limit mustn't be larger than what we can allocate
1322*dfc6aa5cSAndroid Build Coastguard Worker * (should only be a concern in a 16-bit environment).
1323*dfc6aa5cSAndroid Build Coastguard Worker */
1324*dfc6aa5cSAndroid Build Coastguard Worker maxlength = cinfo->mem->max_alloc_chunk - sizeof(struct jpeg_marker_struct);
1325*dfc6aa5cSAndroid Build Coastguard Worker if (((long)length_limit) > maxlength)
1326*dfc6aa5cSAndroid Build Coastguard Worker length_limit = (unsigned int)maxlength;
1327*dfc6aa5cSAndroid Build Coastguard Worker
1328*dfc6aa5cSAndroid Build Coastguard Worker /* Choose processor routine to use.
1329*dfc6aa5cSAndroid Build Coastguard Worker * APP0/APP14 have special requirements.
1330*dfc6aa5cSAndroid Build Coastguard Worker */
1331*dfc6aa5cSAndroid Build Coastguard Worker if (length_limit) {
1332*dfc6aa5cSAndroid Build Coastguard Worker processor = save_marker;
1333*dfc6aa5cSAndroid Build Coastguard Worker /* If saving APP0/APP14, save at least enough for our internal use. */
1334*dfc6aa5cSAndroid Build Coastguard Worker if (marker_code == (int)M_APP0 && length_limit < APP0_DATA_LEN)
1335*dfc6aa5cSAndroid Build Coastguard Worker length_limit = APP0_DATA_LEN;
1336*dfc6aa5cSAndroid Build Coastguard Worker else if (marker_code == (int)M_APP14 && length_limit < APP14_DATA_LEN)
1337*dfc6aa5cSAndroid Build Coastguard Worker length_limit = APP14_DATA_LEN;
1338*dfc6aa5cSAndroid Build Coastguard Worker } else {
1339*dfc6aa5cSAndroid Build Coastguard Worker processor = skip_variable;
1340*dfc6aa5cSAndroid Build Coastguard Worker /* If discarding APP0/APP14, use our regular on-the-fly processor. */
1341*dfc6aa5cSAndroid Build Coastguard Worker if (marker_code == (int)M_APP0 || marker_code == (int)M_APP14)
1342*dfc6aa5cSAndroid Build Coastguard Worker processor = get_interesting_appn;
1343*dfc6aa5cSAndroid Build Coastguard Worker }
1344*dfc6aa5cSAndroid Build Coastguard Worker
1345*dfc6aa5cSAndroid Build Coastguard Worker if (marker_code == (int)M_COM) {
1346*dfc6aa5cSAndroid Build Coastguard Worker marker->process_COM = processor;
1347*dfc6aa5cSAndroid Build Coastguard Worker marker->length_limit_COM = length_limit;
1348*dfc6aa5cSAndroid Build Coastguard Worker } else if (marker_code >= (int)M_APP0 && marker_code <= (int)M_APP15) {
1349*dfc6aa5cSAndroid Build Coastguard Worker marker->process_APPn[marker_code - (int)M_APP0] = processor;
1350*dfc6aa5cSAndroid Build Coastguard Worker marker->length_limit_APPn[marker_code - (int)M_APP0] = length_limit;
1351*dfc6aa5cSAndroid Build Coastguard Worker } else
1352*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
1353*dfc6aa5cSAndroid Build Coastguard Worker }
1354*dfc6aa5cSAndroid Build Coastguard Worker
1355*dfc6aa5cSAndroid Build Coastguard Worker #endif /* SAVE_MARKERS_SUPPORTED */
1356*dfc6aa5cSAndroid Build Coastguard Worker
1357*dfc6aa5cSAndroid Build Coastguard Worker
1358*dfc6aa5cSAndroid Build Coastguard Worker /*
1359*dfc6aa5cSAndroid Build Coastguard Worker * Install a special processing method for COM or APPn markers.
1360*dfc6aa5cSAndroid Build Coastguard Worker */
1361*dfc6aa5cSAndroid Build Coastguard Worker
1362*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(void)
jpeg_set_marker_processor(j_decompress_ptr cinfo,int marker_code,jpeg_marker_parser_method routine)1363*dfc6aa5cSAndroid Build Coastguard Worker jpeg_set_marker_processor(j_decompress_ptr cinfo, int marker_code,
1364*dfc6aa5cSAndroid Build Coastguard Worker jpeg_marker_parser_method routine)
1365*dfc6aa5cSAndroid Build Coastguard Worker {
1366*dfc6aa5cSAndroid Build Coastguard Worker my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
1367*dfc6aa5cSAndroid Build Coastguard Worker
1368*dfc6aa5cSAndroid Build Coastguard Worker if (marker_code == (int)M_COM)
1369*dfc6aa5cSAndroid Build Coastguard Worker marker->process_COM = routine;
1370*dfc6aa5cSAndroid Build Coastguard Worker else if (marker_code >= (int)M_APP0 && marker_code <= (int)M_APP15)
1371*dfc6aa5cSAndroid Build Coastguard Worker marker->process_APPn[marker_code - (int)M_APP0] = routine;
1372*dfc6aa5cSAndroid Build Coastguard Worker else
1373*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
1374*dfc6aa5cSAndroid Build Coastguard Worker }
1375