/src/libjxl/lib/jxl/image_metadata.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 | | // Main codestream header bundles, the metadata that applies to all frames. |
7 | | // Enums must align with the C API definitions in codestream_header.h. |
8 | | |
9 | | #ifndef LIB_JXL_IMAGE_METADATA_H_ |
10 | | #define LIB_JXL_IMAGE_METADATA_H_ |
11 | | |
12 | | #include <stddef.h> |
13 | | #include <stdint.h> |
14 | | |
15 | | #include <string> |
16 | | #include <vector> |
17 | | |
18 | | #include "jxl/codestream_header.h" |
19 | | #include "lib/jxl/color_encoding_internal.h" |
20 | | #include "lib/jxl/fields.h" |
21 | | #include "lib/jxl/headers.h" |
22 | | #include "lib/jxl/jpeg/jpeg_data.h" |
23 | | #include "lib/jxl/opsin_params.h" |
24 | | |
25 | | namespace jxl { |
26 | | |
27 | | // EXIF orientation of the image. This field overrides any field present in |
28 | | // actual EXIF metadata. The value tells which transformation the decoder must |
29 | | // apply after decoding to display the image with the correct orientation. |
30 | | enum class Orientation : uint32_t { |
31 | | // Values 1..8 match the EXIF definitions. |
32 | | kIdentity = JXL_ORIENT_IDENTITY, |
33 | | kFlipHorizontal = JXL_ORIENT_FLIP_HORIZONTAL, |
34 | | kRotate180 = JXL_ORIENT_ROTATE_180, |
35 | | kFlipVertical = JXL_ORIENT_FLIP_VERTICAL, |
36 | | kTranspose = JXL_ORIENT_TRANSPOSE, |
37 | | kRotate90 = JXL_ORIENT_ROTATE_90_CW, |
38 | | kAntiTranspose = JXL_ORIENT_ANTI_TRANSPOSE, |
39 | | kRotate270 = JXL_ORIENT_ROTATE_90_CCW, |
40 | | }; |
41 | | // Don't need an EnumBits because Orientation is not read via Enum(). |
42 | | |
43 | | enum class ExtraChannel : uint32_t { |
44 | | // First two enumerators (most common) are cheaper to encode |
45 | | kAlpha = JXL_CHANNEL_ALPHA, |
46 | | kDepth = JXL_CHANNEL_DEPTH, |
47 | | |
48 | | kSpotColor = JXL_CHANNEL_SPOT_COLOR, |
49 | | kSelectionMask = JXL_CHANNEL_SELECTION_MASK, |
50 | | kBlack = JXL_CHANNEL_BLACK, // for CMYK |
51 | | kCFA = JXL_CHANNEL_CFA, // Bayer channel |
52 | | kThermal = JXL_CHANNEL_THERMAL, |
53 | | kReserved0 = JXL_CHANNEL_RESERVED0, |
54 | | kReserved1 = JXL_CHANNEL_RESERVED1, |
55 | | kReserved2 = JXL_CHANNEL_RESERVED2, |
56 | | kReserved3 = JXL_CHANNEL_RESERVED3, |
57 | | kReserved4 = JXL_CHANNEL_RESERVED4, |
58 | | kReserved5 = JXL_CHANNEL_RESERVED5, |
59 | | kReserved6 = JXL_CHANNEL_RESERVED6, |
60 | | kReserved7 = JXL_CHANNEL_RESERVED7, |
61 | | // disambiguated via name string, raise warning if unsupported |
62 | | kUnknown = JXL_CHANNEL_UNKNOWN, |
63 | | // like kUnknown but can silently be ignored |
64 | | kOptional = JXL_CHANNEL_OPTIONAL |
65 | | }; |
66 | 48 | static inline const char* EnumName(ExtraChannel /*unused*/) { |
67 | 48 | return "ExtraChannel"; |
68 | 48 | } Unexecuted instantiation: decode.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: decode_to_jpeg.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: entropy_coder.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: frame_header.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: icc_codec.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: icc_codec_common.cc:jxl::EnumName(jxl::ExtraChannel) image_metadata.cc:jxl::EnumName(jxl::ExtraChannel) Line | Count | Source | 66 | 48 | static inline const char* EnumName(ExtraChannel /*unused*/) { | 67 | 48 | return "ExtraChannel"; | 68 | 48 | } |
Unexecuted instantiation: dec_jpeg_data_writer.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: loop_filter.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: quant_weights.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: aux_out.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: dec_external_image.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: dec_frame.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: dec_group.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: dec_modular.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: dec_noise.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: dec_patch_dictionary.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: dec_xyb.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: epf.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: image_bundle.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: passes_state.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: render_pipeline.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: simple_render_pipeline.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: stage_upsampling.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: splines.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: blending.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: chroma_from_luma.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: coeff_order.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: compressed_dc.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: dec_cache.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: low_memory_render_pipeline.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: stage_blending.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: stage_chroma_upsampling.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: stage_epf.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: stage_from_linear.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: stage_gaborish.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: stage_noise.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: stage_patches.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: stage_splines.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: stage_spot.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: stage_to_linear.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: stage_tone_mapping.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: stage_write.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: stage_xyb.cc:jxl::EnumName(jxl::ExtraChannel) Unexecuted instantiation: stage_ycbcr.cc:jxl::EnumName(jxl::ExtraChannel) |
69 | 806k | static inline constexpr uint64_t EnumBits(ExtraChannel /*unused*/) { |
70 | 806k | using EC = ExtraChannel; |
71 | 806k | return MakeBit(EC::kAlpha) | MakeBit(EC::kDepth) | MakeBit(EC::kSpotColor) | |
72 | 806k | MakeBit(EC::kSelectionMask) | MakeBit(EC::kBlack) | MakeBit(EC::kCFA) | |
73 | 806k | MakeBit(EC::kThermal) | MakeBit(EC::kUnknown) | MakeBit(EC::kOptional); |
74 | 806k | } Unexecuted instantiation: decode.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: decode_to_jpeg.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: entropy_coder.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: frame_header.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: icc_codec.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: icc_codec_common.cc:jxl::EnumBits(jxl::ExtraChannel) image_metadata.cc:jxl::EnumBits(jxl::ExtraChannel) Line | Count | Source | 69 | 806k | static inline constexpr uint64_t EnumBits(ExtraChannel /*unused*/) { | 70 | 806k | using EC = ExtraChannel; | 71 | 806k | return MakeBit(EC::kAlpha) | MakeBit(EC::kDepth) | MakeBit(EC::kSpotColor) | | 72 | 806k | MakeBit(EC::kSelectionMask) | MakeBit(EC::kBlack) | MakeBit(EC::kCFA) | | 73 | 806k | MakeBit(EC::kThermal) | MakeBit(EC::kUnknown) | MakeBit(EC::kOptional); | 74 | 806k | } |
Unexecuted instantiation: dec_jpeg_data_writer.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: loop_filter.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: quant_weights.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: aux_out.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: dec_external_image.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: dec_frame.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: dec_group.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: dec_modular.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: dec_noise.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: dec_patch_dictionary.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: dec_xyb.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: epf.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: image_bundle.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: passes_state.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: render_pipeline.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: simple_render_pipeline.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: stage_upsampling.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: splines.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: blending.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: chroma_from_luma.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: coeff_order.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: compressed_dc.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: dec_cache.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: low_memory_render_pipeline.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: stage_blending.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: stage_chroma_upsampling.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: stage_epf.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: stage_from_linear.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: stage_gaborish.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: stage_noise.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: stage_patches.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: stage_splines.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: stage_spot.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: stage_to_linear.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: stage_tone_mapping.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: stage_write.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: stage_xyb.cc:jxl::EnumBits(jxl::ExtraChannel) Unexecuted instantiation: stage_ycbcr.cc:jxl::EnumBits(jxl::ExtraChannel) |
75 | | |
76 | | // Used in ImageMetadata and ExtraChannelInfo. |
77 | | struct BitDepth : public Fields { |
78 | | BitDepth(); |
79 | | JXL_FIELDS_NAME(BitDepth) |
80 | | |
81 | | Status VisitFields(Visitor* JXL_RESTRICT visitor) override; |
82 | | |
83 | | std::string DebugString() const; |
84 | | |
85 | | // Whether the original (uncompressed) samples are floating point or |
86 | | // unsigned integer. |
87 | | bool floating_point_sample; |
88 | | |
89 | | // Bit depth of the original (uncompressed) image samples. Must be in the |
90 | | // range [1, 32]. |
91 | | uint32_t bits_per_sample; |
92 | | |
93 | | // Floating point exponent bits of the original (uncompressed) image samples, |
94 | | // only used if floating_point_sample is true. |
95 | | // If used, the samples are floating point with: |
96 | | // - 1 sign bit |
97 | | // - exponent_bits_per_sample exponent bits |
98 | | // - (bits_per_sample - exponent_bits_per_sample - 1) mantissa bits |
99 | | // If used, exponent_bits_per_sample must be in the range |
100 | | // [2, 8] and amount of mantissa bits must be in the range [2, 23]. |
101 | | // NOTE: exponent_bits_per_sample is 8 for single precision binary32 |
102 | | // point, 5 for half precision binary16, 7 for fp24. |
103 | | uint32_t exponent_bits_per_sample; |
104 | | }; |
105 | | |
106 | | // Describes one extra channel. |
107 | | struct ExtraChannelInfo : public Fields { |
108 | | ExtraChannelInfo(); |
109 | | JXL_FIELDS_NAME(ExtraChannelInfo) |
110 | | |
111 | | Status VisitFields(Visitor* JXL_RESTRICT visitor) override; |
112 | | |
113 | | std::string DebugString() const; |
114 | | |
115 | | mutable bool all_default; |
116 | | |
117 | | ExtraChannel type; |
118 | | BitDepth bit_depth; |
119 | | uint32_t dim_shift; // downsampled by 2^dim_shift on each axis |
120 | | |
121 | | std::string name; // UTF-8 |
122 | | |
123 | | // Conditional: |
124 | | bool alpha_associated; // i.e. premultiplied |
125 | | float spot_color[4]; // spot color in linear RGBA |
126 | | uint32_t cfa_channel; |
127 | | }; |
128 | | |
129 | | struct OpsinInverseMatrix : public Fields { |
130 | | OpsinInverseMatrix(); |
131 | | JXL_FIELDS_NAME(OpsinInverseMatrix) |
132 | | |
133 | | Status VisitFields(Visitor* JXL_RESTRICT visitor) override; |
134 | | |
135 | | mutable bool all_default; |
136 | | |
137 | | float inverse_matrix[9]; |
138 | | float opsin_biases[3]; |
139 | | float quant_biases[4]; |
140 | | }; |
141 | | |
142 | | // Information useful for mapping HDR images to lower dynamic range displays. |
143 | | struct ToneMapping : public Fields { |
144 | | ToneMapping(); |
145 | | JXL_FIELDS_NAME(ToneMapping) |
146 | | |
147 | | Status VisitFields(Visitor* JXL_RESTRICT visitor) override; |
148 | | |
149 | | mutable bool all_default; |
150 | | |
151 | | // Upper bound on the intensity level present in the image. For unsigned |
152 | | // integer pixel encodings, this is the brightness of the largest |
153 | | // representable value. The image does not necessarily contain a pixel |
154 | | // actually this bright. An encoder is allowed to set 255 for SDR images |
155 | | // without computing a histogram. |
156 | | float intensity_target; // [nits] |
157 | | |
158 | | // Lower bound on the intensity level present in the image. This may be |
159 | | // loose, i.e. lower than the actual darkest pixel. When tone mapping, a |
160 | | // decoder will map [min_nits, intensity_target] to the display range. |
161 | | float min_nits; |
162 | | |
163 | | bool relative_to_max_display; // see below |
164 | | // The tone mapping will leave unchanged (linear mapping) any pixels whose |
165 | | // brightness is strictly below this. The interpretation depends on |
166 | | // relative_to_max_display. If true, this is a ratio [0, 1] of the maximum |
167 | | // display brightness [nits], otherwise an absolute brightness [nits]. |
168 | | float linear_below; |
169 | | }; |
170 | | |
171 | | // Contains weights to customize some trasnforms - in particular, XYB and |
172 | | // upsampling. |
173 | | struct CustomTransformData : public Fields { |
174 | | CustomTransformData(); |
175 | | JXL_FIELDS_NAME(CustomTransformData) |
176 | | |
177 | | Status VisitFields(Visitor* JXL_RESTRICT visitor) override; |
178 | | |
179 | | // Must be set before calling VisitFields. Must equal xyb_encoded of |
180 | | // ImageMetadata, should be set by ImageMetadata during VisitFields. |
181 | | bool nonserialized_xyb_encoded = false; |
182 | | |
183 | | mutable bool all_default; |
184 | | |
185 | | OpsinInverseMatrix opsin_inverse_matrix; |
186 | | |
187 | | uint32_t custom_weights_mask; |
188 | | float upsampling2_weights[15]; |
189 | | float upsampling4_weights[55]; |
190 | | float upsampling8_weights[210]; |
191 | | }; |
192 | | |
193 | | // Properties of the original image bundle. This enables Encode(Decode()) to |
194 | | // re-create an equivalent image without user input. |
195 | | struct ImageMetadata : public Fields { |
196 | | ImageMetadata(); |
197 | | JXL_FIELDS_NAME(ImageMetadata) |
198 | | |
199 | | Status VisitFields(Visitor* JXL_RESTRICT visitor) override; |
200 | | |
201 | | // Returns bit depth of the JPEG XL compressed alpha channel, or 0 if no alpha |
202 | | // channel present. In the theoretical case that there are multiple alpha |
203 | | // channels, returns the bit depht of the first. |
204 | 0 | uint32_t GetAlphaBits() const { |
205 | 0 | const ExtraChannelInfo* alpha = Find(ExtraChannel::kAlpha); |
206 | 0 | if (alpha == nullptr) return 0; |
207 | 0 | JXL_ASSERT(alpha->bit_depth.bits_per_sample != 0); |
208 | 0 | return alpha->bit_depth.bits_per_sample; |
209 | 0 | } |
210 | | |
211 | | // Sets bit depth of alpha channel, adding extra channel if needed, or |
212 | | // removing all alpha channels if bits is 0. |
213 | | // Assumes integer alpha channel and not designed to support multiple |
214 | | // alpha channels (it's possible to use those features by manipulating |
215 | | // extra_channel_info directly). |
216 | | // |
217 | | // Callers must insert the actual channel image at the same index before any |
218 | | // further modifications to extra_channel_info. |
219 | | void SetAlphaBits(uint32_t bits, bool alpha_is_premultiplied = false); |
220 | | |
221 | 0 | bool HasAlpha() const { return GetAlphaBits() != 0; } |
222 | | |
223 | | // Sets the original bit depth fields to indicate unsigned integer of the |
224 | | // given bit depth. |
225 | | // TODO(lode): move function to BitDepth |
226 | 0 | void SetUintSamples(uint32_t bits) { |
227 | 0 | bit_depth.bits_per_sample = bits; |
228 | 0 | bit_depth.exponent_bits_per_sample = 0; |
229 | 0 | bit_depth.floating_point_sample = false; |
230 | 0 | // RCT / Squeeze may add one bit each, and this is about int16_t, |
231 | 0 | // so uint13 should still be OK but limiting it to 12 seems safer. |
232 | 0 | // TODO(jon): figure out a better way to set this header field. |
233 | 0 | // (in particular, if modular mode is not used it doesn't matter, |
234 | 0 | // and if transforms are restricted, up to 15-bit could be done) |
235 | 0 | if (bits > 12) modular_16_bit_buffer_sufficient = false; |
236 | 0 | } |
237 | | // Sets the original bit depth fields to indicate single precision floating |
238 | | // point. |
239 | | // TODO(lode): move function to BitDepth |
240 | 0 | void SetFloat32Samples() { |
241 | 0 | bit_depth.bits_per_sample = 32; |
242 | 0 | bit_depth.exponent_bits_per_sample = 8; |
243 | 0 | bit_depth.floating_point_sample = true; |
244 | 0 | modular_16_bit_buffer_sufficient = false; |
245 | 0 | } |
246 | | |
247 | 0 | void SetFloat16Samples() { |
248 | 0 | bit_depth.bits_per_sample = 16; |
249 | 0 | bit_depth.exponent_bits_per_sample = 5; |
250 | 0 | bit_depth.floating_point_sample = true; |
251 | 0 | modular_16_bit_buffer_sufficient = false; |
252 | 0 | } |
253 | | |
254 | 0 | void SetIntensityTarget(float intensity_target) { |
255 | 0 | tone_mapping.intensity_target = intensity_target; |
256 | 0 | } |
257 | 23.0k | float IntensityTarget() const { |
258 | 23.0k | JXL_ASSERT(tone_mapping.intensity_target != 0); |
259 | 23.0k | return tone_mapping.intensity_target; |
260 | 23.0k | } |
261 | | |
262 | | // Returns first ExtraChannelInfo of the given type, or nullptr if none. |
263 | 317k | const ExtraChannelInfo* Find(ExtraChannel type) const { |
264 | 317k | for (const ExtraChannelInfo& eci : extra_channel_info) { |
265 | 176k | if (eci.type == type) return &eci; |
266 | 176k | } |
267 | 237k | return nullptr; |
268 | 317k | } |
269 | | |
270 | | // Returns first ExtraChannelInfo of the given type, or nullptr if none. |
271 | 0 | ExtraChannelInfo* Find(ExtraChannel type) { |
272 | 0 | for (ExtraChannelInfo& eci : extra_channel_info) { |
273 | 0 | if (eci.type == type) return &eci; |
274 | 0 | } |
275 | 0 | return nullptr; |
276 | 0 | } |
277 | | |
278 | 317k | Orientation GetOrientation() const { |
279 | 317k | return static_cast<Orientation>(orientation); |
280 | 317k | } |
281 | | |
282 | | bool ExtraFieldsDefault() const; |
283 | | |
284 | | std::string DebugString() const; |
285 | | |
286 | | mutable bool all_default; |
287 | | |
288 | | BitDepth bit_depth; |
289 | | bool modular_16_bit_buffer_sufficient; // otherwise 32 is. |
290 | | |
291 | | // Whether the colors values of the pixels of frames are encoded in the |
292 | | // codestream using the absolute XYB color space, or the using values that |
293 | | // follow the color space defined by the ColorEncoding or ICC profile. This |
294 | | // determines when or whether a CMS (Color Management System) is needed to get |
295 | | // the pixels in a desired color space. In one case, the pixels have one known |
296 | | // color space and a CMS is needed to convert them to the original image's |
297 | | // color space, in the other case the pixels have the color space of the |
298 | | // original image and a CMS is required if a different display space, or a |
299 | | // single known consistent color space for multiple decoded images, is |
300 | | // desired. In all cases, the color space of all frames from a single image is |
301 | | // the same, both VarDCT and modular frames. |
302 | | // |
303 | | // If true: then frames can be decoded to XYB (which can also be converted to |
304 | | // linear and non-linear sRGB with the built in conversion without CMS). The |
305 | | // attached ColorEncoding or ICC profile has no effect on the meaning of the |
306 | | // pixel's color values, but instead indicates what the color profile of the |
307 | | // original image was, and what color profile one should convert to when |
308 | | // decoding to integers to prevent clipping and precision loss. To do that |
309 | | // conversion requires a CMS. |
310 | | // |
311 | | // If false: then the color values of decoded frames are in the space defined |
312 | | // by the attached ColorEncoding or ICC profile. To instead get the pixels in |
313 | | // a chosen known color space, such as sRGB, requires a CMS, since the |
314 | | // attached ColorEncoding or ICC profile could be any arbitrary color space. |
315 | | // This mode is typically used for lossless images encoded as integers. |
316 | | // Frames can also use YCbCr encoding, some frames may and some may not, but |
317 | | // this is not a different color space but a certain encoding of the RGB |
318 | | // values. |
319 | | // |
320 | | // Note: if !xyb_encoded, but the attached color profile indicates XYB (which |
321 | | // can happen either if it's a ColorEncoding with color_space_ == |
322 | | // ColorSpace::kXYB, or if it's an ICC Profile that has been crafted to |
323 | | // represent XYB), then the frames still may not use ColorEncoding kXYB, they |
324 | | // must still use kNone (or kYCbCr, which would mean applying the YCbCr |
325 | | // transform to the 3-channel XYB data), since with !xyb_encoded, the 3 |
326 | | // channels are stored as-is, no matter what meaning the color profile assigns |
327 | | // to them. To use ColorEncoding::kXYB, xyb_encoded must be true. |
328 | | // |
329 | | // This value is defined in image metadata because this is the global |
330 | | // codestream header. This value does not affect the image itself, so is not |
331 | | // image metadata per se, it only affects the encoding, and what color space |
332 | | // the decoder can receive the pixels in without needing a CMS. |
333 | | bool xyb_encoded; |
334 | | |
335 | | ColorEncoding color_encoding; |
336 | | |
337 | | // These values are initialized to defaults such that the 'extra_fields' |
338 | | // condition in VisitFields uses correctly initialized values. |
339 | | uint32_t orientation = 1; |
340 | | bool have_preview = false; |
341 | | bool have_animation = false; |
342 | | bool have_intrinsic_size = false; |
343 | | |
344 | | // If present, the stored image has the dimensions of the first SizeHeader, |
345 | | // but decoders are advised to resample or display per `intrinsic_size`. |
346 | | SizeHeader intrinsic_size; // only if have_intrinsic_size |
347 | | |
348 | | ToneMapping tone_mapping; |
349 | | |
350 | | // When reading: deserialized. When writing: automatically set from vector. |
351 | | uint32_t num_extra_channels; |
352 | | std::vector<ExtraChannelInfo> extra_channel_info; |
353 | | |
354 | | // Only present if m.have_preview. |
355 | | PreviewHeader preview_size; |
356 | | // Only present if m.have_animation. |
357 | | AnimationHeader animation; |
358 | | |
359 | | uint64_t extensions; |
360 | | |
361 | | // Option to stop parsing after basic info, and treat as if the later |
362 | | // fields do not participate. Use to parse only basic image information |
363 | | // excluding the final larger or variable sized data. |
364 | | bool nonserialized_only_parse_basic_info = false; |
365 | | }; |
366 | | |
367 | | Status ReadImageMetadata(BitReader* JXL_RESTRICT reader, |
368 | | ImageMetadata* JXL_RESTRICT metadata); |
369 | | |
370 | | Status WriteImageMetadata(const ImageMetadata& metadata, |
371 | | BitWriter* JXL_RESTRICT writer, size_t layer, |
372 | | AuxOut* aux_out); |
373 | | |
374 | | // All metadata applicable to the entire codestream (dimensions, extra channels, |
375 | | // ...) |
376 | | struct CodecMetadata { |
377 | | // TODO(lode): use the preview and animation fields too, in place of the |
378 | | // nonserialized_ ones in ImageMetadata. |
379 | | ImageMetadata m; |
380 | | // The size of the codestream: this is the nominal size applicable to all |
381 | | // frames, although some frames can have a different effective size through |
382 | | // crop, dc_level or representing a the preview. |
383 | | SizeHeader size; |
384 | | // Often default. |
385 | | CustomTransformData transform_data; |
386 | | |
387 | 596k | size_t xsize() const { return size.xsize(); } |
388 | 596k | size_t ysize() const { return size.ysize(); } |
389 | 93.7k | size_t oriented_xsize(bool keep_orientation) const { |
390 | 93.7k | if (static_cast<uint32_t>(m.GetOrientation()) > 4 && !keep_orientation) { |
391 | 7.76k | return ysize(); |
392 | 85.9k | } else { |
393 | 85.9k | return xsize(); |
394 | 85.9k | } |
395 | 93.7k | } |
396 | 28.2k | size_t oriented_preview_xsize(bool keep_orientation) const { |
397 | 28.2k | if (static_cast<uint32_t>(m.GetOrientation()) > 4 && !keep_orientation) { |
398 | 11.1k | return m.preview_size.ysize(); |
399 | 17.0k | } else { |
400 | 17.0k | return m.preview_size.xsize(); |
401 | 17.0k | } |
402 | 28.2k | } |
403 | 93.7k | size_t oriented_ysize(bool keep_orientation) const { |
404 | 93.7k | if (static_cast<uint32_t>(m.GetOrientation()) > 4 && !keep_orientation) { |
405 | 7.76k | return xsize(); |
406 | 85.9k | } else { |
407 | 85.9k | return ysize(); |
408 | 85.9k | } |
409 | 93.7k | } |
410 | 28.2k | size_t oriented_preview_ysize(bool keep_orientation) const { |
411 | 28.2k | if (static_cast<uint32_t>(m.GetOrientation()) > 4 && !keep_orientation) { |
412 | 11.1k | return m.preview_size.xsize(); |
413 | 17.0k | } else { |
414 | 17.0k | return m.preview_size.ysize(); |
415 | 17.0k | } |
416 | 28.2k | } |
417 | | |
418 | | std::string DebugString() const; |
419 | | }; |
420 | | |
421 | | } // namespace jxl |
422 | | |
423 | | #endif // LIB_JXL_IMAGE_METADATA_H_ |