/src/serenity/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2020, the SerenityOS developers. |
3 | | * Copyright (c) 2022-2023, Lucas Chollet <lucas.chollet@serenityos.org> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #include <AK/Debug.h> |
9 | | #include <AK/Endian.h> |
10 | | #include <AK/Error.h> |
11 | | #include <AK/FixedArray.h> |
12 | | #include <AK/HashMap.h> |
13 | | #include <AK/Math.h> |
14 | | #include <AK/MemoryStream.h> |
15 | | #include <AK/NumericLimits.h> |
16 | | #include <AK/String.h> |
17 | | #include <AK/Try.h> |
18 | | #include <AK/Vector.h> |
19 | | #include <LibGfx/ImageFormats/JPEGLoader.h> |
20 | | #include <LibGfx/ImageFormats/JPEGShared.h> |
21 | | #include <LibGfx/ImageFormats/TIFFLoader.h> |
22 | | #include <LibGfx/ImageFormats/TIFFMetadata.h> |
23 | | |
24 | | namespace Gfx { |
25 | | |
26 | | struct MacroblockMeta { |
27 | | u32 total { 0 }; |
28 | | u32 padded_total { 0 }; |
29 | | u32 hcount { 0 }; |
30 | | u32 vcount { 0 }; |
31 | | u32 hpadded_count { 0 }; |
32 | | u32 vpadded_count { 0 }; |
33 | | }; |
34 | | |
35 | | struct SamplingFactors { |
36 | | u8 horizontal {}; |
37 | | u8 vertical {}; |
38 | | |
39 | 316 | bool operator==(SamplingFactors const&) const = default; |
40 | | }; |
41 | | |
42 | | // In the JPEG format, components are defined first at the frame level, then |
43 | | // referenced in each scan and aggregated with scan-specific information. The |
44 | | // two following structs mimic this hierarchy. |
45 | | |
46 | | struct Component { |
47 | | // B.2.2 - Frame header syntax |
48 | | u8 id { 0 }; // Ci, Component identifier |
49 | | SamplingFactors sampling_factors { 1, 1 }; // Hi, Horizontal sampling factor and Vi, Vertical sampling factor |
50 | | u8 quantization_table_id { 0 }; // Tqi, Quantization table destination selector |
51 | | |
52 | | // The JPEG specification does not specify which component corresponds to |
53 | | // Y, Cb or Cr. This field (actually the index in the parent Vector) will |
54 | | // act as an authority to determine the *real* component. |
55 | | // Please note that this is implementation specific. |
56 | | u8 index { 0 }; |
57 | | }; |
58 | | |
59 | | struct ScanComponent { |
60 | | // B.2.3 - Scan header syntax |
61 | | Component& component; |
62 | | u8 dc_destination_id { 0 }; // Tdj, DC entropy coding table destination selector |
63 | | u8 ac_destination_id { 0 }; // Taj, AC entropy coding table destination selector |
64 | | }; |
65 | | |
66 | | struct StartOfFrame { |
67 | | |
68 | | // Of these, only the first 3 are in mainstream use, and refers to SOF0-2. |
69 | | enum class FrameType { |
70 | | Baseline_DCT = 0, |
71 | | Extended_Sequential_DCT = 1, |
72 | | Progressive_DCT = 2, |
73 | | Sequential_Lossless = 3, |
74 | | Differential_Sequential_DCT = 5, |
75 | | Differential_Progressive_DCT = 6, |
76 | | Differential_Sequential_Lossless = 7, |
77 | | Extended_Sequential_DCT_Arithmetic = 9, |
78 | | Progressive_DCT_Arithmetic = 10, |
79 | | Sequential_Lossless_Arithmetic = 11, |
80 | | Differential_Sequential_DCT_Arithmetic = 13, |
81 | | Differential_Progressive_DCT_Arithmetic = 14, |
82 | | Differential_Sequential_Lossless_Arithmetic = 15, |
83 | | }; |
84 | | |
85 | | FrameType type { FrameType::Baseline_DCT }; |
86 | | u8 precision { 0 }; |
87 | | u16 height { 0 }; |
88 | | u16 width { 0 }; |
89 | | }; |
90 | | |
91 | | struct HuffmanTable { |
92 | | u8 type { 0 }; |
93 | | u8 destination_id { 0 }; |
94 | | u8 code_counts[16] = { 0 }; |
95 | | Vector<u8> symbols; |
96 | | Vector<u16> codes; |
97 | | |
98 | | // Note: The value 8 is chosen quite arbitrarily, the only current constraint |
99 | | // is that both the symbol and the size fit in an u16. I've tested more |
100 | | // values but none stand out, and 8 is the value used by libjpeg-turbo. |
101 | | static constexpr u8 bits_per_cached_code = 8; |
102 | | static constexpr u8 maximum_bits_per_code = 16; |
103 | | u8 first_non_cached_code_index {}; |
104 | | |
105 | | ErrorOr<void> generate_codes() |
106 | 147k | { |
107 | 147k | unsigned code = 0; |
108 | 2.35M | for (auto number_of_codes : code_counts) { |
109 | 2.59M | for (int i = 0; i < number_of_codes; i++) |
110 | 233k | codes.append(code++); |
111 | 2.35M | code <<= 1; |
112 | 2.35M | } |
113 | | |
114 | 147k | TRY(generate_lookup_table()); |
115 | 147k | return {}; |
116 | 147k | } |
117 | | |
118 | | struct SymbolAndSize { |
119 | | u8 symbol {}; |
120 | | u8 size {}; |
121 | | }; |
122 | | |
123 | | ErrorOr<SymbolAndSize> symbol_from_code(u16 code) const |
124 | 468M | { |
125 | 468M | static constexpr u8 shift_for_cache = maximum_bits_per_code - bits_per_cached_code; |
126 | | |
127 | 468M | if (lookup_table[code >> shift_for_cache] != invalid_entry) { |
128 | 460M | u8 const code_length = lookup_table[code >> shift_for_cache] >> bits_per_cached_code; |
129 | 460M | return SymbolAndSize { static_cast<u8>(lookup_table[code >> shift_for_cache]), code_length }; |
130 | 460M | } |
131 | | |
132 | 8.46M | u64 code_cursor = first_non_cached_code_index; |
133 | | |
134 | 58.0M | for (u8 i = HuffmanTable::bits_per_cached_code; i < 16; i++) { |
135 | 58.0M | auto const result = code >> (maximum_bits_per_code - 1 - i); |
136 | 60.2M | for (u32 j = 0; j < code_counts[i]; j++) { |
137 | 10.6M | if (result == codes[code_cursor]) |
138 | 8.46M | return SymbolAndSize { symbols[code_cursor], static_cast<u8>(i + 1) }; |
139 | | |
140 | 2.20M | code_cursor++; |
141 | 2.20M | } |
142 | 58.0M | } |
143 | | |
144 | 94 | return Error::from_string_literal("This kind of JPEG is not yet supported by the decoder"); |
145 | 8.46M | } |
146 | | |
147 | | private: |
148 | | static constexpr u16 invalid_entry = 0xFF; |
149 | | |
150 | | ErrorOr<void> generate_lookup_table() |
151 | 147k | { |
152 | 147k | lookup_table.fill(invalid_entry); |
153 | | |
154 | 147k | u32 code_offset = 0; |
155 | 1.32M | for (u8 code_length = 1; code_length <= bits_per_cached_code; code_length++) { |
156 | 1.23M | for (u32 i = 0; i < code_counts[code_length - 1]; i++, code_offset++) { |
157 | 53.5k | u32 code_key = codes[code_offset] << (bits_per_cached_code - code_length); |
158 | 53.5k | u8 duplicate_count = 1 << (bits_per_cached_code - code_length); |
159 | 53.5k | if (code_key + duplicate_count >= lookup_table.size()) |
160 | 11 | return Error::from_string_literal("Malformed Huffman table"); |
161 | | |
162 | 1.15M | for (; duplicate_count > 0; duplicate_count--) { |
163 | 1.10M | lookup_table[code_key] = (code_length << bits_per_cached_code) | symbols[code_offset]; |
164 | 1.10M | code_key++; |
165 | 1.10M | } |
166 | 53.5k | } |
167 | 1.17M | } |
168 | 147k | return {}; |
169 | 147k | } |
170 | | |
171 | | Array<u16, 1 << bits_per_cached_code> lookup_table {}; |
172 | | }; |
173 | | |
174 | | class HuffmanStream; |
175 | | |
176 | | class JPEGStream { |
177 | | public: |
178 | | static ErrorOr<JPEGStream> create(NonnullOwnPtr<Stream> stream) |
179 | 4.04k | { |
180 | 4.04k | Vector<u8> buffer; |
181 | 4.04k | TRY(buffer.try_resize(buffer_size)); |
182 | 4.04k | JPEGStream jpeg_stream { move(stream), move(buffer) }; |
183 | | |
184 | 4.04k | TRY(jpeg_stream.refill_buffer()); |
185 | 4.04k | jpeg_stream.m_offset_from_start = 0; |
186 | 4.04k | return jpeg_stream; |
187 | 4.04k | } |
188 | | |
189 | | ALWAYS_INLINE ErrorOr<u8> read_u8() |
190 | 35.8M | { |
191 | 35.8M | if (m_byte_offset == m_current_size) |
192 | 12.8k | TRY(refill_buffer()); |
193 | 35.8M | return m_buffer[m_byte_offset++]; |
194 | 35.8M | } |
195 | | |
196 | | ALWAYS_INLINE ErrorOr<u16> read_u16() |
197 | 3.45M | { |
198 | 3.45M | if (m_saved_marker.has_value()) |
199 | 260k | return m_saved_marker.release_value(); |
200 | | |
201 | 3.19M | return (static_cast<u16>(TRY(read_u8())) << 8) | TRY(read_u8()); |
202 | 3.19M | } |
203 | | |
204 | | ALWAYS_INLINE ErrorOr<void> discard(u64 bytes) |
205 | 321k | { |
206 | 321k | auto const discarded_from_buffer = min(m_current_size - m_byte_offset, bytes); |
207 | 321k | m_byte_offset += discarded_from_buffer; |
208 | | |
209 | 321k | if (discarded_from_buffer < bytes) { |
210 | 939 | m_offset_from_start += bytes - discarded_from_buffer; |
211 | 939 | TRY(m_stream->discard(bytes - discarded_from_buffer)); |
212 | 667 | } |
213 | | |
214 | 321k | return {}; |
215 | 321k | } |
216 | | |
217 | | ErrorOr<void> read_until_filled(Bytes bytes) |
218 | 20.9k | { |
219 | 20.9k | auto const copied = m_buffer.span().trim(m_current_size).slice(m_byte_offset).copy_trimmed_to(bytes); |
220 | 20.9k | m_byte_offset += copied; |
221 | | |
222 | 20.9k | if (copied < bytes.size()) { |
223 | 2.19k | m_offset_from_start += bytes.size() - copied; |
224 | 2.19k | TRY(m_stream->read_until_filled(bytes.slice(copied))); |
225 | 2.05k | } |
226 | | |
227 | 20.9k | return {}; |
228 | 20.9k | } |
229 | | |
230 | | Optional<u16>& saved_marker(Badge<HuffmanStream>) |
231 | 273M | { |
232 | 273M | return m_saved_marker; |
233 | 273M | } |
234 | | |
235 | | u64 byte_offset() const |
236 | 0 | { |
237 | 0 | return m_offset_from_start + m_byte_offset; |
238 | 0 | } |
239 | | |
240 | | private: |
241 | | JPEGStream(NonnullOwnPtr<Stream> stream, Vector<u8> buffer) |
242 | 4.04k | : m_stream(move(stream)) |
243 | 4.04k | , m_buffer(move(buffer)) |
244 | 4.04k | { |
245 | 4.04k | } |
246 | | |
247 | | ErrorOr<void> refill_buffer() |
248 | 16.8k | { |
249 | 16.8k | VERIFY(m_byte_offset == m_current_size); |
250 | | |
251 | 16.8k | m_offset_from_start += m_byte_offset; |
252 | | |
253 | 16.8k | m_current_size = TRY(m_stream->read_some(m_buffer.span())).size(); |
254 | 16.8k | if (m_current_size == 0) |
255 | 2.10k | return Error::from_string_literal("Unexpected end of file"); |
256 | | |
257 | 14.7k | m_byte_offset = 0; |
258 | | |
259 | 14.7k | return {}; |
260 | 16.8k | } |
261 | | |
262 | | static constexpr auto buffer_size = 4096; |
263 | | |
264 | | NonnullOwnPtr<Stream> m_stream; |
265 | | |
266 | | Optional<u16> m_saved_marker {}; |
267 | | |
268 | | Vector<u8> m_buffer {}; |
269 | | u64 m_offset_from_start { 0 }; |
270 | | u64 m_byte_offset { buffer_size }; |
271 | | u64 m_current_size { buffer_size }; |
272 | | }; |
273 | | |
274 | | class HuffmanStream { |
275 | | public: |
276 | | ALWAYS_INLINE ErrorOr<u8> next_symbol(HuffmanTable const& table) |
277 | 468M | { |
278 | 468M | u16 const code = TRY(peek_bits(HuffmanTable::maximum_bits_per_code)); |
279 | | |
280 | 468M | auto const symbol_and_size = TRY(table.symbol_from_code(code)); |
281 | | |
282 | 468M | TRY(discard_bits(symbol_and_size.size)); |
283 | 468M | return symbol_and_size.symbol; |
284 | 468M | } |
285 | | |
286 | | ALWAYS_INLINE ErrorOr<u16> read_bits(u8 count = 1) |
287 | 540M | { |
288 | 540M | if (count > NumericLimits<u16>::digits()) { |
289 | 0 | dbgln_if(JPEG_DEBUG, "Can't read {} bits at once!", count); |
290 | 0 | return Error::from_string_literal("Reading too much huffman bits at once"); |
291 | 0 | } |
292 | | |
293 | 540M | u16 const value = TRY(peek_bits(count)); |
294 | 540M | TRY(discard_bits(count)); |
295 | 540M | return value; |
296 | 540M | } |
297 | | |
298 | | ALWAYS_INLINE ErrorOr<u16> peek_bits(u8 count) |
299 | 1.00G | { |
300 | 1.00G | if (count == 0) |
301 | 5.07M | return 0; |
302 | | |
303 | 1.00G | if (count + m_bit_offset > bits_in_reservoir) |
304 | 41.7M | TRY(refill_reservoir()); |
305 | | |
306 | 1.00G | auto const mask = NumericLimits<u16>::max() >> (NumericLimits<u16>::digits() - count); |
307 | | |
308 | 1.00G | return static_cast<u16>((m_bit_reservoir >> (bits_in_reservoir - m_bit_offset - count)) & mask); |
309 | 1.00G | } |
310 | | |
311 | | ALWAYS_INLINE ErrorOr<void> discard_bits(u8 count) |
312 | 1.01G | { |
313 | 1.01G | m_bit_offset += count; |
314 | | |
315 | 1.01G | if (m_bit_offset > bits_in_reservoir) |
316 | 837k | TRY(refill_reservoir()); |
317 | | |
318 | 1.01G | return {}; |
319 | 1.01G | } |
320 | | |
321 | | ErrorOr<void> advance_to_byte_boundary() |
322 | 7.92M | { |
323 | 7.92M | if (auto remainder = m_bit_offset % 8; remainder != 0) |
324 | 112k | TRY(discard_bits(bits_per_byte - remainder)); |
325 | | |
326 | 7.92M | return {}; |
327 | 7.92M | } |
328 | | |
329 | | HuffmanStream(JPEGStream& stream) |
330 | 262k | : jpeg_stream(stream) |
331 | 262k | { |
332 | 262k | } |
333 | | |
334 | | private: |
335 | | ALWAYS_INLINE ErrorOr<void> refill_reservoir() |
336 | 42.6M | { |
337 | 42.6M | auto const bytes_needed = m_bit_offset / bits_per_byte; |
338 | | |
339 | 42.6M | u8 bytes_added {}; |
340 | | |
341 | 270M | auto const append_byte = [&](u8 byte) { |
342 | 270M | m_last_byte_was_ff = false; |
343 | 270M | m_bit_reservoir <<= 8; |
344 | 270M | m_bit_reservoir |= byte; |
345 | 270M | m_bit_offset -= 8; |
346 | 270M | bytes_added++; |
347 | 270M | }; |
348 | | |
349 | 273M | do { |
350 | | // Note: We fake zeroes when we have reached another segment |
351 | | // It allows us to continue peeking seamlessly. |
352 | 273M | u8 const next_byte = jpeg_stream.saved_marker({}).has_value() ? 0 : TRY(jpeg_stream.read_u8()); |
353 | | |
354 | 273M | if (m_last_byte_was_ff) { |
355 | 2.59M | if (next_byte == 0xFF) |
356 | 2.30M | continue; |
357 | | |
358 | 296k | if (next_byte == 0x00) { |
359 | 32.1k | append_byte(0xFF); |
360 | 32.1k | continue; |
361 | 32.1k | } |
362 | | |
363 | 264k | Marker const marker = 0xFF00 | next_byte; |
364 | 264k | if (marker < JPEG_RST0 || marker > JPEG_RST7) { |
365 | | // Note: The only way to know that we reached the end of a segment is to read |
366 | | // the marker of the following one. So we store it for later use. |
367 | 260k | jpeg_stream.saved_marker({}) = marker; |
368 | 260k | m_last_byte_was_ff = false; |
369 | 260k | continue; |
370 | 260k | } |
371 | 264k | } |
372 | | |
373 | 270M | if (next_byte == 0xFF) { |
374 | 296k | m_last_byte_was_ff = true; |
375 | 296k | continue; |
376 | 296k | } |
377 | | |
378 | 270M | append_byte(next_byte); |
379 | 273M | } while (bytes_added < bytes_needed); |
380 | | |
381 | 42.6M | return {}; |
382 | 42.6M | } |
383 | | |
384 | | JPEGStream& jpeg_stream; |
385 | | |
386 | | using Reservoir = u64; |
387 | | static constexpr auto bits_per_byte = 8; |
388 | | static constexpr auto bits_in_reservoir = sizeof(Reservoir) * bits_per_byte; |
389 | | |
390 | | Reservoir m_bit_reservoir {}; |
391 | | u8 m_bit_offset { bits_in_reservoir }; |
392 | | |
393 | | bool m_last_byte_was_ff { false }; |
394 | | }; |
395 | | |
396 | | struct ICCMultiChunkState { |
397 | | u8 seen_number_of_icc_chunks { 0 }; |
398 | | FixedArray<ByteBuffer> chunks; |
399 | | }; |
400 | | |
401 | | struct Scan { |
402 | | Scan(HuffmanStream stream) |
403 | 262k | : huffman_stream(stream) |
404 | 262k | { |
405 | 262k | } |
406 | | |
407 | | // B.2.3 - Scan header syntax |
408 | | Vector<ScanComponent, 4> components; |
409 | | |
410 | | u8 spectral_selection_start {}; // Ss |
411 | | u8 spectral_selection_end {}; // Se |
412 | | u8 successive_approximation_high {}; // Ah |
413 | | u8 successive_approximation_low {}; // Al |
414 | | |
415 | | HuffmanStream huffman_stream; |
416 | | |
417 | | u64 end_of_bands_run_count { 0 }; |
418 | | |
419 | | // See the note on Figure B.4 - Scan header syntax |
420 | | bool are_components_interleaved() const |
421 | 89.5M | { |
422 | 89.5M | return components.size() != 1; |
423 | 89.5M | } |
424 | | }; |
425 | | |
426 | | enum class ColorTransform { |
427 | | // https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.872-201206-I!!PDF-E&type=items |
428 | | // 6.5.3 - APP14 marker segment for colour encoding |
429 | | CmykOrRgb = 0, |
430 | | YCbCr = 1, |
431 | | YCCK = 2, |
432 | | }; |
433 | | |
434 | | struct JPEGLoadingContext { |
435 | | JPEGLoadingContext(JPEGStream jpeg_stream, JPEGDecoderOptions options) |
436 | 4.04k | : stream(move(jpeg_stream)) |
437 | 4.04k | , options(options) |
438 | 4.04k | { |
439 | 4.04k | } |
440 | | |
441 | | static ErrorOr<NonnullOwnPtr<JPEGLoadingContext>> create(NonnullOwnPtr<Stream> stream, JPEGDecoderOptions options) |
442 | 4.04k | { |
443 | 4.04k | auto jpeg_stream = TRY(JPEGStream::create(move(stream))); |
444 | 4.04k | return make<JPEGLoadingContext>(move(jpeg_stream), options); |
445 | 4.04k | } |
446 | | |
447 | | enum State { |
448 | | NotDecoded = 0, |
449 | | Error, |
450 | | FrameDecoded, |
451 | | HeaderDecoded, |
452 | | BitmapDecoded |
453 | | }; |
454 | | |
455 | | State state { State::NotDecoded }; |
456 | | |
457 | | Array<Array<u16, 64>, 4> quantization_tables {}; |
458 | | Array<bool, 4> registered_quantization_tables {}; |
459 | | |
460 | | StartOfFrame frame; |
461 | | SamplingFactors sampling_factors {}; |
462 | | |
463 | | Optional<Scan> current_scan {}; |
464 | | |
465 | | Vector<Component, 4> components; |
466 | | |
467 | | RefPtr<Gfx::Bitmap> bitmap; |
468 | | RefPtr<Gfx::CMYKBitmap> cmyk_bitmap; |
469 | | |
470 | | u16 dc_restart_interval { 0 }; |
471 | | Array<HuffmanTable, 4> dc_tables {}; |
472 | | Array<bool, 4> registered_dc_tables {}; |
473 | | Array<HuffmanTable, 4> ac_tables {}; |
474 | | Array<bool, 4> registered_ac_tables {}; |
475 | | Array<i16, 4> previous_dc_values {}; |
476 | | MacroblockMeta mblock_meta; |
477 | | JPEGStream stream; |
478 | | JPEGDecoderOptions options; |
479 | | |
480 | | Optional<ColorTransform> color_transform {}; |
481 | | |
482 | | OwnPtr<ExifMetadata> exif_metadata {}; |
483 | | |
484 | | Optional<ICCMultiChunkState> icc_multi_chunk_state; |
485 | | Optional<ByteBuffer> icc_data; |
486 | | }; |
487 | | |
488 | | static inline auto* get_component(Macroblock& block, unsigned component) |
489 | 173M | { |
490 | 173M | switch (component) { |
491 | 136M | case 0: |
492 | 136M | return block.y; |
493 | 28.9M | case 1: |
494 | 28.9M | return block.cb; |
495 | 8.03M | case 2: |
496 | 8.03M | return block.cr; |
497 | 13.1k | case 3: |
498 | 13.1k | return block.k; |
499 | 0 | default: |
500 | 0 | VERIFY_NOT_REACHED(); |
501 | 173M | } |
502 | 173M | } |
503 | | |
504 | | static ErrorOr<void> refine_coefficient(Scan& scan, auto& coefficient) |
505 | 74.1M | { |
506 | | // G.1.2.3 - Coding model for subsequent scans of successive approximation |
507 | | // See the correction bit from rule b. |
508 | 74.1M | u8 const bit = TRY(scan.huffman_stream.read_bits(1)); |
509 | 74.1M | if (bit == 1) |
510 | 813k | coefficient |= 1 << scan.successive_approximation_low; |
511 | | |
512 | 74.1M | return {}; |
513 | 74.1M | } |
514 | | |
515 | | enum class JPEGDecodingMode { |
516 | | Sequential, |
517 | | Progressive |
518 | | }; |
519 | | |
520 | | template<JPEGDecodingMode DecodingMode> |
521 | | static ErrorOr<void> add_dc(JPEGLoadingContext& context, Macroblock& macroblock, ScanComponent const& scan_component) |
522 | 82.3M | { |
523 | 82.3M | auto& dc_table = context.dc_tables[scan_component.dc_destination_id]; |
524 | 82.3M | auto& scan = *context.current_scan; |
525 | | |
526 | 82.3M | auto* select_component = get_component(macroblock, scan_component.component.index); |
527 | 82.3M | auto& coefficient = select_component[0]; |
528 | | |
529 | 82.3M | if (DecodingMode == JPEGDecodingMode::Progressive && scan.successive_approximation_high > 0) { |
530 | 3.59M | TRY(refine_coefficient(scan, coefficient)); |
531 | 3.59M | return {}; |
532 | 3.59M | } |
533 | | |
534 | | // For DC coefficients, symbol encodes the length of the coefficient. |
535 | 78.7M | auto dc_length = TRY(scan.huffman_stream.next_symbol(dc_table)); |
536 | | |
537 | | // F.1.2.1.2 - Defining Huffman tables for the DC coefficients |
538 | | // F.1.5.1 - Structure of DC code table for 12-bit sample precision |
539 | 78.7M | if ((context.frame.precision == 8 && dc_length > 11) |
540 | 78.7M | || (context.frame.precision == 12 && dc_length > 15)) { |
541 | 25 | dbgln_if(JPEG_DEBUG, "DC coefficient too long: {}!", dc_length); |
542 | 25 | return Error::from_string_literal("DC coefficient too long"); |
543 | 25 | } |
544 | | |
545 | | // DC coefficients are encoded as the difference between previous and current DC values. |
546 | 78.7M | i16 dc_diff = TRY(scan.huffman_stream.read_bits(dc_length)); |
547 | | |
548 | | // If MSB in diff is 0, the difference is -ve. Otherwise +ve. |
549 | 78.7M | if (dc_length != 0 && dc_diff < (1 << (dc_length - 1))) |
550 | 73.2M | dc_diff -= (1 << dc_length) - 1; |
551 | | |
552 | 78.7M | auto& previous_dc = context.previous_dc_values[scan_component.component.index]; |
553 | 78.7M | previous_dc += dc_diff; |
554 | 78.7M | coefficient = previous_dc << scan.successive_approximation_low; |
555 | | |
556 | 78.7M | return {}; |
557 | 78.7M | } JPEGLoader.cpp:AK::ErrorOr<void, AK::Error> Gfx::add_dc<(Gfx::JPEGDecodingMode)1>(Gfx::JPEGLoadingContext&, Gfx::Detail::Macroblock<short>&, Gfx::ScanComponent const&) Line | Count | Source | 522 | 7.45M | { | 523 | 7.45M | auto& dc_table = context.dc_tables[scan_component.dc_destination_id]; | 524 | 7.45M | auto& scan = *context.current_scan; | 525 | | | 526 | 7.45M | auto* select_component = get_component(macroblock, scan_component.component.index); | 527 | 7.45M | auto& coefficient = select_component[0]; | 528 | | | 529 | 7.45M | if (DecodingMode == JPEGDecodingMode::Progressive && scan.successive_approximation_high > 0) { | 530 | 3.59M | TRY(refine_coefficient(scan, coefficient)); | 531 | 3.59M | return {}; | 532 | 3.59M | } | 533 | | | 534 | | // For DC coefficients, symbol encodes the length of the coefficient. | 535 | 3.86M | auto dc_length = TRY(scan.huffman_stream.next_symbol(dc_table)); | 536 | | | 537 | | // F.1.2.1.2 - Defining Huffman tables for the DC coefficients | 538 | | // F.1.5.1 - Structure of DC code table for 12-bit sample precision | 539 | 3.86M | if ((context.frame.precision == 8 && dc_length > 11) | 540 | 3.86M | || (context.frame.precision == 12 && dc_length > 15)) { | 541 | 6 | dbgln_if(JPEG_DEBUG, "DC coefficient too long: {}!", dc_length); | 542 | 6 | return Error::from_string_literal("DC coefficient too long"); | 543 | 6 | } | 544 | | | 545 | | // DC coefficients are encoded as the difference between previous and current DC values. | 546 | 3.86M | i16 dc_diff = TRY(scan.huffman_stream.read_bits(dc_length)); | 547 | | | 548 | | // If MSB in diff is 0, the difference is -ve. Otherwise +ve. | 549 | 3.86M | if (dc_length != 0 && dc_diff < (1 << (dc_length - 1))) | 550 | 2.47M | dc_diff -= (1 << dc_length) - 1; | 551 | | | 552 | 3.86M | auto& previous_dc = context.previous_dc_values[scan_component.component.index]; | 553 | 3.86M | previous_dc += dc_diff; | 554 | 3.86M | coefficient = previous_dc << scan.successive_approximation_low; | 555 | | | 556 | 3.86M | return {}; | 557 | 3.86M | } |
JPEGLoader.cpp:AK::ErrorOr<void, AK::Error> Gfx::add_dc<(Gfx::JPEGDecodingMode)0>(Gfx::JPEGLoadingContext&, Gfx::Detail::Macroblock<short>&, Gfx::ScanComponent const&) Line | Count | Source | 522 | 74.8M | { | 523 | 74.8M | auto& dc_table = context.dc_tables[scan_component.dc_destination_id]; | 524 | 74.8M | auto& scan = *context.current_scan; | 525 | | | 526 | 74.8M | auto* select_component = get_component(macroblock, scan_component.component.index); | 527 | 74.8M | auto& coefficient = select_component[0]; | 528 | | | 529 | 74.8M | if (DecodingMode == JPEGDecodingMode::Progressive && scan.successive_approximation_high > 0) { | 530 | 0 | TRY(refine_coefficient(scan, coefficient)); | 531 | 0 | return {}; | 532 | 0 | } | 533 | | | 534 | | // For DC coefficients, symbol encodes the length of the coefficient. | 535 | 74.8M | auto dc_length = TRY(scan.huffman_stream.next_symbol(dc_table)); | 536 | | | 537 | | // F.1.2.1.2 - Defining Huffman tables for the DC coefficients | 538 | | // F.1.5.1 - Structure of DC code table for 12-bit sample precision | 539 | 74.8M | if ((context.frame.precision == 8 && dc_length > 11) | 540 | 74.8M | || (context.frame.precision == 12 && dc_length > 15)) { | 541 | 19 | dbgln_if(JPEG_DEBUG, "DC coefficient too long: {}!", dc_length); | 542 | 19 | return Error::from_string_literal("DC coefficient too long"); | 543 | 19 | } | 544 | | | 545 | | // DC coefficients are encoded as the difference between previous and current DC values. | 546 | 74.8M | i16 dc_diff = TRY(scan.huffman_stream.read_bits(dc_length)); | 547 | | | 548 | | // If MSB in diff is 0, the difference is -ve. Otherwise +ve. | 549 | 74.8M | if (dc_length != 0 && dc_diff < (1 << (dc_length - 1))) | 550 | 70.7M | dc_diff -= (1 << dc_length) - 1; | 551 | | | 552 | 74.8M | auto& previous_dc = context.previous_dc_values[scan_component.component.index]; | 553 | 74.8M | previous_dc += dc_diff; | 554 | 74.8M | coefficient = previous_dc << scan.successive_approximation_low; | 555 | | | 556 | 74.8M | return {}; | 557 | 74.8M | } |
|
558 | | |
559 | | template<JPEGDecodingMode DecodingMode> |
560 | | static ALWAYS_INLINE ErrorOr<bool> read_eob(Scan& scan, u32 symbol) |
561 | 390M | { |
562 | | // OPTIMIZATION: This is a fast path for sequential JPEGs, these |
563 | | // only supports EOB with a value of one block. |
564 | | if constexpr (DecodingMode == JPEGDecodingMode::Sequential) |
565 | 320M | return symbol == 0x00; |
566 | | |
567 | | // G.1.2.2 - Progressive encoding of AC coefficients with Huffman coding |
568 | | // Note: We also use it for non-progressive encoding as it supports both EOB and ZRL |
569 | | |
570 | 390M | if (auto const eob = symbol & 0x0F; eob == 0 && symbol != JPEG_ZRL) { |
571 | | // We encountered an EOB marker |
572 | 113k | auto const eob_base = symbol >> 4; |
573 | 113k | auto const additional_value = TRY(scan.huffman_stream.read_bits(eob_base)); |
574 | | |
575 | 113k | scan.end_of_bands_run_count = additional_value + (1 << eob_base) - 1; |
576 | | |
577 | | // end_of_bands_run_count is decremented at the end of `build_macroblocks`. |
578 | | // And we need to now that we reached End of Block in `add_ac`. |
579 | 113k | ++scan.end_of_bands_run_count; |
580 | | |
581 | 113k | return true; |
582 | 113k | } |
583 | | |
584 | 389M | return false; |
585 | 390M | } JPEGLoader.cpp:AK::ErrorOr<bool, AK::Error> Gfx::read_eob<(Gfx::JPEGDecodingMode)1>(Gfx::Scan&, unsigned int) Line | Count | Source | 561 | 69.3M | { | 562 | | // OPTIMIZATION: This is a fast path for sequential JPEGs, these | 563 | | // only supports EOB with a value of one block. | 564 | | if constexpr (DecodingMode == JPEGDecodingMode::Sequential) | 565 | | return symbol == 0x00; | 566 | | | 567 | | // G.1.2.2 - Progressive encoding of AC coefficients with Huffman coding | 568 | | // Note: We also use it for non-progressive encoding as it supports both EOB and ZRL | 569 | | | 570 | 69.3M | if (auto const eob = symbol & 0x0F; eob == 0 && symbol != JPEG_ZRL) { | 571 | | // We encountered an EOB marker | 572 | 113k | auto const eob_base = symbol >> 4; | 573 | 113k | auto const additional_value = TRY(scan.huffman_stream.read_bits(eob_base)); | 574 | | | 575 | 113k | scan.end_of_bands_run_count = additional_value + (1 << eob_base) - 1; | 576 | | | 577 | | // end_of_bands_run_count is decremented at the end of `build_macroblocks`. | 578 | | // And we need to now that we reached End of Block in `add_ac`. | 579 | 113k | ++scan.end_of_bands_run_count; | 580 | | | 581 | 113k | return true; | 582 | 113k | } | 583 | | | 584 | 69.2M | return false; | 585 | 69.3M | } |
JPEGLoader.cpp:AK::ErrorOr<bool, AK::Error> Gfx::read_eob<(Gfx::JPEGDecodingMode)0>(Gfx::Scan&, unsigned int) Line | Count | Source | 561 | 320M | { | 562 | | // OPTIMIZATION: This is a fast path for sequential JPEGs, these | 563 | | // only supports EOB with a value of one block. | 564 | | if constexpr (DecodingMode == JPEGDecodingMode::Sequential) | 565 | 320M | return symbol == 0x00; | 566 | | | 567 | | // G.1.2.2 - Progressive encoding of AC coefficients with Huffman coding | 568 | | // Note: We also use it for non-progressive encoding as it supports both EOB and ZRL | 569 | | | 570 | 320M | if (auto const eob = symbol & 0x0F; eob == 0 && symbol != JPEG_ZRL) { | 571 | | // We encountered an EOB marker | 572 | 0 | auto const eob_base = symbol >> 4; | 573 | 0 | auto const additional_value = TRY(scan.huffman_stream.read_bits(eob_base)); | 574 | |
| 575 | 0 | scan.end_of_bands_run_count = additional_value + (1 << eob_base) - 1; | 576 | | | 577 | | // end_of_bands_run_count is decremented at the end of `build_macroblocks`. | 578 | | // And we need to now that we reached End of Block in `add_ac`. | 579 | 0 | ++scan.end_of_bands_run_count; | 580 | |
| 581 | 0 | return true; | 582 | 0 | } | 583 | | | 584 | 320M | return false; | 585 | 320M | } |
|
586 | | |
587 | | static bool is_progressive(StartOfFrame::FrameType frame_type) |
588 | 97.5M | { |
589 | 97.5M | return frame_type == StartOfFrame::FrameType::Progressive_DCT |
590 | 42.3M | || frame_type == StartOfFrame::FrameType::Progressive_DCT_Arithmetic |
591 | 42.3M | || frame_type == StartOfFrame::FrameType::Differential_Progressive_DCT |
592 | 42.3M | || frame_type == StartOfFrame::FrameType::Differential_Progressive_DCT_Arithmetic; |
593 | 97.5M | } |
594 | | |
595 | | template<JPEGDecodingMode DecodingMode> |
596 | | static ErrorOr<void> add_ac(JPEGLoadingContext& context, Macroblock& macroblock, ScanComponent const& scan_component) |
597 | 78.8M | { |
598 | 78.8M | auto& ac_table = context.ac_tables[scan_component.ac_destination_id]; |
599 | 78.8M | auto* select_component = get_component(macroblock, scan_component.component.index); |
600 | | |
601 | 78.8M | auto& scan = *context.current_scan; |
602 | | |
603 | | // Compute the AC coefficients. |
604 | | |
605 | | // 0th coefficient is the dc, which is already handled |
606 | 78.8M | auto first_coefficient = max(1, scan.spectral_selection_start); |
607 | | |
608 | 78.8M | u32 to_skip = 0; |
609 | 78.8M | Optional<u8> saved_symbol; |
610 | 78.8M | Optional<u8> saved_bit_for_rule_a; |
611 | 78.8M | bool in_zrl = false; |
612 | | |
613 | 1.26G | for (int j = first_coefficient; j <= scan.spectral_selection_end; ++j) { |
614 | 796M | auto& coefficient = select_component[zigzag_map[j]]; |
615 | | |
616 | | // AC symbols encode 2 pieces of information, the high 4 bits represent |
617 | | // number of zeroes to be stuffed before reading the coefficient. Low 4 |
618 | | // bits represent the magnitude of the coefficient. |
619 | 796M | if (!in_zrl && scan.end_of_bands_run_count == 0 && !saved_symbol.has_value()) { |
620 | 390M | saved_symbol = TRY(scan.huffman_stream.next_symbol(ac_table)); |
621 | | |
622 | 390M | if (!TRY(read_eob<DecodingMode>(scan, *saved_symbol))) { |
623 | 389M | to_skip = *saved_symbol >> 4; |
624 | | |
625 | 389M | in_zrl = *saved_symbol == JPEG_ZRL; |
626 | 389M | if (in_zrl) { |
627 | 360k | to_skip++; |
628 | 360k | saved_symbol.clear(); |
629 | 360k | } |
630 | | |
631 | 389M | if constexpr (DecodingMode == JPEGDecodingMode::Sequential) { |
632 | 319M | j += to_skip - 1; |
633 | 319M | to_skip = 0; |
634 | 319M | in_zrl = false; |
635 | 319M | continue; |
636 | 319M | } |
637 | | |
638 | 69.2M | if constexpr (DecodingMode == JPEGDecodingMode::Progressive) { |
639 | 69.2M | if (!in_zrl && scan.successive_approximation_high != 0) { |
640 | | // G.1.2.3 - Coding model for subsequent scans of successive approximation |
641 | | // Bit sign from rule a |
642 | 9.30M | saved_bit_for_rule_a = TRY(scan.huffman_stream.read_bits(1)); |
643 | 9.30M | } |
644 | 69.2M | } |
645 | 389M | } else if constexpr (DecodingMode == JPEGDecodingMode::Sequential) { |
646 | 837k | break; |
647 | 837k | } |
648 | 390M | } |
649 | | |
650 | 639M | if constexpr (DecodingMode == JPEGDecodingMode::Progressive) { |
651 | 156M | if (coefficient != 0) { |
652 | 70.5M | TRY(refine_coefficient(scan, coefficient)); |
653 | 70.5M | continue; |
654 | 70.5M | } |
655 | 156M | } |
656 | | |
657 | 796M | if (to_skip > 0) { |
658 | 1.69M | --to_skip; |
659 | 1.69M | if (to_skip == 0) |
660 | 867k | in_zrl = false; |
661 | 1.69M | continue; |
662 | 1.69M | } |
663 | | |
664 | 794M | if (scan.end_of_bands_run_count > 0) |
665 | 16.4M | continue; |
666 | | |
667 | 777M | if (DecodingMode == JPEGDecodingMode::Progressive && scan.successive_approximation_high != 0) { |
668 | | // G.1.2.3 - Coding model for subsequent scans of successive approximation |
669 | 8.91M | if (auto const low_bits = *saved_symbol & 0x0F; low_bits != 1) { |
670 | 11 | dbgln_if(JPEG_DEBUG, "AC coefficient low bits isn't equal to 1: {}!", low_bits); |
671 | 11 | return Error::from_string_literal("AC coefficient low bits isn't equal to 1"); |
672 | 11 | } |
673 | | |
674 | 8.91M | coefficient = (*saved_bit_for_rule_a == 0 ? -1 : 1) << scan.successive_approximation_low; |
675 | 8.91M | saved_bit_for_rule_a.clear(); |
676 | 768M | } else { |
677 | | // F.1.2.2 - Huffman encoding of AC coefficients |
678 | 768M | u8 const coeff_length = *saved_symbol & 0x0F; |
679 | | |
680 | | // F.1.2.2.1 - Structure of AC code table |
681 | | // F.1.5.2 - Structure of AC code table for 12-bit sample precision |
682 | 768M | if ((context.frame.precision == 8 && coeff_length > 10) |
683 | 377M | || (context.frame.precision == 12 && coeff_length > 14)) { |
684 | 15 | dbgln_if(JPEG_DEBUG, "AC coefficient too long: {}!", coeff_length); |
685 | 15 | return Error::from_string_literal("AC coefficient too long"); |
686 | 15 | } |
687 | | |
688 | 768M | if (coeff_length != 0) { |
689 | 377M | i32 ac_coefficient = TRY(scan.huffman_stream.read_bits(coeff_length)); |
690 | 377M | if (ac_coefficient < (1 << (coeff_length - 1))) |
691 | 373M | ac_coefficient -= (1 << coeff_length) - 1; |
692 | | |
693 | 377M | coefficient = ac_coefficient * (1 << scan.successive_approximation_low); |
694 | 377M | } |
695 | 768M | } |
696 | | |
697 | 777M | saved_symbol.clear(); |
698 | 777M | } |
699 | | |
700 | 470M | if (to_skip > 0) { |
701 | 31 | dbgln_if(JPEG_DEBUG, "Run-length exceeded boundaries. Cursor: {}, Skipping: {}!", scan.spectral_selection_end + to_skip, to_skip); |
702 | 31 | return Error::from_string_literal("Run-length exceeded boundaries"); |
703 | 31 | } |
704 | | |
705 | 470M | return {}; |
706 | 470M | } JPEGLoader.cpp:AK::ErrorOr<void, AK::Error> Gfx::add_ac<(Gfx::JPEGDecodingMode)1>(Gfx::JPEGLoadingContext&, Gfx::Detail::Macroblock<short>&, Gfx::ScanComponent const&) Line | Count | Source | 597 | 3.91M | { | 598 | 3.91M | auto& ac_table = context.ac_tables[scan_component.ac_destination_id]; | 599 | 3.91M | auto* select_component = get_component(macroblock, scan_component.component.index); | 600 | | | 601 | 3.91M | auto& scan = *context.current_scan; | 602 | | | 603 | | // Compute the AC coefficients. | 604 | | | 605 | | // 0th coefficient is the dc, which is already handled | 606 | 3.91M | auto first_coefficient = max(1, scan.spectral_selection_start); | 607 | | | 608 | 3.91M | u32 to_skip = 0; | 609 | 3.91M | Optional<u8> saved_symbol; | 610 | 3.91M | Optional<u8> saved_bit_for_rule_a; | 611 | 3.91M | bool in_zrl = false; | 612 | | | 613 | 230M | for (int j = first_coefficient; j <= scan.spectral_selection_end; ++j) { | 614 | 156M | auto& coefficient = select_component[zigzag_map[j]]; | 615 | | | 616 | | // AC symbols encode 2 pieces of information, the high 4 bits represent | 617 | | // number of zeroes to be stuffed before reading the coefficient. Low 4 | 618 | | // bits represent the magnitude of the coefficient. | 619 | 156M | if (!in_zrl && scan.end_of_bands_run_count == 0 && !saved_symbol.has_value()) { | 620 | 69.3M | saved_symbol = TRY(scan.huffman_stream.next_symbol(ac_table)); | 621 | | | 622 | 69.3M | if (!TRY(read_eob<DecodingMode>(scan, *saved_symbol))) { | 623 | 69.2M | to_skip = *saved_symbol >> 4; | 624 | | | 625 | 69.2M | in_zrl = *saved_symbol == JPEG_ZRL; | 626 | 69.2M | if (in_zrl) { | 627 | 1.84k | to_skip++; | 628 | 1.84k | saved_symbol.clear(); | 629 | 1.84k | } | 630 | | | 631 | | if constexpr (DecodingMode == JPEGDecodingMode::Sequential) { | 632 | | j += to_skip - 1; | 633 | | to_skip = 0; | 634 | | in_zrl = false; | 635 | | continue; | 636 | | } | 637 | | | 638 | 69.2M | if constexpr (DecodingMode == JPEGDecodingMode::Progressive) { | 639 | 69.2M | if (!in_zrl && scan.successive_approximation_high != 0) { | 640 | | // G.1.2.3 - Coding model for subsequent scans of successive approximation | 641 | | // Bit sign from rule a | 642 | 9.30M | saved_bit_for_rule_a = TRY(scan.huffman_stream.read_bits(1)); | 643 | 9.30M | } | 644 | 69.2M | } | 645 | 69.2M | } else if constexpr (DecodingMode == JPEGDecodingMode::Sequential) { | 646 | 113k | break; | 647 | 113k | } | 648 | 69.3M | } | 649 | | | 650 | 156M | if constexpr (DecodingMode == JPEGDecodingMode::Progressive) { | 651 | 156M | if (coefficient != 0) { | 652 | 70.5M | TRY(refine_coefficient(scan, coefficient)); | 653 | 70.5M | continue; | 654 | 70.5M | } | 655 | 156M | } | 656 | | | 657 | 156M | if (to_skip > 0) { | 658 | 1.69M | --to_skip; | 659 | 1.69M | if (to_skip == 0) | 660 | 867k | in_zrl = false; | 661 | 1.69M | continue; | 662 | 1.69M | } | 663 | | | 664 | 154M | if (scan.end_of_bands_run_count > 0) | 665 | 16.4M | continue; | 666 | | | 667 | 137M | if (DecodingMode == JPEGDecodingMode::Progressive && scan.successive_approximation_high != 0) { | 668 | | // G.1.2.3 - Coding model for subsequent scans of successive approximation | 669 | 8.91M | if (auto const low_bits = *saved_symbol & 0x0F; low_bits != 1) { | 670 | 11 | dbgln_if(JPEG_DEBUG, "AC coefficient low bits isn't equal to 1: {}!", low_bits); | 671 | 11 | return Error::from_string_literal("AC coefficient low bits isn't equal to 1"); | 672 | 11 | } | 673 | | | 674 | 8.91M | coefficient = (*saved_bit_for_rule_a == 0 ? -1 : 1) << scan.successive_approximation_low; | 675 | 8.91M | saved_bit_for_rule_a.clear(); | 676 | 129M | } else { | 677 | | // F.1.2.2 - Huffman encoding of AC coefficients | 678 | 129M | u8 const coeff_length = *saved_symbol & 0x0F; | 679 | | | 680 | | // F.1.2.2.1 - Structure of AC code table | 681 | | // F.1.5.2 - Structure of AC code table for 12-bit sample precision | 682 | 129M | if ((context.frame.precision == 8 && coeff_length > 10) | 683 | 58.5M | || (context.frame.precision == 12 && coeff_length > 14)) { | 684 | 1 | dbgln_if(JPEG_DEBUG, "AC coefficient too long: {}!", coeff_length); | 685 | 1 | return Error::from_string_literal("AC coefficient too long"); | 686 | 1 | } | 687 | | | 688 | 129M | if (coeff_length != 0) { | 689 | 58.5M | i32 ac_coefficient = TRY(scan.huffman_stream.read_bits(coeff_length)); | 690 | 58.5M | if (ac_coefficient < (1 << (coeff_length - 1))) | 691 | 57.7M | ac_coefficient -= (1 << coeff_length) - 1; | 692 | | | 693 | 58.5M | coefficient = ac_coefficient * (1 << scan.successive_approximation_low); | 694 | 58.5M | } | 695 | 129M | } | 696 | | | 697 | 137M | saved_symbol.clear(); | 698 | 137M | } | 699 | | | 700 | 74.4M | if (to_skip > 0) { | 701 | 31 | dbgln_if(JPEG_DEBUG, "Run-length exceeded boundaries. Cursor: {}, Skipping: {}!", scan.spectral_selection_end + to_skip, to_skip); | 702 | 31 | return Error::from_string_literal("Run-length exceeded boundaries"); | 703 | 31 | } | 704 | | | 705 | 74.4M | return {}; | 706 | 74.4M | } |
JPEGLoader.cpp:AK::ErrorOr<void, AK::Error> Gfx::add_ac<(Gfx::JPEGDecodingMode)0>(Gfx::JPEGLoadingContext&, Gfx::Detail::Macroblock<short>&, Gfx::ScanComponent const&) Line | Count | Source | 597 | 74.8M | { | 598 | 74.8M | auto& ac_table = context.ac_tables[scan_component.ac_destination_id]; | 599 | 74.8M | auto* select_component = get_component(macroblock, scan_component.component.index); | 600 | | | 601 | 74.8M | auto& scan = *context.current_scan; | 602 | | | 603 | | // Compute the AC coefficients. | 604 | | | 605 | | // 0th coefficient is the dc, which is already handled | 606 | 74.8M | auto first_coefficient = max(1, scan.spectral_selection_start); | 607 | | | 608 | 74.8M | u32 to_skip = 0; | 609 | 74.8M | Optional<u8> saved_symbol; | 610 | 74.8M | Optional<u8> saved_bit_for_rule_a; | 611 | 74.8M | bool in_zrl = false; | 612 | | | 613 | 1.03G | for (int j = first_coefficient; j <= scan.spectral_selection_end; ++j) { | 614 | 639M | auto& coefficient = select_component[zigzag_map[j]]; | 615 | | | 616 | | // AC symbols encode 2 pieces of information, the high 4 bits represent | 617 | | // number of zeroes to be stuffed before reading the coefficient. Low 4 | 618 | | // bits represent the magnitude of the coefficient. | 619 | 639M | if (!in_zrl && scan.end_of_bands_run_count == 0 && !saved_symbol.has_value()) { | 620 | 320M | saved_symbol = TRY(scan.huffman_stream.next_symbol(ac_table)); | 621 | | | 622 | 320M | if (!TRY(read_eob<DecodingMode>(scan, *saved_symbol))) { | 623 | 319M | to_skip = *saved_symbol >> 4; | 624 | | | 625 | 319M | in_zrl = *saved_symbol == JPEG_ZRL; | 626 | 319M | if (in_zrl) { | 627 | 358k | to_skip++; | 628 | 358k | saved_symbol.clear(); | 629 | 358k | } | 630 | | | 631 | 319M | if constexpr (DecodingMode == JPEGDecodingMode::Sequential) { | 632 | 319M | j += to_skip - 1; | 633 | 319M | to_skip = 0; | 634 | 319M | in_zrl = false; | 635 | 319M | continue; | 636 | 319M | } | 637 | | | 638 | | if constexpr (DecodingMode == JPEGDecodingMode::Progressive) { | 639 | | if (!in_zrl && scan.successive_approximation_high != 0) { | 640 | | // G.1.2.3 - Coding model for subsequent scans of successive approximation | 641 | | // Bit sign from rule a | 642 | | saved_bit_for_rule_a = TRY(scan.huffman_stream.read_bits(1)); | 643 | | } | 644 | | } | 645 | 319M | } else if constexpr (DecodingMode == JPEGDecodingMode::Sequential) { | 646 | 837k | break; | 647 | 837k | } | 648 | 320M | } | 649 | | | 650 | | if constexpr (DecodingMode == JPEGDecodingMode::Progressive) { | 651 | | if (coefficient != 0) { | 652 | | TRY(refine_coefficient(scan, coefficient)); | 653 | | continue; | 654 | | } | 655 | | } | 656 | | | 657 | 639M | if (to_skip > 0) { | 658 | 0 | --to_skip; | 659 | 0 | if (to_skip == 0) | 660 | 0 | in_zrl = false; | 661 | 0 | continue; | 662 | 0 | } | 663 | | | 664 | 639M | if (scan.end_of_bands_run_count > 0) | 665 | 0 | continue; | 666 | | | 667 | 639M | if (DecodingMode == JPEGDecodingMode::Progressive && scan.successive_approximation_high != 0) { | 668 | | // G.1.2.3 - Coding model for subsequent scans of successive approximation | 669 | 0 | if (auto const low_bits = *saved_symbol & 0x0F; low_bits != 1) { | 670 | 0 | dbgln_if(JPEG_DEBUG, "AC coefficient low bits isn't equal to 1: {}!", low_bits); | 671 | 0 | return Error::from_string_literal("AC coefficient low bits isn't equal to 1"); | 672 | 0 | } | 673 | | | 674 | 0 | coefficient = (*saved_bit_for_rule_a == 0 ? -1 : 1) << scan.successive_approximation_low; | 675 | 0 | saved_bit_for_rule_a.clear(); | 676 | 639M | } else { | 677 | | // F.1.2.2 - Huffman encoding of AC coefficients | 678 | 639M | u8 const coeff_length = *saved_symbol & 0x0F; | 679 | | | 680 | | // F.1.2.2.1 - Structure of AC code table | 681 | | // F.1.5.2 - Structure of AC code table for 12-bit sample precision | 682 | 639M | if ((context.frame.precision == 8 && coeff_length > 10) | 683 | 319M | || (context.frame.precision == 12 && coeff_length > 14)) { | 684 | 14 | dbgln_if(JPEG_DEBUG, "AC coefficient too long: {}!", coeff_length); | 685 | 14 | return Error::from_string_literal("AC coefficient too long"); | 686 | 14 | } | 687 | | | 688 | 639M | if (coeff_length != 0) { | 689 | 319M | i32 ac_coefficient = TRY(scan.huffman_stream.read_bits(coeff_length)); | 690 | 319M | if (ac_coefficient < (1 << (coeff_length - 1))) | 691 | 316M | ac_coefficient -= (1 << coeff_length) - 1; | 692 | | | 693 | 319M | coefficient = ac_coefficient * (1 << scan.successive_approximation_low); | 694 | 319M | } | 695 | 639M | } | 696 | | | 697 | 639M | saved_symbol.clear(); | 698 | 639M | } | 699 | | | 700 | 395M | if (to_skip > 0) { | 701 | 0 | dbgln_if(JPEG_DEBUG, "Run-length exceeded boundaries. Cursor: {}, Skipping: {}!", scan.spectral_selection_end + to_skip, to_skip); | 702 | 0 | return Error::from_string_literal("Run-length exceeded boundaries"); | 703 | 0 | } | 704 | | | 705 | 395M | return {}; | 706 | 395M | } |
|
707 | | |
708 | | /** |
709 | | * Build the macroblocks possible by reading single (MCU) subsampled pair of CbCr. |
710 | | * Depending on the sampling factors, we may not see triples of y, cb, cr in that |
711 | | * order. If sample factors differ from one, we'll read more than one block of y- |
712 | | * coefficients before we get to read a cb-cr block. |
713 | | |
714 | | * In the function below, `hcursor` and `vcursor` denote the location of the block |
715 | | * we're building in the macroblock matrix. `vfactor_i` and `hfactor_i` are cursors |
716 | | * that iterate over the vertical and horizontal subsampling factors, respectively. |
717 | | * When we finish one iteration of the innermost loop, we'll have the coefficients |
718 | | * of one of the components of block at position `macroblock_index`. When the outermost |
719 | | * loop finishes first iteration, we'll have all the luminance coefficients for all the |
720 | | * macroblocks that share the chrominance data. Next two iterations (assuming that |
721 | | * we are dealing with three components) will fill up the blocks with chroma data. |
722 | | */ |
723 | | template<JPEGDecodingMode DecodingMode> |
724 | | static ErrorOr<void> build_macroblocks(JPEGLoadingContext& context, Vector<Macroblock>& macroblocks, u32 hcursor, u32 vcursor) |
725 | 97.5M | { |
726 | 97.5M | for (auto const& scan_component : context.current_scan->components) { |
727 | 113M | for (u8 vfactor_i = 0; vfactor_i < scan_component.component.sampling_factors.vertical; vfactor_i++) { |
728 | 152M | for (u8 hfactor_i = 0; hfactor_i < scan_component.component.sampling_factors.horizontal; hfactor_i++) { |
729 | | // A.2.3 - Interleaved order |
730 | 89.5M | u32 macroblock_index = (vcursor + vfactor_i) * context.mblock_meta.hpadded_count + (hfactor_i + hcursor); |
731 | 89.5M | if (!context.current_scan->are_components_interleaved()) { |
732 | 30.4M | macroblock_index = vcursor * context.mblock_meta.hpadded_count + (hfactor_i + (hcursor * scan_component.component.sampling_factors.vertical) + (vfactor_i * scan_component.component.sampling_factors.horizontal)); |
733 | | |
734 | | // A.2.4 Completion of partial MCU |
735 | | // If the component is [and only if!] to be interleaved, the encoding process |
736 | | // shall also extend the number of samples by one or more additional blocks. |
737 | | |
738 | | // Horizontally |
739 | 30.4M | if (macroblock_index >= context.mblock_meta.hcount && macroblock_index % context.mblock_meta.hpadded_count >= context.mblock_meta.hcount) |
740 | 31.7k | continue; |
741 | | // Vertically |
742 | 30.4M | if (macroblock_index >= context.mblock_meta.hpadded_count * context.mblock_meta.vcount) |
743 | 387k | continue; |
744 | 30.4M | } |
745 | | |
746 | 89.0M | Macroblock& block = macroblocks[macroblock_index]; |
747 | | |
748 | 89.0M | if constexpr (DecodingMode == JPEGDecodingMode::Sequential) { |
749 | 74.8M | TRY(add_dc<DecodingMode>(context, block, scan_component)); |
750 | 74.8M | TRY(add_ac<DecodingMode>(context, block, scan_component)); |
751 | 74.8M | } else { |
752 | 14.1M | if (context.current_scan->spectral_selection_start == 0) |
753 | 7.45M | TRY(add_dc<DecodingMode>(context, block, scan_component)); |
754 | 14.1M | if (context.current_scan->spectral_selection_end != 0) |
755 | 3.91M | TRY(add_ac<DecodingMode>(context, block, scan_component)); |
756 | | |
757 | | // G.1.2.2 - Progressive encoding of AC coefficients with Huffman coding |
758 | 14.1M | if (context.current_scan->end_of_bands_run_count > 0) { |
759 | 437k | --context.current_scan->end_of_bands_run_count; |
760 | 437k | continue; |
761 | 437k | } |
762 | 14.1M | } |
763 | 89.0M | } |
764 | 63.0M | } |
765 | 49.7M | } |
766 | | |
767 | 55.6M | return {}; |
768 | 97.5M | } JPEGLoader.cpp:AK::ErrorOr<void, AK::Error> Gfx::build_macroblocks<(Gfx::JPEGDecodingMode)1>(Gfx::JPEGLoadingContext&, AK::Vector<Gfx::Detail::Macroblock<short>, 0ul>&, unsigned int, unsigned int) Line | Count | Source | 725 | 55.2M | { | 726 | 55.2M | for (auto const& scan_component : context.current_scan->components) { | 727 | 23.5M | for (u8 vfactor_i = 0; vfactor_i < scan_component.component.sampling_factors.vertical; vfactor_i++) { | 728 | 26.7M | for (u8 hfactor_i = 0; hfactor_i < scan_component.component.sampling_factors.horizontal; hfactor_i++) { | 729 | | // A.2.3 - Interleaved order | 730 | 14.2M | u32 macroblock_index = (vcursor + vfactor_i) * context.mblock_meta.hpadded_count + (hfactor_i + hcursor); | 731 | 14.2M | if (!context.current_scan->are_components_interleaved()) { | 732 | 11.2M | macroblock_index = vcursor * context.mblock_meta.hpadded_count + (hfactor_i + (hcursor * scan_component.component.sampling_factors.vertical) + (vfactor_i * scan_component.component.sampling_factors.horizontal)); | 733 | | | 734 | | // A.2.4 Completion of partial MCU | 735 | | // If the component is [and only if!] to be interleaved, the encoding process | 736 | | // shall also extend the number of samples by one or more additional blocks. | 737 | | | 738 | | // Horizontally | 739 | 11.2M | if (macroblock_index >= context.mblock_meta.hcount && macroblock_index % context.mblock_meta.hpadded_count >= context.mblock_meta.hcount) | 740 | 2.29k | continue; | 741 | | // Vertically | 742 | 11.2M | if (macroblock_index >= context.mblock_meta.hpadded_count * context.mblock_meta.vcount) | 743 | 8.12k | continue; | 744 | 11.2M | } | 745 | | | 746 | 14.1M | Macroblock& block = macroblocks[macroblock_index]; | 747 | | | 748 | | if constexpr (DecodingMode == JPEGDecodingMode::Sequential) { | 749 | | TRY(add_dc<DecodingMode>(context, block, scan_component)); | 750 | | TRY(add_ac<DecodingMode>(context, block, scan_component)); | 751 | 14.1M | } else { | 752 | 14.1M | if (context.current_scan->spectral_selection_start == 0) | 753 | 7.45M | TRY(add_dc<DecodingMode>(context, block, scan_component)); | 754 | 14.1M | if (context.current_scan->spectral_selection_end != 0) | 755 | 3.91M | TRY(add_ac<DecodingMode>(context, block, scan_component)); | 756 | | | 757 | | // G.1.2.2 - Progressive encoding of AC coefficients with Huffman coding | 758 | 14.1M | if (context.current_scan->end_of_bands_run_count > 0) { | 759 | 437k | --context.current_scan->end_of_bands_run_count; | 760 | 437k | continue; | 761 | 437k | } | 762 | 14.1M | } | 763 | 14.1M | } | 764 | 12.0M | } | 765 | 11.0M | } | 766 | | | 767 | 55.6M | return {}; | 768 | 55.2M | } |
JPEGLoader.cpp:AK::ErrorOr<void, AK::Error> Gfx::build_macroblocks<(Gfx::JPEGDecodingMode)0>(Gfx::JPEGLoadingContext&, AK::Vector<Gfx::Detail::Macroblock<short>, 0ul>&, unsigned int, unsigned int) Line | Count | Source | 725 | 42.3M | { | 726 | 42.3M | for (auto const& scan_component : context.current_scan->components) { | 727 | 89.5M | for (u8 vfactor_i = 0; vfactor_i < scan_component.component.sampling_factors.vertical; vfactor_i++) { | 728 | 126M | for (u8 hfactor_i = 0; hfactor_i < scan_component.component.sampling_factors.horizontal; hfactor_i++) { | 729 | | // A.2.3 - Interleaved order | 730 | 75.2M | u32 macroblock_index = (vcursor + vfactor_i) * context.mblock_meta.hpadded_count + (hfactor_i + hcursor); | 731 | 75.2M | if (!context.current_scan->are_components_interleaved()) { | 732 | 19.1M | macroblock_index = vcursor * context.mblock_meta.hpadded_count + (hfactor_i + (hcursor * scan_component.component.sampling_factors.vertical) + (vfactor_i * scan_component.component.sampling_factors.horizontal)); | 733 | | | 734 | | // A.2.4 Completion of partial MCU | 735 | | // If the component is [and only if!] to be interleaved, the encoding process | 736 | | // shall also extend the number of samples by one or more additional blocks. | 737 | | | 738 | | // Horizontally | 739 | 19.1M | if (macroblock_index >= context.mblock_meta.hcount && macroblock_index % context.mblock_meta.hpadded_count >= context.mblock_meta.hcount) | 740 | 29.4k | continue; | 741 | | // Vertically | 742 | 19.1M | if (macroblock_index >= context.mblock_meta.hpadded_count * context.mblock_meta.vcount) | 743 | 379k | continue; | 744 | 19.1M | } | 745 | | | 746 | 74.8M | Macroblock& block = macroblocks[macroblock_index]; | 747 | | | 748 | 74.8M | if constexpr (DecodingMode == JPEGDecodingMode::Sequential) { | 749 | 74.8M | TRY(add_dc<DecodingMode>(context, block, scan_component)); | 750 | 74.8M | TRY(add_ac<DecodingMode>(context, block, scan_component)); | 751 | | } else { | 752 | | if (context.current_scan->spectral_selection_start == 0) | 753 | | TRY(add_dc<DecodingMode>(context, block, scan_component)); | 754 | | if (context.current_scan->spectral_selection_end != 0) | 755 | | TRY(add_ac<DecodingMode>(context, block, scan_component)); | 756 | | | 757 | | // G.1.2.2 - Progressive encoding of AC coefficients with Huffman coding | 758 | | if (context.current_scan->end_of_bands_run_count > 0) { | 759 | | --context.current_scan->end_of_bands_run_count; | 760 | | continue; | 761 | | } | 762 | | } | 763 | 74.8M | } | 764 | 50.9M | } | 765 | 38.6M | } | 766 | | | 767 | 42.3M | return {}; | 768 | 42.3M | } |
|
769 | | |
770 | | static bool is_dct_based(StartOfFrame::FrameType frame_type) |
771 | 7.92M | { |
772 | 7.92M | return frame_type == StartOfFrame::FrameType::Baseline_DCT |
773 | 69.5k | || frame_type == StartOfFrame::FrameType::Extended_Sequential_DCT |
774 | 69.1k | || frame_type == StartOfFrame::FrameType::Progressive_DCT |
775 | 0 | || frame_type == StartOfFrame::FrameType::Differential_Sequential_DCT |
776 | 0 | || frame_type == StartOfFrame::FrameType::Differential_Progressive_DCT |
777 | 0 | || frame_type == StartOfFrame::FrameType::Progressive_DCT_Arithmetic |
778 | 0 | || frame_type == StartOfFrame::FrameType::Differential_Sequential_DCT_Arithmetic |
779 | 0 | || frame_type == StartOfFrame::FrameType::Differential_Progressive_DCT_Arithmetic; |
780 | 7.92M | } |
781 | | |
782 | | static void reset_decoder(JPEGLoadingContext& context) |
783 | 7.92M | { |
784 | | // G.1.2.2 - Progressive encoding of AC coefficients with Huffman coding |
785 | 7.92M | context.current_scan->end_of_bands_run_count = 0; |
786 | | |
787 | | // E.2.4 Control procedure for decoding a restart interval |
788 | 7.92M | if (is_dct_based(context.frame.type)) { |
789 | 7.92M | context.previous_dc_values = {}; |
790 | 7.92M | return; |
791 | 7.92M | } |
792 | | |
793 | 0 | VERIFY_NOT_REACHED(); |
794 | 0 | } |
795 | | |
796 | | static ErrorOr<void> decode_huffman_stream(JPEGLoadingContext& context, Vector<Macroblock>& macroblocks) |
797 | 261k | { |
798 | 4.50M | for (u32 vcursor = 0; vcursor < context.mblock_meta.vcount; vcursor += context.sampling_factors.vertical) { |
799 | 101M | for (u32 hcursor = 0; hcursor < context.mblock_meta.hcount; hcursor += context.sampling_factors.horizontal) { |
800 | | // FIXME: This is likely wrong for non-interleaved scans. |
801 | 97.5M | VERIFY(context.mblock_meta.hpadded_count % context.sampling_factors.horizontal == 0); |
802 | 97.5M | u32 number_of_mcus_decoded_so_far = ((vcursor / context.sampling_factors.vertical) * context.mblock_meta.hpadded_count + hcursor) / context.sampling_factors.horizontal; |
803 | | |
804 | 97.5M | auto& huffman_stream = context.current_scan->huffman_stream; |
805 | | |
806 | 97.5M | if (context.dc_restart_interval > 0) { |
807 | 71.2M | if (number_of_mcus_decoded_so_far != 0 && number_of_mcus_decoded_so_far % context.dc_restart_interval == 0) { |
808 | 7.92M | reset_decoder(context); |
809 | | |
810 | | // Restart markers are stored in byte boundaries. Advance the huffman stream cursor to |
811 | | // the 0th bit of the next byte. |
812 | 7.92M | TRY(huffman_stream.advance_to_byte_boundary()); |
813 | | |
814 | | // Skip the restart marker (RSTn). |
815 | 7.92M | TRY(huffman_stream.discard_bits(8)); |
816 | 7.92M | } |
817 | 71.2M | } |
818 | | |
819 | 97.5M | auto result = [&]() { |
820 | 97.5M | if (is_progressive(context.frame.type)) |
821 | 55.2M | return build_macroblocks<JPEGDecodingMode::Progressive>(context, macroblocks, hcursor, vcursor); |
822 | 42.3M | return build_macroblocks<JPEGDecodingMode::Sequential>(context, macroblocks, hcursor, vcursor); |
823 | 97.5M | }(); |
824 | | |
825 | 97.5M | if (result.is_error()) { |
826 | | if constexpr (JPEG_DEBUG) { |
827 | | dbgln("Failed to build Macroblock {}: {}", number_of_mcus_decoded_so_far, result.error()); |
828 | | dbgln("Huffman stream byte offset {:#x}", context.stream.byte_offset()); |
829 | | } |
830 | 611 | return result.release_error(); |
831 | 611 | } |
832 | 97.5M | } |
833 | 4.24M | } |
834 | 261k | return {}; |
835 | 261k | } |
836 | | |
837 | | static bool is_frame_marker(Marker const marker) |
838 | 6.24M | { |
839 | | // B.1.1.3 - Marker assignments |
840 | 6.24M | bool const is_sof_marker = marker >= JPEG_SOF0 && marker <= JPEG_SOF15; |
841 | | |
842 | | // Start of frame markers are valid for JPEG_SOF0 to JPEG_SOF15 except number 4, 8 (reserved) and 12. |
843 | 6.24M | bool const is_defined_marker = marker != JPEG_DHT && marker != 0xFFC8 && marker != JPEG_DAC; |
844 | | |
845 | 6.24M | return is_sof_marker && is_defined_marker; |
846 | 6.24M | } |
847 | | |
848 | | static inline bool is_supported_marker(Marker const marker) |
849 | 7.16M | { |
850 | 7.16M | if (marker >= JPEG_APPN0 && marker <= JPEG_APPN15) { |
851 | | |
852 | 395k | if (marker != JPEG_APPN0 && marker != JPEG_APPN14) |
853 | 213k | dbgln_if(JPEG_DEBUG, "{:#04x} not supported yet. The decoder may fail!", marker); |
854 | 395k | return true; |
855 | 395k | } |
856 | 6.76M | if (marker >= JPEG_RESERVED1 && marker <= JPEG_RESERVEDD) |
857 | 309 | return true; |
858 | 6.76M | if (marker >= JPEG_RST0 && marker <= JPEG_RST7) |
859 | 32 | return true; |
860 | 6.76M | switch (marker) { |
861 | 7.34k | case JPEG_COM: |
862 | 9.48k | case JPEG_DHP: |
863 | 14.8k | case JPEG_EXP: |
864 | 189k | case JPEG_DHT: |
865 | 205k | case JPEG_DQT: |
866 | 267k | case JPEG_DRI: |
867 | 267k | case JPEG_EOI: |
868 | 267k | case JPEG_SOF0: |
869 | 268k | case JPEG_SOF1: |
870 | 269k | case JPEG_SOF2: |
871 | 273k | case JPEG_SOI: |
872 | 623k | case JPEG_SOS: |
873 | 623k | return true; |
874 | 6.76M | } |
875 | | |
876 | 6.14M | if (is_frame_marker(marker)) |
877 | 493 | dbgln_if(JPEG_DEBUG, "Decoding this frame-type (SOF{}) is not currently supported. Decoder will fail!", marker & 0xf); |
878 | | |
879 | 6.14M | return false; |
880 | 6.76M | } |
881 | | |
882 | | static inline ErrorOr<Marker> read_until_marker(JPEGStream& stream) |
883 | 1.02M | { |
884 | 1.02M | u16 marker = TRY(stream.read_u16()); |
885 | | |
886 | 7.16M | while (!is_supported_marker(marker)) |
887 | 6.14M | marker = marker << 8 | TRY(stream.read_u8()); |
888 | | |
889 | 1.02M | return marker; |
890 | 1.02M | } |
891 | | |
892 | | static ErrorOr<u16> read_effective_chunk_size(JPEGStream& stream) |
893 | 1.01M | { |
894 | | // The stored chunk size includes the size of `stored_size` itself. |
895 | 1.01M | u16 const stored_size = TRY(stream.read_u16()); |
896 | 1.01M | if (stored_size < 2) |
897 | 28 | return Error::from_string_literal("Stored chunk size is too small"); |
898 | 1.01M | return stored_size - 2; |
899 | 1.01M | } |
900 | | |
901 | | static ErrorOr<void> ensure_tables_are_present(JPEGLoadingContext& context) |
902 | 261k | { |
903 | 261k | auto const& current_scan = context.current_scan.value(); |
904 | 514k | for (auto const& component : current_scan.components) { |
905 | 514k | if (!context.registered_quantization_tables[component.component.quantization_table_id]) |
906 | 5 | return Error::from_string_literal("Unknown quantization table id"); |
907 | 514k | if (current_scan.spectral_selection_start == 0 && !context.registered_dc_tables[component.dc_destination_id]) |
908 | 0 | return Error::from_string_literal("Unable to find corresponding DC table"); |
909 | 514k | if (current_scan.spectral_selection_end > 0 && !context.registered_ac_tables[component.ac_destination_id]) |
910 | 20 | return Error::from_string_literal("Unable to find corresponding AC table"); |
911 | 514k | } |
912 | 261k | return {}; |
913 | 261k | } |
914 | | |
915 | | static ErrorOr<void> read_start_of_scan(JPEGStream& stream, JPEGLoadingContext& context) |
916 | 262k | { |
917 | | // B.2.3 - Scan header syntax |
918 | | |
919 | 262k | if (context.state < JPEGLoadingContext::State::FrameDecoded) |
920 | 0 | return Error::from_string_literal("SOS found before reading a SOF"); |
921 | | |
922 | 262k | [[maybe_unused]] u16 const bytes_to_read = TRY(read_effective_chunk_size(stream)); |
923 | 262k | u8 const component_count = TRY(stream.read_u8()); |
924 | | |
925 | 262k | Scan current_scan(HuffmanStream { context.stream }); |
926 | | |
927 | 262k | Optional<u8> last_read; |
928 | 262k | u8 component_read = 0; |
929 | 769k | for (auto& component : context.components) { |
930 | | // See the Csj paragraph: |
931 | | // [...] the ordering in the scan header shall follow the ordering in the frame header. |
932 | 769k | if (component_read == component_count) |
933 | 7.41k | break; |
934 | | |
935 | 761k | if (!last_read.has_value()) |
936 | 759k | last_read = TRY(stream.read_u8()); |
937 | | |
938 | 761k | if (component.id != *last_read) |
939 | 246k | continue; |
940 | | |
941 | 514k | u8 const table_ids = TRY(stream.read_u8()); |
942 | | |
943 | 514k | current_scan.components.empend(component, static_cast<u8>(table_ids >> 4), static_cast<u8>(table_ids & 0x0F)); |
944 | | |
945 | 514k | component_read++; |
946 | 514k | last_read.clear(); |
947 | 514k | } |
948 | | |
949 | | if constexpr (JPEG_DEBUG) { |
950 | | StringBuilder builder; |
951 | | TRY(builder.try_append("Components in scan: "sv)); |
952 | | for (auto const& scan_component : current_scan.components) { |
953 | | TRY(builder.try_append(String::number(scan_component.component.id))); |
954 | | TRY(builder.try_append(' ')); |
955 | | } |
956 | | dbgln(builder.string_view()); |
957 | | } |
958 | | |
959 | 262k | current_scan.spectral_selection_start = TRY(stream.read_u8()); |
960 | 262k | current_scan.spectral_selection_end = TRY(stream.read_u8()); |
961 | 262k | auto const successive_approximation = TRY(stream.read_u8()); |
962 | 262k | current_scan.successive_approximation_high = successive_approximation >> 4; |
963 | 262k | current_scan.successive_approximation_low = successive_approximation & 0x0F; |
964 | | |
965 | 262k | dbgln_if(JPEG_DEBUG, "Start of Selection: {}, End of Selection: {}, Successive Approximation High: {}, Successive Approximation Low: {}", |
966 | 262k | current_scan.spectral_selection_start, |
967 | 262k | current_scan.spectral_selection_end, |
968 | 262k | current_scan.successive_approximation_high, |
969 | 262k | current_scan.successive_approximation_low); |
970 | | |
971 | 262k | if (current_scan.spectral_selection_start > 63 || current_scan.spectral_selection_end > 63 || current_scan.successive_approximation_high > 13 || current_scan.successive_approximation_low > 13) { |
972 | 52 | dbgln_if(JPEG_DEBUG, "ERROR! Start of Selection: {}, End of Selection: {}, Successive Approximation High: {}, Successive Approximation Low: {}!", |
973 | 52 | current_scan.spectral_selection_start, |
974 | 52 | current_scan.spectral_selection_end, |
975 | 52 | current_scan.successive_approximation_high, |
976 | 52 | current_scan.successive_approximation_low); |
977 | 52 | return Error::from_string_literal("Spectral selection is not [0,63] or successive approximation is not null"); |
978 | 52 | } |
979 | | |
980 | 261k | context.current_scan = move(current_scan); |
981 | | |
982 | 261k | TRY(ensure_tables_are_present(context)); |
983 | | |
984 | 261k | return {}; |
985 | 261k | } |
986 | | |
987 | | static ErrorOr<void> read_restart_interval(JPEGStream& stream, JPEGLoadingContext& context) |
988 | 62.3k | { |
989 | | // B.2.4.4 - Restart interval definition syntax |
990 | 62.3k | u16 bytes_to_read = TRY(read_effective_chunk_size(stream)); |
991 | 62.3k | if (bytes_to_read != 2) { |
992 | 4 | dbgln_if(JPEG_DEBUG, "Malformed DRI marker found!"); |
993 | 4 | return Error::from_string_literal("Malformed DRI marker found"); |
994 | 4 | } |
995 | 62.3k | context.dc_restart_interval = TRY(stream.read_u16()); |
996 | 62.3k | dbgln_if(JPEG_DEBUG, "Restart marker: {}", context.dc_restart_interval); |
997 | 62.3k | return {}; |
998 | 62.3k | } |
999 | | |
1000 | | static ErrorOr<void> read_huffman_table(JPEGStream& stream, JPEGLoadingContext& context) |
1001 | 175k | { |
1002 | | // B.2.4.2 - Huffman table-specification syntax |
1003 | | |
1004 | 175k | u16 bytes_to_read = TRY(read_effective_chunk_size(stream)); |
1005 | | |
1006 | 322k | while (bytes_to_read > 0) { |
1007 | 147k | HuffmanTable table; |
1008 | 147k | u8 const table_info = TRY(stream.read_u8()); |
1009 | 147k | u8 const table_type = table_info >> 4; |
1010 | 147k | u8 const table_destination_id = table_info & 0x0F; |
1011 | 147k | if (table_type > 1) { |
1012 | 23 | dbgln_if(JPEG_DEBUG, "Unrecognized huffman table: {}!", table_type); |
1013 | 23 | return Error::from_string_literal("Unrecognized huffman table"); |
1014 | 23 | } |
1015 | | |
1016 | 147k | if ((context.frame.type == StartOfFrame::FrameType::Baseline_DCT && table_destination_id > 1) |
1017 | 147k | || (context.frame.type != StartOfFrame::FrameType::Baseline_DCT && table_destination_id > 3)) { |
1018 | 4 | dbgln_if(JPEG_DEBUG, "Invalid huffman table destination id: {}!", table_destination_id); |
1019 | 4 | return Error::from_string_literal("Invalid huffman table destination id"); |
1020 | 4 | } |
1021 | | |
1022 | 147k | table.type = table_type; |
1023 | 147k | table.destination_id = table_destination_id; |
1024 | 147k | u32 total_codes = 0; |
1025 | | |
1026 | | // Read code counts. At each index K, the value represents the number of K+1 bit codes in this header. |
1027 | 2.50M | for (int i = 0; i < 16; i++) { |
1028 | 2.35M | if (i == HuffmanTable::bits_per_cached_code) |
1029 | 147k | table.first_non_cached_code_index = total_codes; |
1030 | 2.35M | u8 const count = TRY(stream.read_u8()); |
1031 | 2.35M | total_codes += count; |
1032 | 2.35M | table.code_counts[i] = count; |
1033 | 2.35M | } |
1034 | | |
1035 | 147k | table.codes.ensure_capacity(total_codes); |
1036 | 147k | table.symbols.ensure_capacity(total_codes); |
1037 | | |
1038 | | // Read symbols. Read X bytes, where X is the sum of the counts of codes read in the previous step. |
1039 | 390k | for (u32 i = 0; i < total_codes; i++) { |
1040 | 243k | u8 symbol = TRY(stream.read_u8()); |
1041 | 243k | table.symbols.append(symbol); |
1042 | 243k | } |
1043 | | |
1044 | 294k | TRY(table.generate_codes()); |
1045 | | |
1046 | 294k | auto& huffman_table = table.type == 0 ? context.dc_tables : context.ac_tables; |
1047 | 294k | auto& table_register = table.type == 0 ? context.registered_dc_tables : context.registered_ac_tables; |
1048 | 294k | huffman_table[table.destination_id] = table; |
1049 | 294k | table_register[table.destination_id] = true; |
1050 | | |
1051 | 294k | bytes_to_read -= 1 + 16 + total_codes; |
1052 | 294k | } |
1053 | | |
1054 | 174k | if (bytes_to_read != 0) { |
1055 | 0 | dbgln_if(JPEG_DEBUG, "Extra bytes detected in huffman header!"); |
1056 | 0 | return Error::from_string_literal("Extra bytes detected in huffman header"); |
1057 | 0 | } |
1058 | 174k | return {}; |
1059 | 174k | } |
1060 | | |
1061 | | static ErrorOr<void> read_icc_profile(JPEGStream& stream, JPEGLoadingContext& context, int bytes_to_read) |
1062 | 25.7k | { |
1063 | | // https://www.color.org/technotes/ICC-Technote-ProfileEmbedding.pdf, page 5, "JFIF". |
1064 | 25.7k | if (bytes_to_read <= 2) { |
1065 | 310 | dbgln_if(JPEG_DEBUG, "icc marker too small"); |
1066 | 310 | TRY(stream.discard(bytes_to_read)); |
1067 | 310 | return {}; |
1068 | 310 | } |
1069 | | |
1070 | 25.4k | auto chunk_sequence_number = TRY(stream.read_u8()); // 1-based |
1071 | 25.4k | auto number_of_chunks = TRY(stream.read_u8()); |
1072 | 25.4k | bytes_to_read -= 2; |
1073 | | |
1074 | 25.4k | if (!context.icc_multi_chunk_state.has_value()) |
1075 | 239 | context.icc_multi_chunk_state.emplace(ICCMultiChunkState { 0, TRY(FixedArray<ByteBuffer>::create(number_of_chunks)) }); |
1076 | 25.4k | auto& chunk_state = context.icc_multi_chunk_state; |
1077 | | |
1078 | 25.4k | u8 index {}; |
1079 | | |
1080 | 25.4k | auto const ensure_correctness = [&]() -> ErrorOr<void> { |
1081 | 25.4k | if (chunk_state->seen_number_of_icc_chunks >= number_of_chunks) |
1082 | 5.03k | return Error::from_string_literal("Too many ICC chunks"); |
1083 | | |
1084 | 20.4k | if (chunk_state->chunks.size() != number_of_chunks) |
1085 | 627 | return Error::from_string_literal("Inconsistent number of total ICC chunks"); |
1086 | | |
1087 | 19.7k | if (chunk_sequence_number == 0) |
1088 | 3.14k | return Error::from_string_literal("ICC chunk sequence number not 1 based"); |
1089 | | |
1090 | 16.6k | index = chunk_sequence_number - 1; |
1091 | | |
1092 | 16.6k | if (index >= chunk_state->chunks.size()) |
1093 | 14.2k | return Error::from_string_literal("ICC chunk sequence number larger than number of chunks"); |
1094 | | |
1095 | 2.36k | if (!chunk_state->chunks[index].is_empty()) |
1096 | 2.18k | return Error::from_string_literal("Duplicate ICC chunk at sequence number"); |
1097 | | |
1098 | 175 | return {}; |
1099 | 2.36k | }; |
1100 | | |
1101 | 25.4k | if (auto result = ensure_correctness(); result.is_error()) { |
1102 | 25.2k | dbgln_if(JPEG_DEBUG, "JPEG: {}", result.release_error()); |
1103 | 25.2k | TRY(stream.discard(bytes_to_read)); |
1104 | 25.2k | return {}; |
1105 | 25.2k | } |
1106 | | |
1107 | 175 | chunk_state->chunks[index] = TRY(ByteBuffer::create_zeroed(bytes_to_read)); |
1108 | 175 | TRY(stream.read_until_filled(chunk_state->chunks[index])); |
1109 | | |
1110 | 170 | chunk_state->seen_number_of_icc_chunks++; |
1111 | | |
1112 | 170 | if (chunk_state->seen_number_of_icc_chunks != chunk_state->chunks.size()) |
1113 | 169 | return {}; |
1114 | | |
1115 | 1 | if (number_of_chunks == 1) { |
1116 | 0 | context.icc_data = move(chunk_state->chunks[0]); |
1117 | 0 | return {}; |
1118 | 0 | } |
1119 | | |
1120 | 1 | size_t total_size = 0; |
1121 | 1 | for (auto const& chunk : chunk_state->chunks) |
1122 | 2 | total_size += chunk.size(); |
1123 | | |
1124 | 1 | auto icc_bytes = TRY(ByteBuffer::create_zeroed(total_size)); |
1125 | 1 | size_t start = 0; |
1126 | 2 | for (auto const& chunk : chunk_state->chunks) { |
1127 | 2 | memcpy(icc_bytes.data() + start, chunk.data(), chunk.size()); |
1128 | 2 | start += chunk.size(); |
1129 | 2 | } |
1130 | | |
1131 | 1 | context.icc_data = move(icc_bytes); |
1132 | | |
1133 | 1 | return {}; |
1134 | 1 | } |
1135 | | |
1136 | | static ErrorOr<void> read_colour_encoding(JPEGStream& stream, [[maybe_unused]] JPEGLoadingContext& context, int bytes_to_read) |
1137 | 118k | { |
1138 | | // The App 14 segment is application specific in the first JPEG standard. |
1139 | | // However, the Adobe implementation is globally accepted and the value of the color transform |
1140 | | // was latter standardized as a JPEG-1 extension. |
1141 | | |
1142 | | // For the structure of the App 14 segment, see: |
1143 | | // https://www.pdfa.org/norm-refs/5116.DCT_Filter.pdf |
1144 | | // 18 Adobe Application-Specific JPEG Marker |
1145 | | |
1146 | | // For the value of color_transform, see: |
1147 | | // https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.872-201206-I!!PDF-E&type=items |
1148 | | // 6.5.3 - APP14 marker segment for colour encoding |
1149 | | |
1150 | 118k | if (bytes_to_read < 6) |
1151 | 1 | return Error::from_string_literal("App14 segment too small"); |
1152 | | |
1153 | 118k | [[maybe_unused]] auto const version = TRY(stream.read_u8()); |
1154 | 118k | [[maybe_unused]] u16 const flag0 = TRY(stream.read_u16()); |
1155 | 118k | [[maybe_unused]] u16 const flag1 = TRY(stream.read_u16()); |
1156 | 118k | auto const color_transform = TRY(stream.read_u8()); |
1157 | | |
1158 | 118k | if (bytes_to_read > 6) { |
1159 | 8.83k | dbgln_if(JPEG_DEBUG, "Unread bytes in App14 segment: {}", bytes_to_read - 6); |
1160 | 8.83k | TRY(stream.discard(bytes_to_read - 6)); |
1161 | 8.83k | } |
1162 | | |
1163 | 118k | switch (color_transform) { |
1164 | 5.83k | case 0: |
1165 | 5.83k | context.color_transform = ColorTransform::CmykOrRgb; |
1166 | 5.83k | break; |
1167 | 942 | case 1: |
1168 | 942 | context.color_transform = ColorTransform::YCbCr; |
1169 | 942 | break; |
1170 | 77.8k | case 2: |
1171 | 77.8k | context.color_transform = ColorTransform::YCCK; |
1172 | 77.8k | break; |
1173 | 34.2k | default: |
1174 | 34.2k | dbgln("{:#x} is not a specified transform flag value, ignoring", color_transform); |
1175 | 118k | } |
1176 | | |
1177 | 118k | return {}; |
1178 | 118k | } |
1179 | | |
1180 | | static ErrorOr<void> read_exif(JPEGStream& stream, JPEGLoadingContext& context, int bytes_to_read) |
1181 | 145k | { |
1182 | | // This refers to Exif's specification, see TIFFLoader for more information. |
1183 | | // 4.7.2.2. - APP1 internal structure |
1184 | 145k | if (bytes_to_read <= 1) { |
1185 | 124k | TRY(stream.discard(bytes_to_read)); |
1186 | 124k | return {}; |
1187 | 124k | } |
1188 | | |
1189 | | // Discard padding byte |
1190 | 145k | TRY(stream.discard(1)); |
1191 | | |
1192 | 41.5k | auto exif_buffer = TRY(ByteBuffer::create_uninitialized(bytes_to_read - 1)); |
1193 | 20.7k | TRY(stream.read_until_filled(exif_buffer)); |
1194 | | |
1195 | 20.6k | context.exif_metadata = TRY(TIFFImageDecoderPlugin::read_exif_metadata(exif_buffer)); |
1196 | | |
1197 | 19.7k | return {}; |
1198 | 20.6k | } |
1199 | | |
1200 | | static ErrorOr<void> read_app_marker(JPEGStream& stream, JPEGLoadingContext& context, int app_marker_number) |
1201 | 395k | { |
1202 | | // B.2.4.6 - Application data syntax |
1203 | | |
1204 | 395k | u16 bytes_to_read = TRY(read_effective_chunk_size(stream)); |
1205 | | |
1206 | 395k | StringBuilder builder; |
1207 | 5.19M | for (;;) { |
1208 | 5.19M | if (bytes_to_read == 0) { |
1209 | 66.4k | dbgln_if(JPEG_DEBUG, "app marker {} does not start with zero-terminated string", app_marker_number); |
1210 | 66.4k | return {}; |
1211 | 66.4k | } |
1212 | | |
1213 | 5.13M | auto c = TRY(stream.read_u8()); |
1214 | 5.13M | bytes_to_read--; |
1215 | | |
1216 | 5.13M | if (c == '\0') |
1217 | 328k | break; |
1218 | | |
1219 | 9.60M | TRY(builder.try_append(c)); |
1220 | 9.60M | } |
1221 | | |
1222 | 328k | auto app_id = builder.to_byte_string(); |
1223 | | |
1224 | 328k | if (app_marker_number == 1 && app_id == "Exif"sv) |
1225 | 145k | return read_exif(stream, context, bytes_to_read); |
1226 | 183k | if (app_marker_number == 2 && app_id == "ICC_PROFILE"sv) |
1227 | 25.7k | return read_icc_profile(stream, context, bytes_to_read); |
1228 | 157k | if (app_marker_number == 14 && app_id == "Adobe"sv) |
1229 | 118k | return read_colour_encoding(stream, context, bytes_to_read); |
1230 | | |
1231 | 38.5k | return stream.discard(bytes_to_read); |
1232 | 157k | } |
1233 | | |
1234 | | static inline bool validate_sampling_factors_and_modify_context(SamplingFactors const& sampling_factors, JPEGLoadingContext& context) |
1235 | 1.36k | { |
1236 | 1.36k | if ((sampling_factors.horizontal == 1 || sampling_factors.horizontal == 2) && (sampling_factors.vertical == 1 || sampling_factors.vertical == 2)) { |
1237 | 1.36k | context.mblock_meta.hpadded_count += sampling_factors.horizontal == 1 ? 0 : context.mblock_meta.hcount % 2; |
1238 | 1.36k | context.mblock_meta.vpadded_count += sampling_factors.vertical == 1 ? 0 : context.mblock_meta.vcount % 2; |
1239 | 1.36k | context.mblock_meta.padded_total = context.mblock_meta.hpadded_count * context.mblock_meta.vpadded_count; |
1240 | | // For easy reference to relevant sample factors. |
1241 | 1.36k | context.sampling_factors = sampling_factors; |
1242 | | |
1243 | 1.36k | return true; |
1244 | 1.36k | } |
1245 | 0 | return false; |
1246 | 1.36k | } |
1247 | | |
1248 | | static inline void set_macroblock_metadata(JPEGLoadingContext& context) |
1249 | 1.40k | { |
1250 | 1.40k | context.mblock_meta.hcount = ceil_div<u32>(context.frame.width, 8); |
1251 | 1.40k | context.mblock_meta.vcount = ceil_div<u32>(context.frame.height, 8); |
1252 | 1.40k | context.mblock_meta.hpadded_count = context.mblock_meta.hcount; |
1253 | 1.40k | context.mblock_meta.vpadded_count = context.mblock_meta.vcount; |
1254 | 1.40k | context.mblock_meta.total = context.mblock_meta.hcount * context.mblock_meta.vcount; |
1255 | 1.40k | } |
1256 | | |
1257 | | static ErrorOr<void> ensure_standard_precision(StartOfFrame const& frame) |
1258 | 1.42k | { |
1259 | | // B.2.2 - Frame header syntax |
1260 | | // Table B.2 - Frame header parameter sizes and values |
1261 | | |
1262 | 1.42k | if (frame.precision == 8) |
1263 | 900 | return {}; |
1264 | | |
1265 | 526 | if (frame.type == StartOfFrame::FrameType::Extended_Sequential_DCT && frame.precision == 12) |
1266 | 342 | return {}; |
1267 | | |
1268 | 184 | if (frame.type == StartOfFrame::FrameType::Progressive_DCT && frame.precision == 12) |
1269 | 169 | return {}; |
1270 | | |
1271 | 15 | dbgln_if(JPEG_DEBUG, "Unsupported precision: {}, for SOF type: {}!", frame.precision, static_cast<int>(frame.type)); |
1272 | 15 | return Error::from_string_literal("Unsupported SOF precision."); |
1273 | 184 | } |
1274 | | |
1275 | | static ErrorOr<void> read_start_of_frame(JPEGStream& stream, JPEGLoadingContext& context) |
1276 | 1.42k | { |
1277 | 1.42k | if (context.state == JPEGLoadingContext::FrameDecoded) { |
1278 | 0 | dbgln_if(JPEG_DEBUG, "SOF repeated!"); |
1279 | 0 | return Error::from_string_literal("SOF repeated"); |
1280 | 0 | } |
1281 | | |
1282 | | // B.2.2 Frame header syntax |
1283 | | |
1284 | 1.42k | [[maybe_unused]] u16 const bytes_to_read = TRY(read_effective_chunk_size(stream)); |
1285 | | |
1286 | 1.42k | context.frame.precision = TRY(stream.read_u8()); |
1287 | | |
1288 | 1.42k | TRY(ensure_standard_precision(context.frame)); |
1289 | | |
1290 | 1.41k | context.frame.height = TRY(stream.read_u16()); |
1291 | 1.40k | context.frame.width = TRY(stream.read_u16()); |
1292 | 1.40k | if (!context.frame.width || !context.frame.height) { |
1293 | 0 | dbgln_if(JPEG_DEBUG, "ERROR! Image height: {}, Image width: {}!", context.frame.height, context.frame.width); |
1294 | 0 | return Error::from_string_literal("Image frame height of width null"); |
1295 | 0 | } |
1296 | | |
1297 | 1.40k | set_macroblock_metadata(context); |
1298 | | |
1299 | 1.40k | auto component_count = TRY(stream.read_u8()); |
1300 | 1.39k | if (component_count != 1 && component_count != 3 && component_count != 4) { |
1301 | 13 | dbgln_if(JPEG_DEBUG, "Unsupported number of components in SOF: {}!", component_count); |
1302 | 13 | return Error::from_string_literal("Unsupported number of components in SOF"); |
1303 | 13 | } |
1304 | | |
1305 | 4.20k | for (u8 i = 0; i < component_count; i++) { |
1306 | 2.85k | Component component; |
1307 | 2.85k | component.id = TRY(stream.read_u8()); |
1308 | 2.83k | component.index = i; |
1309 | | |
1310 | 2.83k | u8 subsample_factors = TRY(stream.read_u8()); |
1311 | 2.82k | component.sampling_factors.horizontal = subsample_factors >> 4; |
1312 | 2.82k | component.sampling_factors.vertical = subsample_factors & 0x0F; |
1313 | | |
1314 | 2.82k | if (component_count == 1) { |
1315 | | // 4.8.2 Minimum coded unit: "If the compressed image data is non-interleaved, the MCU is defined to be one data unit." |
1316 | 643 | component.sampling_factors = { 1, 1 }; |
1317 | 643 | } |
1318 | | |
1319 | 2.82k | dbgln_if(JPEG_DEBUG, "Component subsampling: {}, {}", component.sampling_factors.horizontal, component.sampling_factors.vertical); |
1320 | | |
1321 | 2.82k | if (component.sampling_factors.horizontal == 0 || component.sampling_factors.horizontal > 4 |
1322 | 2.82k | || component.sampling_factors.vertical == 0 || component.sampling_factors.vertical > 4) { |
1323 | 5 | return Error::from_string_literal("Invalid subsampling factor values"); |
1324 | 5 | } |
1325 | | |
1326 | 2.82k | if (i == 0) { |
1327 | | // By convention, downsampling is applied only on chroma components. So we should |
1328 | | // hope to see the maximum sampling factor in the luma component. |
1329 | 1.36k | if (!validate_sampling_factors_and_modify_context(component.sampling_factors, context)) { |
1330 | 0 | dbgln_if(JPEG_DEBUG, "Unsupported luma subsampling factors: horizontal: {}, vertical: {}", |
1331 | 0 | component.sampling_factors.horizontal, |
1332 | 0 | component.sampling_factors.vertical); |
1333 | 0 | return Error::from_string_literal("Unsupported luma subsampling factors"); |
1334 | 0 | } |
1335 | 1.45k | } else { |
1336 | 1.45k | auto const& y_component = context.components[0]; |
1337 | 1.45k | if (y_component.sampling_factors.horizontal % component.sampling_factors.horizontal != 0 |
1338 | 1.45k | || y_component.sampling_factors.vertical % component.sampling_factors.vertical != 0) { |
1339 | 1 | dbgln_if(JPEG_DEBUG, "Unsupported chroma subsampling factors: horizontal: {}, vertical: {}", |
1340 | 1 | component.sampling_factors.horizontal, |
1341 | 1 | component.sampling_factors.vertical); |
1342 | 1 | return Error::from_string_literal("Unsupported chroma subsampling factors"); |
1343 | 1 | } |
1344 | 1.45k | } |
1345 | | |
1346 | 2.82k | component.quantization_table_id = TRY(stream.read_u8()); |
1347 | | |
1348 | 2.82k | context.components.append(move(component)); |
1349 | 2.82k | } |
1350 | | |
1351 | 1.34k | return {}; |
1352 | 1.38k | } |
1353 | | |
1354 | | static ErrorOr<void> read_quantization_table(JPEGStream& stream, JPEGLoadingContext& context) |
1355 | 15.2k | { |
1356 | | // B.2.4.1 - Quantization table-specification syntax |
1357 | | |
1358 | 15.2k | u16 bytes_to_read = TRY(read_effective_chunk_size(stream)); |
1359 | | |
1360 | 54.3k | while (bytes_to_read > 0) { |
1361 | 39.2k | u8 const info_byte = TRY(stream.read_u8()); |
1362 | 39.2k | u8 const element_unit_hint = info_byte >> 4; |
1363 | 39.2k | if (element_unit_hint > 1) { |
1364 | 12 | dbgln_if(JPEG_DEBUG, "Unsupported unit hint in quantization table: {}!", element_unit_hint); |
1365 | 12 | return Error::from_string_literal("Unsupported unit hint in quantization table"); |
1366 | 12 | } |
1367 | 39.2k | u8 const table_id = info_byte & 0x0F; |
1368 | | |
1369 | 39.2k | if (table_id > 3) { |
1370 | 3 | dbgln_if(JPEG_DEBUG, "Unsupported quantization table id: {}!", table_id); |
1371 | 3 | return Error::from_string_literal("Unsupported quantization table id"); |
1372 | 3 | } |
1373 | | |
1374 | 39.2k | context.registered_quantization_tables[table_id] = true; |
1375 | | |
1376 | 39.2k | auto& table = context.quantization_tables[table_id]; |
1377 | | |
1378 | 2.54M | for (int i = 0; i < 64; i++) { |
1379 | 2.50M | if (element_unit_hint == 0) |
1380 | 1.38M | table[zigzag_map[i]] = TRY(stream.read_u8()); |
1381 | 1.11M | else |
1382 | 1.11M | table[zigzag_map[i]] = TRY(stream.read_u16()); |
1383 | 2.50M | } |
1384 | | |
1385 | 39.2k | bytes_to_read -= 1 + (element_unit_hint == 0 ? 64 : 128); |
1386 | 39.1k | } |
1387 | 15.1k | if (bytes_to_read != 0) { |
1388 | 0 | dbgln_if(JPEG_DEBUG, "Invalid length for one or more quantization tables!"); |
1389 | 0 | return Error::from_string_literal("Invalid length for one or more quantization tables"); |
1390 | 0 | } |
1391 | | |
1392 | 15.1k | return {}; |
1393 | 15.1k | } |
1394 | | |
1395 | | static ErrorOr<void> skip_segment(JPEGStream& stream) |
1396 | 103k | { |
1397 | 103k | u16 bytes_to_skip = TRY(read_effective_chunk_size(stream)); |
1398 | 103k | TRY(stream.discard(bytes_to_skip)); |
1399 | 103k | return {}; |
1400 | 103k | } |
1401 | | |
1402 | | template<CallableAs<void, Component const&, i16*> F> |
1403 | | static void for_each_macroblock_component(JPEGLoadingContext const& context, Vector<Macroblock>& macroblocks, F&& component_handler) |
1404 | 63 | { |
1405 | 45.4k | for (u32 vcursor = 0; vcursor < context.mblock_meta.vcount; vcursor += context.sampling_factors.vertical) { |
1406 | 1.21M | for (u32 hcursor = 0; hcursor < context.mblock_meta.hcount; hcursor += context.sampling_factors.horizontal) { |
1407 | 3.95M | for (u32 i = 0; i < context.components.size(); i++) { |
1408 | 2.78M | auto const& component = context.components[i]; |
1409 | | |
1410 | 6.32M | for (u32 vfactor_i = 0; vfactor_i < component.sampling_factors.vertical; vfactor_i++) { |
1411 | 8.58M | for (u32 hfactor_i = 0; hfactor_i < component.sampling_factors.horizontal; hfactor_i++) { |
1412 | 5.04M | u32 macroblock_index = (vcursor + vfactor_i) * context.mblock_meta.hpadded_count + (hfactor_i + hcursor); |
1413 | 5.04M | Macroblock& block = macroblocks[macroblock_index]; |
1414 | 5.04M | auto* block_component = get_component(block, i); |
1415 | | |
1416 | 5.04M | component_handler(component, block_component); |
1417 | 5.04M | } |
1418 | 3.53M | } |
1419 | 2.78M | } |
1420 | 1.17M | } |
1421 | 45.3k | } |
1422 | 63 | } |
1423 | | |
1424 | | static void dequantize(JPEGLoadingContext const& context, Component const& component, i16* block_component) |
1425 | 5.04M | { |
1426 | 5.04M | auto const& quantization_table = context.quantization_tables[component.quantization_table_id]; |
1427 | | |
1428 | 328M | for (u32 k = 0; k < 64; k++) |
1429 | 323M | block_component[k] *= quantization_table[k]; |
1430 | 5.04M | } |
1431 | | |
1432 | | static void inverse_dct_8x8(i16* block_component) |
1433 | 5.04M | { |
1434 | | // Does a 2-D IDCT by doing two 1-D IDCTs as described in https://unix4lyfe.org/dct/ |
1435 | | // The 1-D DCT idea is described at https://unix4lyfe.org/dct-1d/, read aan.cc from bottom to top. |
1436 | 5.04M | static float const m0 = 2.0f * AK::cos(1.0f / 16.0f * 2.0f * AK::Pi<float>); |
1437 | 5.04M | static float const m1 = 2.0f * AK::cos(2.0f / 16.0f * 2.0f * AK::Pi<float>); |
1438 | 5.04M | static float const m3 = 2.0f * AK::cos(2.0f / 16.0f * 2.0f * AK::Pi<float>); |
1439 | 5.04M | static float const m5 = 2.0f * AK::cos(3.0f / 16.0f * 2.0f * AK::Pi<float>); |
1440 | 5.04M | static float const m2 = m0 - m5; |
1441 | 5.04M | static float const m4 = m0 + m5; |
1442 | 5.04M | static float const s0 = AK::cos(0.0f / 16.0f * AK::Pi<float>) / AK::sqrt(8.0f); |
1443 | 5.04M | static float const s1 = AK::cos(1.0f / 16.0f * AK::Pi<float>) / 2.0f; |
1444 | 5.04M | static float const s2 = AK::cos(2.0f / 16.0f * AK::Pi<float>) / 2.0f; |
1445 | 5.04M | static float const s3 = AK::cos(3.0f / 16.0f * AK::Pi<float>) / 2.0f; |
1446 | 5.04M | static float const s4 = AK::cos(4.0f / 16.0f * AK::Pi<float>) / 2.0f; |
1447 | 5.04M | static float const s5 = AK::cos(5.0f / 16.0f * AK::Pi<float>) / 2.0f; |
1448 | 5.04M | static float const s6 = AK::cos(6.0f / 16.0f * AK::Pi<float>) / 2.0f; |
1449 | 5.04M | static float const s7 = AK::cos(7.0f / 16.0f * AK::Pi<float>) / 2.0f; |
1450 | | |
1451 | 45.4M | for (u32 k = 0; k < 8; ++k) { |
1452 | 40.3M | float const g0 = block_component[0 * 8 + k] * s0; |
1453 | 40.3M | float const g1 = block_component[4 * 8 + k] * s4; |
1454 | 40.3M | float const g2 = block_component[2 * 8 + k] * s2; |
1455 | 40.3M | float const g3 = block_component[6 * 8 + k] * s6; |
1456 | 40.3M | float const g4 = block_component[5 * 8 + k] * s5; |
1457 | 40.3M | float const g5 = block_component[1 * 8 + k] * s1; |
1458 | 40.3M | float const g6 = block_component[7 * 8 + k] * s7; |
1459 | 40.3M | float const g7 = block_component[3 * 8 + k] * s3; |
1460 | | |
1461 | 40.3M | float const f0 = g0; |
1462 | 40.3M | float const f1 = g1; |
1463 | 40.3M | float const f2 = g2; |
1464 | 40.3M | float const f3 = g3; |
1465 | 40.3M | float const f4 = g4 - g7; |
1466 | 40.3M | float const f5 = g5 + g6; |
1467 | 40.3M | float const f6 = g5 - g6; |
1468 | 40.3M | float const f7 = g4 + g7; |
1469 | | |
1470 | 40.3M | float const e0 = f0; |
1471 | 40.3M | float const e1 = f1; |
1472 | 40.3M | float const e2 = f2 - f3; |
1473 | 40.3M | float const e3 = f2 + f3; |
1474 | 40.3M | float const e4 = f4; |
1475 | 40.3M | float const e5 = f5 - f7; |
1476 | 40.3M | float const e6 = f6; |
1477 | 40.3M | float const e7 = f5 + f7; |
1478 | 40.3M | float const e8 = f4 + f6; |
1479 | | |
1480 | 40.3M | float const d0 = e0; |
1481 | 40.3M | float const d1 = e1; |
1482 | 40.3M | float const d2 = e2 * m1; |
1483 | 40.3M | float const d3 = e3; |
1484 | 40.3M | float const d4 = e4 * m2; |
1485 | 40.3M | float const d5 = e5 * m3; |
1486 | 40.3M | float const d6 = e6 * m4; |
1487 | 40.3M | float const d7 = e7; |
1488 | 40.3M | float const d8 = e8 * m5; |
1489 | | |
1490 | 40.3M | float const c0 = d0 + d1; |
1491 | 40.3M | float const c1 = d0 - d1; |
1492 | 40.3M | float const c2 = d2 - d3; |
1493 | 40.3M | float const c3 = d3; |
1494 | 40.3M | float const c4 = d4 + d8; |
1495 | 40.3M | float const c5 = d5 + d7; |
1496 | 40.3M | float const c6 = d6 - d8; |
1497 | 40.3M | float const c7 = d7; |
1498 | 40.3M | float const c8 = c5 - c6; |
1499 | | |
1500 | 40.3M | float const b0 = c0 + c3; |
1501 | 40.3M | float const b1 = c1 + c2; |
1502 | 40.3M | float const b2 = c1 - c2; |
1503 | 40.3M | float const b3 = c0 - c3; |
1504 | 40.3M | float const b4 = c4 - c8; |
1505 | 40.3M | float const b5 = c8; |
1506 | 40.3M | float const b6 = c6 - c7; |
1507 | 40.3M | float const b7 = c7; |
1508 | | |
1509 | 40.3M | block_component[0 * 8 + k] = b0 + b7; |
1510 | 40.3M | block_component[1 * 8 + k] = b1 + b6; |
1511 | 40.3M | block_component[2 * 8 + k] = b2 + b5; |
1512 | 40.3M | block_component[3 * 8 + k] = b3 + b4; |
1513 | 40.3M | block_component[4 * 8 + k] = b3 - b4; |
1514 | 40.3M | block_component[5 * 8 + k] = b2 - b5; |
1515 | 40.3M | block_component[6 * 8 + k] = b1 - b6; |
1516 | 40.3M | block_component[7 * 8 + k] = b0 - b7; |
1517 | 40.3M | } |
1518 | 45.4M | for (u32 l = 0; l < 8; ++l) { |
1519 | 40.3M | float const g0 = block_component[l * 8 + 0] * s0; |
1520 | 40.3M | float const g1 = block_component[l * 8 + 4] * s4; |
1521 | 40.3M | float const g2 = block_component[l * 8 + 2] * s2; |
1522 | 40.3M | float const g3 = block_component[l * 8 + 6] * s6; |
1523 | 40.3M | float const g4 = block_component[l * 8 + 5] * s5; |
1524 | 40.3M | float const g5 = block_component[l * 8 + 1] * s1; |
1525 | 40.3M | float const g6 = block_component[l * 8 + 7] * s7; |
1526 | 40.3M | float const g7 = block_component[l * 8 + 3] * s3; |
1527 | | |
1528 | 40.3M | float const f0 = g0; |
1529 | 40.3M | float const f1 = g1; |
1530 | 40.3M | float const f2 = g2; |
1531 | 40.3M | float const f3 = g3; |
1532 | 40.3M | float const f4 = g4 - g7; |
1533 | 40.3M | float const f5 = g5 + g6; |
1534 | 40.3M | float const f6 = g5 - g6; |
1535 | 40.3M | float const f7 = g4 + g7; |
1536 | | |
1537 | 40.3M | float const e0 = f0; |
1538 | 40.3M | float const e1 = f1; |
1539 | 40.3M | float const e2 = f2 - f3; |
1540 | 40.3M | float const e3 = f2 + f3; |
1541 | 40.3M | float const e4 = f4; |
1542 | 40.3M | float const e5 = f5 - f7; |
1543 | 40.3M | float const e6 = f6; |
1544 | 40.3M | float const e7 = f5 + f7; |
1545 | 40.3M | float const e8 = f4 + f6; |
1546 | | |
1547 | 40.3M | float const d0 = e0; |
1548 | 40.3M | float const d1 = e1; |
1549 | 40.3M | float const d2 = e2 * m1; |
1550 | 40.3M | float const d3 = e3; |
1551 | 40.3M | float const d4 = e4 * m2; |
1552 | 40.3M | float const d5 = e5 * m3; |
1553 | 40.3M | float const d6 = e6 * m4; |
1554 | 40.3M | float const d7 = e7; |
1555 | 40.3M | float const d8 = e8 * m5; |
1556 | | |
1557 | 40.3M | float const c0 = d0 + d1; |
1558 | 40.3M | float const c1 = d0 - d1; |
1559 | 40.3M | float const c2 = d2 - d3; |
1560 | 40.3M | float const c3 = d3; |
1561 | 40.3M | float const c4 = d4 + d8; |
1562 | 40.3M | float const c5 = d5 + d7; |
1563 | 40.3M | float const c6 = d6 - d8; |
1564 | 40.3M | float const c7 = d7; |
1565 | 40.3M | float const c8 = c5 - c6; |
1566 | | |
1567 | 40.3M | float const b0 = c0 + c3; |
1568 | 40.3M | float const b1 = c1 + c2; |
1569 | 40.3M | float const b2 = c1 - c2; |
1570 | 40.3M | float const b3 = c0 - c3; |
1571 | 40.3M | float const b4 = c4 - c8; |
1572 | 40.3M | float const b5 = c8; |
1573 | 40.3M | float const b6 = c6 - c7; |
1574 | 40.3M | float const b7 = c7; |
1575 | | |
1576 | 40.3M | block_component[l * 8 + 0] = b0 + b7; |
1577 | 40.3M | block_component[l * 8 + 1] = b1 + b6; |
1578 | 40.3M | block_component[l * 8 + 2] = b2 + b5; |
1579 | 40.3M | block_component[l * 8 + 3] = b3 + b4; |
1580 | 40.3M | block_component[l * 8 + 4] = b3 - b4; |
1581 | 40.3M | block_component[l * 8 + 5] = b2 - b5; |
1582 | 40.3M | block_component[l * 8 + 6] = b1 - b6; |
1583 | 40.3M | block_component[l * 8 + 7] = b0 - b7; |
1584 | 40.3M | } |
1585 | 5.04M | } |
1586 | | |
1587 | | static void inverse_dct(JPEGLoadingContext const& context, i16* block_component) |
1588 | 5.04M | { |
1589 | 5.04M | inverse_dct_8x8(block_component); |
1590 | | |
1591 | | // F.2.1.5 - Inverse DCT (IDCT) |
1592 | 5.04M | auto const level_shift = 1 << (context.frame.precision - 1); |
1593 | 5.04M | auto const max_value = (1 << context.frame.precision) - 1; |
1594 | | // FIXME: This just truncate all coefficients, it's an easy way to support (read hack) |
1595 | | // 12 bits JPEGs without rewriting all color transformations. |
1596 | 323M | auto const clamp_to_8_bits = [&](u16 color) -> u8 { |
1597 | 323M | if (context.frame.precision == 8) |
1598 | 266M | return static_cast<u8>(color); |
1599 | 56.9M | return static_cast<u8>(color >> 4); |
1600 | 323M | }; |
1601 | | |
1602 | 328M | for (u8 i = 0; i < 64; ++i) |
1603 | 323M | block_component[i] = clamp_to_8_bits(clamp(block_component[i] + level_shift, 0, max_value)); |
1604 | 5.04M | } |
1605 | | |
1606 | | static void undo_subsampling(JPEGLoadingContext const& context, Vector<Macroblock>& macroblocks) |
1607 | 63 | { |
1608 | | // The first component has sampling factors of context.sampling_factors, while the others |
1609 | | // divide the first component's sampling factors. This is enforced by read_start_of_frame(). |
1610 | | // This function undoes the subsampling by duplicating the values of the smaller components. |
1611 | | // See https://www.w3.org/Graphics/JPEG/itu-t81.pdf, A.2 Order of source image data encoding. |
1612 | | // |
1613 | | // FIXME: Allow more combinations of sampling factors. |
1614 | | // See https://calendar.perfplanet.com/2015/why-arent-your-images-using-chroma-subsampling/ for |
1615 | | // subsampling factors visble on the web. In PDF files, YCCK 2111 and 2112 and CMYK 2111 and 2112 are also present. |
1616 | 205 | for (u32 component_i = 0; component_i < context.components.size(); component_i++) { |
1617 | 142 | auto& component = context.components[component_i]; |
1618 | 142 | if (component.sampling_factors == context.sampling_factors) |
1619 | 84 | continue; |
1620 | | |
1621 | 29.1k | for (u32 vcursor = 0; vcursor < context.mblock_meta.vcount; vcursor += context.sampling_factors.vertical) { |
1622 | 1.54M | for (u32 hcursor = 0; hcursor < context.mblock_meta.hcount; hcursor += context.sampling_factors.horizontal) { |
1623 | 1.51M | u32 const component_block_index = vcursor * context.mblock_meta.hpadded_count + hcursor; |
1624 | 1.51M | Macroblock& component_block = macroblocks[component_block_index]; |
1625 | 1.51M | auto* block_component_source = get_component(component_block, component_i); |
1626 | | |
1627 | | // Overflows are intentional. |
1628 | 4.54M | for (u8 vfactor_i = context.sampling_factors.vertical - 1; vfactor_i < context.sampling_factors.vertical; --vfactor_i) { |
1629 | 9.08M | for (u8 hfactor_i = context.sampling_factors.horizontal - 1; hfactor_i < context.sampling_factors.horizontal; --hfactor_i) { |
1630 | 6.05M | u32 macroblock_index = (vcursor + vfactor_i) * context.mblock_meta.hpadded_count + (hfactor_i + hcursor); |
1631 | 6.05M | Macroblock& block = macroblocks[macroblock_index]; |
1632 | 6.05M | auto* block_component_destination = get_component(block, component_i); |
1633 | 54.4M | for (u8 i = 7; i < 8; --i) { |
1634 | 435M | for (u8 j = 7; j < 8; --j) { |
1635 | 387M | u8 const pixel = i * 8 + j; |
1636 | | // The component is 8x8 subsampled 2x2. Upsample its 2x2 4x4 tiles. |
1637 | 387M | u32 const component_pxrow = (i / context.sampling_factors.vertical) + 4 * vfactor_i; |
1638 | 387M | u32 const component_pxcol = (j / context.sampling_factors.horizontal) + 4 * hfactor_i; |
1639 | 387M | u32 const component_pixel = component_pxrow * 8 + component_pxcol; |
1640 | 387M | block_component_destination[pixel] = block_component_source[component_pixel]; |
1641 | 387M | } |
1642 | 48.4M | } |
1643 | 6.05M | } |
1644 | 3.03M | } |
1645 | 1.51M | } |
1646 | 29.1k | } |
1647 | 58 | } |
1648 | 63 | } |
1649 | | |
1650 | | static void ycbcr_to_rgb(Vector<Macroblock>& macroblocks) |
1651 | 35 | { |
1652 | | // Conversion from YCbCr to RGB isn't specified in the first JPEG specification but in the JFIF extension: |
1653 | | // See: https://www.itu.int/rec/dologin_pub.asp?lang=f&id=T-REC-T.871-201105-I!!PDF-E&type=items |
1654 | | // 7 - Conversion to and from RGB |
1655 | 3.06M | for (auto& macroblock : macroblocks) { |
1656 | 3.06M | auto* y = macroblock.y; |
1657 | 3.06M | auto* cb = macroblock.cb; |
1658 | 3.06M | auto* cr = macroblock.cr; |
1659 | 199M | for (u8 i = 0; i < 64; ++i) { |
1660 | 196M | int r = y[i] + 1.402f * (cr[i] - 128); |
1661 | 196M | int g = y[i] - 0.3441f * (cb[i] - 128) - 0.7141f * (cr[i] - 128); |
1662 | 196M | int b = y[i] + 1.772f * (cb[i] - 128); |
1663 | 196M | y[i] = clamp(r, 0, 255); |
1664 | 196M | cb[i] = clamp(g, 0, 255); |
1665 | 196M | cr[i] = clamp(b, 0, 255); |
1666 | 196M | } |
1667 | 3.06M | } |
1668 | 35 | } |
1669 | | |
1670 | | static void invert_colors_for_adobe_images(JPEGLoadingContext const& context, Vector<Macroblock>& macroblocks) |
1671 | 5 | { |
1672 | 5 | if (!context.color_transform.has_value()) |
1673 | 0 | return; |
1674 | | |
1675 | | // From libjpeg-turbo's libjpeg.txt: |
1676 | | // https://github.com/libjpeg-turbo/libjpeg-turbo/blob/main/libjpeg.txt |
1677 | | // CAUTION: it appears that Adobe Photoshop writes inverted data in CMYK JPEG |
1678 | | // files: 0 represents 100% ink coverage, rather than 0% ink as you'd expect. |
1679 | | // This is arguably a bug in Photoshop, but if you need to work with Photoshop |
1680 | | // CMYK files, you will have to deal with it in your application. |
1681 | 4.26k | for (auto& macroblock : macroblocks) { |
1682 | 277k | for (u8 i = 0; i < 64; ++i) { |
1683 | 273k | macroblock.r[i] = 255 - macroblock.r[i]; |
1684 | 273k | macroblock.g[i] = 255 - macroblock.g[i]; |
1685 | 273k | macroblock.b[i] = 255 - macroblock.b[i]; |
1686 | 273k | macroblock.k[i] = 255 - macroblock.k[i]; |
1687 | 273k | } |
1688 | 4.26k | } |
1689 | 5 | } |
1690 | | |
1691 | | static void ycck_to_cmyk(Vector<Macroblock>& macroblocks) |
1692 | 9 | { |
1693 | | // 7 - Conversions between colour encodings |
1694 | | // YCCK is obtained from CMYK by converting the CMY channels to YCC channel. |
1695 | | |
1696 | | // To convert back into RGB, we only need the 3 first components, which are baseline YCbCr |
1697 | 9 | ycbcr_to_rgb(macroblocks); |
1698 | | |
1699 | | // RGB to CMY, as mentioned in https://www.smcm.iqfr.csic.es/docs/intel/ipp/ipp_manual/IPPI/ippi_ch15/functn_YCCKToCMYK_JPEG.htm#functn_YCCKToCMYK_JPEG |
1700 | 163k | for (auto& macroblock : macroblocks) { |
1701 | 10.6M | for (u8 i = 0; i < 64; ++i) { |
1702 | 10.4M | macroblock.r[i] = 255 - macroblock.r[i]; |
1703 | 10.4M | macroblock.g[i] = 255 - macroblock.g[i]; |
1704 | 10.4M | macroblock.b[i] = 255 - macroblock.b[i]; |
1705 | 10.4M | } |
1706 | 163k | } |
1707 | 9 | } |
1708 | | |
1709 | | static void grayscale_to_rgb(Vector<Macroblock>& macroblocks) |
1710 | 26 | { |
1711 | 371k | for (auto& macroblock : macroblocks) { |
1712 | | // r is already filled with luma components. |
1713 | 371k | ReadonlySpan<i16>(macroblock.r).copy_to(macroblock.g); |
1714 | 371k | ReadonlySpan<i16>(macroblock.r).copy_to(macroblock.b); |
1715 | 371k | } |
1716 | 26 | } |
1717 | | |
1718 | | static ErrorOr<void> handle_color_transform(JPEGLoadingContext const& context, Vector<Macroblock>& macroblocks) |
1719 | 63 | { |
1720 | | // Note: This is non-standard but some encoder still add the App14 segment for grayscale images. |
1721 | | // So let's ignore the color transform value if we only have one component. |
1722 | 63 | if (context.color_transform.has_value() && context.components.size() != 1) { |
1723 | | // https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.872-201206-I!!PDF-E&type=items |
1724 | | // 6.5.3 - APP14 marker segment for colour encoding |
1725 | | |
1726 | 16 | switch (*context.color_transform) { |
1727 | 2 | case ColorTransform::CmykOrRgb: |
1728 | 2 | if (context.components.size() == 4) { |
1729 | | // Nothing to do here. |
1730 | 2 | } else if (context.components.size() == 3) { |
1731 | | // Note: components.size() == 3 means that we have an RGB image, so no color transformation is needed. |
1732 | 0 | } else { |
1733 | 0 | return Error::from_string_literal("Wrong number of components for CMYK or RGB, aborting."); |
1734 | 0 | } |
1735 | 2 | break; |
1736 | 5 | case ColorTransform::YCbCr: |
1737 | 5 | ycbcr_to_rgb(macroblocks); |
1738 | 5 | break; |
1739 | 9 | case ColorTransform::YCCK: |
1740 | 9 | ycck_to_cmyk(macroblocks); |
1741 | 9 | break; |
1742 | 16 | } |
1743 | | |
1744 | 16 | return {}; |
1745 | 16 | } |
1746 | | |
1747 | | // No App14 segment is present, assuming : |
1748 | | // - 1 components means grayscale |
1749 | | // - 3 components means YCbCr |
1750 | | // - 4 components means CMYK (Nothing to do here). |
1751 | 47 | if (context.components.size() == 3) |
1752 | 21 | ycbcr_to_rgb(macroblocks); |
1753 | | |
1754 | 47 | if (context.components.size() == 1) |
1755 | 26 | grayscale_to_rgb(macroblocks); |
1756 | | |
1757 | 47 | return {}; |
1758 | 63 | } |
1759 | | |
1760 | | static ErrorOr<void> compose_bitmap(JPEGLoadingContext& context, Vector<Macroblock> const& macroblocks) |
1761 | 58 | { |
1762 | 58 | context.bitmap = TRY(Bitmap::create(BitmapFormat::BGRx8888, { context.frame.width, context.frame.height })); |
1763 | | |
1764 | 136k | for (u32 y = context.frame.height - 1; y < context.frame.height; y--) { |
1765 | 135k | u32 const block_row = y / 8; |
1766 | 135k | u32 const pixel_row = y % 8; |
1767 | 25.9M | for (u32 x = 0; x < context.frame.width; x++) { |
1768 | 25.8M | u32 const block_column = x / 8; |
1769 | 25.8M | auto& block = macroblocks[block_row * context.mblock_meta.hpadded_count + block_column]; |
1770 | 25.8M | u32 const pixel_column = x % 8; |
1771 | 25.8M | u32 const pixel_index = pixel_row * 8 + pixel_column; |
1772 | 25.8M | Color const color { (u8)block.y[pixel_index], (u8)block.cb[pixel_index], (u8)block.cr[pixel_index] }; |
1773 | 25.8M | context.bitmap->set_pixel(x, y, color); |
1774 | 25.8M | } |
1775 | 135k | } |
1776 | | |
1777 | 49 | return {}; |
1778 | 58 | } |
1779 | | |
1780 | | static ErrorOr<void> compose_cmyk_bitmap(JPEGLoadingContext& context, Vector<Macroblock>& macroblocks) |
1781 | 5 | { |
1782 | 5 | if (context.options.cmyk == JPEGDecoderOptions::CMYK::Normal) |
1783 | 5 | invert_colors_for_adobe_images(context, macroblocks); |
1784 | | |
1785 | 5 | context.cmyk_bitmap = TRY(Gfx::CMYKBitmap::create_with_size({ context.frame.width, context.frame.height })); |
1786 | | |
1787 | 6.28k | for (u32 y = context.frame.height - 1; y < context.frame.height; y--) { |
1788 | 6.28k | u32 const block_row = y / 8; |
1789 | 6.28k | u32 const pixel_row = y % 8; |
1790 | 272k | for (u32 x = 0; x < context.frame.width; x++) { |
1791 | 265k | u32 const block_column = x / 8; |
1792 | 265k | auto& block = macroblocks[block_row * context.mblock_meta.hpadded_count + block_column]; |
1793 | 265k | u32 const pixel_column = x % 8; |
1794 | 265k | u32 const pixel_index = pixel_row * 8 + pixel_column; |
1795 | 265k | context.cmyk_bitmap->scanline(y)[x] = { (u8)block.y[pixel_index], (u8)block.cb[pixel_index], (u8)block.cr[pixel_index], (u8)block.k[pixel_index] }; |
1796 | 265k | } |
1797 | 6.28k | } |
1798 | | |
1799 | 5 | return {}; |
1800 | 5 | } |
1801 | | |
1802 | | static bool is_app_marker(Marker const marker) |
1803 | 1.60M | { |
1804 | 1.60M | return marker >= JPEG_APPN0 && marker <= JPEG_APPN15; |
1805 | 1.60M | } |
1806 | | |
1807 | | static bool is_miscellaneous_or_table_marker(Marker const marker) |
1808 | 1.01M | { |
1809 | | // B.2.4 - Table-specification and miscellaneous marker segment syntax |
1810 | | // See also B.6 - Summary: Figure B.17 – Flow of marker segment |
1811 | | |
1812 | 1.01M | bool const is_misc = marker == JPEG_COM || marker == JPEG_DRI || is_app_marker(marker); |
1813 | 1.01M | bool const is_table = marker == JPEG_DQT || marker == JPEG_DAC || marker == JPEG_DHT; |
1814 | | |
1815 | 1.01M | return is_misc || is_table; |
1816 | 1.01M | } |
1817 | | |
1818 | | static ErrorOr<void> handle_miscellaneous_or_table(JPEGStream& stream, JPEGLoadingContext& context, Marker const marker) |
1819 | 655k | { |
1820 | 655k | if (is_app_marker(marker)) { |
1821 | 395k | TRY(read_app_marker(stream, context, marker - JPEG_APPN0)); |
1822 | 394k | return {}; |
1823 | 395k | } |
1824 | | |
1825 | 260k | switch (marker) { |
1826 | 7.34k | case JPEG_COM: |
1827 | 7.34k | case JPEG_DAC: |
1828 | 7.34k | dbgln_if(JPEG_DEBUG, "TODO: implement marker \"{:x}\"", marker); |
1829 | 7.34k | if (auto result = skip_segment(stream); result.is_error()) { |
1830 | 32 | dbgln_if(JPEG_DEBUG, "Error skipping marker: {:x}!", marker); |
1831 | 32 | return result.release_error(); |
1832 | 32 | } |
1833 | 7.30k | break; |
1834 | 175k | case JPEG_DHT: |
1835 | 175k | TRY(read_huffman_table(stream, context)); |
1836 | 174k | break; |
1837 | 15.2k | case JPEG_DQT: |
1838 | 15.2k | TRY(read_quantization_table(stream, context)); |
1839 | 15.1k | break; |
1840 | 62.3k | case JPEG_DRI: |
1841 | 62.3k | TRY(read_restart_interval(stream, context)); |
1842 | 62.3k | break; |
1843 | 0 | default: |
1844 | 0 | dbgln("Unexpected marker: {:x}", marker); |
1845 | 0 | VERIFY_NOT_REACHED(); |
1846 | 260k | } |
1847 | | |
1848 | 259k | return {}; |
1849 | 260k | } |
1850 | | |
1851 | | static ErrorOr<void> parse_header(JPEGStream& stream, JPEGLoadingContext& context) |
1852 | 4.04k | { |
1853 | 4.04k | auto marker = TRY(read_until_marker(stream)); |
1854 | 4.02k | if (marker != JPEG_SOI) { |
1855 | 2 | dbgln_if(JPEG_DEBUG, "SOI not found: {:x}!", marker); |
1856 | 2 | return Error::from_string_literal("SOI not found"); |
1857 | 2 | } |
1858 | 665k | for (;;) { |
1859 | 665k | marker = TRY(read_until_marker(stream)); |
1860 | | |
1861 | 664k | if (is_miscellaneous_or_table_marker(marker)) { |
1862 | 567k | TRY(handle_miscellaneous_or_table(stream, context, marker)); |
1863 | 565k | continue; |
1864 | 567k | } |
1865 | | |
1866 | | // Set frame type if the marker marks a new frame. |
1867 | 97.4k | if (is_frame_marker(marker)) |
1868 | 1.42k | context.frame.type = static_cast<StartOfFrame::FrameType>(marker & 0xF); |
1869 | | |
1870 | 97.4k | switch (marker) { |
1871 | 2 | case JPEG_RST0: |
1872 | 5 | case JPEG_RST1: |
1873 | 9 | case JPEG_RST2: |
1874 | 9 | case JPEG_RST3: |
1875 | 11 | case JPEG_RST4: |
1876 | 11 | case JPEG_RST5: |
1877 | 17 | case JPEG_RST6: |
1878 | 17 | case JPEG_RST7: |
1879 | 82 | case JPEG_SOI: |
1880 | 85 | case JPEG_EOI: |
1881 | 85 | dbgln_if(JPEG_DEBUG, "Unexpected marker {:x}!", marker); |
1882 | 85 | return Error::from_string_literal("Unexpected marker"); |
1883 | 312 | case JPEG_SOF0: |
1884 | 746 | case JPEG_SOF1: |
1885 | 1.42k | case JPEG_SOF2: |
1886 | 1.42k | TRY(read_start_of_frame(stream, context)); |
1887 | 1.34k | context.state = JPEGLoadingContext::FrameDecoded; |
1888 | 1.34k | return {}; |
1889 | 95.9k | default: |
1890 | 95.9k | if (auto result = skip_segment(stream); result.is_error()) { |
1891 | 105 | dbgln_if(JPEG_DEBUG, "Error skipping marker: {:x}!", marker); |
1892 | 105 | return result.release_error(); |
1893 | 105 | } |
1894 | 95.8k | break; |
1895 | 97.4k | } |
1896 | 97.4k | } |
1897 | | |
1898 | 0 | VERIFY_NOT_REACHED(); |
1899 | 0 | } |
1900 | | |
1901 | | static ErrorOr<void> decode_header(JPEGLoadingContext& context) |
1902 | 4.04k | { |
1903 | 4.04k | VERIFY(context.state < JPEGLoadingContext::State::HeaderDecoded); |
1904 | 4.04k | TRY(parse_header(context.stream, context)); |
1905 | | |
1906 | | if constexpr (JPEG_DEBUG) { |
1907 | | dbgln("Image width: {}", context.frame.width); |
1908 | | dbgln("Image height: {}", context.frame.height); |
1909 | | dbgln("Macroblocks in a row: {}", context.mblock_meta.hpadded_count); |
1910 | | dbgln("Macroblocks in a column: {}", context.mblock_meta.vpadded_count); |
1911 | | dbgln("Macroblock meta padded total: {}", context.mblock_meta.padded_total); |
1912 | | } |
1913 | | |
1914 | 1.34k | context.state = JPEGLoadingContext::State::HeaderDecoded; |
1915 | 1.34k | return {}; |
1916 | 4.04k | } |
1917 | | |
1918 | | static ErrorOr<Vector<Macroblock>> construct_macroblocks(JPEGLoadingContext& context) |
1919 | 1.34k | { |
1920 | | // B.6 - Summary |
1921 | | // See: Figure B.16 – Flow of compressed data syntax |
1922 | | // This function handles the "Multi-scan" loop. |
1923 | | |
1924 | 1.34k | Vector<Macroblock> macroblocks; |
1925 | 1.34k | TRY(macroblocks.try_resize(context.mblock_meta.padded_total)); |
1926 | | |
1927 | 1.34k | Marker marker = TRY(read_until_marker(context.stream)); |
1928 | 350k | while (true) { |
1929 | 350k | if (is_miscellaneous_or_table_marker(marker)) { |
1930 | 88.3k | TRY(handle_miscellaneous_or_table(context.stream, context, marker)); |
1931 | 262k | } else if (marker == JPEG_SOS) { |
1932 | 262k | TRY(read_start_of_scan(context.stream, context)); |
1933 | 261k | TRY(decode_huffman_stream(context, macroblocks)); |
1934 | 261k | } else if (marker == JPEG_EOI) { |
1935 | 63 | return macroblocks; |
1936 | 112 | } else { |
1937 | 112 | dbgln_if(JPEG_DEBUG, "Unexpected marker {:x}!", marker); |
1938 | 112 | return Error::from_string_literal("Unexpected marker"); |
1939 | 112 | } |
1940 | | |
1941 | 349k | marker = TRY(read_until_marker(context.stream)); |
1942 | 349k | } |
1943 | 1.34k | } |
1944 | | |
1945 | | static ErrorOr<void> decode_jpeg(JPEGLoadingContext& context) |
1946 | 1.34k | { |
1947 | 1.34k | auto macroblocks = TRY(construct_macroblocks(context)); |
1948 | 5.04M | for_each_macroblock_component(context, macroblocks, [&](Component const& component, i16* block_component) { |
1949 | 5.04M | dequantize(context, component, block_component); |
1950 | 5.04M | inverse_dct(context, block_component); |
1951 | 5.04M | }); |
1952 | 63 | undo_subsampling(context, macroblocks); |
1953 | 63 | TRY(handle_color_transform(context, macroblocks)); |
1954 | 63 | if (context.components.size() == 4) |
1955 | 5 | TRY(compose_cmyk_bitmap(context, macroblocks)); |
1956 | 58 | else |
1957 | 58 | TRY(compose_bitmap(context, macroblocks)); |
1958 | 63 | return {}; |
1959 | 63 | } |
1960 | | |
1961 | | JPEGImageDecoderPlugin::JPEGImageDecoderPlugin(NonnullOwnPtr<JPEGLoadingContext> context) |
1962 | 4.04k | : m_context(move(context)) |
1963 | 4.04k | { |
1964 | 4.04k | } |
1965 | | |
1966 | 4.04k | JPEGImageDecoderPlugin::~JPEGImageDecoderPlugin() = default; |
1967 | | |
1968 | | IntSize JPEGImageDecoderPlugin::size() |
1969 | 0 | { |
1970 | 0 | return { m_context->frame.width, m_context->frame.height }; |
1971 | 0 | } |
1972 | | |
1973 | | bool JPEGImageDecoderPlugin::sniff(ReadonlyBytes data) |
1974 | 0 | { |
1975 | 0 | return data.size() > 3 |
1976 | 0 | && data.data()[0] == 0xFF |
1977 | 0 | && data.data()[1] == 0xD8 |
1978 | 0 | && data.data()[2] == 0xFF; |
1979 | 0 | } |
1980 | | |
1981 | | ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> JPEGImageDecoderPlugin::create(ReadonlyBytes data) |
1982 | 4.04k | { |
1983 | 4.04k | return create_with_options(data, {}); |
1984 | 4.04k | } |
1985 | | |
1986 | | ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> JPEGImageDecoderPlugin::create_with_options(ReadonlyBytes data, JPEGDecoderOptions options) |
1987 | 4.04k | { |
1988 | 4.04k | auto stream = TRY(try_make<FixedMemoryStream>(data)); |
1989 | 4.04k | auto context = TRY(JPEGLoadingContext::create(move(stream), options)); |
1990 | 4.04k | auto plugin = TRY(adopt_nonnull_own_or_enomem(new (nothrow) JPEGImageDecoderPlugin(move(context)))); |
1991 | 4.04k | TRY(decode_header(*plugin->m_context)); |
1992 | 1.34k | return plugin; |
1993 | 4.04k | } |
1994 | | |
1995 | | ErrorOr<ImageFrameDescriptor> JPEGImageDecoderPlugin::frame(size_t index, Optional<IntSize>) |
1996 | 1.34k | { |
1997 | 1.34k | if (index > 0) |
1998 | 0 | return Error::from_string_literal("JPEGImageDecoderPlugin: Invalid frame index"); |
1999 | | |
2000 | 1.34k | if (m_context->state == JPEGLoadingContext::State::Error) |
2001 | 0 | return Error::from_string_literal("JPEGImageDecoderPlugin: Decoding failed"); |
2002 | | |
2003 | 1.34k | if (m_context->state < JPEGLoadingContext::State::BitmapDecoded) { |
2004 | 1.34k | if (auto result = decode_jpeg(*m_context); result.is_error()) { |
2005 | 1.29k | m_context->state = JPEGLoadingContext::State::Error; |
2006 | 1.29k | return result.release_error(); |
2007 | 1.29k | } |
2008 | 54 | m_context->state = JPEGLoadingContext::State::BitmapDecoded; |
2009 | 54 | } |
2010 | | |
2011 | 54 | if (m_context->cmyk_bitmap && !m_context->bitmap) |
2012 | 5 | return ImageFrameDescriptor { TRY(m_context->cmyk_bitmap->to_low_quality_rgb()), 0 }; |
2013 | | |
2014 | 49 | return ImageFrameDescriptor { m_context->bitmap, 0 }; |
2015 | 54 | } |
2016 | | |
2017 | | Optional<Metadata const&> JPEGImageDecoderPlugin::metadata() |
2018 | 0 | { |
2019 | 0 | if (m_context->exif_metadata) |
2020 | 0 | return *m_context->exif_metadata; |
2021 | 0 | return OptionalNone {}; |
2022 | 0 | } |
2023 | | |
2024 | | ErrorOr<Optional<ReadonlyBytes>> JPEGImageDecoderPlugin::icc_data() |
2025 | 0 | { |
2026 | 0 | if (m_context->icc_data.has_value()) |
2027 | 0 | return *m_context->icc_data; |
2028 | 0 | return OptionalNone {}; |
2029 | 0 | } |
2030 | | |
2031 | | NaturalFrameFormat JPEGImageDecoderPlugin::natural_frame_format() const |
2032 | 0 | { |
2033 | 0 | if (m_context->state == JPEGLoadingContext::State::Error) |
2034 | 0 | return NaturalFrameFormat::RGB; |
2035 | 0 | VERIFY(m_context->state >= JPEGLoadingContext::State::HeaderDecoded); |
2036 | 0 | if (m_context->components.size() == 1) |
2037 | 0 | return NaturalFrameFormat::Grayscale; |
2038 | 0 | if (m_context->components.size() == 4) |
2039 | 0 | return NaturalFrameFormat::CMYK; |
2040 | 0 | return NaturalFrameFormat::RGB; |
2041 | 0 | } |
2042 | | |
2043 | | ErrorOr<NonnullRefPtr<CMYKBitmap>> JPEGImageDecoderPlugin::cmyk_frame() |
2044 | 0 | { |
2045 | 0 | VERIFY(natural_frame_format() == NaturalFrameFormat::CMYK); |
2046 | | |
2047 | 0 | if (m_context->state < JPEGLoadingContext::State::BitmapDecoded) { |
2048 | 0 | if (auto result = decode_jpeg(*m_context); result.is_error()) { |
2049 | 0 | m_context->state = JPEGLoadingContext::State::Error; |
2050 | 0 | return result.release_error(); |
2051 | 0 | } |
2052 | 0 | m_context->state = JPEGLoadingContext::State::BitmapDecoded; |
2053 | 0 | } |
2054 | | |
2055 | 0 | return *m_context->cmyk_bitmap; |
2056 | 0 | } |
2057 | | |
2058 | | } |