/src/libjxl/lib/jxl/jpeg/jpeg_data.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) the JPEG XL Project Authors. All rights reserved. |
2 | | // |
3 | | // Use of this source code is governed by a BSD-style |
4 | | // license that can be found in the LICENSE file. |
5 | | |
6 | | // Data structures that represent the non-pixel contents of a jpeg file. |
7 | | |
8 | | #ifndef LIB_JXL_JPEG_JPEG_DATA_H_ |
9 | | #define LIB_JXL_JPEG_JPEG_DATA_H_ |
10 | | |
11 | | #include <array> |
12 | | #include <cstddef> |
13 | | #include <cstdint> |
14 | | #include <vector> |
15 | | |
16 | | #include "lib/jxl/base/status.h" |
17 | | #include "lib/jxl/common.h" // JPEGXL_ENABLE_TRANSCODE_JPEG |
18 | | #include "lib/jxl/field_encodings.h" |
19 | | #include "lib/jxl/fields.h" |
20 | | #include "lib/jxl/frame_dimensions.h" |
21 | | |
22 | | namespace jxl { |
23 | | namespace jpeg { |
24 | | |
25 | | constexpr int kMaxComponents = 4; |
26 | | constexpr int kMaxQuantTables = 4; |
27 | | constexpr int kMaxHuffmanTables = 4; |
28 | | constexpr size_t kJpegHuffmanMaxBitLength = 16; |
29 | | constexpr int kJpegHuffmanAlphabetSize = 256; |
30 | | constexpr int kJpegDCAlphabetSize = 12; |
31 | | constexpr int kMaxDHTMarkers = 512; |
32 | | constexpr int kMaxDimPixels = 65535; |
33 | | constexpr uint8_t kApp1 = 0xE1; |
34 | | constexpr uint8_t kApp2 = 0xE2; |
35 | | const uint8_t kIccProfileTag[12] = "ICC_PROFILE"; |
36 | | const uint8_t kExifTag[6] = "Exif\0"; |
37 | | const uint8_t kXMPTag[29] = "http://ns.adobe.com/xap/1.0/"; |
38 | | |
39 | | /* clang-format off */ |
40 | | constexpr uint32_t kJPEGNaturalOrder[80] = { |
41 | | 0, 1, 8, 16, 9, 2, 3, 10, |
42 | | 17, 24, 32, 25, 18, 11, 4, 5, |
43 | | 12, 19, 26, 33, 40, 48, 41, 34, |
44 | | 27, 20, 13, 6, 7, 14, 21, 28, |
45 | | 35, 42, 49, 56, 57, 50, 43, 36, |
46 | | 29, 22, 15, 23, 30, 37, 44, 51, |
47 | | 58, 59, 52, 45, 38, 31, 39, 46, |
48 | | 53, 60, 61, 54, 47, 55, 62, 63, |
49 | | // extra entries for safety in decoder |
50 | | 63, 63, 63, 63, 63, 63, 63, 63, |
51 | | 63, 63, 63, 63, 63, 63, 63, 63 |
52 | | }; |
53 | | |
54 | | constexpr uint32_t kJPEGZigZagOrder[64] = { |
55 | | 0, 1, 5, 6, 14, 15, 27, 28, |
56 | | 2, 4, 7, 13, 16, 26, 29, 42, |
57 | | 3, 8, 12, 17, 25, 30, 41, 43, |
58 | | 9, 11, 18, 24, 31, 40, 44, 53, |
59 | | 10, 19, 23, 32, 39, 45, 52, 54, |
60 | | 20, 22, 33, 38, 46, 51, 55, 60, |
61 | | 21, 34, 37, 47, 50, 56, 59, 61, |
62 | | 35, 36, 48, 49, 57, 58, 62, 63 |
63 | | }; |
64 | | /* clang-format on */ |
65 | | |
66 | | // Quantization values for an 8x8 pixel block. |
67 | | struct JPEGQuantTable { |
68 | | std::array<int32_t, kDCTBlockSize> values; |
69 | | uint32_t precision = 0; |
70 | | // The index of this quantization table as it was parsed from the input JPEG. |
71 | | // Each DQT marker segment contains an 'index' field, and we save this index |
72 | | // here. Valid values are 0 to 3. |
73 | | uint32_t index = 0; |
74 | | // Set to true if this table is the last one within its marker segment. |
75 | | bool is_last = true; |
76 | | }; |
77 | | |
78 | | // Huffman code and decoding lookup table used for DC and AC coefficients. |
79 | | struct JPEGHuffmanCode { |
80 | | // Bit length histogram. |
81 | | std::array<uint32_t, kJpegHuffmanMaxBitLength + 1> counts = {}; |
82 | | // Symbol values sorted by increasing bit lengths. |
83 | | std::array<uint32_t, kJpegHuffmanAlphabetSize + 1> values = {}; |
84 | | // The index of the Huffman code in the current set of Huffman codes. For AC |
85 | | // component Huffman codes, 0x10 is added to the index. |
86 | | int slot_id = 0; |
87 | | // Set to true if this Huffman code is the last one within its marker segment. |
88 | | bool is_last = true; |
89 | | }; |
90 | | |
91 | | // Huffman table indexes used for one component of one scan. |
92 | | struct JPEGComponentScanInfo { |
93 | | uint32_t comp_idx; |
94 | | uint32_t dc_tbl_idx; |
95 | | uint32_t ac_tbl_idx; |
96 | | }; |
97 | | |
98 | | // Contains information that is used in one scan. |
99 | | struct JPEGScanInfo { |
100 | | // Parameters used for progressive scans (named the same way as in the spec): |
101 | | // Ss : Start of spectral band in zig-zag sequence. |
102 | | // Se : End of spectral band in zig-zag sequence. |
103 | | // Ah : Successive approximation bit position, high. |
104 | | // Al : Successive approximation bit position, low. |
105 | | uint32_t Ss; |
106 | | uint32_t Se; |
107 | | uint32_t Ah; |
108 | | uint32_t Al; |
109 | | uint32_t num_components = 0; |
110 | | std::array<JPEGComponentScanInfo, 4> components; |
111 | | // Last codestream pass that is needed to write this scan. |
112 | | uint32_t last_needed_pass = 0; |
113 | | |
114 | | // Extra information required for bit-precise JPEG file reconstruction. |
115 | | |
116 | | // Set of block indexes where the JPEG encoder has to flush the end-of-block |
117 | | // runs and refinement bits. |
118 | | std::vector<uint32_t> reset_points; |
119 | | // The number of extra zero runs (Huffman symbol 0xf0) before the end of |
120 | | // block (if nonzero), indexed by block index. |
121 | | // All of these symbols can be omitted without changing the pixel values, but |
122 | | // some jpeg encoders put these at the end of blocks. |
123 | | struct ExtraZeroRunInfo { |
124 | | uint32_t block_idx; |
125 | | uint32_t num_extra_zero_runs; |
126 | | }; |
127 | | std::vector<ExtraZeroRunInfo> extra_zero_runs; |
128 | | }; |
129 | | |
130 | | using coeff_t = int16_t; |
131 | | |
132 | | // Represents one component of a jpeg file. |
133 | | struct JPEGComponent { |
134 | | JPEGComponent() |
135 | 0 | : id(0), |
136 | 0 | h_samp_factor(1), |
137 | 0 | v_samp_factor(1), |
138 | 0 | quant_idx(0), |
139 | 0 | width_in_blocks(0), |
140 | 0 | height_in_blocks(0) {} |
141 | | |
142 | | // One-byte id of the component. |
143 | | uint32_t id; |
144 | | // Horizontal and vertical sampling factors. |
145 | | // In interleaved mode, each minimal coded unit (MCU) has |
146 | | // h_samp_factor x v_samp_factor DCT blocks from this component. |
147 | | int h_samp_factor; |
148 | | int v_samp_factor; |
149 | | // The index of the quantization table used for this component. |
150 | | uint32_t quant_idx; |
151 | | // The dimensions of the component measured in 8x8 blocks. |
152 | | uint32_t width_in_blocks; |
153 | | uint32_t height_in_blocks; |
154 | | // The DCT coefficients of this component, laid out block-by-block, divided |
155 | | // through the quantization matrix values. |
156 | | std::vector<coeff_t> coeffs; |
157 | | }; |
158 | | |
159 | | enum class AppMarkerType : uint32_t { |
160 | | kUnknown = 0, |
161 | | kICC = 1, |
162 | | kExif = 2, |
163 | | kXMP = 3, |
164 | | }; |
165 | | |
166 | | // Represents a parsed jpeg file. |
167 | | struct JPEGData : public Fields { |
168 | | JPEGData() |
169 | 0 | : width(0), height(0), restart_interval(0), has_zero_padding_bit(false) {} |
170 | | |
171 | | JXL_FIELDS_NAME(JPEGData) |
172 | | #if JPEGXL_ENABLE_TRANSCODE_JPEG |
173 | | // Doesn't serialize everything - skips brotli-encoded data and what is |
174 | | // already encoded in the codestream. |
175 | | Status VisitFields(Visitor* visitor) override; |
176 | | #else |
177 | | Status VisitFields(Visitor* /* visitor */) override { |
178 | | return JXL_UNREACHABLE("JPEG transcoding support not enabled"); |
179 | | } |
180 | | #endif // JPEGXL_ENABLE_TRANSCODE_JPEG |
181 | | |
182 | | void CalculateMcuSize(const JPEGScanInfo& scan, int* MCUs_per_row, |
183 | | int* MCU_rows) const; |
184 | | |
185 | | int width; |
186 | | int height; |
187 | | uint32_t restart_interval; |
188 | | std::vector<std::vector<uint8_t>> app_data; |
189 | | std::vector<AppMarkerType> app_marker_type; |
190 | | std::vector<std::vector<uint8_t>> com_data; |
191 | | std::vector<JPEGQuantTable> quant; |
192 | | std::vector<JPEGHuffmanCode> huffman_code; |
193 | | std::vector<JPEGComponent> components; |
194 | | std::vector<JPEGScanInfo> scan_info; |
195 | | std::vector<uint8_t> marker_order; |
196 | | std::vector<std::vector<uint8_t>> inter_marker_data; |
197 | | std::vector<uint8_t> tail_data; |
198 | | |
199 | | // Extra information required for bit-precise JPEG file reconstruction. |
200 | | |
201 | | bool has_zero_padding_bit; |
202 | | std::vector<uint8_t> padding_bits; |
203 | | }; |
204 | | |
205 | | #if JPEGXL_ENABLE_TRANSCODE_JPEG |
206 | | // Set ICC profile in jpeg_data. |
207 | | Status SetJPEGDataFromICC(const std::vector<uint8_t>& icc, |
208 | | jpeg::JPEGData* jpeg_data); |
209 | | #else |
210 | | static JXL_INLINE Status SetJPEGDataFromICC( |
211 | | const std::vector<uint8_t>& /* icc */, jpeg::JPEGData* /* jpeg_data */) { |
212 | | return JXL_UNREACHABLE("JPEG transcoding support not enabled"); |
213 | | } |
214 | | #endif // JPEGXL_ENABLE_TRANSCODE_JPEG |
215 | | |
216 | | } // namespace jpeg |
217 | | } // namespace jxl |
218 | | |
219 | | #endif // LIB_JXL_JPEG_JPEG_DATA_H_ |