/src/guetzli/guetzli/jpeg_data_reader.cc
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2016 Google Inc. |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | |
17 | | #include "guetzli/jpeg_data_reader.h" |
18 | | |
19 | | #include <algorithm> |
20 | | #include <stdio.h> |
21 | | #include <string.h> |
22 | | |
23 | | #include "guetzli/jpeg_huffman_decode.h" |
24 | | |
25 | | namespace guetzli { |
26 | | |
27 | | namespace { |
28 | | |
29 | | // Macros for commonly used error conditions. |
30 | | |
31 | | #define VERIFY_LEN(n) \ |
32 | 4.99M | if (*pos + (n) > len) { \ |
33 | 501 | fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \ |
34 | 501 | static_cast<int>(*pos), static_cast<int>(n), \ |
35 | 501 | static_cast<int>(len)); \ |
36 | 501 | jpg->error = JPEG_UNEXPECTED_EOF; \ |
37 | 501 | return false; \ |
38 | 501 | } |
39 | | |
40 | | #define VERIFY_INPUT(var, low, high, code) \ |
41 | 3.35M | if (var < low || var > high) { \ |
42 | 168 | fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var)); \ |
43 | 168 | jpg->error = JPEG_INVALID_ ## code; \ |
44 | 168 | return false; \ |
45 | 168 | } |
46 | | |
47 | | #define VERIFY_MARKER_END() \ |
48 | 41.1k | if (start_pos + marker_len != *pos) { \ |
49 | 151 | fprintf(stderr, "Invalid marker length: declared=%d actual=%d\n", \ |
50 | 151 | static_cast<int>(marker_len), \ |
51 | 151 | static_cast<int>(*pos - start_pos)); \ |
52 | 151 | jpg->error = JPEG_WRONG_MARKER_SIZE; \ |
53 | 151 | return false; \ |
54 | 151 | } |
55 | | |
56 | | #define EXPECT_MARKER() \ |
57 | 7.12M | if (pos + 2 > len || data[pos] != 0xff) { \ |
58 | 601 | fprintf(stderr, "Marker byte (0xff) expected, found: %d " \ |
59 | 601 | "pos=%d len=%d\n", \ |
60 | 601 | (pos < len ? data[pos] : 0), static_cast<int>(pos), \ |
61 | 601 | static_cast<int>(len)); \ |
62 | 601 | jpg->error = JPEG_MARKER_BYTE_NOT_FOUND; \ |
63 | 601 | return false; \ |
64 | 601 | } |
65 | | |
66 | 9.07M | inline int SignedLeftshift(int v, int s) { |
67 | 9.07M | return (v >= 0) ? (v << s) : -((-v) << s); |
68 | 9.07M | } |
69 | | |
70 | | // Returns ceil(a/b). |
71 | 27.7k | inline int DivCeil(int a, int b) { |
72 | 27.7k | return (a + b - 1) / b; |
73 | 27.7k | } |
74 | | |
75 | 5.26M | inline int ReadUint8(const uint8_t* data, size_t* pos) { |
76 | 5.26M | return data[(*pos)++]; |
77 | 5.26M | } |
78 | | |
79 | 2.26M | inline int ReadUint16(const uint8_t* data, size_t* pos) { |
80 | 2.26M | int v = (data[*pos] << 8) + data[*pos + 1]; |
81 | 2.26M | *pos += 2; |
82 | 2.26M | return v; |
83 | 2.26M | } |
84 | | |
85 | | // Reads the Start of Frame (SOF) marker segment and fills in *jpg with the |
86 | | // parsed data. |
87 | | bool ProcessSOF(const uint8_t* data, const size_t len, |
88 | 8.51k | JpegReadMode mode, size_t* pos, JPEGData* jpg) { |
89 | 8.51k | if (jpg->width != 0) { |
90 | 13 | fprintf(stderr, "Duplicate SOF marker.\n"); |
91 | 13 | jpg->error = JPEG_DUPLICATE_SOF; |
92 | 13 | return false; |
93 | 13 | } |
94 | 8.50k | const size_t start_pos = *pos; |
95 | 8.50k | VERIFY_LEN(8); |
96 | 8.49k | size_t marker_len = ReadUint16(data, pos); |
97 | 8.49k | int precision = ReadUint8(data, pos); |
98 | 8.49k | int height = ReadUint16(data, pos); |
99 | 8.49k | int width = ReadUint16(data, pos); |
100 | 8.49k | int num_components = ReadUint8(data, pos); |
101 | 8.49k | VERIFY_INPUT(precision, 8, 8, PRECISION); |
102 | 8.48k | VERIFY_INPUT(height, 1, 65535, HEIGHT); |
103 | 8.47k | VERIFY_INPUT(width, 1, 65535, WIDTH); |
104 | 8.47k | VERIFY_INPUT(num_components, 1, kMaxComponents, NUMCOMP); |
105 | 8.46k | VERIFY_LEN(3 * num_components); |
106 | 8.45k | jpg->height = height; |
107 | 8.45k | jpg->width = width; |
108 | 8.45k | jpg->components.resize(num_components); |
109 | | |
110 | | // Read sampling factors and quant table index for each component. |
111 | 8.45k | std::vector<bool> ids_seen(256, false); |
112 | 28.8k | for (size_t i = 0; i < jpg->components.size(); ++i) { |
113 | 20.4k | const int id = ReadUint8(data, pos); |
114 | 20.4k | if (ids_seen[id]) { // (cf. section B.2.2, syntax of Ci) |
115 | 1 | fprintf(stderr, "Duplicate ID %d in SOF.\n", id); |
116 | 1 | jpg->error = JPEG_DUPLICATE_COMPONENT_ID; |
117 | 1 | return false; |
118 | 1 | } |
119 | 20.4k | ids_seen[id] = true; |
120 | 20.4k | jpg->components[i].id = id; |
121 | 20.4k | int factor = ReadUint8(data, pos); |
122 | 20.4k | int h_samp_factor = factor >> 4; |
123 | 20.4k | int v_samp_factor = factor & 0xf; |
124 | 20.4k | VERIFY_INPUT(h_samp_factor, 1, 15, SAMP_FACTOR); |
125 | 20.4k | VERIFY_INPUT(v_samp_factor, 1, 15, SAMP_FACTOR); |
126 | 20.4k | jpg->components[i].h_samp_factor = h_samp_factor; |
127 | 20.4k | jpg->components[i].v_samp_factor = v_samp_factor; |
128 | 20.4k | jpg->components[i].quant_idx = ReadUint8(data, pos); |
129 | 20.4k | jpg->max_h_samp_factor = std::max(jpg->max_h_samp_factor, h_samp_factor); |
130 | 20.4k | jpg->max_v_samp_factor = std::max(jpg->max_v_samp_factor, v_samp_factor); |
131 | 20.4k | } |
132 | | |
133 | | // We have checked above that none of the sampling factors are 0, so the max |
134 | | // sampling factors can not be 0. |
135 | 8.45k | jpg->MCU_rows = DivCeil(jpg->height, jpg->max_v_samp_factor * 8); |
136 | 8.45k | jpg->MCU_cols = DivCeil(jpg->width, jpg->max_h_samp_factor * 8); |
137 | | // Compute the block dimensions for each component. |
138 | 8.45k | if (mode == JPEG_READ_ALL) { |
139 | 14.3k | for (size_t i = 0; i < jpg->components.size(); ++i) { |
140 | 10.1k | JPEGComponent* c = &jpg->components[i]; |
141 | 10.1k | if (jpg->max_h_samp_factor % c->h_samp_factor != 0 || |
142 | 10.1k | jpg->max_v_samp_factor % c->v_samp_factor != 0) { |
143 | 21 | fprintf(stderr, "Non-integral subsampling ratios.\n"); |
144 | 21 | jpg->error = JPEG_INVALID_SAMPLING_FACTORS; |
145 | 21 | return false; |
146 | 21 | } |
147 | 10.1k | c->width_in_blocks = jpg->MCU_cols * c->h_samp_factor; |
148 | 10.1k | c->height_in_blocks = jpg->MCU_rows * c->v_samp_factor; |
149 | 10.1k | const uint64_t num_blocks = |
150 | 10.1k | static_cast<uint64_t>(c->width_in_blocks) * c->height_in_blocks; |
151 | 10.1k | if (num_blocks > (1ull << 21)) { |
152 | | // Refuse to allocate more than 1 GB of memory for the coefficients, |
153 | | // that is 2M blocks x 64 coeffs x 2 bytes per coeff x max 4 components. |
154 | | // TODO(user) Add this limit to a GuetzliParams struct. |
155 | 0 | fprintf(stderr, "Image too large.\n"); |
156 | 0 | jpg->error = JPEG_IMAGE_TOO_LARGE; |
157 | 0 | return false; |
158 | 0 | } |
159 | 10.1k | c->num_blocks = static_cast<int>(num_blocks); |
160 | 10.1k | c->coeffs.resize(c->num_blocks * kDCTBlockSize); |
161 | 10.1k | } |
162 | 4.20k | } |
163 | 8.42k | VERIFY_MARKER_END(); |
164 | 8.40k | return true; |
165 | 8.42k | } |
166 | | |
167 | | // Reads the Start of Scan (SOS) marker segment and fills in *scan_info with the |
168 | | // parsed data. |
169 | | bool ProcessSOS(const uint8_t* data, const size_t len, size_t* pos, |
170 | 6.28k | JPEGData* jpg) { |
171 | 6.28k | const size_t start_pos = *pos; |
172 | 6.28k | VERIFY_LEN(3); |
173 | 6.27k | size_t marker_len = ReadUint16(data, pos); |
174 | 6.27k | int comps_in_scan = ReadUint8(data, pos); |
175 | 6.27k | VERIFY_INPUT(comps_in_scan, 1, static_cast<int>(jpg->components.size()), |
176 | 6.27k | COMPS_IN_SCAN); |
177 | | |
178 | 6.25k | JPEGScanInfo scan_info; |
179 | 6.25k | scan_info.components.resize(comps_in_scan); |
180 | 6.25k | VERIFY_LEN(2 * comps_in_scan); |
181 | 6.24k | std::vector<bool> ids_seen(256, false); |
182 | 13.8k | for (int i = 0; i < comps_in_scan; ++i) { |
183 | 7.63k | int id = ReadUint8(data, pos); |
184 | 7.63k | if (ids_seen[id]) { // (cf. section B.2.3, regarding CSj) |
185 | 2 | fprintf(stderr, "Duplicate ID %d in SOS.\n", id); |
186 | 2 | jpg->error = JPEG_DUPLICATE_COMPONENT_ID; |
187 | 2 | return false; |
188 | 2 | } |
189 | 7.62k | ids_seen[id] = true; |
190 | 7.62k | bool found_index = false; |
191 | 28.1k | for (size_t j = 0; j < jpg->components.size(); ++j) { |
192 | 20.5k | if (jpg->components[j].id == id) { |
193 | 7.61k | scan_info.components[i].comp_idx = j; |
194 | 7.61k | found_index = true; |
195 | 7.61k | } |
196 | 20.5k | } |
197 | 7.62k | if (!found_index) { |
198 | 13 | fprintf(stderr, "SOS marker: Could not find component with id %d\n", id); |
199 | 13 | jpg->error = JPEG_COMPONENT_NOT_FOUND; |
200 | 13 | return false; |
201 | 13 | } |
202 | 7.61k | int c = ReadUint8(data, pos); |
203 | 7.61k | int dc_tbl_idx = c >> 4; |
204 | 7.61k | int ac_tbl_idx = c & 0xf; |
205 | 7.61k | VERIFY_INPUT(dc_tbl_idx, 0, 3, HUFFMAN_INDEX); |
206 | 7.61k | VERIFY_INPUT(ac_tbl_idx, 0, 3, HUFFMAN_INDEX); |
207 | 7.60k | scan_info.components[i].dc_tbl_idx = dc_tbl_idx; |
208 | 7.60k | scan_info.components[i].ac_tbl_idx = ac_tbl_idx; |
209 | 7.60k | } |
210 | 6.21k | VERIFY_LEN(3); |
211 | 6.20k | scan_info.Ss = ReadUint8(data, pos); |
212 | 6.20k | scan_info.Se = ReadUint8(data, pos); |
213 | 6.20k | VERIFY_INPUT(scan_info.Ss, 0, 63, START_OF_SCAN); |
214 | 6.19k | VERIFY_INPUT(scan_info.Se, scan_info.Ss, 63, END_OF_SCAN); |
215 | 6.18k | int c = ReadUint8(data, pos); |
216 | 6.18k | scan_info.Ah = c >> 4; |
217 | 6.18k | scan_info.Al = c & 0xf; |
218 | | // Check that all the Huffman tables needed for this scan are defined. |
219 | 13.7k | for (int i = 0; i < comps_in_scan; ++i) { |
220 | 7.54k | bool found_dc_table = false; |
221 | 7.54k | bool found_ac_table = false; |
222 | 131k | for (size_t j = 0; j < jpg->huffman_code.size(); ++j) { |
223 | 124k | int slot_id = jpg->huffman_code[j].slot_id; |
224 | 124k | if (slot_id == scan_info.components[i].dc_tbl_idx) { |
225 | 32.3k | found_dc_table = true; |
226 | 91.7k | } else if (slot_id == scan_info.components[i].ac_tbl_idx + 16) { |
227 | 53.1k | found_ac_table = true; |
228 | 53.1k | } |
229 | 124k | } |
230 | 7.54k | if (scan_info.Ss == 0 && !found_dc_table) { |
231 | 11 | fprintf(stderr, "SOS marker: Could not find DC Huffman table with index " |
232 | 11 | "%d\n", scan_info.components[i].dc_tbl_idx); |
233 | 11 | jpg->error = JPEG_HUFFMAN_TABLE_NOT_FOUND; |
234 | 11 | return false; |
235 | 11 | } |
236 | 7.53k | if (scan_info.Se > 0 && !found_ac_table) { |
237 | 10 | fprintf(stderr, "SOS marker: Could not find AC Huffman table with index " |
238 | 10 | "%d\n", scan_info.components[i].ac_tbl_idx); |
239 | 10 | jpg->error = JPEG_HUFFMAN_TABLE_NOT_FOUND; |
240 | 10 | return false; |
241 | 10 | } |
242 | 7.53k | } |
243 | 6.16k | jpg->scan_info.push_back(scan_info); |
244 | 6.16k | VERIFY_MARKER_END(); |
245 | 6.13k | return true; |
246 | 6.16k | } |
247 | | |
248 | | // Reads the Define Huffman Table (DHT) marker segment and fills in *jpg with |
249 | | // the parsed data. Builds the Huffman decoding table in either dc_huff_lut or |
250 | | // ac_huff_lut, depending on the type and solt_id of Huffman code being read. |
251 | | bool ProcessDHT(const uint8_t* data, const size_t len, |
252 | | JpegReadMode mode, |
253 | | std::vector<HuffmanTableEntry>* dc_huff_lut, |
254 | | std::vector<HuffmanTableEntry>* ac_huff_lut, |
255 | | size_t* pos, |
256 | 19.4k | JPEGData* jpg) { |
257 | 19.4k | const size_t start_pos = *pos; |
258 | 19.4k | VERIFY_LEN(2); |
259 | 19.4k | size_t marker_len = ReadUint16(data, pos); |
260 | 19.4k | if (marker_len == 2) { |
261 | 1 | fprintf(stderr, "DHT marker: no Huffman table found\n"); |
262 | 1 | jpg->error = JPEG_EMPTY_DHT; |
263 | 1 | return false; |
264 | 1 | } |
265 | 283k | while (*pos < start_pos + marker_len) { |
266 | 264k | VERIFY_LEN(1 + kJpegHuffmanMaxBitLength); |
267 | 264k | JPEGHuffmanCode huff; |
268 | 264k | huff.slot_id = ReadUint8(data, pos); |
269 | 264k | int huffman_index = huff.slot_id; |
270 | 264k | int is_ac_table = (huff.slot_id & 0x10) != 0; |
271 | 264k | HuffmanTableEntry* huff_lut; |
272 | 264k | if (is_ac_table) { |
273 | 14.4k | huffman_index -= 0x10; |
274 | 14.4k | VERIFY_INPUT(huffman_index, 0, 3, HUFFMAN_INDEX); |
275 | 14.4k | huff_lut = &(*ac_huff_lut)[huffman_index * kJpegHuffmanLutSize]; |
276 | 250k | } else { |
277 | 250k | VERIFY_INPUT(huffman_index, 0, 3, HUFFMAN_INDEX); |
278 | 250k | huff_lut = &(*dc_huff_lut)[huffman_index * kJpegHuffmanLutSize]; |
279 | 250k | } |
280 | 264k | huff.counts[0] = 0; |
281 | 264k | int total_count = 0; |
282 | 264k | int space = 1 << kJpegHuffmanMaxBitLength; |
283 | 264k | int max_depth = 1; |
284 | 4.49M | for (int i = 1; i <= kJpegHuffmanMaxBitLength; ++i) { |
285 | 4.23M | int count = ReadUint8(data, pos); |
286 | 4.23M | if (count != 0) { |
287 | 117k | max_depth = i; |
288 | 117k | } |
289 | 4.23M | huff.counts[i] = count; |
290 | 4.23M | total_count += count; |
291 | 4.23M | space -= count * (1 << (kJpegHuffmanMaxBitLength - i)); |
292 | 4.23M | } |
293 | 264k | if (is_ac_table) { |
294 | 14.4k | VERIFY_INPUT(total_count, 0, kJpegHuffmanAlphabetSize, HUFFMAN_CODE); |
295 | 250k | } else { |
296 | 250k | VERIFY_INPUT(total_count, 0, kJpegDCAlphabetSize, HUFFMAN_CODE); |
297 | 250k | } |
298 | 264k | VERIFY_LEN(total_count); |
299 | 264k | std::vector<bool> values_seen(256, false); |
300 | 481k | for (int i = 0; i < total_count; ++i) { |
301 | 217k | uint8_t value = ReadUint8(data, pos); |
302 | 217k | if (!is_ac_table) { |
303 | 73.9k | VERIFY_INPUT(value, 0, kJpegDCAlphabetSize - 1, HUFFMAN_CODE); |
304 | 73.9k | } |
305 | 217k | if (values_seen[value]) { |
306 | 11 | fprintf(stderr, "Duplicate Huffman code value %d\n", value); |
307 | 11 | jpg->error = JPEG_INVALID_HUFFMAN_CODE; |
308 | 11 | return false; |
309 | 11 | } |
310 | 217k | values_seen[value] = true; |
311 | 217k | huff.values[i] = value; |
312 | 217k | } |
313 | | // Add an invalid symbol that will have the all 1 code. |
314 | 264k | ++huff.counts[max_depth]; |
315 | 264k | huff.values[total_count] = kJpegHuffmanAlphabetSize; |
316 | 264k | space -= (1 << (kJpegHuffmanMaxBitLength - max_depth)); |
317 | 264k | if (space < 0) { |
318 | 20 | fprintf(stderr, "Invalid Huffman code lengths.\n"); |
319 | 20 | jpg->error = JPEG_INVALID_HUFFMAN_CODE; |
320 | 20 | return false; |
321 | 264k | } 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 | 93.7M | for (int i = 0; i < kJpegHuffmanLutSize; ++i) { |
325 | 93.6M | huff_lut[i].bits = 0; |
326 | 93.6M | huff_lut[i].value = 0xffff; |
327 | 93.6M | } |
328 | 123k | } |
329 | 264k | huff.is_last = (*pos == start_pos + marker_len); |
330 | 264k | if (mode == JPEG_READ_ALL && |
331 | 134k | !BuildJpegHuffmanTable(&huff.counts[0], &huff.values[0], huff_lut)) { |
332 | 0 | fprintf(stderr, "Failed to build Huffman table.\n"); |
333 | 0 | jpg->error = JPEG_INVALID_HUFFMAN_CODE; |
334 | 0 | return false; |
335 | 0 | } |
336 | 264k | jpg->huffman_code.push_back(huff); |
337 | 264k | } |
338 | 19.1k | VERIFY_MARKER_END(); |
339 | 19.0k | return true; |
340 | 19.1k | } |
341 | | |
342 | | // Reads the Define Quantization Table (DQT) marker segment and fills in *jpg |
343 | | // with the parsed data. |
344 | | bool ProcessDQT(const uint8_t* data, const size_t len, size_t* pos, |
345 | 6.85k | JPEGData* jpg) { |
346 | 6.85k | const size_t start_pos = *pos; |
347 | 6.85k | VERIFY_LEN(2); |
348 | 6.85k | size_t marker_len = ReadUint16(data, pos); |
349 | 6.85k | if (marker_len == 2) { |
350 | 1 | fprintf(stderr, "DQT marker: no quantization table found\n"); |
351 | 1 | jpg->error = JPEG_EMPTY_DQT; |
352 | 1 | return false; |
353 | 1 | } |
354 | 13.6k | while (*pos < start_pos + marker_len && jpg->quant.size() < kMaxQuantTables) { |
355 | 6.90k | VERIFY_LEN(1); |
356 | 6.88k | int quant_table_index = ReadUint8(data, pos); |
357 | 6.88k | int quant_table_precision = quant_table_index >> 4; |
358 | 6.88k | quant_table_index &= 0xf; |
359 | 6.88k | VERIFY_INPUT(quant_table_index, 0, 3, QUANT_TBL_INDEX); |
360 | 6.88k | VERIFY_LEN((quant_table_precision ? 2 : 1) * kDCTBlockSize); |
361 | 6.84k | JPEGQuantTable table; |
362 | 6.84k | table.index = quant_table_index; |
363 | 6.84k | table.precision = quant_table_precision; |
364 | 444k | for (int i = 0; i < kDCTBlockSize; ++i) { |
365 | 437k | int quant_val = quant_table_precision ? |
366 | 8.21k | ReadUint16(data, pos) : |
367 | 437k | ReadUint8(data, pos); |
368 | 437k | VERIFY_INPUT(quant_val, 1, 65535, QUANT_VAL); |
369 | 437k | table.values[kJPEGNaturalOrder[i]] = quant_val; |
370 | 437k | } |
371 | 6.83k | table.is_last = (*pos == start_pos + marker_len); |
372 | 6.83k | jpg->quant.push_back(table); |
373 | 6.83k | } |
374 | 6.78k | VERIFY_MARKER_END(); |
375 | 6.74k | return true; |
376 | 6.78k | } |
377 | | |
378 | | // Reads the DRI marker and saved the restart interval into *jpg. |
379 | | bool ProcessDRI(const uint8_t* data, const size_t len, size_t* pos, |
380 | 671 | JPEGData* jpg) { |
381 | 671 | if (jpg->restart_interval > 0) { |
382 | 15 | fprintf(stderr, "Duplicate DRI marker.\n"); |
383 | 15 | jpg->error = JPEG_DUPLICATE_DRI; |
384 | 15 | return false; |
385 | 15 | } |
386 | 656 | const size_t start_pos = *pos; |
387 | 656 | VERIFY_LEN(4); |
388 | 648 | size_t marker_len = ReadUint16(data, pos); |
389 | 648 | int restart_interval = ReadUint16(data, pos); |
390 | 648 | jpg->restart_interval = restart_interval; |
391 | 648 | VERIFY_MARKER_END(); |
392 | 639 | return true; |
393 | 648 | } |
394 | | |
395 | | // Saves the APP marker segment as a string to *jpg. |
396 | | bool ProcessAPP(const uint8_t* data, const size_t len, size_t* pos, |
397 | 1.77M | JPEGData* jpg) { |
398 | 1.77M | VERIFY_LEN(2); |
399 | 1.77M | size_t marker_len = ReadUint16(data, pos); |
400 | 1.77M | VERIFY_INPUT(marker_len, 2, 65535, MARKER_LEN); |
401 | 1.77M | VERIFY_LEN(marker_len - 2); |
402 | | // Save the marker type together with the app data. |
403 | 1.77M | std::string app_str(reinterpret_cast<const char*>( |
404 | 1.77M | &data[*pos - 3]), marker_len + 1); |
405 | 1.77M | *pos += marker_len - 2; |
406 | 1.77M | jpg->app_data.push_back(app_str); |
407 | 1.77M | return true; |
408 | 1.77M | } |
409 | | |
410 | | // Saves the COM marker segment as a string to *jpg. |
411 | | bool ProcessCOM(const uint8_t* data, const size_t len, size_t* pos, |
412 | 418k | JPEGData* jpg) { |
413 | 418k | VERIFY_LEN(2); |
414 | 418k | size_t marker_len = ReadUint16(data, pos); |
415 | 418k | VERIFY_INPUT(marker_len, 2, 65535, MARKER_LEN); |
416 | 418k | VERIFY_LEN(marker_len - 2); |
417 | 418k | std::string com_str(reinterpret_cast<const char*>( |
418 | 418k | &data[*pos - 2]), marker_len); |
419 | 418k | *pos += marker_len - 2; |
420 | 418k | jpg->com_data.push_back(com_str); |
421 | 418k | return true; |
422 | 418k | } |
423 | | |
424 | | // Helper structure to read bits from the entropy coded data segment. |
425 | | struct BitReaderState { |
426 | | BitReaderState(const uint8_t* data, const size_t len, size_t pos) |
427 | 6.13k | : data_(data), len_(len) { |
428 | 6.13k | Reset(pos); |
429 | 6.13k | } |
430 | | |
431 | 6.20k | void Reset(size_t pos) { |
432 | 6.20k | pos_ = pos; |
433 | 6.20k | val_ = 0; |
434 | 6.20k | bits_left_ = 0; |
435 | 6.20k | next_marker_pos_ = len_ - 2; |
436 | 6.20k | FillBitWindow(); |
437 | 6.20k | } |
438 | | |
439 | | // Returns the next byte and skips the 0xff/0x00 escape sequences. |
440 | 23.0M | uint8_t GetNextByte() { |
441 | 23.0M | if (pos_ >= next_marker_pos_) { |
442 | 22.4M | ++pos_; |
443 | 22.4M | return 0; |
444 | 22.4M | } |
445 | 641k | uint8_t c = data_[pos_++]; |
446 | 641k | if (c == 0xff) { |
447 | 5.62k | uint8_t escape = data_[pos_]; |
448 | 5.62k | if (escape == 0) { |
449 | 2.93k | ++pos_; |
450 | 2.93k | } else { |
451 | | // 0xff was followed by a non-zero byte, which means that we found the |
452 | | // start of the next marker segment. |
453 | 2.69k | next_marker_pos_ = pos_ - 1; |
454 | 2.69k | } |
455 | 5.62k | } |
456 | 641k | return c; |
457 | 23.0M | } |
458 | | |
459 | 29.3M | void FillBitWindow() { |
460 | 29.3M | if (bits_left_ <= 16) { |
461 | 26.8M | while (bits_left_ <= 56) { |
462 | 23.0M | val_ <<= 8; |
463 | 23.0M | val_ |= (uint64_t)GetNextByte(); |
464 | 23.0M | bits_left_ += 8; |
465 | 23.0M | } |
466 | 3.76M | } |
467 | 29.3M | } |
468 | | |
469 | 14.7M | int ReadBits(int nbits) { |
470 | 14.7M | FillBitWindow(); |
471 | 14.7M | uint64_t val = (val_ >> (bits_left_ - nbits)) & ((1ULL << nbits) - 1); |
472 | 14.7M | bits_left_ -= nbits; |
473 | 14.7M | return val; |
474 | 14.7M | } |
475 | | |
476 | | // Sets *pos to the next stream position where parsing should continue. |
477 | | // Returns false if the stream ended too early. |
478 | 5.80k | bool FinishStream(size_t* pos) { |
479 | | // Give back some bytes that we did not use. |
480 | 5.80k | int unused_bytes_left = bits_left_ >> 3; |
481 | 38.4k | while (unused_bytes_left-- > 0) { |
482 | 32.6k | --pos_; |
483 | | // If we give back a 0 byte, we need to check if it was a 0xff/0x00 escape |
484 | | // sequence, and if yes, we need to give back one more byte. |
485 | 32.6k | if (pos_ < next_marker_pos_ && |
486 | 10.1k | data_[pos_] == 0 && data_[pos_ - 1] == 0xff) { |
487 | 176 | --pos_; |
488 | 176 | } |
489 | 32.6k | } |
490 | 5.80k | if (pos_ > next_marker_pos_) { |
491 | | // Data ran out before the scan was complete. |
492 | 316 | fprintf(stderr, "Unexpected end of scan.\n"); |
493 | 316 | return false; |
494 | 316 | } |
495 | 5.49k | *pos = pos_; |
496 | 5.49k | return true; |
497 | 5.80k | } |
498 | | |
499 | | const uint8_t* data_; |
500 | | const size_t len_; |
501 | | size_t pos_; |
502 | | uint64_t val_; |
503 | | int bits_left_; |
504 | | size_t next_marker_pos_; |
505 | | }; |
506 | | |
507 | | // Returns the next Huffman-coded symbol. |
508 | 14.6M | int ReadSymbol(const HuffmanTableEntry* table, BitReaderState* br) { |
509 | 14.6M | int nbits; |
510 | 14.6M | br->FillBitWindow(); |
511 | 14.6M | int val = (br->val_ >> (br->bits_left_ - 8)) & 0xff; |
512 | 14.6M | table += val; |
513 | 14.6M | nbits = table->bits - 8; |
514 | 14.6M | if (nbits > 0) { |
515 | 9.99M | br->bits_left_ -= 8; |
516 | 9.99M | table += table->value; |
517 | 9.99M | val = (br->val_ >> (br->bits_left_ - nbits)) & ((1 << nbits) - 1); |
518 | 9.99M | table += val; |
519 | 9.99M | } |
520 | 14.6M | br->bits_left_ -= table->bits; |
521 | 14.6M | return table->value; |
522 | 14.6M | } |
523 | | |
524 | | // Returns the DC diff or AC value for extra bits value x and prefix code s. |
525 | | // See Tables F.1 and F.2 of the spec. |
526 | 9.03M | int HuffExtend(int x, int s) { |
527 | 9.03M | return (x < (1 << (s - 1)) ? x - (1 << s) + 1 : x); |
528 | 9.03M | } |
529 | | |
530 | | // Decodes one 8x8 block of DCT coefficients from the bit stream. |
531 | | bool DecodeDCTBlock(const HuffmanTableEntry* dc_huff, |
532 | | const HuffmanTableEntry* ac_huff, |
533 | | int Ss, int Se, int Al, |
534 | | int* eobrun, |
535 | | BitReaderState* br, |
536 | | JPEGData* jpg, |
537 | | coeff_t* last_dc_coeff, |
538 | 314k | coeff_t* coeffs) { |
539 | 314k | int s; |
540 | 314k | int r; |
541 | 314k | bool eobrun_allowed = Ss > 0; |
542 | 314k | if (Ss == 0) { |
543 | 68.2k | s = ReadSymbol(dc_huff, br); |
544 | 68.2k | if (s >= kJpegDCAlphabetSize) { |
545 | 48 | fprintf(stderr, "Invalid Huffman symbol %d for DC coefficient.\n", s); |
546 | 48 | jpg->error = JPEG_INVALID_SYMBOL; |
547 | 48 | return false; |
548 | 48 | } |
549 | 68.2k | if (s > 0) { |
550 | 31.2k | r = br->ReadBits(s); |
551 | 31.2k | s = HuffExtend(r, s); |
552 | 31.2k | } |
553 | 68.2k | s += *last_dc_coeff; |
554 | 68.2k | const int dc_coeff = SignedLeftshift(s, Al); |
555 | 68.2k | coeffs[0] = dc_coeff; |
556 | 68.2k | if (dc_coeff != coeffs[0]) { |
557 | 24 | fprintf(stderr, "Invalid DC coefficient %d\n", dc_coeff); |
558 | 24 | jpg->error = JPEG_NON_REPRESENTABLE_DC_COEFF; |
559 | 24 | return false; |
560 | 24 | } |
561 | 68.1k | *last_dc_coeff = s; |
562 | 68.1k | ++Ss; |
563 | 68.1k | } |
564 | 314k | if (Ss > Se) { |
565 | 12.0k | return true; |
566 | 12.0k | } |
567 | 302k | if (*eobrun > 0) { |
568 | 40.6k | --(*eobrun); |
569 | 40.6k | return true; |
570 | 40.6k | } |
571 | 9.27M | for (int k = Ss; k <= Se; k++) { |
572 | 9.07M | s = ReadSymbol(ac_huff, br); |
573 | 9.07M | if (s >= kJpegHuffmanAlphabetSize) { |
574 | 36 | fprintf(stderr, "Invalid Huffman symbol %d for AC coefficient %d\n", |
575 | 36 | s, k); |
576 | 36 | jpg->error = JPEG_INVALID_SYMBOL; |
577 | 36 | return false; |
578 | 36 | } |
579 | 9.07M | r = s >> 4; |
580 | 9.07M | s &= 15; |
581 | 9.07M | if (s > 0) { |
582 | 9.00M | k += r; |
583 | 9.00M | if (k > Se) { |
584 | 14 | fprintf(stderr, "Out-of-band coefficient %d band was %d-%d\n", |
585 | 14 | k, Ss, Se); |
586 | 14 | jpg->error = JPEG_OUT_OF_BAND_COEFF; |
587 | 14 | return false; |
588 | 14 | } |
589 | 9.00M | if (s + Al >= kJpegDCAlphabetSize) { |
590 | 2 | fprintf(stderr, "Out of range AC coefficient value: s=%d Al=%d k=%d\n", |
591 | 2 | s, Al, k); |
592 | 2 | jpg->error = JPEG_NON_REPRESENTABLE_AC_COEFF; |
593 | 2 | return false; |
594 | 2 | } |
595 | 9.00M | r = br->ReadBits(s); |
596 | 9.00M | s = HuffExtend(r, s); |
597 | 9.00M | coeffs[kJPEGNaturalOrder[k]] = SignedLeftshift(s, Al); |
598 | 9.00M | } else if (r == 15) { |
599 | 6.18k | k += 15; |
600 | 66.0k | } else { |
601 | 66.0k | *eobrun = 1 << r; |
602 | 66.0k | if (r > 0) { |
603 | 17.9k | if (!eobrun_allowed) { |
604 | 1 | fprintf(stderr, "End-of-block run crossing DC coeff.\n"); |
605 | 1 | jpg->error = JPEG_EOB_RUN_TOO_LONG; |
606 | 1 | return false; |
607 | 1 | } |
608 | 17.9k | *eobrun += br->ReadBits(r); |
609 | 17.9k | } |
610 | 66.0k | break; |
611 | 66.0k | } |
612 | 9.07M | } |
613 | 261k | --(*eobrun); |
614 | 261k | return true; |
615 | 261k | } |
616 | | |
617 | | bool RefineDCTBlock(const HuffmanTableEntry* ac_huff, |
618 | | int Ss, int Se, int Al, |
619 | | int* eobrun, |
620 | | BitReaderState* br, |
621 | | JPEGData* jpg, |
622 | 310k | coeff_t* coeffs) { |
623 | 310k | bool eobrun_allowed = Ss > 0; |
624 | 310k | if (Ss == 0) { |
625 | 72.3k | int s = br->ReadBits(1); |
626 | 72.3k | coeff_t dc_coeff = coeffs[0]; |
627 | 72.3k | dc_coeff |= s << Al; |
628 | 72.3k | coeffs[0] = dc_coeff; |
629 | 72.3k | ++Ss; |
630 | 72.3k | } |
631 | 310k | if (Ss > Se) { |
632 | 72.2k | return true; |
633 | 72.2k | } |
634 | 238k | int p1 = 1 << Al; |
635 | 238k | int m1 = -(1 << Al); |
636 | 238k | int k = Ss; |
637 | 238k | int r; |
638 | 238k | int s; |
639 | 238k | bool in_zero_run = false; |
640 | 238k | if (*eobrun <= 0) { |
641 | 5.68M | for (; k <= Se; k++) { |
642 | 5.53M | s = ReadSymbol(ac_huff, br); |
643 | 5.53M | if (s >= kJpegHuffmanAlphabetSize) { |
644 | 72 | fprintf(stderr, "Invalid Huffman symbol %d for AC coefficient %d\n", |
645 | 72 | s, k); |
646 | 72 | jpg->error = JPEG_INVALID_SYMBOL; |
647 | 72 | return false; |
648 | 72 | } |
649 | 5.53M | r = s >> 4; |
650 | 5.53M | s &= 15; |
651 | 5.53M | if (s) { |
652 | 5.49M | if (s != 1) { |
653 | 9 | fprintf(stderr, "Invalid Huffman symbol %d for AC coefficient %d\n", |
654 | 9 | s, k); |
655 | 9 | jpg->error = JPEG_INVALID_SYMBOL; |
656 | 9 | return false; |
657 | 9 | } |
658 | 5.49M | s = br->ReadBits(1) ? p1 : m1; |
659 | 5.49M | in_zero_run = false; |
660 | 5.49M | } else { |
661 | 37.2k | if (r != 15) { |
662 | 36.8k | *eobrun = 1 << r; |
663 | 36.8k | if (r > 0) { |
664 | 18.2k | if (!eobrun_allowed) { |
665 | 2 | fprintf(stderr, "End-of-block run crossing DC coeff.\n"); |
666 | 2 | jpg->error = JPEG_EOB_RUN_TOO_LONG; |
667 | 2 | return false; |
668 | 2 | } |
669 | 18.2k | *eobrun += br->ReadBits(r); |
670 | 18.2k | } |
671 | 36.8k | break; |
672 | 36.8k | } |
673 | 344 | in_zero_run = true; |
674 | 344 | } |
675 | 5.99M | do { |
676 | 5.99M | coeff_t thiscoef = coeffs[kJPEGNaturalOrder[k]]; |
677 | 5.99M | if (thiscoef != 0) { |
678 | 13.5k | if (br->ReadBits(1)) { |
679 | 1.49k | if ((thiscoef & p1) == 0) { |
680 | 1.49k | if (thiscoef >= 0) { |
681 | 367 | thiscoef += p1; |
682 | 1.12k | } else { |
683 | 1.12k | thiscoef += m1; |
684 | 1.12k | } |
685 | 1.49k | } |
686 | 1.49k | } |
687 | 13.5k | coeffs[kJPEGNaturalOrder[k]] = thiscoef; |
688 | 5.98M | } else { |
689 | 5.98M | if (--r < 0) { |
690 | 5.49M | break; |
691 | 5.49M | } |
692 | 5.98M | } |
693 | 494k | k++; |
694 | 494k | } while (k <= Se); |
695 | 5.49M | if (s) { |
696 | 5.49M | if (k > Se) { |
697 | 15 | fprintf(stderr, "Out-of-band coefficient %d band was %d-%d\n", |
698 | 15 | k, Ss, Se); |
699 | 15 | jpg->error = JPEG_OUT_OF_BAND_COEFF; |
700 | 15 | return false; |
701 | 15 | } |
702 | 5.49M | coeffs[kJPEGNaturalOrder[k]] = s; |
703 | 5.49M | } |
704 | 5.49M | } |
705 | 188k | } |
706 | 238k | if (in_zero_run) { |
707 | 14 | fprintf(stderr, "Extra zero run before end-of-block.\n"); |
708 | 14 | jpg->error = JPEG_EXTRA_ZERO_RUN; |
709 | 14 | return false; |
710 | 14 | } |
711 | 238k | if (*eobrun > 0) { |
712 | 3.56M | for (; k <= Se; k++) { |
713 | 3.47M | coeff_t thiscoef = coeffs[kJPEGNaturalOrder[k]]; |
714 | 3.47M | if (thiscoef != 0) { |
715 | 44.5k | if (br->ReadBits(1)) { |
716 | 7.71k | if ((thiscoef & p1) == 0) { |
717 | 7.71k | if (thiscoef >= 0) { |
718 | 398 | thiscoef += p1; |
719 | 7.32k | } else { |
720 | 7.32k | thiscoef += m1; |
721 | 7.32k | } |
722 | 7.71k | } |
723 | 7.71k | } |
724 | 44.5k | coeffs[kJPEGNaturalOrder[k]] = thiscoef; |
725 | 44.5k | } |
726 | 3.47M | } |
727 | 87.1k | } |
728 | 238k | --(*eobrun); |
729 | 238k | return true; |
730 | 238k | } |
731 | | |
732 | | bool ProcessRestart(const uint8_t* data, const size_t len, |
733 | | int* next_restart_marker, BitReaderState* br, |
734 | 166 | JPEGData* jpg) { |
735 | 166 | size_t pos = 0; |
736 | 166 | if (!br->FinishStream(&pos)) { |
737 | 33 | jpg->error = JPEG_INVALID_SCAN; |
738 | 33 | return false; |
739 | 33 | } |
740 | 133 | int expected_marker = 0xd0 + *next_restart_marker; |
741 | 133 | EXPECT_MARKER(); |
742 | 93 | int marker = data[pos + 1]; |
743 | 93 | if (marker != expected_marker) { |
744 | 21 | fprintf(stderr, "Did not find expected restart marker %d actual=%d\n", |
745 | 21 | expected_marker, marker); |
746 | 21 | jpg->error = JPEG_WRONG_RESTART_MARKER; |
747 | 21 | return false; |
748 | 21 | } |
749 | 72 | br->Reset(pos + 2); |
750 | 72 | *next_restart_marker += 1; |
751 | 72 | *next_restart_marker &= 0x7; |
752 | 72 | return true; |
753 | 93 | } |
754 | | |
755 | | bool ProcessScan(const uint8_t* data, const size_t len, |
756 | | const std::vector<HuffmanTableEntry>& dc_huff_lut, |
757 | | const std::vector<HuffmanTableEntry>& ac_huff_lut, |
758 | | uint16_t scan_progression[kMaxComponents][kDCTBlockSize], |
759 | | bool is_progressive, |
760 | | size_t* pos, |
761 | 6.28k | JPEGData* jpg) { |
762 | 6.28k | if (!ProcessSOS(data, len, pos, jpg)) { |
763 | 151 | return false; |
764 | 151 | } |
765 | 6.13k | JPEGScanInfo* scan_info = &jpg->scan_info.back(); |
766 | 6.13k | bool is_interleaved = (scan_info->components.size() > 1); |
767 | 6.13k | int MCUs_per_row; |
768 | 6.13k | int MCU_rows; |
769 | 6.13k | if (is_interleaved) { |
770 | 686 | MCUs_per_row = jpg->MCU_cols; |
771 | 686 | MCU_rows = jpg->MCU_rows; |
772 | 5.44k | } else { |
773 | 5.44k | const JPEGComponent& c = jpg->components[scan_info->components[0].comp_idx]; |
774 | 5.44k | MCUs_per_row = |
775 | 5.44k | DivCeil(jpg->width * c.h_samp_factor, 8 * jpg->max_h_samp_factor); |
776 | 5.44k | MCU_rows = |
777 | 5.44k | DivCeil(jpg->height * c.v_samp_factor, 8 * jpg->max_v_samp_factor); |
778 | 5.44k | } |
779 | 6.13k | coeff_t last_dc_coeff[kMaxComponents] = {0}; |
780 | 6.13k | BitReaderState br(data, len, *pos); |
781 | 6.13k | int restarts_to_go = jpg->restart_interval; |
782 | 6.13k | int next_restart_marker = 0; |
783 | 6.13k | int eobrun = -1; |
784 | 6.13k | int block_scan_index = 0; |
785 | 6.13k | const int Al = is_progressive ? scan_info->Al : 0; |
786 | 6.13k | const int Ah = is_progressive ? scan_info->Ah : 0; |
787 | 6.13k | const int Ss = is_progressive ? scan_info->Ss : 0; |
788 | 6.13k | const int Se = is_progressive ? scan_info->Se : 63; |
789 | 6.13k | const uint16_t scan_bitmask = Ah == 0 ? (0xffff << Al) : (1u << Al); |
790 | 6.13k | const uint16_t refinement_bitmask = (1 << Al) - 1; |
791 | 13.5k | for (size_t i = 0; i < scan_info->components.size(); ++i) { |
792 | 7.45k | int comp_idx = scan_info->components[i].comp_idx; |
793 | 184k | for (int k = Ss; k <= Se; ++k) { |
794 | 176k | if (scan_progression[comp_idx][k] & scan_bitmask) { |
795 | 54 | fprintf(stderr, "Overlapping scans: component=%d k=%d prev_mask=%d " |
796 | 54 | "cur_mask=%d\n", comp_idx, k, scan_progression[i][k], |
797 | 54 | scan_bitmask); |
798 | 54 | jpg->error = JPEG_OVERLAPPING_SCANS; |
799 | 54 | return false; |
800 | 54 | } |
801 | 176k | if (scan_progression[comp_idx][k] & refinement_bitmask) { |
802 | 13 | fprintf(stderr, "Invalid scan order, a more refined scan was already " |
803 | 13 | "done: component=%d k=%d prev_mask=%d cur_mask=%d\n", comp_idx, |
804 | 13 | k, scan_progression[i][k], scan_bitmask); |
805 | 13 | jpg->error = JPEG_INVALID_SCAN_ORDER; |
806 | 13 | return false; |
807 | 13 | } |
808 | 176k | scan_progression[comp_idx][k] |= scan_bitmask; |
809 | 176k | } |
810 | 7.45k | } |
811 | 6.06k | if (Al > 10) { |
812 | 4 | fprintf(stderr, "Scan parameter Al=%d is not supported in guetzli.\n", Al); |
813 | 4 | jpg->error = JPEG_NON_REPRESENTABLE_AC_COEFF; |
814 | 4 | return false; |
815 | 4 | } |
816 | 97.3k | for (int mcu_y = 0; mcu_y < MCU_rows; ++mcu_y) { |
817 | 270k | for (int mcu_x = 0; mcu_x < MCUs_per_row; ++mcu_x) { |
818 | | // Handle the restart intervals. |
819 | 179k | if (jpg->restart_interval > 0) { |
820 | 10.2k | if (restarts_to_go == 0) { |
821 | 166 | if (ProcessRestart(data, len, |
822 | 166 | &next_restart_marker, &br, jpg)) { |
823 | 72 | restarts_to_go = jpg->restart_interval; |
824 | 72 | memset(last_dc_coeff, 0, sizeof(last_dc_coeff)); |
825 | 72 | if (eobrun > 0) { |
826 | 3 | fprintf(stderr, "End-of-block run too long.\n"); |
827 | 3 | jpg->error = JPEG_EOB_RUN_TOO_LONG; |
828 | 3 | return false; |
829 | 3 | } |
830 | 69 | eobrun = -1; // fresh start |
831 | 94 | } else { |
832 | 94 | return false; |
833 | 94 | } |
834 | 166 | } |
835 | 10.1k | --restarts_to_go; |
836 | 10.1k | } |
837 | | // Decode one MCU. |
838 | 395k | for (size_t i = 0; i < scan_info->components.size(); ++i) { |
839 | 215k | JPEGComponentScanInfo* si = &scan_info->components[i]; |
840 | 215k | JPEGComponent* c = &jpg->components[si->comp_idx]; |
841 | 215k | const HuffmanTableEntry* dc_lut = |
842 | 215k | &dc_huff_lut[si->dc_tbl_idx * kJpegHuffmanLutSize]; |
843 | 215k | const HuffmanTableEntry* ac_lut = |
844 | 215k | &ac_huff_lut[si->ac_tbl_idx * kJpegHuffmanLutSize]; |
845 | 215k | int nblocks_y = is_interleaved ? c->v_samp_factor : 1; |
846 | 215k | int nblocks_x = is_interleaved ? c->h_samp_factor : 1; |
847 | 614k | for (int iy = 0; iy < nblocks_y; ++iy) { |
848 | 1.02M | for (int ix = 0; ix < nblocks_x; ++ix) { |
849 | 625k | int block_y = mcu_y * nblocks_y + iy; |
850 | 625k | int block_x = mcu_x * nblocks_x + ix; |
851 | 625k | int block_idx = block_y * c->width_in_blocks + block_x; |
852 | 625k | coeff_t* coeffs = &c->coeffs[block_idx * kDCTBlockSize]; |
853 | 625k | if (Ah == 0) { |
854 | 314k | if (!DecodeDCTBlock(dc_lut, ac_lut, Ss, Se, Al, &eobrun, &br, jpg, |
855 | 314k | &last_dc_coeff[si->comp_idx], coeffs)) { |
856 | 125 | return false; |
857 | 125 | } |
858 | 314k | } else { |
859 | 310k | if (!RefineDCTBlock(ac_lut, Ss, Se, Al, |
860 | 310k | &eobrun, &br, jpg, coeffs)) { |
861 | 112 | return false; |
862 | 112 | } |
863 | 310k | } |
864 | 624k | ++block_scan_index; |
865 | 624k | } |
866 | 398k | } |
867 | 215k | } |
868 | 179k | } |
869 | 91.6k | } |
870 | 5.72k | if (eobrun > 0) { |
871 | 87 | fprintf(stderr, "End-of-block run too long.\n"); |
872 | 87 | jpg->error = JPEG_EOB_RUN_TOO_LONG; |
873 | 87 | return false; |
874 | 87 | } |
875 | 5.64k | if (!br.FinishStream(pos)) { |
876 | 283 | jpg->error = JPEG_INVALID_SCAN; |
877 | 283 | return false; |
878 | 283 | } |
879 | 5.35k | if (*pos > len) { |
880 | 0 | fprintf(stderr, "Unexpected end of file during scan. pos=%d len=%d\n", |
881 | 0 | static_cast<int>(*pos), static_cast<int>(len)); |
882 | 0 | jpg->error = JPEG_UNEXPECTED_EOF; |
883 | 0 | return false; |
884 | 0 | } |
885 | 5.35k | return true; |
886 | 5.35k | } |
887 | | |
888 | | // Changes the quant_idx field of the components to refer to the index of the |
889 | | // quant table in the jpg->quant array. |
890 | 2.66k | bool FixupIndexes(JPEGData* jpg) { |
891 | 10.4k | for (size_t i = 0; i < jpg->components.size(); ++i) { |
892 | 7.79k | JPEGComponent* c = &jpg->components[i]; |
893 | 7.79k | bool found_index = false; |
894 | 8.89k | for (size_t j = 0; j < jpg->quant.size(); ++j) { |
895 | 8.87k | if (jpg->quant[j].index == c->quant_idx) { |
896 | 7.78k | c->quant_idx = j; |
897 | 7.78k | found_index = true; |
898 | 7.78k | break; |
899 | 7.78k | } |
900 | 8.87k | } |
901 | 7.79k | if (!found_index) { |
902 | 14 | fprintf(stderr, "Quantization table with index %zd not found\n", |
903 | 14 | c->quant_idx); |
904 | 14 | jpg->error = JPEG_QUANT_TABLE_NOT_FOUND; |
905 | 14 | return false; |
906 | 14 | } |
907 | 7.79k | } |
908 | 2.64k | return true; |
909 | 2.66k | } |
910 | | |
911 | 7.11M | size_t FindNextMarker(const uint8_t* data, const size_t len, size_t pos) { |
912 | | // kIsValidMarker[i] == 1 means (0xc0 + i) is a valid marker. |
913 | 7.11M | static const uint8_t kIsValidMarker[] = { |
914 | 7.11M | 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
915 | 7.11M | 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, |
916 | 7.11M | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
917 | 7.11M | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, |
918 | 7.11M | }; |
919 | 7.11M | size_t num_skipped = 0; |
920 | 56.2M | while (pos + 1 < len && |
921 | 56.2M | (data[pos] != 0xff || data[pos + 1] < 0xc0 || |
922 | 49.1M | !kIsValidMarker[data[pos + 1] - 0xc0])) { |
923 | 49.1M | ++pos; |
924 | 49.1M | ++num_skipped; |
925 | 49.1M | } |
926 | 7.11M | return num_skipped; |
927 | 7.11M | } |
928 | | |
929 | | } // namespace |
930 | | |
931 | | bool ReadJpeg(const uint8_t* data, const size_t len, JpegReadMode mode, |
932 | 9.18k | JPEGData* jpg) { |
933 | 9.18k | size_t pos = 0; |
934 | | // Check SOI marker. |
935 | 9.18k | EXPECT_MARKER(); |
936 | 9.16k | int marker = data[pos + 1]; |
937 | 9.16k | pos += 2; |
938 | 9.16k | if (marker != 0xd8) { |
939 | 12 | fprintf(stderr, "Did not find expected SOI marker, actual=%d\n", marker); |
940 | 12 | jpg->error = JPEG_SOI_NOT_FOUND; |
941 | 12 | return false; |
942 | 12 | } |
943 | 9.15k | int lut_size = kMaxHuffmanTables * kJpegHuffmanLutSize; |
944 | 9.15k | std::vector<HuffmanTableEntry> dc_huff_lut(lut_size); |
945 | 9.15k | std::vector<HuffmanTableEntry> ac_huff_lut(lut_size); |
946 | 9.15k | bool found_sof = false; |
947 | 9.15k | uint16_t scan_progression[kMaxComponents][kDCTBlockSize] = { { 0 } }; |
948 | | |
949 | 9.15k | bool is_progressive = false; // default |
950 | 7.11M | do { |
951 | | // Read next marker. |
952 | 7.11M | size_t num_skipped = FindNextMarker(data, len, pos); |
953 | 7.11M | if (num_skipped > 0) { |
954 | | // Add a fake marker to indicate arbitrary in-between-markers data. |
955 | 6.69M | jpg->marker_order.push_back(0xff); |
956 | 6.69M | jpg->inter_marker_data.push_back( |
957 | 6.69M | std::string(reinterpret_cast<const char*>(&data[pos]), |
958 | 6.69M | num_skipped)); |
959 | 6.69M | pos += num_skipped; |
960 | 6.69M | } |
961 | 7.11M | EXPECT_MARKER(); |
962 | 7.11M | marker = data[pos + 1]; |
963 | 7.11M | pos += 2; |
964 | 7.11M | bool ok = true; |
965 | 7.11M | switch (marker) { |
966 | 1.05k | case 0xc0: |
967 | 2.52k | case 0xc1: |
968 | 8.51k | case 0xc2: |
969 | 8.51k | is_progressive = (marker == 0xc2); |
970 | 8.51k | ok = ProcessSOF(data, len, mode, &pos, jpg); |
971 | 8.51k | found_sof = true; |
972 | 8.51k | break; |
973 | 19.4k | case 0xc4: |
974 | 19.4k | ok = ProcessDHT(data, len, mode, &dc_huff_lut, &ac_huff_lut, &pos, jpg); |
975 | 19.4k | break; |
976 | 3.88M | case 0xd0: |
977 | 3.88M | case 0xd1: |
978 | 3.88M | case 0xd2: |
979 | 3.90M | case 0xd3: |
980 | 3.90M | case 0xd4: |
981 | 3.91M | case 0xd5: |
982 | 4.16M | case 0xd6: |
983 | 4.87M | case 0xd7: |
984 | | // RST markers do not have any data. |
985 | 4.87M | break; |
986 | 2.66k | case 0xd9: |
987 | | // Found end marker. |
988 | 2.66k | break; |
989 | 6.69k | case 0xda: |
990 | 6.69k | if (mode == JPEG_READ_ALL) { |
991 | 6.28k | ok = ProcessScan(data, len, dc_huff_lut, ac_huff_lut, |
992 | 6.28k | scan_progression, is_progressive, &pos, jpg); |
993 | 6.28k | } |
994 | 6.69k | break; |
995 | 6.85k | case 0xdb: |
996 | 6.85k | ok = ProcessDQT(data, len, &pos, jpg); |
997 | 6.85k | break; |
998 | 671 | case 0xdd: |
999 | 671 | ok = ProcessDRI(data, len, &pos, jpg); |
1000 | 671 | break; |
1001 | 127k | case 0xe0: |
1002 | 713k | case 0xe1: |
1003 | 714k | case 0xe2: |
1004 | 714k | case 0xe3: |
1005 | 714k | case 0xe4: |
1006 | 899k | case 0xe5: |
1007 | 899k | case 0xe6: |
1008 | 900k | case 0xe7: |
1009 | 900k | case 0xe8: |
1010 | 1.24M | case 0xe9: |
1011 | 1.24M | case 0xea: |
1012 | 1.24M | case 0xeb: |
1013 | 1.24M | case 0xec: |
1014 | 1.24M | case 0xed: |
1015 | 1.24M | case 0xee: |
1016 | 1.77M | case 0xef: |
1017 | 1.77M | if (mode != JPEG_READ_TABLES) { |
1018 | 1.77M | ok = ProcessAPP(data, len, &pos, jpg); |
1019 | 1.77M | } |
1020 | 1.77M | break; |
1021 | 418k | case 0xfe: |
1022 | 418k | if (mode != JPEG_READ_TABLES) { |
1023 | 418k | ok = ProcessCOM(data, len, &pos, jpg); |
1024 | 418k | } |
1025 | 418k | break; |
1026 | 0 | default: |
1027 | 0 | fprintf(stderr, "Unsupported marker: %d pos=%d len=%d\n", |
1028 | 0 | marker, static_cast<int>(pos), static_cast<int>(len)); |
1029 | 0 | jpg->error = JPEG_UNSUPPORTED_MARKER; |
1030 | 0 | ok = false; |
1031 | 0 | break; |
1032 | 7.11M | } |
1033 | 7.11M | if (!ok) { |
1034 | 1.71k | return false; |
1035 | 1.71k | } |
1036 | 7.11M | jpg->marker_order.push_back(marker); |
1037 | 7.11M | if (mode == JPEG_READ_HEADER && found_sof) { |
1038 | 4.22k | break; |
1039 | 4.22k | } |
1040 | 7.11M | } while (marker != 0xd9); |
1041 | | |
1042 | 6.89k | if (!found_sof) { |
1043 | 6 | fprintf(stderr, "Missing SOF marker.\n"); |
1044 | 6 | jpg->error = JPEG_SOF_NOT_FOUND; |
1045 | 6 | return false; |
1046 | 6 | } |
1047 | | |
1048 | | // Supplemental checks. |
1049 | 6.88k | if (mode == JPEG_READ_ALL) { |
1050 | 2.66k | if (pos < len) { |
1051 | 275 | jpg->tail_data.assign(reinterpret_cast<const char*>(&data[pos]), |
1052 | 275 | len - pos); |
1053 | 275 | } |
1054 | 2.66k | if (!FixupIndexes(jpg)) { |
1055 | 14 | return false; |
1056 | 14 | } |
1057 | 2.64k | if (jpg->huffman_code.size() == 0) { |
1058 | | // Section B.2.4.2: "If a table has never been defined for a particular |
1059 | | // destination, then when this destination is specified in a scan header, |
1060 | | // the results are unpredictable." |
1061 | 6 | fprintf(stderr, "Need at least one Huffman code table.\n"); |
1062 | 6 | jpg->error = JPEG_HUFFMAN_TABLE_ERROR; |
1063 | 6 | return false; |
1064 | 6 | } |
1065 | 2.64k | if (jpg->huffman_code.size() >= kMaxDHTMarkers) { |
1066 | 1 | fprintf(stderr, "Too many Huffman tables.\n"); |
1067 | 1 | jpg->error = JPEG_HUFFMAN_TABLE_ERROR; |
1068 | 1 | return false; |
1069 | 1 | } |
1070 | 2.64k | } |
1071 | 6.86k | return true; |
1072 | 6.88k | } |
1073 | | |
1074 | | bool ReadJpeg(const std::string& data, JpegReadMode mode, |
1075 | 4.20k | JPEGData* jpg) { |
1076 | 4.20k | return ReadJpeg(reinterpret_cast<const uint8_t*>(data.data()), |
1077 | 4.20k | static_cast<const size_t>(data.size()), |
1078 | 4.20k | mode, jpg); |
1079 | 4.20k | } |
1080 | | |
1081 | | } // namespace guetzli |