/src/libheif/libheif/image/image_description.h
Line | Count | Source |
1 | | /* |
2 | | * HEIF codec. |
3 | | * Copyright (c) 2026 Dirk Farin <dirk.farin@gmail.com> |
4 | | * |
5 | | * This file is part of libheif. |
6 | | * |
7 | | * libheif is free software: you can redistribute it and/or modify |
8 | | * it under the terms of the GNU Lesser General Public License as |
9 | | * published by the Free Software Foundation, either version 3 of |
10 | | * the License, or (at your option) any later version. |
11 | | * |
12 | | * libheif is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public License |
18 | | * along with libheif. If not, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #ifndef LIBHEIF_IMAGE_DESCRIPTION_H |
22 | | #define LIBHEIF_IMAGE_DESCRIPTION_H |
23 | | |
24 | | #include "error.h" |
25 | | #include "nclx.h" |
26 | | #include <libheif/heif_experimental.h> |
27 | | #include <libheif/heif_uncompressed.h> |
28 | | #include "omaf_boxes.h" |
29 | | |
30 | | #include <cassert> |
31 | | #include <map> |
32 | | #include <memory> |
33 | | #include <optional> |
34 | | #include <string> |
35 | | #include <vector> |
36 | | #include <algorithm> |
37 | | #include <utility> |
38 | | |
39 | | |
40 | | // === === Bayer pattern |
41 | | |
42 | | // --- Bayer pattern expressed as ISO 23001-17 cmpd component indices |
43 | | |
44 | | struct BayerPatternPixelCmpd |
45 | | { |
46 | | uint32_t cmpd_index; |
47 | | float component_gain; |
48 | | }; |
49 | | |
50 | | struct BayerPatternCmpd |
51 | | { |
52 | | uint16_t pattern_width = 0; |
53 | | uint16_t pattern_height = 0; |
54 | | std::vector<BayerPatternPixelCmpd> pixels; |
55 | | }; |
56 | | |
57 | | // --- Bayer pattern expressed as libheif components IDs |
58 | | |
59 | | struct BayerPattern |
60 | | { |
61 | | uint16_t pattern_width = 0; |
62 | | uint16_t pattern_height = 0; |
63 | | std::vector<heif_bayer_pattern_pixel> pixels; |
64 | | |
65 | | [[nodiscard]] BayerPatternCmpd resolve_to_cmpd(std::map<uint32_t, uint32_t> comp_id_to_cmpd) const; |
66 | | }; |
67 | | |
68 | | |
69 | | // === Polarization pattern (ISO 23001-17) |
70 | | |
71 | | struct PolarizationPattern |
72 | | { |
73 | | std::vector<uint32_t> component_ids; // empty = applies to all components. Either cmpd-index or component-id, depending on context. |
74 | | uint16_t pattern_width = 0; |
75 | | uint16_t pattern_height = 0; |
76 | | std::vector<float> polarization_angles; // pattern_width * pattern_height entries |
77 | | // 0xFFFFFFFF bit-pattern (NaN) = no polarization filter |
78 | | }; |
79 | | |
80 | | |
81 | | // === Sensor bad pixels map (ISO 23001-17) |
82 | | |
83 | | struct SensorBadPixelsMap |
84 | | { |
85 | | struct BadPixelCoordinate |
86 | | { |
87 | | uint32_t row, column; |
88 | | }; |
89 | | |
90 | | std::vector<uint32_t> component_ids; // empty = applies to all components. Either cmpd-index or component-id, depending on context. |
91 | | bool correction_applied = false; |
92 | | std::vector<uint32_t> bad_rows; |
93 | | std::vector<uint32_t> bad_columns; |
94 | | std::vector<BadPixelCoordinate> bad_pixels; |
95 | | }; |
96 | | |
97 | | |
98 | | // === Sensor non-uniformity correction (ISO 23001-17) |
99 | | |
100 | | struct SensorNonUniformityCorrection |
101 | | { |
102 | | std::vector<uint32_t> component_ids; // empty = applies to all components. Either cmpd-index or component-id, depending on context. |
103 | | bool nuc_is_applied = false; |
104 | | uint32_t image_width = 0; |
105 | | uint32_t image_height = 0; |
106 | | std::vector<float> nuc_gains; // image_width * image_height entries |
107 | | std::vector<float> nuc_offsets; // image_width * image_height entries |
108 | | }; |
109 | | |
110 | | |
111 | | |
112 | | // === Image components |
113 | | |
114 | | // Given a list of libheif component IDs, map them to a list of cmpd IDs through the given map. |
115 | | // The output does not contain duplicates and is in no particular order. |
116 | | std::vector<uint32_t> map_component_ids_to_cmpd(const std::vector<uint32_t>& component_ids, const std::map<uint32_t, uint32_t>& comp_id_to_cmpd); |
117 | | |
118 | | // Map a list of unci component indices to libheif components. |
119 | | // Use to find the libheif components for a metadata box that assigns it through cmpd indices. |
120 | | // The output does not contain duplicates and is in no particular order. |
121 | | std::vector<uint32_t> map_cmpd_to_component_ids(const std::vector<uint32_t>& cmpd_indices, const std::vector<std::vector<uint32_t>>& cmpd_to_comp_ids); |
122 | | |
123 | | // Find the closest matching heif_channel for an ISO 23001-17 component type. |
124 | | // Returns heif_channel_unknown if no good mapping exists. |
125 | | heif_channel map_uncompressed_component_to_channel(uint16_t component_type); |
126 | | |
127 | | |
128 | | // Per-component description, independent of pixel data. |
129 | | // Lives on ImageDescription so both ImageItem (handle side, before decoding) |
130 | | // and HeifPixelImage (decoded side) can carry the same structural view. |
131 | | struct ComponentDescription |
132 | | { |
133 | | uint32_t component_id = 0; // stable id, matches HeifPixelImage::m_storage ids |
134 | | |
135 | | heif_channel channel = heif_channel_unknown; |
136 | | uint16_t component_type = 0; // heif_cmpd_component_type_* |
137 | | |
138 | | // The numeric values of heif_component_datatype are aligned with the |
139 | | // ISO 23001-17 Table 2 component_format byte (from the uncC box), so on |
140 | | // the unci read path this field directly holds the file byte and on the |
141 | | // write path it is emitted as the file byte. For non-unci codecs |
142 | | // (HEVC/AVIF/JPEG/...) the codec sets this to the appropriate value |
143 | | // (typically heif_component_datatype_unsigned_integer). |
144 | | heif_component_datatype datatype = heif_component_datatype_undefined; |
145 | | |
146 | | uint16_t bit_depth = 0; // logical bit depth (1..256) |
147 | | uint32_t width = 0; |
148 | | uint32_t height = 0; |
149 | | bool has_data_plane = true; // false for cpat reference colors |
150 | | |
151 | | // Empty string means "no content id assigned". |
152 | | std::string gimi_content_id; |
153 | | }; |
154 | | |
155 | | |
156 | | class ImageDescription |
157 | | { |
158 | | public: |
159 | | virtual ~ImageDescription(); |
160 | | |
161 | | // TODO: Decide who is responsible for writing the colr boxes. |
162 | | // Currently it is distributed over various places. |
163 | | // Either here, in image_item.cc or in grid.cc. |
164 | | std::vector<std::shared_ptr<Box>> generate_property_boxes(bool generate_colr_boxes) const; |
165 | | |
166 | | |
167 | | // --- color profile |
168 | | |
169 | | bool has_nclx_color_profile() const; |
170 | | |
171 | 76.0k | virtual void set_color_profile_nclx(const nclx_profile& profile) { m_color_profile_nclx = profile; } |
172 | | |
173 | 264k | nclx_profile get_color_profile_nclx() const { return m_color_profile_nclx; } |
174 | | |
175 | | // get the stored nclx fallback or return the default nclx if none is stored |
176 | | nclx_profile get_color_profile_nclx_with_fallback() const; |
177 | | |
178 | 18.5k | virtual void set_color_profile_icc(const std::shared_ptr<const color_profile_raw>& profile) { m_color_profile_icc = profile; } |
179 | | |
180 | 15.7k | bool has_icc_color_profile() const { return m_color_profile_icc != nullptr; } |
181 | | |
182 | 108k | const std::shared_ptr<const color_profile_raw>& get_color_profile_icc() const { return m_color_profile_icc; } |
183 | | |
184 | | void set_color_profile(const std::shared_ptr<const color_profile>& profile) |
185 | 33.1k | { |
186 | 33.1k | auto icc = std::dynamic_pointer_cast<const color_profile_raw>(profile); |
187 | 33.1k | if (icc) { |
188 | 15.7k | set_color_profile_icc(icc); |
189 | 15.7k | } |
190 | | |
191 | 33.1k | auto nclx = std::dynamic_pointer_cast<const color_profile_nclx>(profile); |
192 | 33.1k | if (nclx) { |
193 | 17.3k | set_color_profile_nclx(nclx->get_nclx_color_profile()); |
194 | 17.3k | } |
195 | 33.1k | } |
196 | | |
197 | | |
198 | | // --- premultiplied alpha |
199 | | |
200 | 0 | bool is_premultiplied_alpha() const { return m_premultiplied_alpha; } |
201 | | |
202 | 0 | virtual void set_premultiplied_alpha(bool flag) { m_premultiplied_alpha = flag; } |
203 | | |
204 | | |
205 | | // --- pixel aspect ratio |
206 | | |
207 | 0 | bool has_nonsquare_pixel_ratio() const { return m_PixelAspectRatio_h != m_PixelAspectRatio_v; } |
208 | | |
209 | | void get_pixel_ratio(uint32_t* h, uint32_t* v) const |
210 | 0 | { |
211 | 0 | *h = m_PixelAspectRatio_h; |
212 | 0 | *v = m_PixelAspectRatio_v; |
213 | 0 | } |
214 | | |
215 | | virtual void set_pixel_ratio(uint32_t h, uint32_t v) |
216 | 261 | { |
217 | 261 | m_PixelAspectRatio_h = h; |
218 | 261 | m_PixelAspectRatio_v = v; |
219 | 261 | } |
220 | | |
221 | | // --- clli |
222 | | |
223 | 0 | bool has_clli() const { return m_clli.max_content_light_level != 0 || m_clli.max_pic_average_light_level != 0; } |
224 | | |
225 | 0 | heif_content_light_level get_clli() const { return m_clli; } |
226 | | |
227 | 1 | virtual void set_clli(const heif_content_light_level& clli) { m_clli = clli; } |
228 | | |
229 | | // --- mdcv |
230 | | |
231 | 0 | bool has_mdcv() const { return m_mdcv.has_value(); } |
232 | | |
233 | 0 | heif_mastering_display_colour_volume get_mdcv() const { return *m_mdcv; } |
234 | | |
235 | | virtual void set_mdcv(const heif_mastering_display_colour_volume& mdcv) |
236 | 0 | { |
237 | 0 | m_mdcv = mdcv; |
238 | 0 | } |
239 | | |
240 | 0 | void unset_mdcv() { m_mdcv.reset(); } |
241 | | |
242 | | // --- amve (ambient viewing environment) |
243 | | |
244 | 0 | bool has_amve() const { return m_amve.has_value(); } |
245 | | |
246 | 0 | heif_ambient_viewing_environment get_amve() const { return *m_amve; } |
247 | | |
248 | | virtual void set_amve(const heif_ambient_viewing_environment& amve) |
249 | 0 | { |
250 | 0 | m_amve = amve; |
251 | 0 | } |
252 | | |
253 | 0 | void unset_amve() { m_amve.reset(); } |
254 | | |
255 | | // --- ndwt (nominal diffuse white) |
256 | | |
257 | | // Note: a luminance of 0 is a valid value (it selects the ISO/TS 22028-5 |
258 | | // default), so presence is tracked separately from the value via std::optional. |
259 | | |
260 | 0 | bool has_nominal_diffuse_white() const { return m_nominal_diffuse_white_luminance.has_value(); } |
261 | | |
262 | | // Nominal diffuse white luminance in units of 0.0001 cd/m^2. |
263 | 0 | uint32_t get_nominal_diffuse_white_luminance() const { return m_nominal_diffuse_white_luminance.value_or(0); } |
264 | | |
265 | | virtual void set_nominal_diffuse_white_luminance(uint32_t luminance) |
266 | 0 | { |
267 | 0 | m_nominal_diffuse_white_luminance = luminance; |
268 | 0 | } |
269 | | |
270 | 0 | void unset_nominal_diffuse_white() { m_nominal_diffuse_white_luminance.reset(); } |
271 | | |
272 | 0 | virtual Error set_tai_timestamp(const heif_tai_timestamp_packet* tai) { |
273 | 0 | delete m_tai_timestamp; |
274 | |
|
275 | 0 | m_tai_timestamp = heif_tai_timestamp_packet_alloc(); |
276 | 0 | heif_tai_timestamp_packet_copy(m_tai_timestamp, tai); |
277 | 0 | return Error::Ok; |
278 | 0 | } |
279 | | |
280 | 0 | [[nodiscard]] const heif_tai_timestamp_packet* get_tai_timestamp() const { |
281 | 0 | return m_tai_timestamp; |
282 | 0 | } |
283 | | |
284 | | // --- GIMI content ID |
285 | | |
286 | 0 | virtual void set_gimi_sample_content_id(std::string id) { m_gimi_sample_content_id = std::move(id); } |
287 | | |
288 | 0 | [[nodiscard]] bool has_gimi_sample_content_id() const { return !m_gimi_sample_content_id.empty(); } |
289 | | |
290 | 0 | [[nodiscard]] const std::string& get_gimi_sample_content_id() const { return m_gimi_sample_content_id; } |
291 | | |
292 | | |
293 | | [[nodiscard]] bool has_component_content_ids() const |
294 | 0 | { |
295 | 0 | return std::any_of(m_components.begin(), m_components.end(), |
296 | 0 | [](const ComponentDescription& c) { return !c.gimi_content_id.empty(); }); |
297 | 0 | } |
298 | | |
299 | | // Returns a positional vector: entry i is m_components[i].gimi_content_id |
300 | | // (empty string if unset). Returned by value because it is reconstructed. |
301 | | [[nodiscard]] std::vector<std::string> get_component_content_ids() const |
302 | 0 | { |
303 | 0 | std::vector<std::string> ids; |
304 | 0 | ids.reserve(m_components.size()); |
305 | 0 | for (const auto& c : m_components) { |
306 | 0 | ids.push_back(c.gimi_content_id); |
307 | 0 | } |
308 | 0 | return ids; |
309 | 0 | } |
310 | | |
311 | | |
312 | | // --- per-component descriptions (id-based) |
313 | | // These describe each component independent of pixel storage. Both ImageItem |
314 | | // (before decoding) and HeifPixelImage (after decoding) carry the same list. |
315 | | |
316 | 243k | [[nodiscard]] const std::vector<ComponentDescription>& get_component_descriptions() const { return m_components; } |
317 | | |
318 | | // Append a ComponentDescription. The caller is expected to have set |
319 | | // component_id, either from a fresh mint_component_id() call or by |
320 | | // matching an id already used by a parallel structure (e.g. |
321 | | // HeifPixelImage::ComponentStorage::m_component_ids). |
322 | | void add_component_description(ComponentDescription desc) |
323 | 392k | { |
324 | 392k | m_components.push_back(std::move(desc)); |
325 | 392k | } |
326 | | |
327 | | // Bulk-replace the component descriptions and sync the next-id allocator. |
328 | | // Used by clone/apply paths that rebuild the whole list at once. |
329 | | void set_component_descriptions(std::vector<ComponentDescription> components, uint32_t next_id) |
330 | 3.63k | { |
331 | 3.63k | m_components = std::move(components); |
332 | 3.63k | m_next_component_id = next_id; |
333 | 3.63k | } |
334 | | |
335 | | // Erase the description matching this component_id. Returns true if one was |
336 | | // removed. |
337 | | bool remove_component_description(uint32_t component_id) |
338 | 48 | { |
339 | 48 | auto it = std::find_if(m_components.begin(), m_components.end(), |
340 | 48 | [component_id](const ComponentDescription& c) { |
341 | 48 | return c.component_id == component_id; |
342 | 48 | }); |
343 | 48 | if (it == m_components.end()) return false; |
344 | 48 | m_components.erase(it); |
345 | 48 | return true; |
346 | 48 | } |
347 | | |
348 | | // Mint a fresh component id (monotonically increasing, starting at 1). |
349 | 392k | [[nodiscard]] uint32_t mint_component_id() { return m_next_component_id++; } |
350 | | |
351 | | // Read-only view of the next id that mint_component_id() would return. |
352 | | // Used by HeifPixelImage::clone_component_descriptions_from() to keep the |
353 | | // counter aligned across an item-to-image clone. |
354 | 3.63k | [[nodiscard]] uint32_t peek_next_component_id() const { return m_next_component_id; } |
355 | | |
356 | | [[nodiscard]] ComponentDescription* find_component_description(uint32_t component_id) |
357 | 5.67k | { |
358 | 11.5k | for (auto& c : m_components) { |
359 | 11.5k | if (c.component_id == component_id) return &c; |
360 | 11.5k | } |
361 | 0 | return nullptr; |
362 | 5.67k | } |
363 | | |
364 | | [[nodiscard]] const ComponentDescription* find_component_description(uint32_t component_id) const |
365 | 1.33k | { |
366 | 2.65k | for (const auto& c : m_components) { |
367 | 2.65k | if (c.component_id == component_id) return &c; |
368 | 2.65k | } |
369 | 0 | return nullptr; |
370 | 1.33k | } |
371 | | |
372 | | |
373 | | // --- bayer pattern |
374 | | |
375 | 0 | bool has_bayer_pattern(uint32_t component_id) const { return m_bayer_pattern.has_value(); } |
376 | | |
377 | 0 | bool has_any_bayer_pattern() const { return m_bayer_pattern.has_value(); } |
378 | | |
379 | 0 | const BayerPattern& get_bayer_pattern(uint32_t component_id) const { assert(has_bayer_pattern(component_id)); return *m_bayer_pattern; } |
380 | | |
381 | 0 | const BayerPattern& get_any_bayer_pattern() const { assert(has_any_bayer_pattern()); return *m_bayer_pattern; } |
382 | | |
383 | 0 | virtual void set_bayer_pattern(const BayerPattern& pattern) { m_bayer_pattern = pattern; } |
384 | | |
385 | | |
386 | | // --- polarization pattern |
387 | | |
388 | 0 | bool has_polarization_patterns() const { return !m_polarization_patterns.empty(); } |
389 | | |
390 | 0 | const std::vector<PolarizationPattern>& get_polarization_patterns() const { return m_polarization_patterns; } |
391 | | |
392 | 0 | virtual void set_polarization_patterns(const std::vector<PolarizationPattern>& p) { m_polarization_patterns = p; } |
393 | | |
394 | 0 | virtual void add_polarization_pattern(const PolarizationPattern& p) { m_polarization_patterns.push_back(p); } |
395 | | |
396 | | |
397 | | // --- sensor bad pixels map |
398 | | |
399 | 0 | bool has_sensor_bad_pixels_maps() const { return !m_sensor_bad_pixels_maps.empty(); } |
400 | | |
401 | 0 | const std::vector<SensorBadPixelsMap>& get_sensor_bad_pixels_maps() const { return m_sensor_bad_pixels_maps; } |
402 | | |
403 | 0 | virtual void set_sensor_bad_pixels_maps(const std::vector<SensorBadPixelsMap>& m) { m_sensor_bad_pixels_maps = m; } |
404 | | |
405 | 0 | virtual void add_sensor_bad_pixels_map(const SensorBadPixelsMap& m) { m_sensor_bad_pixels_maps.push_back(m); } |
406 | | |
407 | | |
408 | | // --- sensor non-uniformity correction |
409 | | |
410 | 0 | bool has_sensor_nuc() const { return !m_sensor_nuc.empty(); } |
411 | | |
412 | 0 | const std::vector<SensorNonUniformityCorrection>& get_sensor_nuc() const { return m_sensor_nuc; } |
413 | | |
414 | 0 | virtual void set_sensor_nuc(const std::vector<SensorNonUniformityCorrection>& n) { m_sensor_nuc = n; } |
415 | | |
416 | 0 | virtual void add_sensor_nuc(const SensorNonUniformityCorrection& n) { m_sensor_nuc.push_back(n); } |
417 | | |
418 | | |
419 | | // --- chroma sample location (ISO 23001-17, Section 6.1.4) |
420 | | |
421 | 0 | bool has_chroma_location() const { return m_chroma_location.has_value(); } |
422 | | |
423 | 0 | uint8_t get_chroma_location() const { return m_chroma_location.value_or(0); } |
424 | | |
425 | 0 | virtual void set_chroma_location(uint8_t loc) { m_chroma_location = loc; } |
426 | | |
427 | | |
428 | | // --- sample duration (for images that are frames in a sequence) |
429 | | // 0 means "no duration assigned" (the default for still images). |
430 | | |
431 | 0 | void set_sample_duration(uint32_t d) { m_sample_duration = d; } |
432 | | |
433 | 0 | uint32_t get_sample_duration() const { return m_sample_duration; } |
434 | | |
435 | | |
436 | 0 | bool has_omaf_image_projection() const { |
437 | 0 | return (m_omaf_image_projection != heif_omaf_image_projection_flat); |
438 | 0 | } |
439 | | |
440 | 0 | const heif_omaf_image_projection get_omaf_image_projection() const { |
441 | 0 | return m_omaf_image_projection; |
442 | 0 | } |
443 | | |
444 | 0 | virtual void set_omaf_image_projection(const heif_omaf_image_projection projection) { |
445 | 0 | m_omaf_image_projection = projection; |
446 | 0 | } |
447 | | |
448 | | // Copies all per-image metadata from `other` (color profiles, premultiplied |
449 | | // alpha, pixel aspect ratio, clli, mdcv, tai timestamp, gimi sample content |
450 | | // id, bayer pattern, polarization patterns, sensor maps, sensor nuc, chroma |
451 | | // location, omaf projection). Per-component descriptions |
452 | | // (m_components / m_next_component_id) are intentionally not copied; those |
453 | | // are managed separately by callers (via add_channel / add_component, or |
454 | | // set_component_descriptions on the destination). |
455 | | // |
456 | | // Bayer / polarization / sensor-map metadata refers to image geometry; |
457 | | // transforms that change orientation or position copy them verbatim and |
458 | | // would need separate geometry adjustment to remain semantically correct. |
459 | | void copy_metadata_from(const ImageDescription& other); |
460 | | |
461 | | private: |
462 | | bool m_premultiplied_alpha = false; |
463 | | nclx_profile m_color_profile_nclx = nclx_profile::undefined(); |
464 | | std::shared_ptr<const color_profile_raw> m_color_profile_icc; |
465 | | |
466 | | uint32_t m_PixelAspectRatio_h = 1; |
467 | | uint32_t m_PixelAspectRatio_v = 1; |
468 | | heif_content_light_level m_clli{}; |
469 | | std::optional<heif_mastering_display_colour_volume> m_mdcv; |
470 | | std::optional<heif_ambient_viewing_environment> m_amve; |
471 | | std::optional<uint32_t> m_nominal_diffuse_white_luminance; |
472 | | |
473 | | heif_tai_timestamp_packet* m_tai_timestamp = nullptr; |
474 | | |
475 | | // Empty string means "no content id assigned". |
476 | | std::string m_gimi_sample_content_id; |
477 | | |
478 | | // Per-component description vector. Single source of truth for per-component |
479 | | // metadata (id, channel, type, format, datatype, bit depth, dims, content ID). |
480 | | std::vector<ComponentDescription> m_components; |
481 | | |
482 | | // ID allocator for the per-component descriptions above. Used both by |
483 | | // HeifPixelImage (decoded side) and ImageItem (handle side) via the |
484 | | // mint_component_id() / peek_next_component_id() accessors. |
485 | | uint32_t m_next_component_id = 1; |
486 | | |
487 | | std::optional<BayerPattern> m_bayer_pattern; |
488 | | |
489 | | std::vector<PolarizationPattern> m_polarization_patterns; |
490 | | |
491 | | std::vector<SensorBadPixelsMap> m_sensor_bad_pixels_maps; |
492 | | |
493 | | std::vector<SensorNonUniformityCorrection> m_sensor_nuc; |
494 | | |
495 | | std::optional<uint8_t> m_chroma_location; |
496 | | |
497 | | uint32_t m_sample_duration = 0; // duration of a sequence frame, 0 for stills |
498 | | |
499 | | heif_omaf_image_projection m_omaf_image_projection = heif_omaf_image_projection::heif_omaf_image_projection_flat; |
500 | | |
501 | | protected: |
502 | | std::shared_ptr<Box_clli> create_clli_box() const; |
503 | | |
504 | | std::shared_ptr<Box_mdcv> create_mdcv_box() const; |
505 | | |
506 | | std::shared_ptr<Box_amve> create_amve_box() const; |
507 | | |
508 | | std::shared_ptr<Box_ndwt> create_ndwt_box() const; |
509 | | |
510 | | std::shared_ptr<Box_pasp> create_pasp_box() const; |
511 | | |
512 | | std::shared_ptr<Box_colr> create_colr_box_nclx() const; |
513 | | |
514 | | std::shared_ptr<Box_colr> create_colr_box_icc() const; |
515 | | |
516 | | std::shared_ptr<Box_prfr> create_prfr_box() const; |
517 | | }; |
518 | | |
519 | | #endif |