Coverage Report

Created: 2025-11-14 07:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libheif/libheif/error.cc
Line
Count
Source
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
#include "error.h"
22
23
#include <cassert>
24
#include <cstring>
25
26
27
const heif_error heif_error_null_pointer_argument {
28
  heif_error_Usage_error,
29
  heif_suberror_Null_pointer_argument,
30
  "NULL argument passed"
31
};
32
33
34
// static
35
const char Error::kSuccess[] = "Success";
36
const char* cUnknownError = "Unknown error";
37
38
39
const Error Error::Ok(heif_error_Ok);
40
41
const Error Error::InternalError{heif_error_Unsupported_feature, // TODO: use better value
42
                                 heif_suberror_Unspecified,
43
                                 "Internal error"};
44
45
46
56.6k
Error::Error() = default;
47
48
49
Error::Error(heif_error_code c,
50
                   heif_suberror_code sc,
51
                   const std::string& msg)
52
20.8k
    : error_code(c),
53
20.8k
      sub_error_code(sc),
54
20.8k
      message(msg)
55
20.8k
{
56
20.8k
}
57
58
59
// Replacement for C++20 std::string::starts_with()
60
736
static bool starts_with(const std::string& str, const std::string& prefix) {
61
736
    if (str.length() < prefix.length()) {
62
0
        return false;
63
0
    }
64
736
    return str.rfind(prefix, 0) == 0;
65
736
}
66
67
68
Error Error::from_heif_error(const heif_error& c_error)
69
736
{
70
  // unpack the concatenated error message and extract the last part only
71
72
736
  const char* err_string = get_error_string(c_error.code);
73
736
  const char* sub_err_string = get_error_string(c_error.subcode);
74
75
736
  std::string msg = c_error.message;
76
736
  if (starts_with(msg, err_string)) {
77
0
    msg = msg.substr(strlen(err_string));
78
79
0
    if (starts_with(msg, ": ")) {
80
0
      msg = msg.substr(2);
81
0
    }
82
83
0
    if (starts_with(msg, sub_err_string)) {
84
0
      msg = msg.substr(strlen(sub_err_string));
85
86
0
      if (starts_with(msg, ": ")) {
87
0
        msg = msg.substr(2);
88
0
      }
89
0
    }
90
0
  }
91
92
736
  return {c_error.code, c_error.subcode, msg};
93
736
}
94
95
96
const char* Error::get_error_string(heif_error_code err)
97
9.82k
{
98
9.82k
  switch (err) {
99
0
    case heif_error_Ok:
100
0
      return "Success";
101
0
    case heif_error_Input_does_not_exist:
102
0
      return "Input file does not exist";
103
5.20k
    case heif_error_Invalid_input:
104
5.20k
      return "Invalid input";
105
851
    case heif_error_Unsupported_filetype:
106
851
      return "Unsupported file-type";
107
1.75k
    case heif_error_Unsupported_feature:
108
1.75k
      return "Unsupported feature";
109
0
    case heif_error_Usage_error:
110
0
      return "Usage error";
111
236
    case heif_error_Memory_allocation_error:
112
236
      return "Memory allocation error";
113
1.63k
    case heif_error_Decoder_plugin_error:
114
1.63k
      return "Decoder plugin generated an error";
115
0
    case heif_error_Encoder_plugin_error:
116
0
      return "Encoder plugin generated an error";
117
0
    case heif_error_Encoding_error:
118
0
      return "Error during encoding or writing output file";
119
0
    case heif_error_Color_profile_does_not_exist:
120
0
      return "Color profile does not exist";
121
140
    case heif_error_Plugin_loading_error:
122
140
      return "Error while loading plugin";
123
0
    case heif_error_Canceled:
124
0
      return "Canceled by user";
125
0
    case heif_error_End_of_sequence:
126
0
      return "End of sequence";
127
9.82k
  }
128
129
9.82k
  assert(false);
130
0
  return "Unknown error";
131
9.82k
}
132
133
const char* Error::get_error_string(heif_suberror_code err)
134
9.82k
{
135
9.82k
  switch (err) {
136
2.91k
    case heif_suberror_Unspecified:
137
2.91k
      return "Unspecified";
138
139
      // --- Invalid_input ---
140
141
2.82k
    case heif_suberror_End_of_data:
142
2.82k
      return "Unexpected end of file";
143
105
    case heif_suberror_Invalid_box_size:
144
105
      return "Invalid box size";
145
44
    case heif_suberror_Invalid_grid_data:
146
44
      return "Invalid grid data";
147
95
    case heif_suberror_Missing_grid_images:
148
95
      return "Missing grid images";
149
204
    case heif_suberror_No_ftyp_box:
150
204
      return "No 'ftyp' box";
151
6
    case heif_suberror_No_idat_box:
152
6
      return "No 'idat' box";
153
109
    case heif_suberror_No_meta_box:
154
109
      return "No 'meta' box";
155
0
    case heif_suberror_No_hdlr_box:
156
0
      return "No 'hdlr' box";
157
22
    case heif_suberror_No_hvcC_box:
158
22
      return "No 'hvcC' box";
159
0
    case heif_suberror_No_vvcC_box:
160
0
      return "No 'vvcC' box";
161
64
    case heif_suberror_No_av1C_box:
162
64
      return "No 'av1C' box";
163
0
    case heif_suberror_No_avcC_box:
164
0
      return "No 'avcC' box";
165
87
    case heif_suberror_No_pitm_box:
166
87
      return "No 'pitm' box";
167
18
    case heif_suberror_No_ipco_box:
168
18
      return "No 'ipco' box";
169
13
    case heif_suberror_No_ipma_box:
170
13
      return "No 'ipma' box";
171
12
    case heif_suberror_No_iloc_box:
172
12
      return "No 'iloc' box";
173
13
    case heif_suberror_No_iinf_box:
174
13
      return "No 'iinf' box";
175
45
    case heif_suberror_No_iprp_box:
176
45
      return "No 'iprp' box";
177
45
    case heif_suberror_No_iref_box:
178
45
      return "No 'iref' box";
179
0
    case heif_suberror_No_infe_box:
180
0
      return "No 'infe' box";
181
15
    case heif_suberror_No_pict_handler:
182
15
      return "Not a 'pict' handler";
183
36
    case heif_suberror_Ipma_box_references_nonexisting_property:
184
36
      return "'ipma' box references a non-existing property";
185
56
    case heif_suberror_No_properties_assigned_to_item:
186
56
      return "No properties assigned to item";
187
135
    case heif_suberror_No_item_data:
188
135
      return "Item has no data";
189
60
    case heif_suberror_Invalid_clean_aperture:
190
60
      return "Invalid clean-aperture specification";
191
10
    case heif_suberror_Invalid_overlay_data:
192
10
      return "Invalid overlay data";
193
0
    case heif_suberror_Overlay_image_outside_of_canvas:
194
0
      return "Overlay image outside of canvas area";
195
17
    case heif_suberror_Auxiliary_image_type_unspecified:
196
17
      return "Type of auxiliary image unspecified";
197
0
    case heif_suberror_No_or_invalid_primary_item:
198
0
      return "No or invalid primary item";
199
62
    case heif_suberror_Unknown_color_profile_type:
200
62
      return "Unknown color profile type";
201
0
    case heif_suberror_Wrong_tile_image_chroma_format:
202
0
      return "Wrong tile image chroma format";
203
4
    case heif_suberror_Invalid_fractional_number:
204
4
      return "Invalid fractional number";
205
10
    case heif_suberror_Invalid_image_size:
206
10
      return "Invalid image size";
207
0
    case heif_suberror_Invalid_pixi_box:
208
0
      return "Invalid pixi box";
209
0
    case heif_suberror_Wrong_tile_image_pixel_depth:
210
0
      return "Wrong tile image pixel depth";
211
0
    case heif_suberror_Unknown_NCLX_color_primaries:
212
0
      return "Unknown NCLX color primaries";
213
0
    case heif_suberror_Unknown_NCLX_transfer_characteristics:
214
0
      return "Unknown NCLX transfer characteristics";
215
0
    case heif_suberror_Unknown_NCLX_matrix_coefficients:
216
0
      return "Unknown NCLX matrix coefficients";
217
0
    case heif_suberror_Invalid_region_data:
218
0
      return "Invalid region item data";
219
6
    case heif_suberror_No_ispe_property:
220
6
      return "Image has no 'ispe' property";
221
0
    case heif_suberror_Camera_intrinsic_matrix_undefined:
222
0
      return "Camera intrinsic matrix undefined";
223
0
    case heif_suberror_Camera_extrinsic_matrix_undefined:
224
0
      return "Camera extrinsic matrix undefined";
225
0
    case heif_suberror_Invalid_J2K_codestream:
226
0
      return "Invalid JPEG 2000 codestream";
227
0
    case heif_suberror_Decompression_invalid_data:
228
0
      return "Invalid data in generic compression inflation";
229
83
    case heif_suberror_No_moov_box:
230
83
      return "No 'moov' box";
231
0
    case heif_suberror_No_icbr_box:
232
0
      return "No 'icbr' box";
233
0
    case heif_suberror_Invalid_mini_box:
234
0
      return "Unsupported or invalid 'mini' box";
235
236
237
      // --- Memory_allocation_error ---
238
239
406
    case heif_suberror_Security_limit_exceeded:
240
406
      return "Security limit exceeded";
241
0
    case heif_suberror_Compression_initialisation_error:
242
0
      return "Compression initialisation method error";
243
244
      // --- Usage_error ---
245
246
385
    case heif_suberror_Nonexisting_item_referenced:
247
385
      return "Non-existing item ID referenced";
248
0
    case heif_suberror_Null_pointer_argument:
249
0
      return "NULL argument received";
250
0
    case heif_suberror_Nonexisting_image_channel_referenced:
251
0
      return "Non-existing image channel referenced";
252
0
    case heif_suberror_Unsupported_plugin_version:
253
0
      return "The version of the passed plugin is not supported";
254
0
    case heif_suberror_Unsupported_writer_version:
255
0
      return "The version of the passed writer is not supported";
256
0
    case heif_suberror_Unsupported_parameter:
257
0
      return "Unsupported parameter";
258
3
    case heif_suberror_Invalid_parameter_value:
259
3
      return "Invalid parameter value";
260
0
    case heif_suberror_Invalid_property:
261
0
      return "Invalid property";
262
14
    case heif_suberror_Item_reference_cycle:
263
14
      return "Image reference cycle";
264
265
      // --- Unsupported_feature ---
266
267
3
    case heif_suberror_Unsupported_codec:
268
3
      return "Unsupported codec";
269
3
    case heif_suberror_Unsupported_image_type:
270
3
      return "Unsupported image type";
271
144
    case heif_suberror_Unsupported_data_version:
272
144
      return "Unsupported data version";
273
1.47k
    case heif_suberror_Unsupported_color_conversion:
274
1.47k
      return "Unsupported color conversion";
275
106
    case heif_suberror_Unsupported_item_construction_method:
276
106
      return "Unsupported item construction method";
277
1
    case heif_suberror_Unsupported_header_compression_method:
278
1
      return "Unsupported header compression method";
279
0
    case heif_suberror_Unsupported_generic_compression_method:
280
0
      return "Unsupported generic compression method";
281
21
    case heif_suberror_Unsupported_essential_property:
282
21
      return "Unsupported essential item property";
283
284
      // --- Encoder_plugin_error --
285
286
0
    case heif_suberror_Unsupported_bit_depth:
287
0
      return "Unsupported bit depth";
288
289
      // --- Encoding_error --
290
291
0
    case heif_suberror_Cannot_write_output_data:
292
0
      return "Cannot write output data";
293
0
    case heif_suberror_Encoder_initialization:
294
0
      return "Initialization problem";
295
0
    case heif_suberror_Encoder_encoding:
296
0
      return "Encoding problem";
297
0
    case heif_suberror_Encoder_cleanup:
298
0
      return "Cleanup problem";
299
0
    case heif_suberror_Too_many_regions:
300
0
      return "Too many regions (>255) in an 'rgan' item.";
301
302
      // --- Plugin_loading_error ---
303
304
0
    case heif_suberror_Plugin_loading_error:
305
0
      return "Plugin file cannot be loaded";
306
0
    case heif_suberror_Plugin_is_not_loaded:
307
0
      return "Trying to remove a plugin that is not loaded";
308
0
    case heif_suberror_Cannot_read_plugin_directory:
309
0
      return "Error while scanning the directory for plugins";
310
140
    case heif_suberror_No_matching_decoder_installed:
311
#if ENABLE_PLUGIN_LOADING
312
      return "No decoding plugin installed for this compression format";
313
#else
314
140
      return "Support for this compression format has not been built in";
315
9.82k
#endif
316
9.82k
  }
317
318
9.82k
  assert(false);
319
0
  return cUnknownError;
320
9.82k
}
321
322
323
heif_error Error::error_struct(ErrorBuffer* error_buffer) const
324
23.6k
{
325
23.6k
  if (error_buffer) {
326
20.3k
    if (error_code == heif_error_Ok) {
327
11.2k
      error_buffer->set_success();
328
11.2k
    }
329
9.08k
    else {
330
9.08k
      std::stringstream sstr;
331
9.08k
      sstr << get_error_string(error_code) << ": "
332
9.08k
           << get_error_string(sub_error_code);
333
9.08k
      if (!message.empty()) {
334
4.30k
        sstr << ": " << message;
335
4.30k
      }
336
337
9.08k
      error_buffer->set_error(sstr.str());
338
9.08k
    }
339
20.3k
  }
340
341
23.6k
  heif_error err;
342
23.6k
  err.code = error_code;
343
23.6k
  err.subcode = sub_error_code;
344
23.6k
  if (error_buffer) {
345
20.3k
    err.message = error_buffer->get_error();
346
20.3k
  }
347
3.31k
  else {
348
3.31k
    err.message = cUnknownError;
349
3.31k
  }
350
23.6k
  return err;
351
23.6k
}