1 /*
2 * HEIF codec.
3 * Copyright (c) 2017 struktur AG, Dirk Farin <farin@struktur.de>
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 #if defined(HAVE_CONFIG_H)
22 #include "config.h"
23 #endif
24
25 #include "heif.h"
26 #include "heif_file.h"
27 #include "heif_image.h"
28 #include "heif_api_structs.h"
29 #include "heif_context.h"
30 #include "heif_plugin_registry.h"
31 #include "error.h"
32 #include "bitstream.h"
33
34 #if defined(__EMSCRIPTEN__)
35 #include "heif_emscripten.h"
36 #endif
37
38 #include <algorithm>
39 #include <iostream>
40 #include <fstream>
41 #include <memory>
42 #include <string>
43 #include <utility>
44 #include <vector>
45 #include <cstring>
46
47 #if (defined(__MINGW32__) || defined(__MINGW64__) || defined(_MSC_VER)) && !defined(HAVE_UNISTD_H)
48 // for _write
49 #include <io.h>
50 #else
51
52 #include <unistd.h>
53
54 #endif
55
56 using namespace heif;
57
58 static struct heif_error error_Ok = {heif_error_Ok, heif_suberror_Unspecified, kSuccess};
59 static struct heif_error error_unsupported_parameter = {heif_error_Usage_error,
60 heif_suberror_Unsupported_parameter,
61 "Unsupported encoder parameter"};
62 static struct heif_error error_invalid_parameter_value = {heif_error_Usage_error,
63 heif_suberror_Invalid_parameter_value,
64 "Invalid parameter value"};
65 static struct heif_error error_unsupported_plugin_version = {heif_error_Usage_error,
66 heif_suberror_Unsupported_plugin_version,
67 "Unsupported plugin version"};
68 static struct heif_error error_null_parameter = {heif_error_Usage_error,
69 heif_suberror_Null_pointer_argument,
70 "NULL passed"};
71
heif_get_version(void)72 const char* heif_get_version(void)
73 {
74 return (LIBHEIF_VERSION);
75 }
76
heif_get_version_number(void)77 uint32_t heif_get_version_number(void)
78 {
79 return (LIBHEIF_NUMERIC_VERSION);
80 }
81
heif_get_version_number_major(void)82 int heif_get_version_number_major(void)
83 {
84 return ((LIBHEIF_NUMERIC_VERSION) >> 24) & 0xFF;
85 }
86
heif_get_version_number_minor(void)87 int heif_get_version_number_minor(void)
88 {
89 return ((LIBHEIF_NUMERIC_VERSION) >> 16) & 0xFF;
90 }
91
heif_get_version_number_maintenance(void)92 int heif_get_version_number_maintenance(void)
93 {
94 return ((LIBHEIF_NUMERIC_VERSION) >> 8) & 0xFF;
95 }
96
97
heif_check_filetype(const uint8_t * data,int len)98 heif_filetype_result heif_check_filetype(const uint8_t* data, int len)
99 {
100 if (len < 8) {
101 return heif_filetype_maybe;
102 }
103
104 if (data[4] != 'f' ||
105 data[5] != 't' ||
106 data[6] != 'y' ||
107 data[7] != 'p') {
108 return heif_filetype_no;
109 }
110
111 if (len >= 12) {
112 heif_brand brand = heif_main_brand(data, len);
113
114 if (brand == heif_heic) {
115 return heif_filetype_yes_supported;
116 }
117 else if (brand == heif_heix) {
118 return heif_filetype_yes_supported;
119 }
120 else if (brand == heif_avif) {
121 return heif_filetype_yes_supported;
122 }
123 else if (brand == heif_unknown_brand) {
124 return heif_filetype_no;
125 }
126 else if (brand == heif_mif1) {
127 return heif_filetype_maybe;
128 }
129 else {
130 return heif_filetype_yes_unsupported;
131 }
132 }
133
134 return heif_filetype_maybe;
135 }
136
137
heif_main_brand(const uint8_t * data,int len)138 heif_brand heif_main_brand(const uint8_t* data, int len)
139 {
140 if (len < 12) {
141 return heif_unknown_brand;
142 }
143
144 char brand[5];
145 brand[0] = data[8];
146 brand[1] = data[9];
147 brand[2] = data[10];
148 brand[3] = data[11];
149 brand[4] = 0;
150
151 if (strcmp(brand, "heic") == 0) {
152 return heif_heic;
153 }
154 else if (strcmp(brand, "heix") == 0) {
155 return heif_heix;
156 }
157 else if (strcmp(brand, "hevc") == 0) {
158 return heif_hevc;
159 }
160 else if (strcmp(brand, "hevx") == 0) {
161 return heif_hevx;
162 }
163 else if (strcmp(brand, "heim") == 0) {
164 return heif_heim;
165 }
166 else if (strcmp(brand, "heis") == 0) {
167 return heif_heis;
168 }
169 else if (strcmp(brand, "hevm") == 0) {
170 return heif_hevm;
171 }
172 else if (strcmp(brand, "hevs") == 0) {
173 return heif_hevs;
174 }
175 else if (strcmp(brand, "mif1") == 0) {
176 return heif_mif1;
177 }
178 else if (strcmp(brand, "msf1") == 0) {
179 return heif_msf1;
180 }
181 else if (strcmp(brand, "avif") == 0) {
182 return heif_avif;
183 }
184 else if (strcmp(brand, "avis") == 0) {
185 return heif_avis;
186 }
187 else {
188 return heif_unknown_brand;
189 }
190 }
191
192
193 enum class TriBool
194 {
195 No, Yes, Unknown
196 };
197
is_jpeg(const uint8_t * data,int len)198 TriBool is_jpeg(const uint8_t* data, int len)
199 {
200 if (len < 12) {
201 return TriBool::Unknown;
202 }
203
204 if (data[0] == 0xFF && data[1] == 0xD8 && data[2] == 0xFF && data[3] == 0xE0 &&
205 data[4] == 0x00 && data[5] == 0x10 && data[6] == 0x4A && data[7] == 0x46 &&
206 data[8] == 0x49 && data[9] == 0x46 && data[10] == 0x00 && data[11] == 0x01) {
207 return TriBool::Yes;
208 }
209 if (data[0] == 0xFF && data[1] == 0xD8 && data[2] == 0xFF && data[3] == 0xE1 &&
210 data[6] == 0x45 && data[7] == 0x78 && data[8] == 0x69 && data[9] == 0x66 &&
211 data[10] == 0x00 && data[11] == 0x00) {
212 return TriBool::Yes;
213 }
214 else {
215 return TriBool::No;
216 }
217 }
218
219
is_png(const uint8_t * data,int len)220 TriBool is_png(const uint8_t* data, int len)
221 {
222 if (len < 8) {
223 return TriBool::Unknown;
224 }
225
226 if (data[0] == 0x89 && data[1] == 0x50 && data[2] == 0x4E && data[3] == 0x47 &&
227 data[4] == 0x0D && data[5] == 0x0A && data[6] == 0x1A && data[7] == 0x0A) {
228 return TriBool::Yes;
229 }
230 else {
231 return TriBool::No;
232 }
233 }
234
235
heif_get_file_mime_type(const uint8_t * data,int len)236 const char* heif_get_file_mime_type(const uint8_t* data, int len)
237 {
238 heif_brand mainBrand = heif_main_brand(data, len);
239
240 if (mainBrand == heif_heic ||
241 mainBrand == heif_heix ||
242 mainBrand == heif_heim ||
243 mainBrand == heif_heis) {
244 return "image/heic";
245 }
246 else if (mainBrand == heif_mif1) {
247 return "image/heif";
248 }
249 else if (mainBrand == heif_hevc ||
250 mainBrand == heif_hevx ||
251 mainBrand == heif_hevm ||
252 mainBrand == heif_hevs) {
253 return "image/heic-sequence";
254 }
255 else if (mainBrand == heif_msf1) {
256 return "image/heif-sequence";
257 }
258 else if (mainBrand == heif_avif) {
259 return "image/avif";
260 }
261 else if (mainBrand == heif_avis) {
262 return "image/avif-sequence";
263 }
264 else if (is_jpeg(data, len) == TriBool::Yes) {
265 return "image/jpeg";
266 }
267 else if (is_png(data, len) == TriBool::Yes) {
268 return "image/png";
269 }
270 else {
271 return "";
272 }
273 }
274
275
heif_context_alloc()276 heif_context* heif_context_alloc()
277 {
278 struct heif_context* ctx = new heif_context;
279 ctx->context = std::make_shared<HeifContext>();
280
281 return ctx;
282 }
283
heif_context_free(heif_context * ctx)284 void heif_context_free(heif_context* ctx)
285 {
286 delete ctx;
287 }
288
heif_context_read_from_file(heif_context * ctx,const char * filename,const struct heif_reading_options *)289 heif_error heif_context_read_from_file(heif_context* ctx, const char* filename,
290 const struct heif_reading_options*)
291 {
292 Error err = ctx->context->read_from_file(filename);
293 return err.error_struct(ctx->context.get());
294 }
295
heif_context_read_from_memory(heif_context * ctx,const void * mem,size_t size,const struct heif_reading_options *)296 heif_error heif_context_read_from_memory(heif_context* ctx, const void* mem, size_t size,
297 const struct heif_reading_options*)
298 {
299 Error err = ctx->context->read_from_memory(mem, size, true);
300 return err.error_struct(ctx->context.get());
301 }
302
heif_context_read_from_memory_without_copy(heif_context * ctx,const void * mem,size_t size,const struct heif_reading_options *)303 heif_error heif_context_read_from_memory_without_copy(heif_context* ctx, const void* mem, size_t size,
304 const struct heif_reading_options*)
305 {
306 Error err = ctx->context->read_from_memory(mem, size, false);
307 return err.error_struct(ctx->context.get());
308 }
309
heif_context_read_from_reader(struct heif_context * ctx,const struct heif_reader * reader_func_table,void * userdata,const struct heif_reading_options *)310 heif_error heif_context_read_from_reader(struct heif_context* ctx,
311 const struct heif_reader* reader_func_table,
312 void* userdata,
313 const struct heif_reading_options*)
314 {
315 auto reader = std::make_shared<StreamReader_CApi>(reader_func_table, userdata);
316
317 Error err = ctx->context->read(reader);
318 return err.error_struct(ctx->context.get());
319 }
320
321 // TODO: heif_error heif_context_read_from_file_descriptor(heif_context*, int fd);
322
heif_context_debug_dump_boxes_to_file(struct heif_context * ctx,int fd)323 void heif_context_debug_dump_boxes_to_file(struct heif_context* ctx, int fd)
324 {
325 if (!ctx) {
326 return;
327 }
328
329 std::string dump = ctx->context->debug_dump_boxes();
330 // TODO(fancycode): Should we return an error if writing fails?
331 #if (defined(__MINGW32__) || defined(__MINGW64__) || defined(_MSC_VER)) && !defined(HAVE_UNISTD_H)
332 auto written = _write(fd, dump.c_str(), dump.size());
333 #else
334 auto written = write(fd, dump.c_str(), dump.size());
335 #endif
336 (void) written;
337 }
338
heif_context_get_primary_image_handle(heif_context * ctx,heif_image_handle ** img)339 heif_error heif_context_get_primary_image_handle(heif_context* ctx, heif_image_handle** img)
340 {
341 if (!img) {
342 Error err(heif_error_Usage_error,
343 heif_suberror_Null_pointer_argument);
344 return err.error_struct(ctx->context.get());
345 }
346
347 std::shared_ptr<HeifContext::Image> primary_image = ctx->context->get_primary_image();
348
349 // It is a requirement of an HEIF file there is always a primary image.
350 // If there is none, an error is generated when loading the file.
351 if (!primary_image) {
352 Error err(heif_error_Invalid_input,
353 heif_suberror_No_or_invalid_primary_item);
354 return err.error_struct(ctx->context.get());
355 }
356
357 *img = new heif_image_handle();
358 (*img)->image = std::move(primary_image);
359 (*img)->context = ctx->context;
360
361 return Error::Ok.error_struct(ctx->context.get());
362 }
363
364
heif_context_get_primary_image_ID(struct heif_context * ctx,heif_item_id * id)365 struct heif_error heif_context_get_primary_image_ID(struct heif_context* ctx, heif_item_id* id)
366 {
367 if (!id) {
368 return Error(heif_error_Usage_error,
369 heif_suberror_Null_pointer_argument).error_struct(ctx->context.get());
370 }
371
372 std::shared_ptr<HeifContext::Image> primary = ctx->context->get_primary_image();
373 if (!primary) {
374 return Error(heif_error_Invalid_input,
375 heif_suberror_No_or_invalid_primary_item).error_struct(ctx->context.get());
376 }
377
378 *id = primary->get_id();
379
380 return Error::Ok.error_struct(ctx->context.get());
381 }
382
383
heif_context_is_top_level_image_ID(struct heif_context * ctx,heif_item_id id)384 int heif_context_is_top_level_image_ID(struct heif_context* ctx, heif_item_id id)
385 {
386 const std::vector<std::shared_ptr<HeifContext::Image>> images = ctx->context->get_top_level_images();
387
388 for (const auto& img : images) {
389 if (img->get_id() == id) {
390 return true;
391 }
392 }
393
394 return false;
395 }
396
397
heif_context_get_number_of_top_level_images(heif_context * ctx)398 int heif_context_get_number_of_top_level_images(heif_context* ctx)
399 {
400 return (int) ctx->context->get_top_level_images().size();
401 }
402
403
heif_context_get_list_of_top_level_image_IDs(struct heif_context * ctx,heif_item_id * ID_array,int count)404 int heif_context_get_list_of_top_level_image_IDs(struct heif_context* ctx,
405 heif_item_id* ID_array,
406 int count)
407 {
408 if (ID_array == nullptr || count == 0 || ctx == nullptr) {
409 return 0;
410 }
411
412
413 // fill in ID values into output array
414
415 const std::vector<std::shared_ptr<HeifContext::Image>> imgs = ctx->context->get_top_level_images();
416 int n = (int) std::min(count, (int) imgs.size());
417 for (int i = 0; i < n; i++) {
418 ID_array[i] = imgs[i]->get_id();
419 }
420
421 return n;
422 }
423
424
heif_context_get_image_handle(struct heif_context * ctx,heif_item_id id,struct heif_image_handle ** imgHdl)425 struct heif_error heif_context_get_image_handle(struct heif_context* ctx,
426 heif_item_id id,
427 struct heif_image_handle** imgHdl)
428 {
429 if (!imgHdl) {
430 Error err(heif_error_Usage_error,
431 heif_suberror_Null_pointer_argument);
432 return err.error_struct(ctx->context.get());
433 }
434
435 const std::vector<std::shared_ptr<HeifContext::Image>> images = ctx->context->get_top_level_images();
436
437 std::shared_ptr<HeifContext::Image> image;
438 for (auto& img : images) {
439 if (img->get_id() == id) {
440 image = img;
441 break;
442 }
443 }
444
445 if (!image) {
446 Error err(heif_error_Usage_error, heif_suberror_Nonexisting_item_referenced);
447 return err.error_struct(ctx->context.get());
448 }
449
450 *imgHdl = new heif_image_handle();
451 (*imgHdl)->image = image;
452 (*imgHdl)->context = ctx->context;
453
454 return Error::Ok.error_struct(ctx->context.get());
455 }
456
457
heif_image_handle_is_primary_image(const struct heif_image_handle * handle)458 int heif_image_handle_is_primary_image(const struct heif_image_handle* handle)
459 {
460 return handle->image->is_primary();
461 }
462
463
heif_image_handle_get_number_of_thumbnails(const struct heif_image_handle * handle)464 int heif_image_handle_get_number_of_thumbnails(const struct heif_image_handle* handle)
465 {
466 return (int) handle->image->get_thumbnails().size();
467 }
468
469
heif_image_handle_get_list_of_thumbnail_IDs(const struct heif_image_handle * handle,heif_item_id * ids,int count)470 int heif_image_handle_get_list_of_thumbnail_IDs(const struct heif_image_handle* handle,
471 heif_item_id* ids, int count)
472 {
473 if (ids == nullptr) {
474 return 0;
475 }
476
477 auto thumbnails = handle->image->get_thumbnails();
478 int n = (int) std::min(count, (int) thumbnails.size());
479
480 for (int i = 0; i < n; i++) {
481 ids[i] = thumbnails[i]->get_id();
482 }
483
484 return n;
485 }
486
487
heif_image_handle_get_thumbnail(const struct heif_image_handle * handle,heif_item_id thumbnail_id,struct heif_image_handle ** out_thumbnail_handle)488 heif_error heif_image_handle_get_thumbnail(const struct heif_image_handle* handle,
489 heif_item_id thumbnail_id,
490 struct heif_image_handle** out_thumbnail_handle)
491 {
492 if (!out_thumbnail_handle) {
493 return Error(heif_error_Usage_error,
494 heif_suberror_Null_pointer_argument).error_struct(handle->image.get());
495 }
496
497 auto thumbnails = handle->image->get_thumbnails();
498 for (auto thumb : thumbnails) {
499 if (thumb->get_id() == thumbnail_id) {
500 *out_thumbnail_handle = new heif_image_handle();
501 (*out_thumbnail_handle)->image = thumb;
502 (*out_thumbnail_handle)->context = handle->context;
503
504 return Error::Ok.error_struct(handle->image.get());
505 }
506 }
507
508 Error err(heif_error_Usage_error, heif_suberror_Nonexisting_item_referenced);
509 return err.error_struct(handle->image.get());
510 }
511
512
heif_image_handle_get_number_of_auxiliary_images(const struct heif_image_handle * handle,int include_alpha_image)513 int heif_image_handle_get_number_of_auxiliary_images(const struct heif_image_handle* handle,
514 int include_alpha_image)
515 {
516 return (int) handle->image->get_aux_images(include_alpha_image).size();
517 }
518
519
heif_image_handle_get_list_of_auxiliary_image_IDs(const struct heif_image_handle * handle,int include_alpha_image,heif_item_id * ids,int count)520 int heif_image_handle_get_list_of_auxiliary_image_IDs(const struct heif_image_handle* handle,
521 int include_alpha_image,
522 heif_item_id* ids, int count)
523 {
524 if (ids == nullptr) {
525 return 0;
526 }
527
528 auto auxImages = handle->image->get_aux_images(include_alpha_image);
529 int n = (int) std::min(count, (int) auxImages.size());
530
531 for (int i = 0; i < n; i++) {
532 ids[i] = auxImages[i]->get_id();
533 }
534
535 return n;
536 }
537
538
heif_image_handle_get_auxiliary_type(const struct heif_image_handle * handle,const char ** out_type)539 struct heif_error heif_image_handle_get_auxiliary_type(const struct heif_image_handle* handle,
540 const char** out_type)
541 {
542 if (out_type == nullptr) {
543 return Error(heif_error_Usage_error,
544 heif_suberror_Null_pointer_argument).error_struct(handle->image.get());
545 }
546
547 auto auxType = handle->image->get_aux_type();
548
549 char* buf = (char*)malloc(auxType.length()+1);
550 strcpy(buf, auxType.c_str());
551 *out_type = buf;
552
553 return {heif_error_Ok, heif_suberror_Unspecified, Error::kSuccess};
554 }
555
556
heif_image_handle_get_auxiliary_image_handle(const struct heif_image_handle * main_image_handle,heif_item_id auxiliary_id,struct heif_image_handle ** out_auxiliary_handle)557 struct heif_error heif_image_handle_get_auxiliary_image_handle(const struct heif_image_handle* main_image_handle,
558 heif_item_id auxiliary_id,
559 struct heif_image_handle** out_auxiliary_handle)
560 {
561 if (!out_auxiliary_handle) {
562 return Error(heif_error_Usage_error,
563 heif_suberror_Null_pointer_argument).error_struct(main_image_handle->image.get());
564 }
565
566 auto auxImages = main_image_handle->image->get_aux_images();
567 for (auto aux : auxImages) {
568 if (aux->get_id() == auxiliary_id) {
569 *out_auxiliary_handle = new heif_image_handle();
570 (*out_auxiliary_handle)->image = aux;
571 (*out_auxiliary_handle)->context = main_image_handle->context;
572
573 return Error::Ok.error_struct(main_image_handle->image.get());
574 }
575 }
576
577 Error err(heif_error_Usage_error, heif_suberror_Nonexisting_item_referenced);
578 return err.error_struct(main_image_handle->image.get());
579 }
580
581
heif_image_handle_get_width(const struct heif_image_handle * handle)582 int heif_image_handle_get_width(const struct heif_image_handle* handle)
583 {
584 if (handle && handle->image) {
585 return handle->image->get_width();
586 }
587 else {
588 return 0;
589 }
590 }
591
592
heif_image_handle_get_height(const struct heif_image_handle * handle)593 int heif_image_handle_get_height(const struct heif_image_handle* handle)
594 {
595 if (handle && handle->image) {
596 return handle->image->get_height();
597 }
598 else {
599 return 0;
600 }
601 }
602
603
heif_image_handle_get_ispe_width(const struct heif_image_handle * handle)604 int heif_image_handle_get_ispe_width(const struct heif_image_handle* handle)
605 {
606 if (handle && handle->image) {
607 return handle->image->get_ispe_width();
608 }
609 else {
610 return 0;
611 }
612 }
613
614
heif_image_handle_get_ispe_height(const struct heif_image_handle * handle)615 int heif_image_handle_get_ispe_height(const struct heif_image_handle* handle)
616 {
617 if (handle && handle->image) {
618 return handle->image->get_ispe_height();
619 }
620 else {
621 return 0;
622 }
623 }
624
625
heif_image_handle_has_alpha_channel(const struct heif_image_handle * handle)626 int heif_image_handle_has_alpha_channel(const struct heif_image_handle* handle)
627 {
628 return handle->image->get_alpha_channel() != nullptr;
629 }
630
631
heif_image_handle_get_luma_bits_per_pixel(const struct heif_image_handle * handle)632 int heif_image_handle_get_luma_bits_per_pixel(const struct heif_image_handle* handle)
633 {
634 return handle->image->get_luma_bits_per_pixel();
635 }
636
637
heif_image_handle_get_chroma_bits_per_pixel(const struct heif_image_handle * handle)638 int heif_image_handle_get_chroma_bits_per_pixel(const struct heif_image_handle* handle)
639 {
640 return handle->image->get_chroma_bits_per_pixel();
641 }
642
643
heif_image_handle_has_depth_image(const struct heif_image_handle * handle)644 int heif_image_handle_has_depth_image(const struct heif_image_handle* handle)
645 {
646 return handle->image->get_depth_channel() != nullptr;
647 }
648
heif_depth_representation_info_free(const struct heif_depth_representation_info * info)649 void heif_depth_representation_info_free(const struct heif_depth_representation_info* info)
650 {
651 delete info;
652 }
653
heif_image_handle_get_depth_image_representation_info(const struct heif_image_handle * handle,heif_item_id depth_image_id,const struct heif_depth_representation_info ** out)654 int heif_image_handle_get_depth_image_representation_info(const struct heif_image_handle* handle,
655 heif_item_id depth_image_id,
656 const struct heif_depth_representation_info** out)
657 {
658 if (out) {
659 if (handle->image->has_depth_representation_info()) {
660 auto info = new heif_depth_representation_info;
661 *info = handle->image->get_depth_representation_info();
662 *out = info;
663 return true;
664 }
665 else {
666 *out = nullptr;
667 }
668 }
669
670 return false;
671 }
672
673
heif_image_handle_get_number_of_depth_images(const struct heif_image_handle * handle)674 int heif_image_handle_get_number_of_depth_images(const struct heif_image_handle* handle)
675 {
676 auto depth_image = handle->image->get_depth_channel();
677
678 if (depth_image) {
679 return 1;
680 }
681 else {
682 return 0;
683 }
684 }
685
686
heif_image_handle_get_list_of_depth_image_IDs(const struct heif_image_handle * handle,heif_item_id * ids,int count)687 int heif_image_handle_get_list_of_depth_image_IDs(const struct heif_image_handle* handle,
688 heif_item_id* ids, int count)
689 {
690 auto depth_image = handle->image->get_depth_channel();
691
692 if (count == 0) {
693 return 0;
694 }
695
696 if (depth_image) {
697 ids[0] = depth_image->get_id();
698 return 1;
699 }
700 else {
701 return 0;
702 }
703 }
704
705
heif_image_handle_get_depth_image_handle(const struct heif_image_handle * handle,heif_item_id depth_id,struct heif_image_handle ** out_depth_handle)706 struct heif_error heif_image_handle_get_depth_image_handle(const struct heif_image_handle* handle,
707 heif_item_id depth_id,
708 struct heif_image_handle** out_depth_handle)
709 {
710 auto depth_image = handle->image->get_depth_channel();
711
712 if (depth_image->get_id() != depth_id) {
713 *out_depth_handle = nullptr;
714
715 Error err(heif_error_Usage_error, heif_suberror_Nonexisting_item_referenced);
716 return err.error_struct(handle->image.get());
717 }
718
719 *out_depth_handle = new heif_image_handle();
720 (*out_depth_handle)->image = depth_image;
721 (*out_depth_handle)->context = handle->context;
722
723 return Error::Ok.error_struct(handle->image.get());
724 }
725
726
heif_decoding_options_alloc()727 heif_decoding_options* heif_decoding_options_alloc()
728 {
729 auto options = new heif_decoding_options;
730
731 options->version = 2;
732
733 options->ignore_transformations = false;
734
735 options->start_progress = NULL;
736 options->on_progress = NULL;
737 options->end_progress = NULL;
738 options->progress_user_data = NULL;
739
740 // version 2
741
742 options->convert_hdr_to_8bit = false;
743
744 return options;
745 }
746
747
heif_decoding_options_free(heif_decoding_options * options)748 void heif_decoding_options_free(heif_decoding_options* options)
749 {
750 delete options;
751 }
752
753
heif_decode_image(const struct heif_image_handle * in_handle,struct heif_image ** out_img,heif_colorspace colorspace,heif_chroma chroma,const struct heif_decoding_options * options)754 struct heif_error heif_decode_image(const struct heif_image_handle* in_handle,
755 struct heif_image** out_img,
756 heif_colorspace colorspace,
757 heif_chroma chroma,
758 const struct heif_decoding_options* options)
759 {
760 std::shared_ptr<HeifPixelImage> img;
761
762 heif_item_id id = in_handle->image->get_id();
763
764 Error err = in_handle->context->decode_image_user(id, img,
765 colorspace,
766 chroma,
767 options);
768 if (err.error_code != heif_error_Ok) {
769 return err.error_struct(in_handle->image.get());
770 }
771
772 *out_img = new heif_image();
773 (*out_img)->image = std::move(img);
774
775 return Error::Ok.error_struct(in_handle->image.get());
776 }
777
778
heif_image_create(int width,int height,heif_colorspace colorspace,heif_chroma chroma,struct heif_image ** image)779 struct heif_error heif_image_create(int width, int height,
780 heif_colorspace colorspace,
781 heif_chroma chroma,
782 struct heif_image** image)
783 {
784 struct heif_image* img = new heif_image;
785 img->image = std::make_shared<HeifPixelImage>();
786
787 img->image->create(width, height, colorspace, chroma);
788
789 *image = img;
790
791 struct heif_error err = {heif_error_Ok, heif_suberror_Unspecified, Error::kSuccess};
792 return err;
793 }
794
heif_image_release(const struct heif_image * img)795 void heif_image_release(const struct heif_image* img)
796 {
797 delete img;
798 }
799
heif_image_handle_release(const struct heif_image_handle * handle)800 void heif_image_handle_release(const struct heif_image_handle* handle)
801 {
802 delete handle;
803 }
804
805
heif_image_get_colorspace(const struct heif_image * img)806 enum heif_colorspace heif_image_get_colorspace(const struct heif_image* img)
807 {
808 return img->image->get_colorspace();
809 }
810
heif_image_get_chroma_format(const struct heif_image * img)811 enum heif_chroma heif_image_get_chroma_format(const struct heif_image* img)
812 {
813 return img->image->get_chroma_format();
814 }
815
816
heif_image_get_width(const struct heif_image * img,enum heif_channel channel)817 int heif_image_get_width(const struct heif_image* img, enum heif_channel channel)
818 {
819 return img->image->get_width(channel);
820 }
821
822
heif_image_get_height(const struct heif_image * img,enum heif_channel channel)823 int heif_image_get_height(const struct heif_image* img, enum heif_channel channel)
824 {
825 return img->image->get_height(channel);
826 }
827
828
heif_image_get_primary_width(const struct heif_image * img)829 int heif_image_get_primary_width(const struct heif_image* img)
830 {
831 if (img->image->get_colorspace() == heif_colorspace_RGB) {
832 if (img->image->get_chroma_format() == heif_chroma_444) {
833 return img->image->get_width(heif_channel_G);
834 }
835 else {
836 return img->image->get_width(heif_channel_interleaved);
837 }
838 }
839 else {
840 return img->image->get_width(heif_channel_Y);
841 }
842 }
843
844
heif_image_get_primary_height(const struct heif_image * img)845 int heif_image_get_primary_height(const struct heif_image* img)
846 {
847 if (img->image->get_colorspace() == heif_colorspace_RGB) {
848 if (img->image->get_chroma_format() == heif_chroma_444) {
849 return img->image->get_height(heif_channel_G);
850 }
851 else {
852 return img->image->get_height(heif_channel_interleaved);
853 }
854 }
855 else {
856 return img->image->get_height(heif_channel_Y);
857 }
858 }
859
860
heif_image_crop(struct heif_image * img,int left,int right,int top,int bottom)861 heif_error heif_image_crop(struct heif_image* img,
862 int left, int right, int top, int bottom)
863 {
864 std::shared_ptr<HeifPixelImage> out_img;
865
866 int w = img->image->get_width();
867 int h = img->image->get_height();
868
869 Error err = img->image->crop(left, w - 1 - right, top, h - 1 - bottom, out_img);
870 if (err) {
871 return err.error_struct(img->image.get());
872 }
873
874 img->image = out_img;
875
876 return heif_error{heif_error_Ok, heif_suberror_Unspecified, Error::kSuccess};
877 }
878
879
heif_image_get_bits_per_pixel(const struct heif_image * img,enum heif_channel channel)880 int heif_image_get_bits_per_pixel(const struct heif_image* img, enum heif_channel channel)
881 {
882 return img->image->get_storage_bits_per_pixel(channel);
883 }
884
885
heif_image_get_bits_per_pixel_range(const struct heif_image * img,enum heif_channel channel)886 int heif_image_get_bits_per_pixel_range(const struct heif_image* img, enum heif_channel channel)
887 {
888 return img->image->get_bits_per_pixel(channel);
889 }
890
891
heif_image_has_channel(const struct heif_image * img,enum heif_channel channel)892 int heif_image_has_channel(const struct heif_image* img, enum heif_channel channel)
893 {
894 return img->image->has_channel(channel);
895 }
896
897
heif_image_add_plane(struct heif_image * image,heif_channel channel,int width,int height,int bit_depth)898 struct heif_error heif_image_add_plane(struct heif_image* image,
899 heif_channel channel, int width, int height, int bit_depth)
900 {
901 if (!image->image->add_plane(channel, width, height, bit_depth)) {
902 struct heif_error err = {heif_error_Memory_allocation_error,
903 heif_suberror_Unspecified,
904 "Cannot allocate memory for image plane"};
905 return err;
906 }
907 else {
908 struct heif_error err = {heif_error_Ok, heif_suberror_Unspecified, Error::kSuccess};
909 return err;
910 }
911 }
912
913
heif_image_get_plane_readonly(const struct heif_image * image,enum heif_channel channel,int * out_stride)914 const uint8_t* heif_image_get_plane_readonly(const struct heif_image* image,
915 enum heif_channel channel,
916 int* out_stride)
917 {
918 if (!image || !image->image) {
919 *out_stride = 0;
920 return nullptr;
921 }
922
923 return image->image->get_plane(channel, out_stride);
924 }
925
926
heif_image_get_plane(struct heif_image * image,enum heif_channel channel,int * out_stride)927 uint8_t* heif_image_get_plane(struct heif_image* image,
928 enum heif_channel channel,
929 int* out_stride)
930 {
931 if (!image || !image->image) {
932 *out_stride = 0;
933 return nullptr;
934 }
935
936 return image->image->get_plane(channel, out_stride);
937 }
938
939
heif_image_scale_image(const struct heif_image * input,struct heif_image ** output,int width,int height,const struct heif_scaling_options * options)940 struct heif_error heif_image_scale_image(const struct heif_image* input,
941 struct heif_image** output,
942 int width, int height,
943 const struct heif_scaling_options* options)
944 {
945 std::shared_ptr<HeifPixelImage> out_img;
946
947 Error err = input->image->scale_nearest_neighbor(out_img, width, height);
948 if (err) {
949 return err.error_struct(input->image.get());
950 }
951
952 *output = new heif_image;
953 (*output)->image = out_img;
954
955 return Error::Ok.error_struct(input->image.get());
956 }
957
heif_image_set_raw_color_profile(struct heif_image * image,const char * color_profile_type_fourcc,const void * profile_data,const size_t profile_size)958 struct heif_error heif_image_set_raw_color_profile(struct heif_image* image,
959 const char* color_profile_type_fourcc,
960 const void* profile_data,
961 const size_t profile_size)
962 {
963 if (strlen(color_profile_type_fourcc) != 4) {
964 heif_error err = {heif_error_Usage_error,
965 heif_suberror_Unspecified,
966 "Invalid color_profile_type (must be 4 characters)"};
967 return err;
968 }
969
970 uint32_t color_profile_type = fourcc(color_profile_type_fourcc);
971
972 std::vector<uint8_t> data;
973 data.insert(data.end(),
974 (const uint8_t*) profile_data,
975 (const uint8_t*) profile_data + profile_size);
976
977 auto color_profile = std::make_shared<color_profile_raw>(color_profile_type, data);
978
979 image->image->set_color_profile_icc(color_profile);
980
981 struct heif_error err = {heif_error_Ok, heif_suberror_Unspecified, Error::kSuccess};
982 return err;
983 }
984
985
heif_image_set_nclx_color_profile(struct heif_image * image,const struct heif_color_profile_nclx * color_profile)986 struct heif_error heif_image_set_nclx_color_profile(struct heif_image* image,
987 const struct heif_color_profile_nclx* color_profile)
988 {
989 auto nclx = std::make_shared<color_profile_nclx>();
990
991 nclx->set_colour_primaries(color_profile->color_primaries);
992 nclx->set_transfer_characteristics(color_profile->transfer_characteristics);
993 nclx->set_matrix_coefficients(color_profile->matrix_coefficients);
994 nclx->set_full_range_flag(color_profile->full_range_flag);
995
996 image->image->set_color_profile_nclx(nclx);
997
998 return error_Ok;
999 }
1000
1001
1002 /*
1003 void heif_image_remove_color_profile(struct heif_image* image)
1004 {
1005 image->image->set_color_profile(nullptr);
1006 }
1007 */
1008
1009
heif_image_handle_get_number_of_metadata_blocks(const struct heif_image_handle * handle,const char * type_filter)1010 int heif_image_handle_get_number_of_metadata_blocks(const struct heif_image_handle* handle,
1011 const char* type_filter)
1012 {
1013 auto metadata_list = handle->image->get_metadata();
1014
1015 int cnt = 0;
1016 for (const auto& metadata : metadata_list) {
1017 if (type_filter == nullptr ||
1018 metadata->item_type == type_filter) {
1019 cnt++;
1020 }
1021 }
1022
1023 return cnt;
1024 }
1025
1026
heif_image_handle_get_list_of_metadata_block_IDs(const struct heif_image_handle * handle,const char * type_filter,heif_item_id * ids,int count)1027 int heif_image_handle_get_list_of_metadata_block_IDs(const struct heif_image_handle* handle,
1028 const char* type_filter,
1029 heif_item_id* ids, int count)
1030 {
1031 auto metadata_list = handle->image->get_metadata();
1032
1033 int cnt = 0;
1034 for (const auto& metadata : metadata_list) {
1035 if (type_filter == nullptr ||
1036 metadata->item_type == type_filter) {
1037 if (cnt < count) {
1038 ids[cnt] = metadata->item_id;
1039 cnt++;
1040 }
1041 else {
1042 break;
1043 }
1044 }
1045 }
1046
1047 return cnt;
1048 }
1049
1050
heif_image_handle_get_metadata_type(const struct heif_image_handle * handle,heif_item_id metadata_id)1051 const char* heif_image_handle_get_metadata_type(const struct heif_image_handle* handle,
1052 heif_item_id metadata_id)
1053 {
1054 auto metadata_list = handle->image->get_metadata();
1055
1056 for (auto metadata : metadata_list) {
1057 if (metadata->item_id == metadata_id) {
1058 return metadata->item_type.c_str();
1059 }
1060 }
1061
1062 return NULL;
1063 }
1064
1065
heif_image_handle_get_metadata_content_type(const struct heif_image_handle * handle,heif_item_id metadata_id)1066 const char* heif_image_handle_get_metadata_content_type(const struct heif_image_handle* handle,
1067 heif_item_id metadata_id)
1068 {
1069 auto metadata_list = handle->image->get_metadata();
1070
1071 for (auto metadata : metadata_list) {
1072 if (metadata->item_id == metadata_id) {
1073 return metadata->content_type.c_str();
1074 }
1075 }
1076
1077 return NULL;
1078 }
1079
1080
heif_image_handle_get_metadata_size(const struct heif_image_handle * handle,heif_item_id metadata_id)1081 size_t heif_image_handle_get_metadata_size(const struct heif_image_handle* handle,
1082 heif_item_id metadata_id)
1083 {
1084 auto metadata_list = handle->image->get_metadata();
1085
1086 for (auto metadata : metadata_list) {
1087 if (metadata->item_id == metadata_id) {
1088 return metadata->m_data.size();
1089 }
1090 }
1091
1092 return 0;
1093 }
1094
1095
heif_image_handle_get_metadata(const struct heif_image_handle * handle,heif_item_id metadata_id,void * out_data)1096 struct heif_error heif_image_handle_get_metadata(const struct heif_image_handle* handle,
1097 heif_item_id metadata_id,
1098 void* out_data)
1099 {
1100 if (out_data == nullptr) {
1101 Error err(heif_error_Usage_error,
1102 heif_suberror_Null_pointer_argument);
1103 return err.error_struct(handle->image.get());
1104 }
1105
1106 auto metadata_list = handle->image->get_metadata();
1107
1108 for (auto metadata : metadata_list) {
1109 if (metadata->item_id == metadata_id) {
1110 memcpy(out_data,
1111 metadata->m_data.data(),
1112 metadata->m_data.size());
1113
1114 return Error::Ok.error_struct(handle->image.get());
1115 }
1116 }
1117
1118 Error err(heif_error_Usage_error,
1119 heif_suberror_Nonexisting_item_referenced);
1120 return err.error_struct(handle->image.get());
1121 }
1122
heif_image_handle_get_color_profile_type(const struct heif_image_handle * handle)1123 heif_color_profile_type heif_image_handle_get_color_profile_type(const struct heif_image_handle* handle)
1124 {
1125 auto profile_icc = handle->image->get_color_profile_icc();
1126 if (profile_icc) {
1127 return (heif_color_profile_type) profile_icc->get_type();
1128 }
1129
1130 auto profile_nclx = handle->image->get_color_profile_nclx();
1131 if (profile_nclx) {
1132 return (heif_color_profile_type) profile_nclx->get_type();
1133 }
1134 else {
1135 return heif_color_profile_type_not_present;
1136 }
1137 }
1138
heif_image_handle_get_raw_color_profile_size(const struct heif_image_handle * handle)1139 size_t heif_image_handle_get_raw_color_profile_size(const struct heif_image_handle* handle)
1140 {
1141 auto profile_icc = handle->image->get_color_profile_icc();
1142 if (profile_icc) {
1143 return profile_icc->get_data().size();
1144 }
1145 else {
1146 return 0;
1147 }
1148 }
1149
1150
heif_image_handle_get_nclx_color_profile(const struct heif_image_handle * handle,struct heif_color_profile_nclx ** out_data)1151 struct heif_error heif_image_handle_get_nclx_color_profile(const struct heif_image_handle* handle,
1152 struct heif_color_profile_nclx** out_data)
1153 {
1154 if (!out_data) {
1155 Error err(heif_error_Usage_error,
1156 heif_suberror_Null_pointer_argument);
1157 return err.error_struct(handle->image.get());
1158 }
1159
1160 auto nclx_profile = handle->image->get_color_profile_nclx();
1161 if (!nclx_profile) {
1162 Error err(heif_error_Color_profile_does_not_exist,
1163 heif_suberror_Unspecified);
1164 return err.error_struct(handle->image.get());
1165 }
1166
1167 Error err = nclx_profile->get_nclx_color_profile(out_data);
1168
1169 return err.error_struct(handle->image.get());
1170 }
1171
1172
heif_image_handle_get_raw_color_profile(const struct heif_image_handle * handle,void * out_data)1173 struct heif_error heif_image_handle_get_raw_color_profile(const struct heif_image_handle* handle,
1174 void* out_data)
1175 {
1176 if (out_data == nullptr) {
1177 Error err(heif_error_Usage_error,
1178 heif_suberror_Null_pointer_argument);
1179 return err.error_struct(handle->image.get());
1180 }
1181
1182 auto raw_profile = handle->image->get_color_profile_icc();
1183 if (raw_profile) {
1184 memcpy(out_data,
1185 raw_profile->get_data().data(),
1186 raw_profile->get_data().size());
1187 }
1188 else {
1189 Error err(heif_error_Color_profile_does_not_exist,
1190 heif_suberror_Unspecified);
1191 return err.error_struct(handle->image.get());
1192 }
1193
1194 return Error::Ok.error_struct(handle->image.get());
1195 }
1196
1197
heif_image_get_color_profile_type(const struct heif_image * image)1198 enum heif_color_profile_type heif_image_get_color_profile_type(const struct heif_image* image)
1199 {
1200 std::shared_ptr<const color_profile> profile;
1201
1202 profile = image->image->get_color_profile_icc();
1203 if (!profile) {
1204 profile = image->image->get_color_profile_nclx();
1205 }
1206
1207 if (!profile) {
1208 return heif_color_profile_type_not_present;
1209 }
1210 else {
1211 return (heif_color_profile_type) profile->get_type();
1212 }
1213 }
1214
1215
heif_image_get_raw_color_profile_size(const struct heif_image * image)1216 size_t heif_image_get_raw_color_profile_size(const struct heif_image* image)
1217 {
1218 auto raw_profile = image->image->get_color_profile_icc();
1219 if (raw_profile) {
1220 return raw_profile->get_data().size();
1221 }
1222 else {
1223 return 0;
1224 }
1225 }
1226
1227
heif_image_get_raw_color_profile(const struct heif_image * image,void * out_data)1228 struct heif_error heif_image_get_raw_color_profile(const struct heif_image* image,
1229 void* out_data)
1230 {
1231 if (out_data == nullptr) {
1232 Error err(heif_error_Usage_error,
1233 heif_suberror_Null_pointer_argument);
1234 return err.error_struct(image->image.get());
1235 }
1236
1237 auto raw_profile = image->image->get_color_profile_icc();
1238 if (raw_profile) {
1239 memcpy(out_data,
1240 raw_profile->get_data().data(),
1241 raw_profile->get_data().size());
1242 }
1243
1244 return Error::Ok.error_struct(image->image.get());
1245 }
1246
1247
heif_image_get_nclx_color_profile(const struct heif_image * image,struct heif_color_profile_nclx ** out_data)1248 struct heif_error heif_image_get_nclx_color_profile(const struct heif_image* image,
1249 struct heif_color_profile_nclx** out_data)
1250 {
1251 if (!out_data) {
1252 Error err(heif_error_Usage_error,
1253 heif_suberror_Null_pointer_argument);
1254 return err.error_struct(image->image.get());
1255 }
1256
1257 auto nclx_profile = image->image->get_color_profile_nclx();
1258 Error err = nclx_profile->get_nclx_color_profile(out_data);
1259
1260 return err.error_struct(image->image.get());
1261 }
1262
1263
heif_nclx_color_profile_alloc()1264 struct heif_color_profile_nclx* heif_nclx_color_profile_alloc()
1265 {
1266 return color_profile_nclx::alloc_nclx_color_profile();
1267 }
1268
1269
heif_nclx_color_profile_free(struct heif_color_profile_nclx * nclx_profile)1270 void heif_nclx_color_profile_free(struct heif_color_profile_nclx* nclx_profile)
1271 {
1272 color_profile_nclx::free_nclx_color_profile(nclx_profile);
1273 }
1274
1275
1276 // DEPRECATED
heif_register_decoder(heif_context * heif,const heif_decoder_plugin * decoder_plugin)1277 struct heif_error heif_register_decoder(heif_context* heif, const heif_decoder_plugin* decoder_plugin)
1278 {
1279 if (!decoder_plugin) {
1280 return error_null_parameter;
1281 }
1282 else if (decoder_plugin->plugin_api_version != 1) {
1283 return error_unsupported_plugin_version;
1284 }
1285
1286 heif->context->register_decoder(decoder_plugin);
1287 return Error::Ok.error_struct(heif->context.get());
1288 }
1289
1290
heif_register_decoder_plugin(const heif_decoder_plugin * decoder_plugin)1291 struct heif_error heif_register_decoder_plugin(const heif_decoder_plugin* decoder_plugin)
1292 {
1293 if (!decoder_plugin) {
1294 return error_null_parameter;
1295 }
1296 else if (decoder_plugin->plugin_api_version != 1) {
1297 return error_unsupported_plugin_version;
1298 }
1299
1300 register_decoder(decoder_plugin);
1301 return error_Ok;
1302 }
1303
1304
heif_register_encoder_plugin(const heif_encoder_plugin * encoder_plugin)1305 struct heif_error heif_register_encoder_plugin(const heif_encoder_plugin* encoder_plugin)
1306 {
1307 if (!encoder_plugin) {
1308 return error_null_parameter;
1309 }
1310 else if (encoder_plugin->plugin_api_version != 1) {
1311 return error_unsupported_plugin_version;
1312 }
1313
1314 register_encoder(encoder_plugin);
1315 return error_Ok;
1316 }
1317
1318
1319
1320
1321 /*
1322 int heif_image_get_number_of_data_chunks(heif_image* img);
1323
1324 void heif_image_get_data_chunk(heif_image* img, int chunk_index,
1325 uint8_t const*const* dataptr,
1326 int const* data_size);
1327
1328 void heif_image_free_data_chunk(heif_image* img, int chunk_index);
1329 */
1330
1331
1332 /*
1333 void heif_context_reset(struct heif_context* ctx)
1334 {
1335 ctx->context->reset_to_empty_heif();
1336 }
1337 */
1338
heif_file_writer_write(struct heif_context * ctx,const void * data,size_t size,void * userdata)1339 static struct heif_error heif_file_writer_write(struct heif_context* ctx,
1340 const void* data, size_t size, void* userdata)
1341 {
1342 const char* filename = static_cast<const char*>(userdata);
1343
1344 #ifdef _MSC_VER
1345 std::ofstream ostr(HeifFile::convert_utf8_path_to_utf16(filename).c_str(), std::ios_base::binary);
1346 #else
1347 std::ofstream ostr(filename, std::ios_base::binary);
1348 #endif
1349 ostr.write(static_cast<const char*>(data), size);
1350 // TODO: handle write errors
1351 return Error::Ok.error_struct(ctx->context.get());
1352 }
1353
1354
heif_context_write_to_file(struct heif_context * ctx,const char * filename)1355 struct heif_error heif_context_write_to_file(struct heif_context* ctx,
1356 const char* filename)
1357 {
1358 heif_writer writer;
1359 writer.writer_api_version = 1;
1360 writer.write = heif_file_writer_write;
1361 return heif_context_write(ctx, &writer, (void*) filename);
1362 }
1363
1364
heif_context_write(struct heif_context * ctx,struct heif_writer * writer,void * userdata)1365 struct heif_error heif_context_write(struct heif_context* ctx,
1366 struct heif_writer* writer,
1367 void* userdata)
1368 {
1369 if (!writer) {
1370 return Error(heif_error_Usage_error,
1371 heif_suberror_Null_pointer_argument).error_struct(ctx->context.get());
1372 }
1373 else if (writer->writer_api_version != 1) {
1374 Error err(heif_error_Usage_error, heif_suberror_Unsupported_writer_version);
1375 return err.error_struct(ctx->context.get());
1376 }
1377
1378 StreamWriter swriter;
1379 ctx->context->write(swriter);
1380
1381 const auto& data = swriter.get_data();
1382 return writer->write(ctx, data.data(), data.size(), userdata);
1383 }
1384
1385
heif_context_get_encoder_descriptors(struct heif_context * ctx,enum heif_compression_format format,const char * name,const struct heif_encoder_descriptor ** out_encoder_descriptors,int count)1386 int heif_context_get_encoder_descriptors(struct heif_context* ctx,
1387 enum heif_compression_format format,
1388 const char* name,
1389 const struct heif_encoder_descriptor** out_encoder_descriptors,
1390 int count)
1391 {
1392 if (out_encoder_descriptors == nullptr || count <= 0) {
1393 return 0;
1394 }
1395
1396 std::vector<const struct heif_encoder_descriptor*> descriptors;
1397 descriptors = get_filtered_encoder_descriptors(format, name);
1398
1399 int i;
1400 for (i = 0; i < count && static_cast<size_t>(i) < descriptors.size(); i++) {
1401 out_encoder_descriptors[i] = descriptors[i];
1402 }
1403
1404 return i;
1405 }
1406
1407
heif_encoder_descriptor_get_name(const struct heif_encoder_descriptor * descriptor)1408 const char* heif_encoder_descriptor_get_name(const struct heif_encoder_descriptor* descriptor)
1409 {
1410 return descriptor->plugin->get_plugin_name();
1411 }
1412
1413
heif_encoder_descriptor_get_id_name(const struct heif_encoder_descriptor * descriptor)1414 const char* heif_encoder_descriptor_get_id_name(const struct heif_encoder_descriptor* descriptor)
1415 {
1416 return descriptor->plugin->id_name;
1417 }
1418
1419
1420 enum heif_compression_format
heif_encoder_descriptor_get_compression_format(const struct heif_encoder_descriptor * descriptor)1421 heif_encoder_descriptor_get_compression_format(const struct heif_encoder_descriptor* descriptor)
1422 {
1423 return descriptor->plugin->compression_format;
1424 }
1425
1426
heif_encoder_descriptor_supports_lossy_compression(const struct heif_encoder_descriptor * descriptor)1427 int heif_encoder_descriptor_supports_lossy_compression(const struct heif_encoder_descriptor* descriptor)
1428 {
1429 return descriptor->plugin->supports_lossy_compression;
1430 }
1431
1432
heif_encoder_descriptor_supports_lossless_compression(const struct heif_encoder_descriptor * descriptor)1433 int heif_encoder_descriptor_supports_lossless_compression(const struct heif_encoder_descriptor* descriptor)
1434 {
1435 return descriptor->plugin->supports_lossless_compression;
1436 }
1437
1438
1439 // DEPRECATED: typo in functino name
heif_encoder_descriptor_supportes_lossy_compression(const struct heif_encoder_descriptor * descriptor)1440 int heif_encoder_descriptor_supportes_lossy_compression(const struct heif_encoder_descriptor* descriptor)
1441 {
1442 return descriptor->plugin->supports_lossy_compression;
1443 }
1444
1445
1446 // DEPRECATED: typo in functino name
heif_encoder_descriptor_supportes_lossless_compression(const struct heif_encoder_descriptor * descriptor)1447 int heif_encoder_descriptor_supportes_lossless_compression(const struct heif_encoder_descriptor* descriptor)
1448 {
1449 return descriptor->plugin->supports_lossless_compression;
1450 }
1451
1452
heif_encoder_get_name(const struct heif_encoder * encoder)1453 const char* heif_encoder_get_name(const struct heif_encoder* encoder)
1454 {
1455 return encoder->plugin->get_plugin_name();
1456 }
1457
1458
heif_context_get_encoder(struct heif_context * context,const struct heif_encoder_descriptor * descriptor,struct heif_encoder ** encoder)1459 struct heif_error heif_context_get_encoder(struct heif_context* context,
1460 const struct heif_encoder_descriptor* descriptor,
1461 struct heif_encoder** encoder)
1462 {
1463 // Note: be aware that context may be NULL as we explicitly allowed that in an earlier documentation.
1464
1465 if (!descriptor || !encoder) {
1466 Error err(heif_error_Usage_error,
1467 heif_suberror_Null_pointer_argument);
1468 return err.error_struct(context ? context->context.get() : nullptr);
1469 }
1470
1471 *encoder = new struct heif_encoder(descriptor->plugin);
1472 return (*encoder)->alloc();
1473 }
1474
1475
heif_have_decoder_for_format(enum heif_compression_format format)1476 int heif_have_decoder_for_format(enum heif_compression_format format)
1477 {
1478 auto plugin = heif::get_decoder(format);
1479 return plugin != nullptr;
1480 }
1481
1482
heif_have_encoder_for_format(enum heif_compression_format format)1483 int heif_have_encoder_for_format(enum heif_compression_format format)
1484 {
1485 auto plugin = heif::get_encoder(format);
1486 return plugin != nullptr;
1487 }
1488
1489
heif_context_get_encoder_for_format(struct heif_context * context,enum heif_compression_format format,struct heif_encoder ** encoder)1490 struct heif_error heif_context_get_encoder_for_format(struct heif_context* context,
1491 enum heif_compression_format format,
1492 struct heif_encoder** encoder)
1493 {
1494 // Note: be aware that context may be NULL as we explicitly allowed that in an earlier documentation.
1495
1496 if (!encoder) {
1497 Error err(heif_error_Usage_error,
1498 heif_suberror_Null_pointer_argument);
1499 return err.error_struct(context ? context->context.get() : nullptr);
1500 }
1501
1502 std::vector<const struct heif_encoder_descriptor*> descriptors;
1503 descriptors = get_filtered_encoder_descriptors(format, nullptr);
1504
1505 if (descriptors.size() > 0) {
1506 *encoder = new struct heif_encoder(descriptors[0]->plugin);
1507 return (*encoder)->alloc();
1508 }
1509 else {
1510 Error err(heif_error_Unsupported_filetype, // TODO: is this the right error code?
1511 heif_suberror_Unspecified);
1512 return err.error_struct(context ? context->context.get() : nullptr);
1513 }
1514 }
1515
1516
heif_encoder_release(struct heif_encoder * encoder)1517 void heif_encoder_release(struct heif_encoder* encoder)
1518 {
1519 if (encoder) {
1520 delete encoder;
1521 }
1522 }
1523
1524
1525 //struct heif_encoder_param* heif_encoder_get_param(struct heif_encoder* encoder)
1526 //{
1527 // return nullptr;
1528 //}
1529
1530
1531 //void heif_encoder_release_param(struct heif_encoder_param* param)
1532 //{
1533 //}
1534
1535
1536 // Set a 'quality' factor (0-100). How this is mapped to actual encoding parameters is
1537 // encoder dependent.
heif_encoder_set_lossy_quality(struct heif_encoder * encoder,int quality)1538 struct heif_error heif_encoder_set_lossy_quality(struct heif_encoder* encoder,
1539 int quality)
1540 {
1541 if (!encoder) {
1542 return Error(heif_error_Usage_error,
1543 heif_suberror_Null_pointer_argument).error_struct(nullptr);
1544 }
1545
1546 return encoder->plugin->set_parameter_quality(encoder->encoder, quality);
1547 }
1548
1549
heif_encoder_set_lossless(struct heif_encoder * encoder,int enable)1550 struct heif_error heif_encoder_set_lossless(struct heif_encoder* encoder, int enable)
1551 {
1552 if (!encoder) {
1553 return Error(heif_error_Usage_error,
1554 heif_suberror_Null_pointer_argument).error_struct(nullptr);
1555 }
1556
1557 return encoder->plugin->set_parameter_lossless(encoder->encoder, enable);
1558 }
1559
1560
heif_encoder_set_logging_level(struct heif_encoder * encoder,int level)1561 struct heif_error heif_encoder_set_logging_level(struct heif_encoder* encoder, int level)
1562 {
1563 if (!encoder) {
1564 return Error(heif_error_Usage_error,
1565 heif_suberror_Null_pointer_argument).error_struct(nullptr);
1566 }
1567
1568 if (encoder->plugin->set_parameter_logging_level) {
1569 return encoder->plugin->set_parameter_logging_level(encoder->encoder, level);
1570 }
1571
1572 struct heif_error err = {heif_error_Ok, heif_suberror_Unspecified, kSuccess};
1573 return err;
1574 }
1575
1576
heif_encoder_list_parameters(struct heif_encoder * encoder)1577 const struct heif_encoder_parameter* const* heif_encoder_list_parameters(struct heif_encoder* encoder)
1578 {
1579 return encoder->plugin->list_parameters(encoder->encoder);
1580 }
1581
1582
heif_encoder_parameter_get_name(const struct heif_encoder_parameter * param)1583 const char* heif_encoder_parameter_get_name(const struct heif_encoder_parameter* param)
1584 {
1585 return param->name;
1586 }
1587
1588 enum heif_encoder_parameter_type
heif_encoder_parameter_get_type(const struct heif_encoder_parameter * param)1589 heif_encoder_parameter_get_type(const struct heif_encoder_parameter* param)
1590 {
1591 return param->type;
1592 }
1593
1594
heif_encoder_set_parameter_integer(struct heif_encoder * encoder,const char * parameter_name,int value)1595 struct heif_error heif_encoder_set_parameter_integer(struct heif_encoder* encoder,
1596 const char* parameter_name,
1597 int value)
1598 {
1599 // --- check if parameter is valid
1600
1601 for (const struct heif_encoder_parameter* const* params = heif_encoder_list_parameters(encoder);
1602 *params;
1603 params++) {
1604 if (strcmp((*params)->name, parameter_name) == 0) {
1605
1606 int have_minimum = 0, have_maximum = 0, minimum = 0, maximum = 0, num_valid_values = 0;
1607 const int* valid_values;
1608 heif_error err = heif_encoder_parameter_get_valid_integer_values((*params), &have_minimum, &have_maximum,
1609 &minimum, &maximum,
1610 &num_valid_values,
1611 &valid_values);
1612 if (err.code) {
1613 return err;
1614 }
1615
1616 if ((have_minimum && value < minimum) ||
1617 (have_maximum && value > maximum)) {
1618 return error_invalid_parameter_value;
1619 }
1620
1621 if (num_valid_values > 0) {
1622 bool found = false;
1623 for (int i = 0; i < num_valid_values; i++) {
1624 if (valid_values[i] == value) {
1625 found = true;
1626 break;
1627 }
1628 }
1629
1630 if (!found) {
1631 return error_invalid_parameter_value;
1632 }
1633 }
1634 }
1635 }
1636
1637
1638 // --- parameter is ok, pass it to the encoder plugin
1639
1640 return encoder->plugin->set_parameter_integer(encoder->encoder, parameter_name, value);
1641 }
1642
heif_encoder_get_parameter_integer(struct heif_encoder * encoder,const char * parameter_name,int * value_ptr)1643 struct heif_error heif_encoder_get_parameter_integer(struct heif_encoder* encoder,
1644 const char* parameter_name,
1645 int* value_ptr)
1646 {
1647 return encoder->plugin->get_parameter_integer(encoder->encoder, parameter_name, value_ptr);
1648 }
1649
1650 struct heif_error
heif_encoder_parameter_get_valid_integer_range(const struct heif_encoder_parameter * param,int * have_minimum_maximum,int * minimum,int * maximum)1651 heif_encoder_parameter_get_valid_integer_range(const struct heif_encoder_parameter* param,
1652 int* have_minimum_maximum,
1653 int* minimum, int* maximum)
1654 {
1655 if (param->type != heif_encoder_parameter_type_integer) {
1656 return error_unsupported_parameter; // TODO: correct error ?
1657 }
1658
1659 if (param->integer.have_minimum_maximum) {
1660 if (minimum) {
1661 *minimum = param->integer.minimum;
1662 }
1663
1664 if (maximum) {
1665 *maximum = param->integer.maximum;
1666 }
1667 }
1668
1669 if (have_minimum_maximum) {
1670 *have_minimum_maximum = param->integer.have_minimum_maximum;
1671 }
1672
1673 return error_Ok;
1674 }
1675
1676 LIBHEIF_API
heif_encoder_parameter_get_valid_integer_values(const struct heif_encoder_parameter * param,int * have_minimum,int * have_maximum,int * minimum,int * maximum,int * num_valid_values,const int ** out_integer_array)1677 struct heif_error heif_encoder_parameter_get_valid_integer_values(const struct heif_encoder_parameter* param,
1678 int* have_minimum, int* have_maximum,
1679 int* minimum, int* maximum,
1680 int* num_valid_values,
1681 const int** out_integer_array)
1682 {
1683 if (param->type != heif_encoder_parameter_type_integer) {
1684 return error_unsupported_parameter; // TODO: correct error ?
1685 }
1686
1687
1688 // --- range of values
1689
1690 if (param->integer.have_minimum_maximum) {
1691 if (minimum) {
1692 *minimum = param->integer.minimum;
1693 }
1694
1695 if (maximum) {
1696 *maximum = param->integer.maximum;
1697 }
1698 }
1699
1700 if (have_minimum) {
1701 *have_minimum = param->integer.have_minimum_maximum;
1702 }
1703
1704 if (have_maximum) {
1705 *have_maximum = param->integer.have_minimum_maximum;
1706 }
1707
1708
1709 // --- set of valid values
1710
1711 if (param->integer.num_valid_values > 0) {
1712 if (out_integer_array) {
1713 *out_integer_array = param->integer.valid_values;
1714 }
1715 }
1716
1717 if (num_valid_values) {
1718 *num_valid_values = param->integer.num_valid_values;
1719 }
1720
1721 return error_Ok;
1722 }
1723
1724
1725 struct heif_error
heif_encoder_parameter_get_valid_string_values(const struct heif_encoder_parameter * param,const char * const ** out_stringarray)1726 heif_encoder_parameter_get_valid_string_values(const struct heif_encoder_parameter* param,
1727 const char* const** out_stringarray)
1728 {
1729 if (param->type != heif_encoder_parameter_type_string) {
1730 return error_unsupported_parameter; // TODO: correct error ?
1731 }
1732
1733 if (out_stringarray) {
1734 *out_stringarray = param->string.valid_values;
1735 }
1736
1737 return error_Ok;
1738 }
1739
heif_encoder_parameter_integer_valid_range(struct heif_encoder * encoder,const char * parameter_name,int * have_minimum_maximum,int * minimum,int * maximum)1740 struct heif_error heif_encoder_parameter_integer_valid_range(struct heif_encoder* encoder,
1741 const char* parameter_name,
1742 int* have_minimum_maximum,
1743 int* minimum, int* maximum)
1744 {
1745 for (const struct heif_encoder_parameter* const* params = heif_encoder_list_parameters(encoder);
1746 *params;
1747 params++) {
1748 if (strcmp((*params)->name, parameter_name) == 0) {
1749 return heif_encoder_parameter_get_valid_integer_range(*params, have_minimum_maximum,
1750 minimum, maximum);
1751 }
1752 }
1753
1754 return error_unsupported_parameter;
1755 }
1756
heif_encoder_set_parameter_boolean(struct heif_encoder * encoder,const char * parameter_name,int value)1757 struct heif_error heif_encoder_set_parameter_boolean(struct heif_encoder* encoder,
1758 const char* parameter_name,
1759 int value)
1760 {
1761 return encoder->plugin->set_parameter_boolean(encoder->encoder, parameter_name, value);
1762 }
1763
heif_encoder_get_parameter_boolean(struct heif_encoder * encoder,const char * parameter_name,int * value_ptr)1764 struct heif_error heif_encoder_get_parameter_boolean(struct heif_encoder* encoder,
1765 const char* parameter_name,
1766 int* value_ptr)
1767 {
1768 return encoder->plugin->get_parameter_boolean(encoder->encoder, parameter_name, value_ptr);
1769 }
1770
heif_encoder_set_parameter_string(struct heif_encoder * encoder,const char * parameter_name,const char * value)1771 struct heif_error heif_encoder_set_parameter_string(struct heif_encoder* encoder,
1772 const char* parameter_name,
1773 const char* value)
1774 {
1775 return encoder->plugin->set_parameter_string(encoder->encoder, parameter_name, value);
1776 }
1777
heif_encoder_get_parameter_string(struct heif_encoder * encoder,const char * parameter_name,char * value_ptr,int value_size)1778 struct heif_error heif_encoder_get_parameter_string(struct heif_encoder* encoder,
1779 const char* parameter_name,
1780 char* value_ptr, int value_size)
1781 {
1782 return encoder->plugin->get_parameter_string(encoder->encoder, parameter_name,
1783 value_ptr, value_size);
1784 }
1785
heif_encoder_parameter_string_valid_values(struct heif_encoder * encoder,const char * parameter_name,const char * const ** out_stringarray)1786 struct heif_error heif_encoder_parameter_string_valid_values(struct heif_encoder* encoder,
1787 const char* parameter_name,
1788 const char* const** out_stringarray)
1789 {
1790 for (const struct heif_encoder_parameter* const* params = heif_encoder_list_parameters(encoder);
1791 *params;
1792 params++) {
1793 if (strcmp((*params)->name, parameter_name) == 0) {
1794 return heif_encoder_parameter_get_valid_string_values(*params, out_stringarray);
1795 }
1796 }
1797
1798 return error_unsupported_parameter;
1799 }
1800
heif_encoder_parameter_integer_valid_values(struct heif_encoder * encoder,const char * parameter_name,int * have_minimum,int * have_maximum,int * minimum,int * maximum,int * num_valid_values,const int ** out_integer_array)1801 struct heif_error heif_encoder_parameter_integer_valid_values(struct heif_encoder* encoder,
1802 const char* parameter_name,
1803 int* have_minimum, int* have_maximum,
1804 int* minimum, int* maximum,
1805 int* num_valid_values,
1806 const int** out_integer_array)
1807 {
1808 for (const struct heif_encoder_parameter* const* params = heif_encoder_list_parameters(encoder);
1809 *params;
1810 params++) {
1811 if (strcmp((*params)->name, parameter_name) == 0) {
1812 return heif_encoder_parameter_get_valid_integer_values(*params, have_minimum, have_maximum, minimum, maximum,
1813 num_valid_values, out_integer_array);
1814 }
1815 }
1816
1817 return error_unsupported_parameter;
1818 }
1819
1820
parse_boolean(const char * value)1821 static bool parse_boolean(const char* value)
1822 {
1823 if (strcmp(value, "true") == 0) {
1824 return true;
1825 }
1826 else if (strcmp(value, "false") == 0) {
1827 return false;
1828 }
1829 else if (strcmp(value, "1") == 0) {
1830 return true;
1831 }
1832 else if (strcmp(value, "0") == 0) {
1833 return false;
1834 }
1835
1836 return false;
1837 }
1838
1839
heif_encoder_set_parameter(struct heif_encoder * encoder,const char * parameter_name,const char * value)1840 struct heif_error heif_encoder_set_parameter(struct heif_encoder* encoder,
1841 const char* parameter_name,
1842 const char* value)
1843 {
1844 for (const struct heif_encoder_parameter* const* params = heif_encoder_list_parameters(encoder);
1845 *params;
1846 params++) {
1847 if (strcmp((*params)->name, parameter_name) == 0) {
1848 switch ((*params)->type) {
1849 case heif_encoder_parameter_type_integer:
1850 return heif_encoder_set_parameter_integer(encoder, parameter_name, atoi(value));
1851
1852 case heif_encoder_parameter_type_boolean:
1853 return heif_encoder_set_parameter_boolean(encoder, parameter_name, parse_boolean(value));
1854
1855 case heif_encoder_parameter_type_string:
1856 return heif_encoder_set_parameter_string(encoder, parameter_name, value);
1857 break;
1858 }
1859
1860 return error_Ok;
1861 }
1862 }
1863
1864 return heif_encoder_set_parameter_string(encoder, parameter_name, value);
1865
1866 //return error_unsupported_parameter;
1867 }
1868
1869
heif_encoder_get_parameter(struct heif_encoder * encoder,const char * parameter_name,char * value_ptr,int value_size)1870 struct heif_error heif_encoder_get_parameter(struct heif_encoder* encoder,
1871 const char* parameter_name,
1872 char* value_ptr, int value_size)
1873 {
1874 for (const struct heif_encoder_parameter* const* params = heif_encoder_list_parameters(encoder);
1875 *params;
1876 params++) {
1877 if (strcmp((*params)->name, parameter_name) == 0) {
1878 switch ((*params)->type) {
1879 case heif_encoder_parameter_type_integer: {
1880 int value;
1881 struct heif_error error = heif_encoder_get_parameter_integer(encoder, parameter_name, &value);
1882 if (error.code) {
1883 return error;
1884 }
1885 else {
1886 snprintf(value_ptr, value_size, "%d", value);
1887 }
1888 }
1889 break;
1890
1891 case heif_encoder_parameter_type_boolean: {
1892 int value;
1893 struct heif_error error = heif_encoder_get_parameter_boolean(encoder, parameter_name, &value);
1894 if (error.code) {
1895 return error;
1896 }
1897 else {
1898 snprintf(value_ptr, value_size, "%d", value);
1899 }
1900 }
1901 break;
1902
1903 case heif_encoder_parameter_type_string: {
1904 struct heif_error error = heif_encoder_get_parameter_string(encoder, parameter_name,
1905 value_ptr, value_size);
1906 if (error.code) {
1907 return error;
1908 }
1909 }
1910 break;
1911 }
1912
1913 return error_Ok;
1914 }
1915 }
1916
1917 return error_unsupported_parameter;
1918 }
1919
1920
heif_encoder_has_default(struct heif_encoder * encoder,const char * parameter_name)1921 int heif_encoder_has_default(struct heif_encoder* encoder,
1922 const char* parameter_name)
1923 {
1924 for (const struct heif_encoder_parameter* const* params = heif_encoder_list_parameters(encoder);
1925 *params;
1926 params++) {
1927 if (strcmp((*params)->name, parameter_name) == 0) {
1928
1929 if ((*params)->version >= 2) {
1930 return (*params)->has_default;
1931 }
1932 else {
1933 return true;
1934 }
1935 }
1936 }
1937
1938 return false;
1939 }
1940
1941
set_default_options(heif_encoding_options & options)1942 static void set_default_options(heif_encoding_options& options)
1943 {
1944 options.version = 3;
1945
1946 options.save_alpha_channel = true;
1947 options.macOS_compatibility_workaround = true;
1948 options.save_two_colr_boxes_when_ICC_and_nclx_available = false;
1949 }
1950
1951
heif_encoding_options_alloc()1952 heif_encoding_options* heif_encoding_options_alloc()
1953 {
1954 auto options = new heif_encoding_options;
1955
1956 set_default_options(*options);
1957
1958 return options;
1959 }
1960
1961
heif_encoding_options_free(heif_encoding_options * options)1962 void heif_encoding_options_free(heif_encoding_options* options)
1963 {
1964 delete options;
1965 }
1966
heif_context_encode_image(struct heif_context * ctx,const struct heif_image * input_image,struct heif_encoder * encoder,const struct heif_encoding_options * options,struct heif_image_handle ** out_image_handle)1967 struct heif_error heif_context_encode_image(struct heif_context* ctx,
1968 const struct heif_image* input_image,
1969 struct heif_encoder* encoder,
1970 const struct heif_encoding_options* options,
1971 struct heif_image_handle** out_image_handle)
1972 {
1973 if (!encoder) {
1974 return Error(heif_error_Usage_error,
1975 heif_suberror_Null_pointer_argument).error_struct(ctx->context.get());
1976 }
1977
1978 heif_encoding_options default_options;
1979 if (options == nullptr) {
1980 set_default_options(default_options);
1981 options = &default_options;
1982 }
1983
1984 std::shared_ptr<HeifContext::Image> image;
1985 Error error;
1986
1987 error = ctx->context->encode_image(input_image->image,
1988 encoder,
1989 options,
1990 heif_image_input_class_normal,
1991 image);
1992 if (error != Error::Ok) {
1993 return error.error_struct(ctx->context.get());
1994 }
1995
1996 // mark the new image as primary image
1997
1998 if (ctx->context->is_primary_image_set() == false) {
1999 ctx->context->set_primary_image(image);
2000 }
2001
2002 if (out_image_handle) {
2003 *out_image_handle = new heif_image_handle;
2004 (*out_image_handle)->image = image;
2005 (*out_image_handle)->context = ctx->context;
2006 }
2007
2008 return error_Ok;
2009 }
2010
2011
heif_context_assign_thumbnail(struct heif_context * ctx,const struct heif_image_handle * master_image,const struct heif_image_handle * thumbnail_image)2012 struct heif_error heif_context_assign_thumbnail(struct heif_context* ctx,
2013 const struct heif_image_handle* master_image,
2014 const struct heif_image_handle* thumbnail_image)
2015 {
2016 Error error = ctx->context->assign_thumbnail(thumbnail_image->image, master_image->image);
2017 return error.error_struct(ctx->context.get());
2018 }
2019
2020
heif_context_encode_thumbnail(struct heif_context * ctx,const struct heif_image * image,const struct heif_image_handle * image_handle,struct heif_encoder * encoder,const struct heif_encoding_options * options,int bbox_size,struct heif_image_handle ** out_image_handle)2021 struct heif_error heif_context_encode_thumbnail(struct heif_context* ctx,
2022 const struct heif_image* image,
2023 const struct heif_image_handle* image_handle,
2024 struct heif_encoder* encoder,
2025 const struct heif_encoding_options* options,
2026 int bbox_size,
2027 struct heif_image_handle** out_image_handle)
2028 {
2029 std::shared_ptr<HeifContext::Image> thumbnail_image;
2030
2031 heif_encoding_options default_options;
2032 if (options == nullptr) {
2033 set_default_options(default_options);
2034 options = &default_options;
2035 }
2036
2037 Error error = ctx->context->encode_thumbnail(image->image,
2038 encoder,
2039 options,
2040 bbox_size,
2041 thumbnail_image);
2042 if (error != Error::Ok) {
2043 return error.error_struct(ctx->context.get());
2044 }
2045 else if (!thumbnail_image) {
2046 Error err(heif_error_Usage_error,
2047 heif_suberror_Invalid_parameter_value,
2048 "Thumbnail images must be smaller than the original image.");
2049 return err.error_struct(ctx->context.get());
2050 }
2051
2052 error = ctx->context->assign_thumbnail(image_handle->image, thumbnail_image);
2053 if (error != Error::Ok) {
2054 return error.error_struct(ctx->context.get());
2055 }
2056
2057
2058 if (out_image_handle) {
2059 if (thumbnail_image) {
2060 *out_image_handle = new heif_image_handle;
2061 (*out_image_handle)->image = thumbnail_image;
2062 (*out_image_handle)->context = ctx->context;
2063 }
2064 else {
2065 *out_image_handle = nullptr;
2066 }
2067 }
2068
2069 return error_Ok;
2070 }
2071
2072
heif_context_set_primary_image(struct heif_context * ctx,struct heif_image_handle * image_handle)2073 struct heif_error heif_context_set_primary_image(struct heif_context* ctx,
2074 struct heif_image_handle* image_handle)
2075 {
2076 ctx->context->set_primary_image(image_handle->image);
2077
2078 return error_Ok;
2079 }
2080
2081
heif_context_add_exif_metadata(struct heif_context * ctx,const struct heif_image_handle * image_handle,const void * data,int size)2082 struct heif_error heif_context_add_exif_metadata(struct heif_context* ctx,
2083 const struct heif_image_handle* image_handle,
2084 const void* data, int size)
2085 {
2086 Error error = ctx->context->add_exif_metadata(image_handle->image, data, size);
2087 if (error != Error::Ok) {
2088 return error.error_struct(ctx->context.get());
2089 }
2090 else {
2091 return error_Ok;
2092 }
2093 }
2094
2095
heif_context_add_XMP_metadata(struct heif_context * ctx,const struct heif_image_handle * image_handle,const void * data,int size)2096 struct heif_error heif_context_add_XMP_metadata(struct heif_context* ctx,
2097 const struct heif_image_handle* image_handle,
2098 const void* data, int size)
2099 {
2100 Error error = ctx->context->add_XMP_metadata(image_handle->image, data, size);
2101 if (error != Error::Ok) {
2102 return error.error_struct(ctx->context.get());
2103 }
2104 else {
2105 return error_Ok;
2106 }
2107 }
2108
2109
heif_context_add_generic_metadata(struct heif_context * ctx,const struct heif_image_handle * image_handle,const void * data,int size,const char * item_type,const char * content_type)2110 struct heif_error heif_context_add_generic_metadata(struct heif_context* ctx,
2111 const struct heif_image_handle* image_handle,
2112 const void* data, int size,
2113 const char* item_type, const char* content_type)
2114 {
2115 Error error = ctx->context->add_generic_metadata(image_handle->image, data, size,
2116 item_type, content_type);
2117 if (error != Error::Ok) {
2118 return error.error_struct(ctx->context.get());
2119 }
2120 else {
2121 return error_Ok;
2122 }
2123 }
2124
2125
heif_context_set_maximum_image_size_limit(struct heif_context * ctx,int maximum_width)2126 void heif_context_set_maximum_image_size_limit(struct heif_context* ctx, int maximum_width)
2127 {
2128 ctx->context->set_maximum_image_size_limit(maximum_width);
2129 }
2130