Coverage Report

Created: 2022-08-24 06:33

/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_