/src/libheif/libheif/image-items/image_item.h
Line | Count | Source |
1 | | /* |
2 | | * HEIF image base codec. |
3 | | * Copyright (c) 2024 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_IMAGEITEM_H |
22 | | #define LIBHEIF_IMAGEITEM_H |
23 | | |
24 | | #include "api/libheif/heif.h" |
25 | | #include "error.h" |
26 | | #include "nclx.h" |
27 | | #include <string> |
28 | | #include <vector> |
29 | | #include <memory> |
30 | | #include <mutex> |
31 | | #include <utility> |
32 | | #include <set> |
33 | | |
34 | | #include "image/pixelimage.h" |
35 | | #include "api/libheif/heif_plugin.h" |
36 | | #include "codecs/encoder.h" |
37 | | |
38 | | |
39 | | class HeifContext; |
40 | | |
41 | | class HeifPixelImage; |
42 | | |
43 | | |
44 | | class ImageMetadata |
45 | | { |
46 | | public: |
47 | | heif_item_id item_id; |
48 | | std::string item_type; // e.g. "Exif" |
49 | | std::string content_type; |
50 | | std::string item_uri_type; |
51 | | std::vector<uint8_t> m_data; |
52 | | }; |
53 | | |
54 | | |
55 | | class ImageItem : public ImageDescription, |
56 | | public ErrorBuffer |
57 | | { |
58 | | public: |
59 | | ImageItem(HeifContext* ctx); |
60 | | |
61 | | ImageItem(HeifContext* ctx, heif_item_id id); |
62 | | |
63 | | static std::shared_ptr<ImageItem> alloc_for_infe_box(HeifContext*, const std::shared_ptr<Box_infe>&); |
64 | | |
65 | | static std::shared_ptr<ImageItem> alloc_for_compression_format(HeifContext*, heif_compression_format); |
66 | | |
67 | | static heif_compression_format compression_format_from_fourcc_infe_type(uint32_t type); |
68 | | |
69 | | static uint32_t compression_format_to_fourcc_infe_type(heif_compression_format); |
70 | | |
71 | 0 | virtual uint32_t get_infe_type() const { return 0; } |
72 | | |
73 | 0 | virtual const char* get_auxC_alpha_channel_type() const { return "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha"; } |
74 | | |
75 | 0 | virtual bool is_ispe_essential() const { return false; } |
76 | | |
77 | | bool is_property_essential(const std::shared_ptr<Box>& property) const; |
78 | | |
79 | 72.6k | virtual Error get_item_error() const { return Error::Ok; } |
80 | | |
81 | 0 | virtual heif_compression_format get_compression_format() const { return heif_compression_undefined; } |
82 | | |
83 | 0 | virtual Result<std::vector<uint8_t>> read_bitstream_configuration_data() const { return std::vector<uint8_t>{}; } |
84 | | |
85 | | void clear() |
86 | 18.6k | { |
87 | 18.6k | m_thumbnails.clear(); |
88 | 18.6k | m_alpha_channel.reset(); |
89 | 18.6k | m_depth_channel.reset(); |
90 | 18.6k | m_aux_images.clear(); |
91 | 18.6k | } |
92 | | |
93 | 14.1k | HeifContext* get_context() { return m_heif_context; } |
94 | | |
95 | 46.7k | const HeifContext* get_context() const { return m_heif_context; } |
96 | | |
97 | | std::shared_ptr<class HeifFile> get_file() const; |
98 | | |
99 | 20.0k | void set_properties(std::vector<std::shared_ptr<Box>> properties) { |
100 | 20.0k | m_properties = std::move(properties); |
101 | | // Codec-config-independent populate (e.g. unci, which reads cmpd/uncC |
102 | | // directly off the just-set property boxes). Visual codecs leave |
103 | | // m_components empty here; their populate runs after initialize_decoder() |
104 | | // because they need codec config (colorspace, bit depth) which only the |
105 | | // decoder can read. |
106 | 20.0k | populate_component_descriptions(); |
107 | 20.0k | } |
108 | | |
109 | | // Populate the inherited ImageDescription::m_components from the just-set |
110 | | // property boxes / codec config. The unci subclass overrides this and |
111 | | // reads cmpd/uncC directly. The base implementation handles visual codecs |
112 | | // (HEVC/AVC/AVIF/JPEG/JPEG2000/VVC) by querying get_coded_image_colorspace() |
113 | | // + get_luma_bits_per_pixel() + get_chroma_bits_per_pixel() and emitting |
114 | | // Y/Cb/Cr or R/G/B / monochrome descriptions in canonical order. |
115 | | // Idempotent: skips work if m_components is already populated. |
116 | | // Alpha-from-aux (separate alpha item linked via auxl) is *not* emitted |
117 | | // here; the alpha plane is attached at decode time via |
118 | | // transfer_channel_from_image_as, which mints its own component on the |
119 | | // destination. |
120 | | virtual void populate_component_descriptions(); |
121 | | |
122 | | // Populate this item's m_components by cloning descriptions from a child |
123 | | // item (e.g. tili's tile item, grid/iden/iovl's first child) and rescaling |
124 | | // per-component dims from the child's logical size to this item's full |
125 | | // image (ispe) size. Returns true on success. Returns false (and leaves |
126 | | // m_components untouched) if the child has no descriptions or sizes are |
127 | | // unusable, so the caller can fall back to the base populate. |
128 | | bool populate_descriptions_from_child(const class ImageItem& child, |
129 | | uint32_t child_w, uint32_t child_h); |
130 | | |
131 | | template<class BoxType> |
132 | | std::shared_ptr<BoxType> get_property() const |
133 | 84.5k | { |
134 | 195k | for (auto& property : m_properties) { |
135 | 195k | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { |
136 | 49.5k | return box; |
137 | 49.5k | } |
138 | 195k | } |
139 | | |
140 | 35.0k | return nullptr; |
141 | 84.5k | } std::__1::shared_ptr<Box_clli> ImageItem::get_property<Box_clli>() const Line | Count | Source | 133 | 629 | { | 134 | 2.76k | for (auto& property : m_properties) { | 135 | 2.76k | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 0 | return box; | 137 | 0 | } | 138 | 2.76k | } | 139 | | | 140 | 629 | return nullptr; | 141 | 629 | } |
std::__1::shared_ptr<Box_mdcv> ImageItem::get_property<Box_mdcv>() const Line | Count | Source | 133 | 629 | { | 134 | 2.76k | for (auto& property : m_properties) { | 135 | 2.76k | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 0 | return box; | 137 | 0 | } | 138 | 2.76k | } | 139 | | | 140 | 629 | return nullptr; | 141 | 629 | } |
std::__1::shared_ptr<Box_gimi_content_id> ImageItem::get_property<Box_gimi_content_id>() const Line | Count | Source | 133 | 14.2k | { | 134 | 40.8k | for (auto& property : m_properties) { | 135 | 40.8k | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 0 | return box; | 137 | 0 | } | 138 | 40.8k | } | 139 | | | 140 | 14.2k | return nullptr; | 141 | 14.2k | } |
std::__1::shared_ptr<Box_prfr> ImageItem::get_property<Box_prfr>() const Line | Count | Source | 133 | 14.2k | { | 134 | 40.8k | for (auto& property : m_properties) { | 135 | 40.8k | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 14 | return box; | 137 | 14 | } | 138 | 40.8k | } | 139 | | | 140 | 14.2k | return nullptr; | 141 | 14.2k | } |
std::__1::shared_ptr<Box_auxC> ImageItem::get_property<Box_auxC>() const Line | Count | Source | 133 | 131 | { | 134 | 386 | for (auto& property : m_properties) { | 135 | 386 | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 120 | return box; | 137 | 120 | } | 138 | 386 | } | 139 | | | 140 | 11 | return nullptr; | 141 | 131 | } |
Unexecuted instantiation: std::__1::shared_ptr<Box_taic> ImageItem::get_property<Box_taic>() const std::__1::shared_ptr<Box_itai> ImageItem::get_property<Box_itai>() const Line | Count | Source | 133 | 629 | { | 134 | 2.76k | for (auto& property : m_properties) { | 135 | 2.76k | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 0 | return box; | 137 | 0 | } | 138 | 2.76k | } | 139 | | | 140 | 629 | return nullptr; | 141 | 629 | } |
std::__1::shared_ptr<Box_pasp> ImageItem::get_property<Box_pasp>() const Line | Count | Source | 133 | 629 | { | 134 | 2.76k | for (auto& property : m_properties) { | 135 | 2.76k | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 0 | return box; | 137 | 0 | } | 138 | 2.76k | } | 139 | | | 140 | 629 | return nullptr; | 141 | 629 | } |
std::__1::shared_ptr<Box_ispe> ImageItem::get_property<Box_ispe>() const Line | Count | Source | 133 | 39.6k | { | 134 | 79.9k | for (auto& property : m_properties) { | 135 | 79.9k | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 36.7k | return box; | 137 | 36.7k | } | 138 | 79.9k | } | 139 | | | 140 | 2.90k | return nullptr; | 141 | 39.6k | } |
std::__1::shared_ptr<Box_mskC> ImageItem::get_property<Box_mskC>() const Line | Count | Source | 133 | 422 | { | 134 | 1.20k | for (auto& property : m_properties) { | 135 | 1.20k | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 403 | return box; | 137 | 403 | } | 138 | 1.20k | } | 139 | | | 140 | 19 | return nullptr; | 141 | 422 | } |
std::__1::shared_ptr<Box_jpgC> ImageItem::get_property<Box_jpgC>() const Line | Count | Source | 133 | 152 | { | 134 | 458 | for (auto& property : m_properties) { | 135 | 458 | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 0 | return box; | 137 | 0 | } | 138 | 458 | } | 139 | | | 140 | 152 | return nullptr; | 141 | 152 | } |
std::__1::shared_ptr<Box_hvcC> ImageItem::get_property<Box_hvcC>() const Line | Count | Source | 133 | 11.6k | { | 134 | 16.2k | for (auto& property : m_properties) { | 135 | 16.2k | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 11.2k | return box; | 137 | 11.2k | } | 138 | 16.2k | } | 139 | | | 140 | 352 | return nullptr; | 141 | 11.6k | } |
std::__1::shared_ptr<Box_av1C> ImageItem::get_property<Box_av1C>() const Line | Count | Source | 133 | 1.52k | { | 134 | 4.48k | for (auto& property : m_properties) { | 135 | 4.48k | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 991 | return box; | 137 | 991 | } | 138 | 4.48k | } | 139 | | | 140 | 533 | return nullptr; | 141 | 1.52k | } |
std::__1::shared_ptr<Box_avcC> ImageItem::get_property<Box_avcC>() const Line | Count | Source | 133 | 22 | { | 134 | 99 | for (auto& property : m_properties) { | 135 | 99 | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 2 | return box; | 137 | 2 | } | 138 | 99 | } | 139 | | | 140 | 20 | return nullptr; | 141 | 22 | } |
std::__1::shared_ptr<Box_j2kH> ImageItem::get_property<Box_j2kH>() const Line | Count | Source | 133 | 20 | { | 134 | 91 | for (auto& property : m_properties) { | 135 | 91 | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 0 | return box; | 137 | 0 | } | 138 | 91 | } | 139 | | | 140 | 20 | return nullptr; | 141 | 20 | } |
std::__1::shared_ptr<Box_vvcC> ImageItem::get_property<Box_vvcC>() const Line | Count | Source | 133 | 10 | { | 134 | 33 | for (auto& property : m_properties) { | 135 | 33 | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 0 | return box; | 137 | 0 | } | 138 | 33 | } | 139 | | | 140 | 10 | return nullptr; | 141 | 10 | } |
Unexecuted instantiation: std::__1::shared_ptr<Box_pixi> ImageItem::get_property<Box_pixi>() const std::__1::shared_ptr<Box_tilC> ImageItem::get_property<Box_tilC>() const Line | Count | Source | 133 | 6 | { | 134 | 15 | for (auto& property : m_properties) { | 135 | 15 | if (auto box = std::dynamic_pointer_cast<BoxType>(property)) { | 136 | 0 | return box; | 137 | 0 | } | 138 | 15 | } | 139 | | | 140 | 6 | return nullptr; | 141 | 6 | } |
|
142 | | |
143 | | template<class BoxType> |
144 | | std::vector<std::shared_ptr<const BoxType>> get_all_properties() const |
145 | | { |
146 | | std::vector<std::shared_ptr<const BoxType>> result; |
147 | | for (auto& property : m_properties) { |
148 | | if (auto box = std::dynamic_pointer_cast<const BoxType>(property)) { |
149 | | result.push_back(box); |
150 | | } |
151 | | } |
152 | | return result; |
153 | | } |
154 | | |
155 | | heif_property_id add_property(std::shared_ptr<Box> property, bool essential); |
156 | | |
157 | | heif_property_id add_property_without_deduplication(std::shared_ptr<Box> property, bool essential); |
158 | | |
159 | | void set_resolution(uint32_t w, uint32_t h) |
160 | 14.5k | { |
161 | 14.5k | m_width = w; |
162 | 14.5k | m_height = h; |
163 | 14.5k | } |
164 | | |
165 | 94.9k | heif_item_id get_id() const { return m_id; } |
166 | | |
167 | 0 | void set_id(heif_item_id id) { m_id = id; } |
168 | | |
169 | 9.43k | void set_primary(bool flag = true) { m_is_primary = flag; } |
170 | | |
171 | 0 | bool is_primary() const { return m_is_primary; } |
172 | | |
173 | | // 32bit limitation from `ispe` |
174 | 20.6k | uint32_t get_width() const { return m_width; } |
175 | | |
176 | 20.6k | uint32_t get_height() const { return m_height; } |
177 | | |
178 | | bool has_ispe_resolution() const; |
179 | | |
180 | | uint32_t get_ispe_width() const; |
181 | | |
182 | | uint32_t get_ispe_height() const; |
183 | | |
184 | | // Default behavior: forward call to Decoder |
185 | | [[nodiscard]] virtual int get_luma_bits_per_pixel() const; |
186 | | |
187 | | // Default behavior: forward call to Decoder |
188 | | [[nodiscard]] virtual int get_chroma_bits_per_pixel() const; |
189 | | |
190 | | void set_size(uint32_t w, uint32_t h) |
191 | 0 | { |
192 | 0 | m_width = w; |
193 | 0 | m_height = h; |
194 | 0 | } |
195 | | |
196 | | virtual void get_tile_size(uint32_t& w, uint32_t& h) const; |
197 | | |
198 | | virtual Error get_coded_image_colorspace(heif_colorspace* out_colorspace, heif_chroma* out_chroma) const; |
199 | | |
200 | | Error postprocess_coded_image_colorspace(heif_colorspace* inout_colorspace, heif_chroma* inout_chroma) const; |
201 | | |
202 | 0 | virtual Error process_before_write() { return {}; } |
203 | | |
204 | | // -- thumbnails |
205 | | |
206 | | void set_is_thumbnail() |
207 | 111 | { |
208 | 111 | m_is_thumbnail = true; |
209 | 111 | } |
210 | | |
211 | 91 | void add_thumbnail(const std::shared_ptr<ImageItem>& img) { m_thumbnails.push_back(img); } |
212 | | |
213 | 93 | bool is_thumbnail() const { return m_is_thumbnail; } |
214 | | |
215 | 0 | const std::vector<std::shared_ptr<ImageItem>>& get_thumbnails() const { return m_thumbnails; } |
216 | | |
217 | | |
218 | | // --- alpha channel |
219 | | |
220 | | void set_is_alpha_channel() |
221 | 24 | { |
222 | 24 | m_is_alpha_channel = true; |
223 | 24 | } |
224 | | |
225 | | // Attach an alpha aux ImageItem and append a corresponding Alpha |
226 | | // ComponentDescription to this item's m_components. Idempotent. |
227 | | void set_alpha_channel(std::shared_ptr<ImageItem> img); |
228 | | |
229 | 0 | bool is_alpha_channel() const { return m_is_alpha_channel; } |
230 | | |
231 | 11.7k | const std::shared_ptr<ImageItem>& get_alpha_channel() const { return m_alpha_channel; } |
232 | | |
233 | 364 | void set_is_premultiplied_alpha(bool flag) { m_premultiplied_alpha = flag; } |
234 | | |
235 | 0 | bool is_premultiplied_alpha() const { return m_premultiplied_alpha; } |
236 | | |
237 | | // Whether the image has an alpha channel coded in the main image (not as an auxiliary image) |
238 | 8.64k | virtual bool has_coded_alpha_channel() const { return false; } |
239 | | |
240 | | // --- depth channel |
241 | | |
242 | | void set_is_depth_channel() |
243 | 28 | { |
244 | 28 | m_is_depth_channel = true; |
245 | 28 | } |
246 | | |
247 | 26 | void set_depth_channel(std::shared_ptr<ImageItem> img) { m_depth_channel = std::move(img); } |
248 | | |
249 | 0 | bool is_depth_channel() const { return m_is_depth_channel; } |
250 | | |
251 | 0 | const std::shared_ptr<ImageItem>& get_depth_channel() const { return m_depth_channel; } |
252 | | |
253 | | |
254 | | void set_depth_representation_info(heif_depth_representation_info& info) |
255 | 0 | { |
256 | 0 | m_has_depth_representation_info = true; |
257 | 0 | m_depth_representation_info = info; |
258 | 0 | } |
259 | | |
260 | | bool has_depth_representation_info() const |
261 | 0 | { |
262 | 0 | return m_has_depth_representation_info; |
263 | 0 | } |
264 | | |
265 | | const heif_depth_representation_info& get_depth_representation_info() const |
266 | 0 | { |
267 | 0 | return m_depth_representation_info; |
268 | 0 | } |
269 | | |
270 | | |
271 | | // --- generic aux image |
272 | | |
273 | | void set_is_aux_image(const std::string& aux_type) |
274 | 85 | { |
275 | 85 | m_is_aux_image = true; |
276 | 85 | m_aux_image_type = aux_type; |
277 | 85 | } |
278 | | |
279 | 64 | void add_aux_image(std::shared_ptr<ImageItem> img) { m_aux_images.push_back(std::move(img)); } |
280 | | |
281 | 0 | bool is_aux_image() const { return m_is_aux_image; } |
282 | | |
283 | 0 | const std::string& get_aux_type() const { return m_aux_image_type; } |
284 | | |
285 | | std::vector<std::shared_ptr<ImageItem>> get_aux_images(int aux_image_filter = 0) const |
286 | 0 | { |
287 | 0 | if (aux_image_filter == 0) { |
288 | 0 | return m_aux_images; |
289 | 0 | } |
290 | 0 | else { |
291 | 0 | std::vector<std::shared_ptr<ImageItem>> auxImgs; |
292 | 0 | for (const auto& aux : m_aux_images) { |
293 | 0 | if ((aux_image_filter & LIBHEIF_AUX_IMAGE_FILTER_OMIT_ALPHA) && aux->is_alpha_channel()) { |
294 | 0 | continue; |
295 | 0 | } |
296 | | |
297 | 0 | if ((aux_image_filter & LIBHEIF_AUX_IMAGE_FILTER_OMIT_DEPTH) && |
298 | 0 | aux->is_depth_channel()) { |
299 | 0 | continue; |
300 | 0 | } |
301 | | |
302 | 0 | auxImgs.push_back(aux); |
303 | 0 | } |
304 | |
|
305 | 0 | return auxImgs; |
306 | 0 | } |
307 | 0 | } |
308 | | |
309 | | |
310 | | // --- metadata |
311 | | |
312 | | void add_metadata(std::shared_ptr<ImageMetadata> metadata) |
313 | 73 | { |
314 | 73 | m_metadata.push_back(std::move(metadata)); |
315 | 73 | } |
316 | | |
317 | 17.3k | const std::vector<std::shared_ptr<ImageMetadata>>& get_metadata() const { return m_metadata; } |
318 | | |
319 | | |
320 | | |
321 | | // --- ImageDescription |
322 | | |
323 | | void set_clli(const heif_content_light_level& clli) override; |
324 | | |
325 | | void set_mdcv(const heif_mastering_display_colour_volume& mdcv) override; |
326 | | |
327 | | void set_pixel_ratio(uint32_t h, uint32_t v) override; |
328 | | |
329 | | void set_color_profile_nclx(const nclx_profile& profile) override; |
330 | | |
331 | | void set_color_profile_icc(const std::shared_ptr<const color_profile_raw>& profile) override; |
332 | | |
333 | | #if HEIF_WITH_OMAF |
334 | | void set_omaf_image_projection(heif_omaf_image_projection image_projection) override; |
335 | | #endif |
336 | | |
337 | | // --- miaf |
338 | | |
339 | | // TODO: we should have a function that checks all MIAF constraints and sets the compatibility flag. |
340 | 0 | void mark_not_miaf_compatible() { m_miaf_compatible = false; } |
341 | | |
342 | 0 | bool is_miaf_compatible() const { return m_miaf_compatible; } |
343 | | |
344 | | // return 0 if we don't know the brand |
345 | 0 | virtual heif_brand2 get_compatible_brand() const { return 0; } |
346 | | |
347 | | // === decoding === |
348 | | |
349 | 3.65k | virtual Error initialize_decoder() { return Error::Ok; } |
350 | | |
351 | 4.86k | virtual void set_decoder_input_data() { } |
352 | | |
353 | | virtual Result<std::shared_ptr<HeifPixelImage>> decode_image(const heif_decoding_options& options, |
354 | | bool decode_tile_only, uint32_t tile_x0, |
355 | | uint32_t tile_y0, |
356 | | std::set<heif_item_id> processed_ids) const; |
357 | | |
358 | | virtual Result<std::shared_ptr<HeifPixelImage>> decode_compressed_image(const heif_decoding_options& options, |
359 | | bool decode_tile_only, uint32_t tile_x0, |
360 | | uint32_t tile_y0, |
361 | | std::set<heif_item_id> processed_ids) const; |
362 | | |
363 | | // Validate the just-decoded pixel image against the size signaled for this item. |
364 | | // Called by decode_image() right after decode_compressed_image(), BEFORE transforms, |
365 | | // so the reference is the pre-transform coded size (ispe), or the signaled tile size |
366 | | // for a tile decode -- NOT get_width()/get_height() (which are post-transform). |
367 | | // Default impl handles plain coded codecs (HEVC/AVC/VVC/AVIF/JPEG). Subclasses |
368 | | // override where the size source or component layout differs. |
369 | | virtual Error check_decoded_image_size(const HeifPixelImage& img, |
370 | | bool decode_tile_only, |
371 | | uint32_t tile_x0, uint32_t tile_y0) const; |
372 | | |
373 | | Result<std::vector<std::shared_ptr<Box>>> get_properties() const; |
374 | | |
375 | | bool has_essential_property_other_than(const std::set<uint32_t>&) const; |
376 | | |
377 | | // === encoding === |
378 | | |
379 | | Result<Encoder::CodedImageData> encode_to_bitstream_and_boxes(const std::shared_ptr<HeifPixelImage>& image, |
380 | | heif_encoder* encoder, |
381 | | const heif_encoding_options& options, |
382 | | heif_image_input_class input_class); |
383 | | |
384 | | // Entry point for encoding pixel images. |
385 | | Error encode_to_item(HeifContext* ctx, |
386 | | const std::shared_ptr<HeifPixelImage>& image, |
387 | | heif_encoder* encoder, |
388 | | const heif_encoding_options& options, |
389 | | heif_image_input_class input_class); |
390 | | |
391 | 0 | void set_intrinsic_matrix(const Box_cmin::RelativeIntrinsicMatrix& cmin) { |
392 | 0 | m_has_intrinsic_matrix = true; |
393 | 0 | m_intrinsic_matrix = cmin.to_absolute(get_ispe_width(), get_ispe_height()); |
394 | 0 | } |
395 | | |
396 | 1.39k | bool has_intrinsic_matrix() const { return m_has_intrinsic_matrix; } |
397 | | |
398 | 346 | Box_cmin::AbsoluteIntrinsicMatrix& get_intrinsic_matrix() { return m_intrinsic_matrix; } |
399 | | |
400 | 0 | const Box_cmin::AbsoluteIntrinsicMatrix& get_intrinsic_matrix() const { return m_intrinsic_matrix; } |
401 | | |
402 | | |
403 | 4 | void set_extrinsic_matrix(const Box_cmex::ExtrinsicMatrix& cmex) { |
404 | 4 | m_has_extrinsic_matrix = true; |
405 | 4 | m_extrinsic_matrix = cmex; |
406 | 4 | } |
407 | | |
408 | 0 | bool has_extrinsic_matrix() const { return m_has_extrinsic_matrix; } |
409 | | |
410 | 0 | Box_cmex::ExtrinsicMatrix& get_extrinsic_matrix() { return m_extrinsic_matrix; } |
411 | | |
412 | 0 | const Box_cmex::ExtrinsicMatrix& get_extrinsic_matrix() const { return m_extrinsic_matrix; } |
413 | | |
414 | | |
415 | 16 | void add_region_item_id(heif_item_id id) { m_region_item_ids.push_back(id); } |
416 | | |
417 | 0 | const std::vector<heif_item_id>& get_region_item_ids() const { return m_region_item_ids; } |
418 | | |
419 | | |
420 | 4.10k | void add_decoding_warning(Error err) const { m_decoding_warnings.emplace_back(std::move(err)); } |
421 | | |
422 | 629 | const std::vector<Error>& get_decoding_warnings() const { return m_decoding_warnings; } |
423 | | |
424 | | virtual heif_image_tiling get_heif_image_tiling() const; |
425 | | |
426 | | Error process_image_transformations_on_tiling(heif_image_tiling&) const; |
427 | | |
428 | | Error transform_requested_tile_position_to_original_tile_position(uint32_t& tile_x, uint32_t& tile_y) const; |
429 | | |
430 | | virtual Result<std::shared_ptr<class Decoder>> get_decoder() const |
431 | 8.85k | { |
432 | 8.85k | return Error{ |
433 | 8.85k | heif_error_Unsupported_feature, |
434 | 8.85k | heif_suberror_No_matching_decoder_installed, |
435 | 8.85k | "No decoder for this image format" |
436 | 8.85k | }; |
437 | 8.85k | } |
438 | | |
439 | 0 | virtual std::shared_ptr<class Encoder> get_encoder() const { return nullptr; } |
440 | | |
441 | 5 | void add_text_item_id(heif_item_id id) { |
442 | 5 | m_text_item_ids.push_back(id); |
443 | 5 | } |
444 | | |
445 | 0 | const std::vector<heif_item_id>& get_text_item_ids() const { return m_text_item_ids; } |
446 | | |
447 | | private: |
448 | | HeifContext* m_heif_context; |
449 | | std::vector<std::shared_ptr<Box>> m_properties; |
450 | | |
451 | | heif_item_id m_id = 0; |
452 | | uint32_t m_width = 0, m_height = 0; // after all transformations have been applied |
453 | | bool m_is_primary = false; |
454 | | |
455 | | bool m_is_thumbnail = false; |
456 | | |
457 | | std::vector<std::shared_ptr<ImageItem>> m_thumbnails; |
458 | | |
459 | | bool m_is_alpha_channel = false; |
460 | | bool m_premultiplied_alpha = false; |
461 | | std::shared_ptr<ImageItem> m_alpha_channel; |
462 | | |
463 | | bool m_is_depth_channel = false; |
464 | | std::shared_ptr<ImageItem> m_depth_channel; |
465 | | |
466 | | bool m_has_depth_representation_info = false; |
467 | | heif_depth_representation_info m_depth_representation_info; |
468 | | |
469 | | bool m_is_aux_image = false; |
470 | | std::string m_aux_image_type; |
471 | | std::vector<std::shared_ptr<ImageItem>> m_aux_images; |
472 | | |
473 | | std::vector<std::shared_ptr<ImageMetadata>> m_metadata; |
474 | | |
475 | | bool m_miaf_compatible = true; |
476 | | |
477 | | std::vector<heif_item_id> m_region_item_ids; |
478 | | |
479 | | bool m_has_intrinsic_matrix = false; |
480 | | Box_cmin::AbsoluteIntrinsicMatrix m_intrinsic_matrix{}; |
481 | | |
482 | | bool m_has_extrinsic_matrix = false; |
483 | | Box_cmex::ExtrinsicMatrix m_extrinsic_matrix{}; |
484 | | |
485 | | mutable std::vector<Error> m_decoding_warnings; |
486 | | |
487 | | mutable std::mutex m_decode_mutex; |
488 | | |
489 | | std::vector<heif_item_id> m_text_item_ids; |
490 | | |
491 | | void generate_property_boxes_for_ImageDescription(); |
492 | | |
493 | | protected: |
494 | | // Result<std::vector<uint8_t>> read_bitstream_configuration_data_override(heif_item_id itemId, heif_compression_format format) const; |
495 | | |
496 | | virtual Result<Encoder::CodedImageData> encode(const std::shared_ptr<HeifPixelImage>& image, |
497 | | heif_encoder* encoder, |
498 | | const heif_encoding_options& options, |
499 | | heif_image_input_class input_class); |
500 | | |
501 | | // --- encoding utility functions |
502 | | |
503 | | static std::vector<std::shared_ptr<Box_colr> > |
504 | | add_color_profile(const std::shared_ptr<HeifPixelImage>& image, |
505 | | const heif_encoding_options& options, |
506 | | heif_image_input_class input_class, |
507 | | const heif_color_profile_nclx* target_heif_nclx); |
508 | | }; |
509 | | |
510 | | |
511 | | class ImageItem_Error : public ImageItem |
512 | | { |
513 | | public: |
514 | | // dummy ImageItem class that is a placeholder for unsupported item types |
515 | | |
516 | | ImageItem_Error(uint32_t item_type, heif_item_id id, Error err) |
517 | 4.80k | : ImageItem(nullptr, id), m_item_type(item_type), m_item_error(err) {} |
518 | | |
519 | | uint32_t get_infe_type() const override |
520 | 8 | { |
521 | 8 | return m_item_type; |
522 | 8 | } |
523 | | |
524 | 14.4k | Error get_item_error() const override { return m_item_error; } |
525 | | |
526 | | Result<std::shared_ptr<HeifPixelImage>> decode_image(const heif_decoding_options& options, |
527 | | bool decode_tile_only, uint32_t tile_x0, |
528 | | uint32_t tile_y0, |
529 | | std::set<heif_item_id> processed_ids) const override |
530 | 0 | { |
531 | 0 | return m_item_error; |
532 | 0 | } |
533 | | |
534 | | Result<std::shared_ptr<HeifPixelImage>> decode_compressed_image(const heif_decoding_options& options, |
535 | | bool decode_tile_only, uint32_t tile_x0, |
536 | | uint32_t tile_y0, std::set<heif_item_id> processed_ids) const override |
537 | 0 | { |
538 | 0 | return m_item_error; |
539 | 0 | } |
540 | | |
541 | 33 | [[nodiscard]] int get_luma_bits_per_pixel() const override { return -1; } |
542 | | |
543 | 0 | [[nodiscard]] int get_chroma_bits_per_pixel() const override { return -1; } |
544 | | |
545 | | private: |
546 | | uint32_t m_item_type; |
547 | | Error m_item_error; |
548 | | }; |
549 | | |
550 | | #endif //LIBHEIF_IMAGEITEM_H |