Coverage Report

Created: 2026-05-24 07:45

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