Coverage Report

Created: 2025-08-11 08:01

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