1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file.
5
6 #include "lib/jxl/jpeg/enc_jpeg_data_reader.h"
7
8 #include <inttypes.h>
9 #include <string.h>
10
11 #include <algorithm>
12 #include <string>
13 #include <vector>
14
15 #include "lib/jxl/base/status.h"
16 #include "lib/jxl/common.h"
17 #include "lib/jxl/jpeg/enc_jpeg_huffman_decode.h"
18 #include "lib/jxl/jpeg/jpeg_data.h"
19
20 // By default only print debug messages when JXL_DEBUG_ON_ERROR is enabled.
21 #ifndef JXL_DEBUG_JPEG_DATA_READER
22 #define JXL_DEBUG_JPEG_DATA_READER JXL_DEBUG_ON_ERROR
23 #endif // JXL_DEBUG_JPEG_DATA_READER
24
25 #define JXL_JPEG_DEBUG(format, ...) \
26 JXL_DEBUG(JXL_DEBUG_JPEG_DATA_READER, format, ##__VA_ARGS__)
27
28 namespace jxl {
29 namespace jpeg {
30
31 namespace {
32 static const int kBrunsliMaxSampling = 15;
33 static const size_t kBrunsliMaxNumBlocks = 1ull << 24;
34
35 // Macros for commonly used error conditions.
36
37 #define JXL_JPEG_VERIFY_LEN(n) \
38 if (*pos + (n) > len) { \
39 JXL_JPEG_DEBUG("Unexpected end of input: pos=%zu need=%d len=%zu", *pos, \
40 static_cast<int>(n), len); \
41 jpg->error = JPEGReadError::UNEXPECTED_EOF; \
42 return false; \
43 }
44
45 #define JXL_JPEG_VERIFY_INPUT(var, low, high, code) \
46 if ((var) < (low) || (var) > (high)) { \
47 JXL_JPEG_DEBUG("Invalid " #var ": %d", static_cast<int>(var)); \
48 jpg->error = JPEGReadError::INVALID_##code; \
49 return false; \
50 }
51
52 #define JXL_JPEG_VERIFY_MARKER_END() \
53 if (start_pos + marker_len != *pos) { \
54 JXL_JPEG_DEBUG("Invalid marker length: declared=%zu actual=%zu", \
55 marker_len, (*pos - start_pos)); \
56 jpg->error = JPEGReadError::WRONG_MARKER_SIZE; \
57 return false; \
58 }
59
60 #define JXL_JPEG_EXPECT_MARKER() \
61 if (pos + 2 > len || data[pos] != 0xff) { \
62 JXL_JPEG_DEBUG( \
63 "Marker byte (0xff) expected, found: 0x%.2x pos=%zu len=%zu", \
64 (pos < len ? data[pos] : 0), pos, len); \
65 jpg->error = JPEGReadError::MARKER_BYTE_NOT_FOUND; \
66 return false; \
67 }
68
ReadUint8(const uint8_t * data,size_t * pos)69 inline int ReadUint8(const uint8_t* data, size_t* pos) {
70 return data[(*pos)++];
71 }
72
ReadUint16(const uint8_t * data,size_t * pos)73 inline int ReadUint16(const uint8_t* data, size_t* pos) {
74 int v = (data[*pos] << 8) + data[*pos + 1];
75 *pos += 2;
76 return v;
77 }
78
79 // Reads the Start of Frame (SOF) marker segment and fills in *jpg with the
80 // parsed data.
ProcessSOF(const uint8_t * data,const size_t len,JpegReadMode mode,size_t * pos,JPEGData * jpg)81 bool ProcessSOF(const uint8_t* data, const size_t len, JpegReadMode mode,
82 size_t* pos, JPEGData* jpg) {
83 if (jpg->width != 0) {
84 JXL_JPEG_DEBUG("Duplicate SOF marker.");
85 jpg->error = JPEGReadError::DUPLICATE_SOF;
86 return false;
87 }
88 const size_t start_pos = *pos;
89 JXL_JPEG_VERIFY_LEN(8);
90 size_t marker_len = ReadUint16(data, pos);
91 int precision = ReadUint8(data, pos);
92 int height = ReadUint16(data, pos);
93 int width = ReadUint16(data, pos);
94 int num_components = ReadUint8(data, pos);
95 JXL_JPEG_VERIFY_INPUT(precision, 8, 8, PRECISION);
96 JXL_JPEG_VERIFY_INPUT(height, 1, kMaxDimPixels, HEIGHT);
97 JXL_JPEG_VERIFY_INPUT(width, 1, kMaxDimPixels, WIDTH);
98 JXL_JPEG_VERIFY_INPUT(num_components, 1, kMaxComponents, NUMCOMP);
99 JXL_JPEG_VERIFY_LEN(3 * num_components);
100 jpg->height = height;
101 jpg->width = width;
102 jpg->components.resize(num_components);
103
104 // Read sampling factors and quant table index for each component.
105 std::vector<bool> ids_seen(256, false);
106 int max_h_samp_factor = 1;
107 int max_v_samp_factor = 1;
108 for (size_t i = 0; i < jpg->components.size(); ++i) {
109 const int id = ReadUint8(data, pos);
110 if (ids_seen[id]) { // (cf. section B.2.2, syntax of Ci)
111 JXL_JPEG_DEBUG("Duplicate ID %d in SOF.", id);
112 jpg->error = JPEGReadError::DUPLICATE_COMPONENT_ID;
113 return false;
114 }
115 ids_seen[id] = true;
116 jpg->components[i].id = id;
117 int factor = ReadUint8(data, pos);
118 int h_samp_factor = factor >> 4;
119 int v_samp_factor = factor & 0xf;
120 JXL_JPEG_VERIFY_INPUT(h_samp_factor, 1, kBrunsliMaxSampling, SAMP_FACTOR);
121 JXL_JPEG_VERIFY_INPUT(v_samp_factor, 1, kBrunsliMaxSampling, SAMP_FACTOR);
122 jpg->components[i].h_samp_factor = h_samp_factor;
123 jpg->components[i].v_samp_factor = v_samp_factor;
124 jpg->components[i].quant_idx = ReadUint8(data, pos);
125 max_h_samp_factor = std::max(max_h_samp_factor, h_samp_factor);
126 max_v_samp_factor = std::max(max_v_samp_factor, v_samp_factor);
127 }
128
129 // We have checked above that none of the sampling factors are 0, so the max
130 // sampling factors can not be 0.
131 int MCU_rows = DivCeil(jpg->height, max_v_samp_factor * 8);
132 int MCU_cols = DivCeil(jpg->width, max_h_samp_factor * 8);
133 // Compute the block dimensions for each component.
134 for (size_t i = 0; i < jpg->components.size(); ++i) {
135 JPEGComponent* c = &jpg->components[i];
136 if (max_h_samp_factor % c->h_samp_factor != 0 ||
137 max_v_samp_factor % c->v_samp_factor != 0) {
138 JXL_JPEG_DEBUG("Non-integral subsampling ratios.");
139 jpg->error = JPEGReadError::INVALID_SAMPLING_FACTORS;
140 return false;
141 }
142 c->width_in_blocks = MCU_cols * c->h_samp_factor;
143 c->height_in_blocks = MCU_rows * c->v_samp_factor;
144 const uint64_t num_blocks =
145 static_cast<uint64_t>(c->width_in_blocks) * c->height_in_blocks;
146 if (num_blocks > kBrunsliMaxNumBlocks) {
147 JXL_JPEG_DEBUG("Image too large.");
148 jpg->error = JPEGReadError::IMAGE_TOO_LARGE;
149 return false;
150 }
151 if (mode == JpegReadMode::kReadAll) {
152 c->coeffs.resize(num_blocks * kDCTBlockSize);
153 }
154 }
155 JXL_JPEG_VERIFY_MARKER_END();
156 return true;
157 }
158
159 // Reads the Start of Scan (SOS) marker segment and fills in *scan_info with the
160 // parsed data.
ProcessSOS(const uint8_t * data,const size_t len,size_t * pos,JPEGData * jpg)161 bool ProcessSOS(const uint8_t* data, const size_t len, size_t* pos,
162 JPEGData* jpg) {
163 const size_t start_pos = *pos;
164 JXL_JPEG_VERIFY_LEN(3);
165 size_t marker_len = ReadUint16(data, pos);
166 size_t comps_in_scan = ReadUint8(data, pos);
167 JXL_JPEG_VERIFY_INPUT(comps_in_scan, 1, jpg->components.size(),
168 COMPS_IN_SCAN);
169
170 JPEGScanInfo scan_info;
171 scan_info.num_components = comps_in_scan;
172 JXL_JPEG_VERIFY_LEN(2 * comps_in_scan);
173 std::vector<bool> ids_seen(256, false);
174 for (size_t i = 0; i < comps_in_scan; ++i) {
175 uint32_t id = ReadUint8(data, pos);
176 if (ids_seen[id]) { // (cf. section B.2.3, regarding CSj)
177 JXL_JPEG_DEBUG("Duplicate ID %d in SOS.", id);
178 jpg->error = JPEGReadError::DUPLICATE_COMPONENT_ID;
179 return false;
180 }
181 ids_seen[id] = true;
182 bool found_index = false;
183 for (size_t j = 0; j < jpg->components.size(); ++j) {
184 if (jpg->components[j].id == id) {
185 scan_info.components[i].comp_idx = j;
186 found_index = true;
187 }
188 }
189 if (!found_index) {
190 JXL_JPEG_DEBUG("SOS marker: Could not find component with id %d", id);
191 jpg->error = JPEGReadError::COMPONENT_NOT_FOUND;
192 return false;
193 }
194 int c = ReadUint8(data, pos);
195 int dc_tbl_idx = c >> 4;
196 int ac_tbl_idx = c & 0xf;
197 JXL_JPEG_VERIFY_INPUT(dc_tbl_idx, 0, 3, HUFFMAN_INDEX);
198 JXL_JPEG_VERIFY_INPUT(ac_tbl_idx, 0, 3, HUFFMAN_INDEX);
199 scan_info.components[i].dc_tbl_idx = dc_tbl_idx;
200 scan_info.components[i].ac_tbl_idx = ac_tbl_idx;
201 }
202 JXL_JPEG_VERIFY_LEN(3);
203 scan_info.Ss = ReadUint8(data, pos);
204 scan_info.Se = ReadUint8(data, pos);
205 JXL_JPEG_VERIFY_INPUT(static_cast<int>(scan_info.Ss), 0, 63, START_OF_SCAN);
206 JXL_JPEG_VERIFY_INPUT(scan_info.Se, scan_info.Ss, 63, END_OF_SCAN);
207 int c = ReadUint8(data, pos);
208 scan_info.Ah = c >> 4;
209 scan_info.Al = c & 0xf;
210 if (scan_info.Ah != 0 && scan_info.Al != scan_info.Ah - 1) {
211 // section G.1.1.1.2 : Successive approximation control only improves
212 // by one bit at a time. But it's not always respected, so we just issue
213 // a warning.
214 JXL_WARNING("Invalid progressive parameters: Al=%d Ah=%d", scan_info.Al,
215 scan_info.Ah);
216 }
217 // Check that all the Huffman tables needed for this scan are defined.
218 for (size_t i = 0; i < comps_in_scan; ++i) {
219 bool found_dc_table = false;
220 bool found_ac_table = false;
221 for (size_t j = 0; j < jpg->huffman_code.size(); ++j) {
222 uint32_t slot_id = jpg->huffman_code[j].slot_id;
223 if (slot_id == scan_info.components[i].dc_tbl_idx) {
224 found_dc_table = true;
225 } else if (slot_id == scan_info.components[i].ac_tbl_idx + 16) {
226 found_ac_table = true;
227 }
228 }
229 if (scan_info.Ss == 0 && !found_dc_table) {
230 JXL_JPEG_DEBUG(
231 "SOS marker: Could not find DC Huffman table with index %d",
232 scan_info.components[i].dc_tbl_idx);
233 jpg->error = JPEGReadError::HUFFMAN_TABLE_NOT_FOUND;
234 return false;
235 }
236 if (scan_info.Se > 0 && !found_ac_table) {
237 JXL_JPEG_DEBUG(
238 "SOS marker: Could not find AC Huffman table with index %d",
239 scan_info.components[i].ac_tbl_idx);
240 jpg->error = JPEGReadError::HUFFMAN_TABLE_NOT_FOUND;
241 return false;
242 }
243 }
244 jpg->scan_info.push_back(scan_info);
245 JXL_JPEG_VERIFY_MARKER_END();
246 return true;
247 }
248
249 // Reads the Define Huffman Table (DHT) marker segment and fills in *jpg with
250 // the parsed data. Builds the Huffman decoding table in either dc_huff_lut or
251 // ac_huff_lut, depending on the type and solt_id of Huffman code being read.
ProcessDHT(const uint8_t * data,const size_t len,JpegReadMode mode,std::vector<HuffmanTableEntry> * dc_huff_lut,std::vector<HuffmanTableEntry> * ac_huff_lut,size_t * pos,JPEGData * jpg)252 bool ProcessDHT(const uint8_t* data, const size_t len, JpegReadMode mode,
253 std::vector<HuffmanTableEntry>* dc_huff_lut,
254 std::vector<HuffmanTableEntry>* ac_huff_lut, size_t* pos,
255 JPEGData* jpg) {
256 const size_t start_pos = *pos;
257 JXL_JPEG_VERIFY_LEN(2);
258 size_t marker_len = ReadUint16(data, pos);
259 if (marker_len == 2) {
260 JXL_JPEG_DEBUG("DHT marker: no Huffman table found");
261 jpg->error = JPEGReadError::EMPTY_DHT;
262 return false;
263 }
264 while (*pos < start_pos + marker_len) {
265 JXL_JPEG_VERIFY_LEN(1 + kJpegHuffmanMaxBitLength);
266 JPEGHuffmanCode huff;
267 huff.slot_id = ReadUint8(data, pos);
268 int huffman_index = huff.slot_id;
269 int is_ac_table = (huff.slot_id & 0x10) != 0;
270 HuffmanTableEntry* huff_lut;
271 if (is_ac_table) {
272 huffman_index -= 0x10;
273 JXL_JPEG_VERIFY_INPUT(huffman_index, 0, 3, HUFFMAN_INDEX);
274 huff_lut = &(*ac_huff_lut)[huffman_index * kJpegHuffmanLutSize];
275 } else {
276 JXL_JPEG_VERIFY_INPUT(huffman_index, 0, 3, HUFFMAN_INDEX);
277 huff_lut = &(*dc_huff_lut)[huffman_index * kJpegHuffmanLutSize];
278 }
279 huff.counts[0] = 0;
280 int total_count = 0;
281 int space = 1 << kJpegHuffmanMaxBitLength;
282 int max_depth = 1;
283 for (size_t i = 1; i <= kJpegHuffmanMaxBitLength; ++i) {
284 int count = ReadUint8(data, pos);
285 if (count != 0) {
286 max_depth = i;
287 }
288 huff.counts[i] = count;
289 total_count += count;
290 space -= count * (1 << (kJpegHuffmanMaxBitLength - i));
291 }
292 if (is_ac_table) {
293 JXL_JPEG_VERIFY_INPUT(total_count, 0, kJpegHuffmanAlphabetSize,
294 HUFFMAN_CODE);
295 } else {
296 JXL_JPEG_VERIFY_INPUT(total_count, 0, kJpegDCAlphabetSize, HUFFMAN_CODE);
297 }
298 JXL_JPEG_VERIFY_LEN(total_count);
299 std::vector<bool> values_seen(256, false);
300 for (int i = 0; i < total_count; ++i) {
301 int value = ReadUint8(data, pos);
302 if (!is_ac_table) {
303 JXL_JPEG_VERIFY_INPUT(value, 0, kJpegDCAlphabetSize - 1, HUFFMAN_CODE);
304 }
305 if (values_seen[value]) {
306 JXL_JPEG_DEBUG("Duplicate Huffman code value %d", value);
307 jpg->error = JPEGReadError::INVALID_HUFFMAN_CODE;
308 return false;
309 }
310 values_seen[value] = true;
311 huff.values[i] = value;
312 }
313 // Add an invalid symbol that will have the all 1 code.
314 ++huff.counts[max_depth];
315 huff.values[total_count] = kJpegHuffmanAlphabetSize;
316 space -= (1 << (kJpegHuffmanMaxBitLength - max_depth));
317 if (space < 0) {
318 JXL_JPEG_DEBUG("Invalid Huffman code lengths.");
319 jpg->error = JPEGReadError::INVALID_HUFFMAN_CODE;
320 return false;
321 } else if (space > 0 && huff_lut[0].value != 0xffff) {
322 // Re-initialize the values to an invalid symbol so that we can recognize
323 // it when reading the bit stream using a Huffman code with space > 0.
324 for (int i = 0; i < kJpegHuffmanLutSize; ++i) {
325 huff_lut[i].bits = 0;
326 huff_lut[i].value = 0xffff;
327 }
328 }
329 huff.is_last = (*pos == start_pos + marker_len);
330 if (mode == JpegReadMode::kReadAll) {
331 BuildJpegHuffmanTable(&huff.counts[0], &huff.values[0], huff_lut);
332 }
333 jpg->huffman_code.push_back(huff);
334 }
335 JXL_JPEG_VERIFY_MARKER_END();
336 return true;
337 }
338
339 // Reads the Define Quantization Table (DQT) marker segment and fills in *jpg
340 // with the parsed data.
ProcessDQT(const uint8_t * data,const size_t len,size_t * pos,JPEGData * jpg)341 bool ProcessDQT(const uint8_t* data, const size_t len, size_t* pos,
342 JPEGData* jpg) {
343 const size_t start_pos = *pos;
344 JXL_JPEG_VERIFY_LEN(2);
345 size_t marker_len = ReadUint16(data, pos);
346 if (marker_len == 2) {
347 JXL_JPEG_DEBUG("DQT marker: no quantization table found");
348 jpg->error = JPEGReadError::EMPTY_DQT;
349 return false;
350 }
351 while (*pos < start_pos + marker_len && jpg->quant.size() < kMaxQuantTables) {
352 JXL_JPEG_VERIFY_LEN(1);
353 int quant_table_index = ReadUint8(data, pos);
354 int quant_table_precision = quant_table_index >> 4;
355 JXL_JPEG_VERIFY_INPUT(quant_table_precision, 0, 1, QUANT_TBL_PRECISION);
356 quant_table_index &= 0xf;
357 JXL_JPEG_VERIFY_INPUT(quant_table_index, 0, 3, QUANT_TBL_INDEX);
358 JXL_JPEG_VERIFY_LEN((quant_table_precision + 1) * kDCTBlockSize);
359 JPEGQuantTable table;
360 table.index = quant_table_index;
361 table.precision = quant_table_precision;
362 for (size_t i = 0; i < kDCTBlockSize; ++i) {
363 int quant_val =
364 quant_table_precision ? ReadUint16(data, pos) : ReadUint8(data, pos);
365 JXL_JPEG_VERIFY_INPUT(quant_val, 1, 65535, QUANT_VAL);
366 table.values[kJPEGNaturalOrder[i]] = quant_val;
367 }
368 table.is_last = (*pos == start_pos + marker_len);
369 jpg->quant.push_back(table);
370 }
371 JXL_JPEG_VERIFY_MARKER_END();
372 return true;
373 }
374
375 // Reads the DRI marker and saves the restart interval into *jpg.
ProcessDRI(const uint8_t * data,const size_t len,size_t * pos,bool * found_dri,JPEGData * jpg)376 bool ProcessDRI(const uint8_t* data, const size_t len, size_t* pos,
377 bool* found_dri, JPEGData* jpg) {
378 if (*found_dri) {
379 JXL_JPEG_DEBUG("Duplicate DRI marker.");
380 jpg->error = JPEGReadError::DUPLICATE_DRI;
381 return false;
382 }
383 *found_dri = true;
384 const size_t start_pos = *pos;
385 JXL_JPEG_VERIFY_LEN(4);
386 size_t marker_len = ReadUint16(data, pos);
387 int restart_interval = ReadUint16(data, pos);
388 jpg->restart_interval = restart_interval;
389 JXL_JPEG_VERIFY_MARKER_END();
390 return true;
391 }
392
393 // Saves the APP marker segment as a string to *jpg.
ProcessAPP(const uint8_t * data,const size_t len,size_t * pos,JPEGData * jpg)394 bool ProcessAPP(const uint8_t* data, const size_t len, size_t* pos,
395 JPEGData* jpg) {
396 JXL_JPEG_VERIFY_LEN(2);
397 size_t marker_len = ReadUint16(data, pos);
398 JXL_JPEG_VERIFY_INPUT(marker_len, 2, 65535, MARKER_LEN);
399 JXL_JPEG_VERIFY_LEN(marker_len - 2);
400 JXL_DASSERT(*pos >= 3);
401 // Save the marker type together with the app data.
402 const uint8_t* app_str_start = data + *pos - 3;
403 std::vector<uint8_t> app_str(app_str_start, app_str_start + marker_len + 1);
404 *pos += marker_len - 2;
405 jpg->app_data.push_back(app_str);
406 return true;
407 }
408
409 // Saves the COM marker segment as a string to *jpg.
ProcessCOM(const uint8_t * data,const size_t len,size_t * pos,JPEGData * jpg)410 bool ProcessCOM(const uint8_t* data, const size_t len, size_t* pos,
411 JPEGData* jpg) {
412 JXL_JPEG_VERIFY_LEN(2);
413 size_t marker_len = ReadUint16(data, pos);
414 JXL_JPEG_VERIFY_INPUT(marker_len, 2, 65535, MARKER_LEN);
415 JXL_JPEG_VERIFY_LEN(marker_len - 2);
416 const uint8_t* com_str_start = data + *pos - 3;
417 std::vector<uint8_t> com_str(com_str_start, com_str_start + marker_len + 1);
418 *pos += marker_len - 2;
419 jpg->com_data.push_back(com_str);
420 return true;
421 }
422
423 // Helper structure to read bits from the entropy coded data segment.
424 struct BitReaderState {
BitReaderStatejxl::jpeg::__anon59df6e1c0111::BitReaderState425 BitReaderState(const uint8_t* data, const size_t len, size_t pos)
426 : data_(data), len_(len) {
427 Reset(pos);
428 }
429
Resetjxl::jpeg::__anon59df6e1c0111::BitReaderState430 void Reset(size_t pos) {
431 pos_ = pos;
432 val_ = 0;
433 bits_left_ = 0;
434 next_marker_pos_ = len_ - 2;
435 FillBitWindow();
436 }
437
438 // Returns the next byte and skips the 0xff/0x00 escape sequences.
GetNextBytejxl::jpeg::__anon59df6e1c0111::BitReaderState439 uint8_t GetNextByte() {
440 if (pos_ >= next_marker_pos_) {
441 ++pos_;
442 return 0;
443 }
444 uint8_t c = data_[pos_++];
445 if (c == 0xff) {
446 uint8_t escape = data_[pos_];
447 if (escape == 0) {
448 ++pos_;
449 } else {
450 // 0xff was followed by a non-zero byte, which means that we found the
451 // start of the next marker segment.
452 next_marker_pos_ = pos_ - 1;
453 }
454 }
455 return c;
456 }
457
FillBitWindowjxl::jpeg::__anon59df6e1c0111::BitReaderState458 void FillBitWindow() {
459 if (bits_left_ <= 16) {
460 while (bits_left_ <= 56) {
461 val_ <<= 8;
462 val_ |= (uint64_t)GetNextByte();
463 bits_left_ += 8;
464 }
465 }
466 }
467
ReadBitsjxl::jpeg::__anon59df6e1c0111::BitReaderState468 int ReadBits(int nbits) {
469 FillBitWindow();
470 uint64_t val = (val_ >> (bits_left_ - nbits)) & ((1ULL << nbits) - 1);
471 bits_left_ -= nbits;
472 return val;
473 }
474
475 // Sets *pos to the next stream position where parsing should continue.
476 // Enqueue the padding bits seen (0 or 1).
477 // Returns false if there is inconsistent or invalid padding or the stream
478 // ended too early.
FinishStreamjxl::jpeg::__anon59df6e1c0111::BitReaderState479 bool FinishStream(JPEGData* jpg, size_t* pos) {
480 int npadbits = bits_left_ & 7;
481 if (npadbits > 0) {
482 uint64_t padmask = (1ULL << npadbits) - 1;
483 uint64_t padbits = (val_ >> (bits_left_ - npadbits)) & padmask;
484 if (padbits != padmask) {
485 jpg->has_zero_padding_bit = true;
486 }
487 for (int i = npadbits - 1; i >= 0; --i) {
488 jpg->padding_bits.push_back((padbits >> i) & 1);
489 }
490 }
491 // Give back some bytes that we did not use.
492 int unused_bytes_left = bits_left_ >> 3;
493 while (unused_bytes_left-- > 0) {
494 --pos_;
495 // If we give back a 0 byte, we need to check if it was a 0xff/0x00 escape
496 // sequence, and if yes, we need to give back one more byte.
497 if (pos_ < next_marker_pos_ && data_[pos_] == 0 &&
498 data_[pos_ - 1] == 0xff) {
499 --pos_;
500 }
501 }
502 if (pos_ > next_marker_pos_) {
503 // Data ran out before the scan was complete.
504 JXL_JPEG_DEBUG("Unexpected end of scan.");
505 return false;
506 }
507 *pos = pos_;
508 return true;
509 }
510
511 const uint8_t* data_;
512 const size_t len_;
513 size_t pos_;
514 uint64_t val_;
515 int bits_left_;
516 size_t next_marker_pos_;
517 };
518
519 // Returns the next Huffman-coded symbol.
ReadSymbol(const HuffmanTableEntry * table,BitReaderState * br)520 int ReadSymbol(const HuffmanTableEntry* table, BitReaderState* br) {
521 int nbits;
522 br->FillBitWindow();
523 int val = (br->val_ >> (br->bits_left_ - 8)) & 0xff;
524 table += val;
525 nbits = table->bits - 8;
526 if (nbits > 0) {
527 br->bits_left_ -= 8;
528 table += table->value;
529 val = (br->val_ >> (br->bits_left_ - nbits)) & ((1 << nbits) - 1);
530 table += val;
531 }
532 br->bits_left_ -= table->bits;
533 return table->value;
534 }
535
536 /**
537 * Returns the DC diff or AC value for extra bits value x and prefix code s.
538 *
539 * CCITT Rec. T.81 (1992 E)
540 * Table F.1 – Difference magnitude categories for DC coding
541 * SSSS | DIFF values
542 * ------+--------------------------
543 * 0 | 0
544 * 1 | –1, 1
545 * 2 | –3, –2, 2, 3
546 * 3 | –7..–4, 4..7
547 * ......|..........................
548 * 11 | –2047..–1024, 1024..2047
549 *
550 * CCITT Rec. T.81 (1992 E)
551 * Table F.2 – Categories assigned to coefficient values
552 * [ Same as Table F.1, but does not include SSSS equal to 0 and 11]
553 *
554 *
555 * CCITT Rec. T.81 (1992 E)
556 * F.1.2.1.1 Structure of DC code table
557 * For each category,... additional bits... appended... to uniquely identify
558 * which difference... occurred... When DIFF is positive... SSSS... bits of DIFF
559 * are appended. When DIFF is negative... SSSS... bits of (DIFF – 1) are
560 * appended... Most significant bit... is 0 for negative differences and 1 for
561 * positive differences.
562 *
563 * In other words the upper half of extra bits range represents DIFF as is.
564 * The lower half represents the negative DIFFs with an offset.
565 */
HuffExtend(int x,int s)566 int HuffExtend(int x, int s) {
567 JXL_DASSERT(s >= 1);
568 int half = 1 << (s - 1);
569 if (x >= half) {
570 JXL_DASSERT(x < (1 << s));
571 return x;
572 } else {
573 return x - (1 << s) + 1;
574 }
575 }
576
577 // Decodes one 8x8 block of DCT coefficients from the bit stream.
DecodeDCTBlock(const HuffmanTableEntry * dc_huff,const HuffmanTableEntry * ac_huff,int Ss,int Se,int Al,int * eobrun,bool * reset_state,int * num_zero_runs,BitReaderState * br,JPEGData * jpg,coeff_t * last_dc_coeff,coeff_t * coeffs)578 bool DecodeDCTBlock(const HuffmanTableEntry* dc_huff,
579 const HuffmanTableEntry* ac_huff, int Ss, int Se, int Al,
580 int* eobrun, bool* reset_state, int* num_zero_runs,
581 BitReaderState* br, JPEGData* jpg, coeff_t* last_dc_coeff,
582 coeff_t* coeffs) {
583 // Nowadays multiplication is even faster than variable shift.
584 int Am = 1 << Al;
585 bool eobrun_allowed = Ss > 0;
586 if (Ss == 0) {
587 int s = ReadSymbol(dc_huff, br);
588 if (s >= kJpegDCAlphabetSize) {
589 JXL_JPEG_DEBUG("Invalid Huffman symbol %d for DC coefficient.", s);
590 jpg->error = JPEGReadError::INVALID_SYMBOL;
591 return false;
592 }
593 int diff = 0;
594 if (s > 0) {
595 int bits = br->ReadBits(s);
596 diff = HuffExtend(bits, s);
597 }
598 int coeff = diff + *last_dc_coeff;
599 const int dc_coeff = coeff * Am;
600 coeffs[0] = dc_coeff;
601 // TODO(eustas): is there a more elegant / explicit way to check this?
602 if (dc_coeff != coeffs[0]) {
603 JXL_JPEG_DEBUG("Invalid DC coefficient %d", dc_coeff);
604 jpg->error = JPEGReadError::NON_REPRESENTABLE_DC_COEFF;
605 return false;
606 }
607 *last_dc_coeff = coeff;
608 ++Ss;
609 }
610 if (Ss > Se) {
611 return true;
612 }
613 if (*eobrun > 0) {
614 --(*eobrun);
615 return true;
616 }
617 *num_zero_runs = 0;
618 for (int k = Ss; k <= Se; k++) {
619 int sr = ReadSymbol(ac_huff, br);
620 if (sr >= kJpegHuffmanAlphabetSize) {
621 JXL_JPEG_DEBUG("Invalid Huffman symbol %d for AC coefficient %d", sr, k);
622 jpg->error = JPEGReadError::INVALID_SYMBOL;
623 return false;
624 }
625 int r = sr >> 4;
626 int s = sr & 15;
627 if (s > 0) {
628 k += r;
629 if (k > Se) {
630 JXL_JPEG_DEBUG("Out-of-band coefficient %d band was %d-%d", k, Ss, Se);
631 jpg->error = JPEGReadError::OUT_OF_BAND_COEFF;
632 return false;
633 }
634 if (s + Al >= kJpegDCAlphabetSize) {
635 JXL_JPEG_DEBUG(
636 "Out of range AC coefficient value: s = %d Al = %d k = %d", s, Al,
637 k);
638 jpg->error = JPEGReadError::NON_REPRESENTABLE_AC_COEFF;
639 return false;
640 }
641 int bits = br->ReadBits(s);
642 int coeff = HuffExtend(bits, s);
643 coeffs[kJPEGNaturalOrder[k]] = coeff * Am;
644 *num_zero_runs = 0;
645 } else if (r == 15) {
646 k += 15;
647 ++(*num_zero_runs);
648 } else {
649 if (eobrun_allowed && k == Ss && *eobrun == 0) {
650 // We have two end-of-block runs right after each other, so we signal
651 // the jpeg encoder to force a state reset at this point.
652 *reset_state = true;
653 }
654 *eobrun = 1 << r;
655 if (r > 0) {
656 if (!eobrun_allowed) {
657 JXL_JPEG_DEBUG("End-of-block run crossing DC coeff.");
658 jpg->error = JPEGReadError::EOB_RUN_TOO_LONG;
659 return false;
660 }
661 *eobrun += br->ReadBits(r);
662 }
663 break;
664 }
665 }
666 --(*eobrun);
667 return true;
668 }
669
RefineDCTBlock(const HuffmanTableEntry * ac_huff,int Ss,int Se,int Al,int * eobrun,bool * reset_state,BitReaderState * br,JPEGData * jpg,coeff_t * coeffs)670 bool RefineDCTBlock(const HuffmanTableEntry* ac_huff, int Ss, int Se, int Al,
671 int* eobrun, bool* reset_state, BitReaderState* br,
672 JPEGData* jpg, coeff_t* coeffs) {
673 // Nowadays multiplication is even faster than variable shift.
674 int Am = 1 << Al;
675 bool eobrun_allowed = Ss > 0;
676 if (Ss == 0) {
677 int s = br->ReadBits(1);
678 coeff_t dc_coeff = coeffs[0];
679 dc_coeff |= s * Am;
680 coeffs[0] = dc_coeff;
681 ++Ss;
682 }
683 if (Ss > Se) {
684 return true;
685 }
686 int p1 = Am;
687 int m1 = -Am;
688 int k = Ss;
689 int r;
690 int s;
691 bool in_zero_run = false;
692 if (*eobrun <= 0) {
693 for (; k <= Se; k++) {
694 s = ReadSymbol(ac_huff, br);
695 if (s >= kJpegHuffmanAlphabetSize) {
696 JXL_JPEG_DEBUG("Invalid Huffman symbol %d for AC coefficient %d", s, k);
697 jpg->error = JPEGReadError::INVALID_SYMBOL;
698 return false;
699 }
700 r = s >> 4;
701 s &= 15;
702 if (s) {
703 if (s != 1) {
704 JXL_JPEG_DEBUG("Invalid Huffman symbol %d for AC coefficient %d", s,
705 k);
706 jpg->error = JPEGReadError::INVALID_SYMBOL;
707 return false;
708 }
709 s = br->ReadBits(1) ? p1 : m1;
710 in_zero_run = false;
711 } else {
712 if (r != 15) {
713 if (eobrun_allowed && k == Ss && *eobrun == 0) {
714 // We have two end-of-block runs right after each other, so we
715 // signal the jpeg encoder to force a state reset at this point.
716 *reset_state = true;
717 }
718 *eobrun = 1 << r;
719 if (r > 0) {
720 if (!eobrun_allowed) {
721 JXL_JPEG_DEBUG("End-of-block run crossing DC coeff.");
722 jpg->error = JPEGReadError::EOB_RUN_TOO_LONG;
723 return false;
724 }
725 *eobrun += br->ReadBits(r);
726 }
727 break;
728 }
729 in_zero_run = true;
730 }
731 do {
732 coeff_t thiscoef = coeffs[kJPEGNaturalOrder[k]];
733 if (thiscoef != 0) {
734 if (br->ReadBits(1)) {
735 if ((thiscoef & p1) == 0) {
736 if (thiscoef >= 0) {
737 thiscoef += p1;
738 } else {
739 thiscoef += m1;
740 }
741 }
742 }
743 coeffs[kJPEGNaturalOrder[k]] = thiscoef;
744 } else {
745 if (--r < 0) {
746 break;
747 }
748 }
749 k++;
750 } while (k <= Se);
751 if (s) {
752 if (k > Se) {
753 JXL_JPEG_DEBUG("Out-of-band coefficient %d band was %d-%d", k, Ss,
754 Se);
755 jpg->error = JPEGReadError::OUT_OF_BAND_COEFF;
756 return false;
757 }
758 coeffs[kJPEGNaturalOrder[k]] = s;
759 }
760 }
761 }
762 if (in_zero_run) {
763 JXL_JPEG_DEBUG("Extra zero run before end-of-block.");
764 jpg->error = JPEGReadError::EXTRA_ZERO_RUN;
765 return false;
766 }
767 if (*eobrun > 0) {
768 for (; k <= Se; k++) {
769 coeff_t thiscoef = coeffs[kJPEGNaturalOrder[k]];
770 if (thiscoef != 0) {
771 if (br->ReadBits(1)) {
772 if ((thiscoef & p1) == 0) {
773 if (thiscoef >= 0) {
774 thiscoef += p1;
775 } else {
776 thiscoef += m1;
777 }
778 }
779 }
780 coeffs[kJPEGNaturalOrder[k]] = thiscoef;
781 }
782 }
783 }
784 --(*eobrun);
785 return true;
786 }
787
ProcessRestart(const uint8_t * data,const size_t len,int * next_restart_marker,BitReaderState * br,JPEGData * jpg)788 bool ProcessRestart(const uint8_t* data, const size_t len,
789 int* next_restart_marker, BitReaderState* br,
790 JPEGData* jpg) {
791 size_t pos = 0;
792 if (!br->FinishStream(jpg, &pos)) {
793 jpg->error = JPEGReadError::INVALID_SCAN;
794 return false;
795 }
796 int expected_marker = 0xd0 + *next_restart_marker;
797 JXL_JPEG_EXPECT_MARKER();
798 int marker = data[pos + 1];
799 if (marker != expected_marker) {
800 JXL_JPEG_DEBUG("Did not find expected restart marker %d actual %d",
801 expected_marker, marker);
802 jpg->error = JPEGReadError::WRONG_RESTART_MARKER;
803 return false;
804 }
805 br->Reset(pos + 2);
806 *next_restart_marker += 1;
807 *next_restart_marker &= 0x7;
808 return true;
809 }
810
ProcessScan(const uint8_t * data,const size_t len,const std::vector<HuffmanTableEntry> & dc_huff_lut,const std::vector<HuffmanTableEntry> & ac_huff_lut,uint16_t scan_progression[kMaxComponents][kDCTBlockSize],bool is_progressive,size_t * pos,JPEGData * jpg)811 bool ProcessScan(const uint8_t* data, const size_t len,
812 const std::vector<HuffmanTableEntry>& dc_huff_lut,
813 const std::vector<HuffmanTableEntry>& ac_huff_lut,
814 uint16_t scan_progression[kMaxComponents][kDCTBlockSize],
815 bool is_progressive, size_t* pos, JPEGData* jpg) {
816 if (!ProcessSOS(data, len, pos, jpg)) {
817 return false;
818 }
819 JPEGScanInfo* scan_info = &jpg->scan_info.back();
820 bool is_interleaved = (scan_info->num_components > 1);
821 int max_h_samp_factor = 1;
822 int max_v_samp_factor = 1;
823 for (size_t i = 0; i < jpg->components.size(); ++i) {
824 max_h_samp_factor =
825 std::max(max_h_samp_factor, jpg->components[i].h_samp_factor);
826 max_v_samp_factor =
827 std::max(max_v_samp_factor, jpg->components[i].v_samp_factor);
828 }
829
830 int MCU_rows = DivCeil(jpg->height, max_v_samp_factor * 8);
831 int MCUs_per_row = DivCeil(jpg->width, max_h_samp_factor * 8);
832 if (!is_interleaved) {
833 const JPEGComponent& c = jpg->components[scan_info->components[0].comp_idx];
834 MCUs_per_row = DivCeil(jpg->width * c.h_samp_factor, 8 * max_h_samp_factor);
835 MCU_rows = DivCeil(jpg->height * c.v_samp_factor, 8 * max_v_samp_factor);
836 }
837 coeff_t last_dc_coeff[kMaxComponents] = {0};
838 BitReaderState br(data, len, *pos);
839 int restarts_to_go = jpg->restart_interval;
840 int next_restart_marker = 0;
841 int eobrun = -1;
842 int block_scan_index = 0;
843 const int Al = is_progressive ? scan_info->Al : 0;
844 const int Ah = is_progressive ? scan_info->Ah : 0;
845 const int Ss = is_progressive ? scan_info->Ss : 0;
846 const int Se = is_progressive ? scan_info->Se : 63;
847 const uint16_t scan_bitmask = Ah == 0 ? (0xffff << Al) : (1u << Al);
848 const uint16_t refinement_bitmask = (1 << Al) - 1;
849 for (size_t i = 0; i < scan_info->num_components; ++i) {
850 int comp_idx = scan_info->components[i].comp_idx;
851 for (int k = Ss; k <= Se; ++k) {
852 if (scan_progression[comp_idx][k] & scan_bitmask) {
853 JXL_JPEG_DEBUG(
854 "Overlapping scans: component=%d k=%d prev_mask: %u cur_mask %u",
855 comp_idx, k, scan_progression[i][k], scan_bitmask);
856 jpg->error = JPEGReadError::OVERLAPPING_SCANS;
857 return false;
858 }
859 if (scan_progression[comp_idx][k] & refinement_bitmask) {
860 JXL_JPEG_DEBUG(
861 "Invalid scan order, a more refined scan was already done: "
862 "component=%d k=%d prev_mask=%u cur_mask=%u",
863 comp_idx, k, scan_progression[i][k], scan_bitmask);
864 jpg->error = JPEGReadError::INVALID_SCAN_ORDER;
865 return false;
866 }
867 scan_progression[comp_idx][k] |= scan_bitmask;
868 }
869 }
870 if (Al > 10) {
871 JXL_JPEG_DEBUG("Scan parameter Al=%d is not supported.", Al);
872 jpg->error = JPEGReadError::NON_REPRESENTABLE_AC_COEFF;
873 return false;
874 }
875 for (int mcu_y = 0; mcu_y < MCU_rows; ++mcu_y) {
876 for (int mcu_x = 0; mcu_x < MCUs_per_row; ++mcu_x) {
877 // Handle the restart intervals.
878 if (jpg->restart_interval > 0) {
879 if (restarts_to_go == 0) {
880 if (ProcessRestart(data, len, &next_restart_marker, &br, jpg)) {
881 restarts_to_go = jpg->restart_interval;
882 memset(static_cast<void*>(last_dc_coeff), 0, sizeof(last_dc_coeff));
883 if (eobrun > 0) {
884 JXL_JPEG_DEBUG("End-of-block run too long.");
885 jpg->error = JPEGReadError::EOB_RUN_TOO_LONG;
886 return false;
887 }
888 eobrun = -1; // fresh start
889 } else {
890 return false;
891 }
892 }
893 --restarts_to_go;
894 }
895 // Decode one MCU.
896 for (size_t i = 0; i < scan_info->num_components; ++i) {
897 JPEGComponentScanInfo* si = &scan_info->components[i];
898 JPEGComponent* c = &jpg->components[si->comp_idx];
899 const HuffmanTableEntry* dc_lut =
900 &dc_huff_lut[si->dc_tbl_idx * kJpegHuffmanLutSize];
901 const HuffmanTableEntry* ac_lut =
902 &ac_huff_lut[si->ac_tbl_idx * kJpegHuffmanLutSize];
903 int nblocks_y = is_interleaved ? c->v_samp_factor : 1;
904 int nblocks_x = is_interleaved ? c->h_samp_factor : 1;
905 for (int iy = 0; iy < nblocks_y; ++iy) {
906 for (int ix = 0; ix < nblocks_x; ++ix) {
907 int block_y = mcu_y * nblocks_y + iy;
908 int block_x = mcu_x * nblocks_x + ix;
909 int block_idx = block_y * c->width_in_blocks + block_x;
910 bool reset_state = false;
911 int num_zero_runs = 0;
912 coeff_t* coeffs = &c->coeffs[block_idx * kDCTBlockSize];
913 if (Ah == 0) {
914 if (!DecodeDCTBlock(dc_lut, ac_lut, Ss, Se, Al, &eobrun,
915 &reset_state, &num_zero_runs, &br, jpg,
916 &last_dc_coeff[si->comp_idx], coeffs)) {
917 return false;
918 }
919 } else {
920 if (!RefineDCTBlock(ac_lut, Ss, Se, Al, &eobrun, &reset_state,
921 &br, jpg, coeffs)) {
922 return false;
923 }
924 }
925 if (reset_state) {
926 scan_info->reset_points.emplace_back(block_scan_index);
927 }
928 if (num_zero_runs > 0) {
929 JPEGScanInfo::ExtraZeroRunInfo info;
930 info.block_idx = block_scan_index;
931 info.num_extra_zero_runs = num_zero_runs;
932 scan_info->extra_zero_runs.push_back(info);
933 }
934 ++block_scan_index;
935 }
936 }
937 }
938 }
939 }
940 if (eobrun > 0) {
941 JXL_JPEG_DEBUG("End-of-block run too long.");
942 jpg->error = JPEGReadError::EOB_RUN_TOO_LONG;
943 return false;
944 }
945 if (!br.FinishStream(jpg, pos)) {
946 jpg->error = JPEGReadError::INVALID_SCAN;
947 return false;
948 }
949 if (*pos > len) {
950 JXL_JPEG_DEBUG("Unexpected end of file during scan. pos=%zu len=%zu", *pos,
951 len);
952 jpg->error = JPEGReadError::UNEXPECTED_EOF;
953 return false;
954 }
955 return true;
956 }
957
958 // Changes the quant_idx field of the components to refer to the index of the
959 // quant table in the jpg->quant array.
FixupIndexes(JPEGData * jpg)960 bool FixupIndexes(JPEGData* jpg) {
961 for (size_t i = 0; i < jpg->components.size(); ++i) {
962 JPEGComponent* c = &jpg->components[i];
963 bool found_index = false;
964 for (size_t j = 0; j < jpg->quant.size(); ++j) {
965 if (jpg->quant[j].index == c->quant_idx) {
966 c->quant_idx = j;
967 found_index = true;
968 break;
969 }
970 }
971 if (!found_index) {
972 JXL_JPEG_DEBUG("Quantization table with index %u not found",
973 c->quant_idx);
974 jpg->error = JPEGReadError::QUANT_TABLE_NOT_FOUND;
975 return false;
976 }
977 }
978 return true;
979 }
980
FindNextMarker(const uint8_t * data,const size_t len,size_t pos)981 size_t FindNextMarker(const uint8_t* data, const size_t len, size_t pos) {
982 // kIsValidMarker[i] == 1 means (0xc0 + i) is a valid marker.
983 static const uint8_t kIsValidMarker[] = {
984 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
985 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
986 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
987 };
988 size_t num_skipped = 0;
989 while (pos + 1 < len && (data[pos] != 0xff || data[pos + 1] < 0xc0 ||
990 !kIsValidMarker[data[pos + 1] - 0xc0])) {
991 ++pos;
992 ++num_skipped;
993 }
994 return num_skipped;
995 }
996
997 } // namespace
998
ReadJpeg(const uint8_t * data,const size_t len,JpegReadMode mode,JPEGData * jpg)999 bool ReadJpeg(const uint8_t* data, const size_t len, JpegReadMode mode,
1000 JPEGData* jpg) {
1001 size_t pos = 0;
1002 // Check SOI marker.
1003 JXL_JPEG_EXPECT_MARKER();
1004 int marker = data[pos + 1];
1005 pos += 2;
1006 if (marker != 0xd8) {
1007 JXL_JPEG_DEBUG("Did not find expected SOI marker, actual=%d", marker);
1008 jpg->error = JPEGReadError::SOI_NOT_FOUND;
1009 return false;
1010 }
1011 int lut_size = kMaxHuffmanTables * kJpegHuffmanLutSize;
1012 std::vector<HuffmanTableEntry> dc_huff_lut(lut_size);
1013 std::vector<HuffmanTableEntry> ac_huff_lut(lut_size);
1014 bool found_sof = false;
1015 bool found_dri = false;
1016 uint16_t scan_progression[kMaxComponents][kDCTBlockSize] = {{0}};
1017
1018 jpg->padding_bits.resize(0);
1019 bool is_progressive = false; // default
1020 do {
1021 // Read next marker.
1022 size_t num_skipped = FindNextMarker(data, len, pos);
1023 if (num_skipped > 0) {
1024 // Add a fake marker to indicate arbitrary in-between-markers data.
1025 jpg->marker_order.push_back(0xff);
1026 jpg->inter_marker_data.emplace_back(data + pos, data + pos + num_skipped);
1027 pos += num_skipped;
1028 }
1029 JXL_JPEG_EXPECT_MARKER();
1030 marker = data[pos + 1];
1031 pos += 2;
1032 bool ok = true;
1033 switch (marker) {
1034 case 0xc0:
1035 case 0xc1:
1036 case 0xc2:
1037 is_progressive = (marker == 0xc2);
1038 ok = ProcessSOF(data, len, mode, &pos, jpg);
1039 found_sof = true;
1040 break;
1041 case 0xc4:
1042 ok = ProcessDHT(data, len, mode, &dc_huff_lut, &ac_huff_lut, &pos, jpg);
1043 break;
1044 case 0xd0:
1045 case 0xd1:
1046 case 0xd2:
1047 case 0xd3:
1048 case 0xd4:
1049 case 0xd5:
1050 case 0xd6:
1051 case 0xd7:
1052 // RST markers do not have any data.
1053 break;
1054 case 0xd9:
1055 // Found end marker.
1056 break;
1057 case 0xda:
1058 if (mode == JpegReadMode::kReadAll) {
1059 ok = ProcessScan(data, len, dc_huff_lut, ac_huff_lut,
1060 scan_progression, is_progressive, &pos, jpg);
1061 }
1062 break;
1063 case 0xdb:
1064 ok = ProcessDQT(data, len, &pos, jpg);
1065 break;
1066 case 0xdd:
1067 ok = ProcessDRI(data, len, &pos, &found_dri, jpg);
1068 break;
1069 case 0xe0:
1070 case 0xe1:
1071 case 0xe2:
1072 case 0xe3:
1073 case 0xe4:
1074 case 0xe5:
1075 case 0xe6:
1076 case 0xe7:
1077 case 0xe8:
1078 case 0xe9:
1079 case 0xea:
1080 case 0xeb:
1081 case 0xec:
1082 case 0xed:
1083 case 0xee:
1084 case 0xef:
1085 if (mode != JpegReadMode::kReadTables) {
1086 ok = ProcessAPP(data, len, &pos, jpg);
1087 }
1088 break;
1089 case 0xfe:
1090 if (mode != JpegReadMode::kReadTables) {
1091 ok = ProcessCOM(data, len, &pos, jpg);
1092 }
1093 break;
1094 default:
1095 JXL_JPEG_DEBUG("Unsupported marker: %d pos=%zu len=%zu", marker, pos,
1096 len);
1097 jpg->error = JPEGReadError::UNSUPPORTED_MARKER;
1098 ok = false;
1099 break;
1100 }
1101 if (!ok) {
1102 return false;
1103 }
1104 jpg->marker_order.push_back(marker);
1105 if (mode == JpegReadMode::kReadHeader && found_sof) {
1106 break;
1107 }
1108 } while (marker != 0xd9);
1109
1110 if (!found_sof) {
1111 JXL_JPEG_DEBUG("Missing SOF marker.");
1112 jpg->error = JPEGReadError::SOF_NOT_FOUND;
1113 return false;
1114 }
1115
1116 // Supplemental checks.
1117 if (mode == JpegReadMode::kReadAll) {
1118 if (pos < len) {
1119 jpg->tail_data = std::vector<uint8_t>(data + pos, data + len);
1120 }
1121 if (!FixupIndexes(jpg)) {
1122 return false;
1123 }
1124 if (jpg->huffman_code.empty()) {
1125 // Section B.2.4.2: "If a table has never been defined for a particular
1126 // destination, then when this destination is specified in a scan header,
1127 // the results are unpredictable."
1128 JXL_JPEG_DEBUG("Need at least one Huffman code table.");
1129 jpg->error = JPEGReadError::HUFFMAN_TABLE_ERROR;
1130 return false;
1131 }
1132 if (jpg->huffman_code.size() >= kMaxDHTMarkers) {
1133 JXL_JPEG_DEBUG("Too many Huffman tables.");
1134 jpg->error = JPEGReadError::HUFFMAN_TABLE_ERROR;
1135 return false;
1136 }
1137 }
1138 return true;
1139 }
1140
1141 } // namespace jpeg
1142 } // namespace jxl
1143