/src/libheif/libheif/codecs/uncompressed/unc_boxes.h
Line | Count | Source |
1 | | /* |
2 | | * HEIF codec. |
3 | | * Copyright (c) 2023 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 | | |
22 | | #ifndef LIBHEIF_UNC_BOXES_H |
23 | | #define LIBHEIF_UNC_BOXES_H |
24 | | |
25 | | #include "box.h" |
26 | | #include "bitstream.h" |
27 | | #include "pixelimage.h" |
28 | | #include "unc_types.h" |
29 | | #include "sequences/seq_boxes.h" |
30 | | |
31 | | #include <cstdint> |
32 | | #include <string> |
33 | | #include <vector> |
34 | | #include <memory> |
35 | | #include <utility> |
36 | | |
37 | | |
38 | | /** |
39 | | * Component definition (cmpd) box. |
40 | | */ |
41 | | class Box_cmpd : public Box |
42 | | { |
43 | | public: |
44 | | Box_cmpd() |
45 | 0 | { |
46 | 0 | set_short_type(fourcc("cmpd")); |
47 | 0 | } |
48 | | |
49 | | std::string dump(Indent&) const override; |
50 | | |
51 | | Error write(StreamWriter& writer) const override; |
52 | | |
53 | 0 | bool is_essential() const override { return true; } |
54 | | |
55 | | struct Component |
56 | | { |
57 | | uint16_t component_type; |
58 | | std::string component_type_uri; |
59 | | |
60 | 0 | std::string get_component_type_name() const { return get_component_type_name(component_type); } |
61 | | |
62 | | static std::string get_component_type_name(uint16_t type); |
63 | | }; |
64 | | |
65 | 0 | const std::vector<Component>& get_components() const { return m_components; } |
66 | | |
67 | | bool has_component(heif_uncompressed_component_type) const; |
68 | | |
69 | | uint16_t add_component(const Component& component) |
70 | 0 | { |
71 | 0 | auto index = static_cast<uint16_t>(m_components.size()); |
72 | 0 | m_components.push_back(component); |
73 | 0 | return index; |
74 | 0 | } |
75 | | |
76 | | void set_components(const std::vector<uint16_t>&); |
77 | | |
78 | | protected: |
79 | | Error parse(BitstreamRange& range, const heif_security_limits* limits) override; |
80 | | |
81 | | std::vector<Component> m_components; |
82 | | }; |
83 | | |
84 | | /** |
85 | | * Uncompressed Frame Configuration Box |
86 | | */ |
87 | | class Box_uncC : public FullBox |
88 | | { |
89 | | public: |
90 | 0 | Box_uncC() { |
91 | 0 | set_short_type(fourcc("uncC")); |
92 | 0 | } |
93 | | |
94 | 0 | bool is_essential() const override { return true; } |
95 | | |
96 | | bool is_minimized() const |
97 | 0 | { |
98 | 0 | return m_profile != 0 && m_num_tile_cols==1 && m_num_tile_rows==1; |
99 | 0 | } |
100 | | |
101 | | void derive_box_version() override |
102 | 0 | { |
103 | 0 | set_version(is_minimized() ? 1 : 0); |
104 | 0 | } |
105 | | |
106 | | std::string dump(Indent&) const override; |
107 | | |
108 | | Error write(StreamWriter& writer) const override; |
109 | | |
110 | | struct Component |
111 | | { |
112 | | uint32_t component_index; |
113 | | uint16_t component_bit_depth; // range [1..256] |
114 | | uint8_t component_format; |
115 | | uint8_t component_align_size; |
116 | | }; |
117 | | |
118 | 0 | const std::vector<Component>& get_components() const { return m_components; } |
119 | | |
120 | | void add_component(Component component) |
121 | 0 | { |
122 | 0 | m_components.push_back(component); |
123 | 0 | } |
124 | | |
125 | 0 | uint32_t get_profile() const { return m_profile; } |
126 | | |
127 | | void set_profile(const uint32_t profile) |
128 | 0 | { |
129 | 0 | m_profile = profile; |
130 | 0 | } |
131 | | |
132 | 0 | uint8_t get_sampling_type() const { return m_sampling_type; } |
133 | | |
134 | | void set_sampling_type(const uint8_t sampling_type) |
135 | 0 | { |
136 | 0 | m_sampling_type = sampling_type; |
137 | 0 | } |
138 | | |
139 | 0 | uint8_t get_interleave_type() const { return m_interleave_type; } |
140 | | |
141 | | void set_interleave_type(const uint8_t interleave_type) |
142 | 0 | { |
143 | 0 | m_interleave_type = interleave_type; |
144 | 0 | } |
145 | | |
146 | 0 | uint8_t get_block_size() const { return m_block_size; } |
147 | | |
148 | | void set_block_size(const uint8_t block_size) |
149 | 0 | { |
150 | 0 | m_block_size = block_size; |
151 | 0 | } |
152 | | |
153 | 0 | bool is_components_little_endian() const { return m_components_little_endian; } |
154 | | |
155 | | void set_components_little_endian (const bool components_little_endian) |
156 | 0 | { |
157 | 0 | m_components_little_endian = components_little_endian; |
158 | 0 | } |
159 | | |
160 | 0 | bool is_block_pad_lsb() const { return m_block_pad_lsb; } |
161 | | |
162 | | void set_block_pad_lsb(const bool block_pad_lsb) |
163 | 0 | { |
164 | 0 | m_block_pad_lsb = block_pad_lsb; |
165 | 0 | } |
166 | | |
167 | 0 | bool is_block_little_endian() const { return m_block_little_endian; } |
168 | | |
169 | | void set_block_little_endian(const bool block_little_endian) |
170 | 0 | { |
171 | 0 | m_block_little_endian = block_little_endian; |
172 | 0 | } |
173 | | |
174 | 0 | bool is_block_reversed() const { return m_block_reversed; } |
175 | | |
176 | | void set_block_reversed(const bool block_reversed) |
177 | 0 | { |
178 | 0 | m_block_reversed = block_reversed; |
179 | 0 | } |
180 | | |
181 | 0 | bool is_pad_unknown() const { return m_pad_unknown; } |
182 | | |
183 | | void set_pad_unknown(const bool pad_unknown) |
184 | 0 | { |
185 | 0 | m_pad_unknown = pad_unknown; |
186 | 0 | } |
187 | | |
188 | 0 | uint32_t get_pixel_size() const { return m_pixel_size; } |
189 | | |
190 | | void set_pixel_size(const uint32_t pixel_size) |
191 | 0 | { |
192 | 0 | m_pixel_size = pixel_size; |
193 | 0 | } |
194 | | |
195 | 0 | uint32_t get_row_align_size() const { return m_row_align_size; } |
196 | | |
197 | | void set_row_align_size(const uint32_t row_align_size) |
198 | 0 | { |
199 | 0 | m_row_align_size = row_align_size; |
200 | 0 | } |
201 | | |
202 | 0 | uint32_t get_tile_align_size() const { return m_tile_align_size; } |
203 | | |
204 | | void set_tile_align_size(const uint32_t tile_align_size) |
205 | 0 | { |
206 | 0 | m_tile_align_size = tile_align_size; |
207 | 0 | } |
208 | | |
209 | 0 | uint32_t get_number_of_tile_columns() const { return m_num_tile_cols; } |
210 | | |
211 | | void set_number_of_tile_columns(const uint32_t num_tile_cols) |
212 | 0 | { |
213 | 0 | m_num_tile_cols = num_tile_cols; |
214 | 0 | } |
215 | | |
216 | 0 | uint32_t get_number_of_tile_rows() const { return m_num_tile_rows; } |
217 | | |
218 | | void set_number_of_tile_rows(const uint32_t num_tile_rows) |
219 | 0 | { |
220 | 0 | m_num_tile_rows = num_tile_rows; |
221 | 0 | } |
222 | | |
223 | 0 | uint32_t get_number_of_tiles() const { return m_num_tile_rows * m_num_tile_rows; } |
224 | | |
225 | 0 | std::shared_ptr<Box_cmpd> get_synthetic_cmpd() const { return m_synthetic_cmpd; } |
226 | | |
227 | 0 | void set_synthetic_cmpd(std::shared_ptr<Box_cmpd> cmpd) { m_synthetic_cmpd = std::move(cmpd); } |
228 | | |
229 | | protected: |
230 | | Error parse(BitstreamRange& range, const heif_security_limits* limits) override; |
231 | | |
232 | | uint32_t m_profile = 0; // 0 = not compliant to any profile |
233 | | |
234 | | std::vector<Component> m_components; |
235 | | uint8_t m_sampling_type = sampling_mode_no_subsampling; // no subsampling |
236 | | uint8_t m_interleave_type = interleave_mode_pixel; // component interleaving |
237 | | uint8_t m_block_size = 0; |
238 | | bool m_components_little_endian = false; |
239 | | bool m_block_pad_lsb = false; |
240 | | bool m_block_little_endian = false; |
241 | | bool m_block_reversed = false; |
242 | | bool m_pad_unknown = false; |
243 | | uint32_t m_pixel_size = 0; |
244 | | uint32_t m_row_align_size = 0; |
245 | | uint32_t m_tile_align_size = 0; |
246 | | uint32_t m_num_tile_cols = 1; |
247 | | uint32_t m_num_tile_rows = 1; |
248 | | |
249 | | std::shared_ptr<Box_cmpd> m_synthetic_cmpd; |
250 | | }; |
251 | | |
252 | | |
253 | | enum heif_cmpC_compressed_unit_type { |
254 | | heif_cmpC_compressed_unit_type_full_item = 0, |
255 | | heif_cmpC_compressed_unit_type_image = 1, |
256 | | heif_cmpC_compressed_unit_type_image_tile = 2, |
257 | | heif_cmpC_compressed_unit_type_image_row = 3, |
258 | | heif_cmpC_compressed_unit_type_image_pixel = 4 |
259 | | }; |
260 | | |
261 | | /** |
262 | | * Generic compression configuration box (cmpC). |
263 | | * |
264 | | * This is from ISO/IEC 23001-17 Amd 2. |
265 | | */ |
266 | | class Box_cmpC : public FullBox |
267 | | { |
268 | | public: |
269 | | Box_cmpC() |
270 | 0 | { |
271 | 0 | set_short_type(fourcc("cmpC")); |
272 | 0 | } |
273 | | |
274 | | std::string dump(Indent&) const override; |
275 | | |
276 | 0 | uint32_t get_compression_type() const { return m_compression_type; } |
277 | | |
278 | 0 | heif_cmpC_compressed_unit_type get_compressed_unit_type() const { return m_compressed_unit_type; } |
279 | | |
280 | 0 | void set_compression_type(uint32_t type) { m_compression_type = type; } |
281 | | |
282 | 0 | void set_compressed_unit_type(heif_cmpC_compressed_unit_type type) { m_compressed_unit_type = type; } |
283 | | |
284 | | Error write(StreamWriter& writer) const override; |
285 | | |
286 | | protected: |
287 | | Error parse(BitstreamRange& range, const heif_security_limits* limits) override; |
288 | | |
289 | | uint32_t m_compression_type = 0; |
290 | | heif_cmpC_compressed_unit_type m_compressed_unit_type = heif_cmpC_compressed_unit_type_full_item; |
291 | | }; |
292 | | |
293 | | /** |
294 | | * Generically compressed units item info (icef). |
295 | | * |
296 | | * This describes the units of compressed data for an item. |
297 | | * |
298 | | * The box is from ISO/IEC 23001-17 Amd 2. |
299 | | */ |
300 | | class Box_icef : public FullBox |
301 | | { |
302 | | public: |
303 | | Box_icef() |
304 | 0 | { |
305 | 0 | set_short_type(fourcc("icef")); |
306 | 0 | } |
307 | | |
308 | | struct CompressedUnitInfo |
309 | | { |
310 | | uint64_t unit_offset = 0; |
311 | | uint64_t unit_size = 0; |
312 | | }; |
313 | | |
314 | 0 | const std::vector<CompressedUnitInfo>& get_units() const { return m_unit_infos; } |
315 | | |
316 | | void add_component(const CompressedUnitInfo& unit_info) |
317 | 0 | { |
318 | 0 | m_unit_infos.push_back(unit_info); |
319 | 0 | } |
320 | | |
321 | | void set_component(uint32_t tile_idx, const CompressedUnitInfo& unit_info) |
322 | 0 | { |
323 | 0 | if (tile_idx >= m_unit_infos.size()) { |
324 | 0 | m_unit_infos.resize(tile_idx+1); |
325 | 0 | } |
326 | 0 |
|
327 | 0 | m_unit_infos[tile_idx] = unit_info; |
328 | 0 | } |
329 | | |
330 | | std::string dump(Indent&) const override; |
331 | | |
332 | | Error write(StreamWriter& writer) const override; |
333 | | |
334 | | protected: |
335 | | Error parse(BitstreamRange& range, const heif_security_limits* limits) override; |
336 | | |
337 | | std::vector<CompressedUnitInfo> m_unit_infos; |
338 | | |
339 | | private: |
340 | | const uint8_t get_required_offset_code(uint64_t offset) const; |
341 | | const uint8_t get_required_size_code(uint64_t size) const; |
342 | | }; |
343 | | |
344 | | |
345 | | /** |
346 | | * Component pattern definition box (cpat). |
347 | | * |
348 | | * The component pattern is used when representing filter array |
349 | | * data, such as Bayer. It defines the filter mask in the raw |
350 | | * data. |
351 | | * |
352 | | * This is from ISO/IEC 23001-17 Section 6.1.3. |
353 | | */ |
354 | | class Box_cpat : public FullBox |
355 | | { |
356 | | public: |
357 | | Box_cpat() |
358 | 0 | { |
359 | 0 | set_short_type(fourcc("cpat")); |
360 | 0 | } |
361 | | |
362 | 0 | uint16_t get_pattern_width() const { return m_pattern.pattern_width; } |
363 | | |
364 | 0 | uint16_t get_pattern_height() const { return m_pattern.pattern_height; } |
365 | | |
366 | 0 | const BayerPattern& get_pattern() const { return m_pattern; } |
367 | | |
368 | 0 | void set_pattern(const BayerPattern& pattern) { m_pattern = pattern; } |
369 | | |
370 | | std::string dump(Indent&) const override; |
371 | | |
372 | | Error write(StreamWriter& writer) const override; |
373 | | |
374 | | protected: |
375 | | Error parse(BitstreamRange& range, const heif_security_limits* limits) override; |
376 | | |
377 | | BayerPattern m_pattern; |
378 | | }; |
379 | | |
380 | | |
381 | | /** |
382 | | * Polarization pattern definition box (splz). |
383 | | * |
384 | | * Describes the polarization filter array pattern on an image sensor. |
385 | | * Multiple splz boxes can exist (one per set of components with |
386 | | * different polarization filters). |
387 | | * |
388 | | * This is from ISO/IEC 23001-17 Section 6.1.5. |
389 | | */ |
390 | | class Box_splz : public FullBox |
391 | | { |
392 | | public: |
393 | 0 | Box_splz() { set_short_type(fourcc("splz")); } |
394 | | |
395 | 0 | const PolarizationPattern& get_pattern() const { return m_pattern; } |
396 | | |
397 | 0 | void set_pattern(const PolarizationPattern& pattern) { m_pattern = pattern; } |
398 | | |
399 | | std::string dump(Indent&) const override; |
400 | | |
401 | | Error write(StreamWriter& writer) const override; |
402 | | |
403 | | protected: |
404 | | Error parse(BitstreamRange& range, const heif_security_limits* limits) override; |
405 | | |
406 | | PolarizationPattern m_pattern; |
407 | | }; |
408 | | |
409 | | |
410 | | /** |
411 | | * Sensor bad pixels map box (sbpm). |
412 | | * |
413 | | * Identifies bad pixels on a sensor for which at least one component |
414 | | * value is corrupted. Supports bad rows, bad columns, and individual |
415 | | * bad pixel coordinates. |
416 | | * |
417 | | * This is from ISO/IEC 23001-17 Section 6.1.7. |
418 | | */ |
419 | | class Box_sbpm : public FullBox |
420 | | { |
421 | | public: |
422 | 0 | Box_sbpm() { set_short_type(fourcc("sbpm")); } |
423 | | |
424 | 0 | const SensorBadPixelsMap& get_bad_pixels_map() const { return m_map; } |
425 | 0 | void set_bad_pixels_map(const SensorBadPixelsMap& map) { m_map = map; } |
426 | | |
427 | | std::string dump(Indent&) const override; |
428 | | Error write(StreamWriter& writer) const override; |
429 | | |
430 | | protected: |
431 | | Error parse(BitstreamRange& range, const heif_security_limits* limits) override; |
432 | | |
433 | | SensorBadPixelsMap m_map; |
434 | | }; |
435 | | |
436 | | |
437 | | /** |
438 | | * Sensor non-uniformity correction box (snuc). |
439 | | * |
440 | | * Provides per-pixel gain and offset tables for sensor non-uniformity |
441 | | * correction. The correction equation is: y = nuc_gain * x + nuc_offset. |
442 | | * |
443 | | * This is from ISO/IEC 23001-17 Section 6.1.6. |
444 | | */ |
445 | | class Box_snuc : public FullBox |
446 | | { |
447 | | public: |
448 | 0 | Box_snuc() { set_short_type(fourcc("snuc")); } |
449 | | |
450 | 0 | const SensorNonUniformityCorrection& get_nuc() const { return m_nuc; } |
451 | 0 | void set_nuc(const SensorNonUniformityCorrection& nuc) { m_nuc = nuc; } |
452 | | |
453 | | std::string dump(Indent&) const override; |
454 | | Error write(StreamWriter& writer) const override; |
455 | | |
456 | | protected: |
457 | | Error parse(BitstreamRange& range, const heif_security_limits* limits) override; |
458 | | |
459 | | MemoryHandle m_memory_handle; |
460 | | SensorNonUniformityCorrection m_nuc; |
461 | | }; |
462 | | |
463 | | |
464 | | /** |
465 | | * Chroma location box (cloc). |
466 | | * |
467 | | * Signals the chroma sample position for subsampled images. |
468 | | * |
469 | | * This is from ISO/IEC 23001-17 Section 6.1.4. |
470 | | */ |
471 | | class Box_cloc : public FullBox |
472 | | { |
473 | | public: |
474 | 0 | Box_cloc() { set_short_type(fourcc("cloc")); } |
475 | | |
476 | 0 | uint8_t get_chroma_location() const { return m_chroma_location; } |
477 | 0 | void set_chroma_location(uint8_t loc) { m_chroma_location = loc; } |
478 | | |
479 | | std::string dump(Indent&) const override; |
480 | | Error write(StreamWriter& writer) const override; |
481 | | |
482 | | protected: |
483 | | Error parse(BitstreamRange& range, const heif_security_limits* limits) override; |
484 | | |
485 | | uint8_t m_chroma_location = 0; |
486 | | }; |
487 | | |
488 | | |
489 | | void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC, |
490 | | std::shared_ptr<Box_cmpd>& cmpd); |
491 | | |
492 | | |
493 | | class Box_uncv : public Box_VisualSampleEntry |
494 | | { |
495 | | public: |
496 | | Box_uncv() |
497 | 0 | { |
498 | 0 | set_short_type(fourcc("uncv")); |
499 | 0 | } |
500 | | }; |
501 | | |
502 | | |
503 | | /** |
504 | | * GIMI ItemComponentContentIDProperty. |
505 | | * |
506 | | * A UUID-type item property that assigns a unique Content ID string |
507 | | * to each cmpd component of an image item. |
508 | | * |
509 | | * UUID: 9db9dd6e-373c-5a4e-8110-21fc83a911fd |
510 | | */ |
511 | | class Box_gimi_component_content_ids : public Box |
512 | | { |
513 | | public: |
514 | | Box_gimi_component_content_ids() |
515 | 0 | { |
516 | 0 | set_uuid_type(std::vector<uint8_t>{0x9d, 0xb9, 0xdd, 0x6e, 0x37, 0x3c, 0x5a, 0x4e, |
517 | 0 | 0x81, 0x10, 0x21, 0xfc, 0x83, 0xa9, 0x11, 0xfd}); |
518 | 0 | } |
519 | | |
520 | 0 | bool is_essential() const override { return false; } |
521 | | |
522 | 0 | bool is_transformative_property() const override { return false; } |
523 | | |
524 | | std::string dump(Indent&) const override; |
525 | | |
526 | 0 | const char* debug_box_name() const override { return "GIMI Component Content IDs"; } |
527 | | |
528 | 0 | const std::vector<std::string>& get_content_ids() const { return m_content_ids; } |
529 | | |
530 | 0 | void set_content_ids(const std::vector<std::string>& ids) { m_content_ids = ids; } |
531 | | |
532 | 0 | [[nodiscard]] parse_error_fatality get_parse_error_fatality() const override { return parse_error_fatality::ignorable; } |
533 | | |
534 | | protected: |
535 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
536 | | |
537 | | Error write(StreamWriter& writer) const override; |
538 | | |
539 | | private: |
540 | | std::vector<std::string> m_content_ids; |
541 | | }; |
542 | | |
543 | | |
544 | | #endif //LIBHEIF_UNC_BOXES_H |