Coverage Report

Created: 2024-05-21 06:41

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