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