Coverage Report

Created: 2025-07-09 06:34

/src/libheif/libheif/file.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * HEIF codec.
3
 * Copyright (c) 2017 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_FILE_H
22
#define LIBHEIF_FILE_H
23
24
#include "box.h"
25
#include "nclx.h"
26
#include "image-items/avif.h"
27
#include "image-items/hevc.h"
28
#include "image-items/vvc.h"
29
//#include "codecs/uncompressed/unc_boxes.h"
30
#include "file_layout.h"
31
32
#include <map>
33
#include <memory>
34
#include <string>
35
#include <map>
36
#include <vector>
37
#include <unordered_set>
38
#include <limits>
39
#include <utility>
40
#include "mdat_data.h"
41
42
#if ENABLE_PARALLEL_TILE_DECODING
43
44
#include <mutex>
45
46
#endif
47
48
49
class HeifPixelImage;
50
51
class Box_j2kH;
52
53
class Box_moov;
54
55
class Box_mvhd;
56
57
58
59
class HeifFile
60
{
61
public:
62
  HeifFile();
63
64
  ~HeifFile();
65
66
  // The limits will be shared from the HeifContext limits.
67
  // You have to make sure that the pointer points to a valid object as long as the HeifFile is used.
68
1.40k
  void set_security_limits(const heif_security_limits* limits) { m_limits = limits; }
69
70
  Error read(const std::shared_ptr<StreamReader>& reader);
71
72
  Error read_from_file(const char* input_filename);
73
74
  Error read_from_memory(const void* data, size_t size, bool copy);
75
76
325
  bool has_images() const { return m_meta_box != nullptr; }
77
78
220
  bool has_sequences() const { return m_moov_box != nullptr; }
79
80
0
  std::shared_ptr<StreamReader> get_reader() { return m_input_stream; }
81
82
  void new_empty_file();
83
84
  void init_for_image();
85
86
  void init_for_sequence();
87
88
0
  void set_hdlr_box(std::shared_ptr<Box_hdlr> box) { m_hdlr_box = std::move(box); }
89
90
  size_t append_mdat_data(const std::vector<uint8_t>& data);
91
92
  void derive_box_versions();
93
94
  void write(StreamWriter& writer);
95
96
0
  int get_num_images() const { return static_cast<int>(m_infe_boxes.size()); }
97
98
1.03k
  heif_item_id get_primary_image_ID() const { return m_pitm_box->get_item_ID(); }
99
100
0
  size_t get_number_of_items() const { return m_infe_boxes.size(); }
101
102
  std::vector<heif_item_id> get_item_IDs() const;
103
104
  bool item_exists(heif_item_id ID) const;
105
106
  bool has_item_with_id(heif_item_id ID) const;
107
108
  uint32_t get_item_type_4cc(heif_item_id ID) const;
109
110
  std::string get_content_type(heif_item_id ID) const;
111
112
  std::string get_item_uri_type(heif_item_id ID) const;
113
114
  Error get_uncompressed_item_data(heif_item_id ID, std::vector<uint8_t>* data) const;
115
116
  Error append_data_from_file_range(std::vector<uint8_t>& out_data, uint64_t offset, uint32_t size) const;
117
118
  Error append_data_from_iloc(heif_item_id ID, std::vector<uint8_t>& out_data, uint64_t offset, uint64_t size) const;
119
120
133
  Error append_data_from_iloc(heif_item_id ID, std::vector<uint8_t>& out_data) const {
121
133
    return append_data_from_iloc(ID, out_data, 0, std::numeric_limits<uint64_t>::max());
122
133
  }
123
124
  Error get_item_data(heif_item_id ID, std::vector<uint8_t> *out_data, heif_metadata_compression* out_compression) const;
125
126
0
  std::shared_ptr<Box_ftyp> get_ftyp_box() { return m_ftyp_box; }
127
128
0
  void init_meta_box() { m_meta_box = std::make_shared<Box_meta>(); }
129
130
  std::shared_ptr<const Box_infe> get_infe_box(heif_item_id imageID) const;
131
132
  std::shared_ptr<Box_infe> get_infe_box(heif_item_id imageID);
133
134
  void set_iref_box(std::shared_ptr<Box_iref>);
135
136
674
  std::shared_ptr<Box_iref> get_iref_box() { return m_iref_box; }
137
138
0
  std::shared_ptr<const Box_iref> get_iref_box() const { return m_iref_box; }
139
140
2.71k
  std::shared_ptr<Box_ipco> get_ipco_box() { return m_ipco_box; }
141
142
  void set_ipco_box(std::shared_ptr<Box_ipco>);
143
144
0
  std::shared_ptr<Box_ipco> get_ipco_box() const { return m_ipco_box; }
145
146
  void set_ipma_box(std::shared_ptr<Box_ipma>);
147
148
2.71k
  std::shared_ptr<Box_ipma> get_ipma_box() { return m_ipma_box; }
149
150
0
  std::shared_ptr<Box_ipma> get_ipma_box() const { return m_ipma_box; }
151
152
0
  std::shared_ptr<Box_grpl> get_grpl_box() const { return m_grpl_box; }
153
154
0
  std::shared_ptr<Box_meta> get_meta_box() const { return m_meta_box; }
155
156
  std::shared_ptr<Box_EntityToGroup> get_entity_group(heif_entity_group_id id);
157
158
  Error get_properties(heif_item_id imageID,
159
                       std::vector<std::shared_ptr<Box>>& properties) const;
160
161
  template<class BoxType>
162
  std::shared_ptr<BoxType> get_property_for_item(heif_item_id imageID) const
163
0
  {
164
0
    std::vector<std::shared_ptr<Box>> properties;
165
0
    Error err = get_properties(imageID, properties);
166
0
    if (err) {
167
0
      return nullptr;
168
0
    }
169
170
0
    for (auto& property : properties) {
171
0
      if (auto box = std::dynamic_pointer_cast<BoxType>(property)) {
172
0
        return box;
173
0
      }
174
0
    }
175
176
0
    return nullptr;
177
0
  }
Unexecuted instantiation: std::__1::shared_ptr<Box_taic> HeifFile::get_property_for_item<Box_taic>(unsigned int) const
Unexecuted instantiation: std::__1::shared_ptr<Box_itai> HeifFile::get_property_for_item<Box_itai>(unsigned int) const
Unexecuted instantiation: std::__1::shared_ptr<Box_pixi> HeifFile::get_property_for_item<Box_pixi>(unsigned int) const
178
179
  std::string debug_dump_boxes() const;
180
181
182
  // --- writing ---
183
184
  heif_item_id get_unused_item_id() const;
185
186
  heif_item_id add_new_image(uint32_t item_type);
187
188
  std::shared_ptr<Box_infe> add_new_infe_box(uint32_t item_type);
189
190
  void add_ispe_property(heif_item_id id, uint32_t width, uint32_t height, bool essential);
191
192
  // set irot/imir according to heif_orientation
193
  void add_orientation_properties(heif_item_id id, heif_orientation);
194
195
  // TODO: can we remove the 'essential' parameter and take this from the box? Or is that depending on the context?
196
  heif_property_id add_property(heif_item_id id, const std::shared_ptr<Box>& property, bool essential);
197
198
  heif_property_id add_property_without_deduplication(heif_item_id id, const std::shared_ptr<Box>& property, bool essential);
199
200
  Result<heif_item_id> add_infe(uint32_t item_type, const uint8_t* data, size_t size);
201
202
  void add_infe_box(heif_item_id, std::shared_ptr<Box_infe> infe);
203
204
  Result<heif_item_id> add_infe_mime(const char* content_type, heif_metadata_compression content_encoding, const uint8_t* data, size_t size);
205
206
  Result<heif_item_id> add_precompressed_infe_mime(const char* content_type, std::string content_encoding, const uint8_t* data, size_t size);
207
208
  Result<heif_item_id> add_infe_uri(const char* item_uri_type, const uint8_t* data, size_t size);
209
210
  Error set_item_data(const std::shared_ptr<Box_infe>& item, const uint8_t* data, size_t size, heif_metadata_compression compression);
211
212
  Error set_precompressed_item_data(const std::shared_ptr<Box_infe>& item, const uint8_t* data, size_t size, std::string content_encoding);
213
214
  void append_iloc_data(heif_item_id id, const std::vector<uint8_t>& nal_packets, uint8_t construction_method);
215
216
  void replace_iloc_data(heif_item_id id, uint64_t offset, const std::vector<uint8_t>& data, uint8_t construction_method = 0);
217
218
  void set_iloc_box(std::shared_ptr<Box_iloc>);
219
220
0
  std::shared_ptr<Box_iloc> get_iloc_box() { return m_iloc_box; }
221
222
  void set_primary_item_id(heif_item_id id);
223
224
  void add_iref_reference(heif_item_id from, uint32_t type,
225
                          const std::vector<heif_item_id>& to);
226
227
  void set_iref_reference(heif_item_id from, uint32_t type, int reference_idx, heif_item_id to_item);
228
229
  void add_entity_group_box(const std::shared_ptr<Box>& entity_group_box);
230
231
  void set_auxC_property(heif_item_id id, const std::string& type);
232
233
#if defined(__MINGW32__) || defined(__MINGW64__) || defined(_MSC_VER)
234
  static std::wstring convert_utf8_path_to_utf16(std::string pathutf8);
235
#endif
236
237
238
  // --- sequences
239
240
0
  std::shared_ptr<Box_moov> get_moov_box() { return m_moov_box; }
241
242
0
  std::shared_ptr<Box_mvhd> get_mvhd_box() { return m_mvhd_box; }
243
244
private:
245
#if ENABLE_PARALLEL_TILE_DECODING
246
  mutable std::mutex m_read_mutex;
247
#endif
248
249
  std::shared_ptr<FileLayout> m_file_layout;
250
251
  std::shared_ptr<StreamReader> m_input_stream;
252
253
  std::vector<std::shared_ptr<Box> > m_top_level_boxes;
254
255
  std::shared_ptr<Box_ftyp> m_ftyp_box;
256
  std::shared_ptr<Box_hdlr> m_hdlr_box;
257
  std::shared_ptr<Box_meta> m_meta_box;
258
#if ENABLE_EXPERIMENTAL_MINI_FORMAT
259
  std::shared_ptr<Box_mini> m_mini_box; // meta alternative
260
#endif
261
262
  std::shared_ptr<Box_ipco> m_ipco_box;
263
  std::shared_ptr<Box_ipma> m_ipma_box;
264
  std::shared_ptr<Box_iloc> m_iloc_box;
265
  std::shared_ptr<Box_idat> m_idat_box;
266
  std::shared_ptr<Box_iref> m_iref_box;
267
  std::shared_ptr<Box_pitm> m_pitm_box;
268
  std::shared_ptr<Box_iinf> m_iinf_box;
269
  std::shared_ptr<Box_grpl> m_grpl_box;
270
271
  std::shared_ptr<Box_iprp> m_iprp_box;
272
273
  std::map<heif_item_id, std::shared_ptr<Box_infe> > m_infe_boxes;
274
275
  std::unique_ptr<MdatData> m_mdat_data;
276
277
  // returns the position of the first data byte in the file
278
  Result<size_t> write_mdat(StreamWriter& writer);
279
280
  // --- sequences
281
282
  std::shared_ptr<Box_moov> m_moov_box;
283
  std::shared_ptr<Box_mvhd> m_mvhd_box;
284
285
  const heif_security_limits* m_limits = nullptr;
286
287
  Error parse_heif_file();
288
289
  Error parse_heif_images();
290
291
  Error parse_heif_sequences();
292
293
  Error check_for_ref_cycle(heif_item_id ID,
294
                            const std::shared_ptr<Box_iref>& iref_box) const;
295
296
  Error check_for_ref_cycle_recursion(heif_item_id ID,
297
                                      const std::shared_ptr<Box_iref>& iref_box,
298
                                      std::unordered_set<heif_item_id>& parent_items) const;
299
};
300
301
#endif