heif_cxx.h 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  1. /*
  2. * C++ interface to libheif
  3. * Copyright (c) 2018 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. #ifndef LIBHEIF_HEIF_CXX_H
  21. #define LIBHEIF_HEIF_CXX_H
  22. #include <memory>
  23. #include <string>
  24. #include <vector>
  25. #include <cassert>
  26. extern "C" {
  27. #include <libheif/heif.h>
  28. }
  29. namespace heif {
  30. class Error
  31. {
  32. public:
  33. Error()
  34. {
  35. m_code = heif_error_Ok;
  36. m_subcode = heif_suberror_Unspecified;
  37. m_message = "Ok";
  38. }
  39. Error(const heif_error& err)
  40. {
  41. assert(err.message);
  42. m_code = err.code;
  43. m_subcode = err.subcode;
  44. m_message = err.message;
  45. }
  46. Error(heif_error_code code, heif_suberror_code subcode, const std::string& msg)
  47. {
  48. m_code = code;
  49. m_subcode = subcode;
  50. m_message = msg;
  51. }
  52. const std::string& get_message() const
  53. { return m_message; }
  54. heif_error_code get_code() const
  55. { return m_code; }
  56. heif_suberror_code get_subcode() const
  57. { return m_subcode; }
  58. operator bool() const
  59. { return m_code != heif_error_Ok; }
  60. private:
  61. heif_error_code m_code;
  62. heif_suberror_code m_subcode;
  63. std::string m_message;
  64. };
  65. class ImageHandle;
  66. class Image;
  67. class Encoder;
  68. class EncoderParameter;
  69. class EncoderDescriptor;
  70. class Context
  71. {
  72. public:
  73. Context();
  74. class ReadingOptions
  75. {
  76. };
  77. // throws Error
  78. void read_from_file(const std::string& filename, const ReadingOptions& opts = ReadingOptions());
  79. // DEPRECATED. Use read_from_memory_without_copy() instead.
  80. // throws Error
  81. void read_from_memory(const void* mem, size_t size, const ReadingOptions& opts = ReadingOptions());
  82. // throws Error
  83. void read_from_memory_without_copy(const void* mem, size_t size, const ReadingOptions& opts = ReadingOptions());
  84. class Reader
  85. {
  86. public:
  87. virtual ~Reader() = default;
  88. virtual int64_t get_position() const = 0;
  89. virtual int read(void* data, size_t size) = 0;
  90. virtual int seek(int64_t position) = 0;
  91. virtual heif_reader_grow_status wait_for_file_size(int64_t target_size) = 0;
  92. };
  93. // throws Error
  94. void read_from_reader(Reader&, const ReadingOptions& opts = ReadingOptions());
  95. int get_number_of_top_level_images() const noexcept;
  96. bool is_top_level_image_ID(heif_item_id id) const noexcept;
  97. std::vector<heif_item_id> get_list_of_top_level_image_IDs() const noexcept;
  98. // throws Error
  99. heif_item_id get_primary_image_ID() const;
  100. // throws Error
  101. ImageHandle get_primary_image_handle() const;
  102. ImageHandle get_image_handle(heif_item_id id) const;
  103. class EncodingOptions : public heif_encoding_options
  104. {
  105. public:
  106. EncodingOptions();
  107. };
  108. // throws Error
  109. ImageHandle encode_image(const Image& img, Encoder& encoder,
  110. const EncodingOptions& options = EncodingOptions());
  111. // throws Error
  112. void set_primary_image(ImageHandle& new_primary_image_handle);
  113. // throws Error
  114. ImageHandle encode_thumbnail(const Image& image,
  115. const ImageHandle& master_image,
  116. Encoder& encoder,
  117. const EncodingOptions&,
  118. int bbox_size);
  119. // throws Error
  120. void assign_thumbnail(const ImageHandle& thumbnail_image,
  121. const ImageHandle& master_image);
  122. // throws Error
  123. void add_exif_metadata(const ImageHandle& master_image,
  124. const void* data, int size);
  125. // throws Error
  126. void add_XMP_metadata(const ImageHandle& master_image,
  127. const void* data, int size);
  128. class Writer
  129. {
  130. public:
  131. virtual ~Writer() = default;
  132. virtual heif_error write(const void* data, size_t size) = 0;
  133. };
  134. // throws Error
  135. void write(Writer&);
  136. // throws Error
  137. void write_to_file(const std::string& filename) const;
  138. private:
  139. std::shared_ptr<heif_context> m_context;
  140. friend struct ::heif_error heif_writer_trampoline_write(struct heif_context* ctx,
  141. const void* data,
  142. size_t size,
  143. void* userdata);
  144. //static Context wrap_without_releasing(heif_context*); // internal use in friend function only
  145. };
  146. class ImageHandle
  147. {
  148. public:
  149. ImageHandle() = default;
  150. ImageHandle(heif_image_handle* handle);
  151. bool empty() const noexcept
  152. { return !m_image_handle; }
  153. bool is_primary_image() const noexcept;
  154. int get_width() const noexcept;
  155. int get_height() const noexcept;
  156. bool has_alpha_channel() const noexcept;
  157. bool is_premultiplied_alpha() const noexcept;
  158. int get_luma_bits_per_pixel() const noexcept;
  159. int get_chroma_bits_per_pixel() const noexcept;
  160. int get_ispe_width() const noexcept;
  161. int get_ispe_height() const noexcept;
  162. // ------------------------- depth images -------------------------
  163. // TODO
  164. // ------------------------- thumbnails -------------------------
  165. int get_number_of_thumbnails() const noexcept;
  166. std::vector<heif_item_id> get_list_of_thumbnail_IDs() const noexcept;
  167. // throws Error
  168. ImageHandle get_thumbnail(heif_item_id id);
  169. // ------------------------- metadata (Exif / XMP) -------------------------
  170. // Can optionally be filtered by type ("Exif" / "XMP")
  171. std::vector<heif_item_id> get_list_of_metadata_block_IDs(const char* type_filter = nullptr) const noexcept;
  172. std::string get_metadata_type(heif_item_id metadata_id) const noexcept;
  173. std::string get_metadata_content_type(heif_item_id metadata_id) const noexcept;
  174. // throws error
  175. std::vector<uint8_t> get_metadata(heif_item_id) const;
  176. class DecodingOptions
  177. {
  178. };
  179. // throws Error
  180. Image decode_image(heif_colorspace colorspace, heif_chroma chroma,
  181. const DecodingOptions& options = DecodingOptions());
  182. heif_image_handle* get_raw_image_handle() noexcept
  183. { return m_image_handle.get(); }
  184. const heif_image_handle* get_raw_image_handle() const noexcept
  185. { return m_image_handle.get(); }
  186. private:
  187. std::shared_ptr<heif_image_handle> m_image_handle;
  188. };
  189. class ColorProfile_nclx
  190. {
  191. public:
  192. ColorProfile_nclx();
  193. ~ColorProfile_nclx();
  194. heif_color_primaries get_color_primaries() const;
  195. heif_transfer_characteristics get_transfer_characteristics() const;
  196. heif_matrix_coefficients get_matrix_coefficients() const;
  197. bool is_full_range() const;
  198. void set_color_primaries(heif_color_primaries cp);
  199. // DEPRECATED: typo in function name. Use set_color_primaries() instead.
  200. void set_color_primaties(heif_color_primaries cp);
  201. void set_transfer_characteristics(heif_transfer_characteristics tc);
  202. void set_matrix_coefficients(heif_matrix_coefficients mc);
  203. void set_full_range_flag(bool is_full_range);
  204. private:
  205. ColorProfile_nclx(heif_color_profile_nclx* nclx)
  206. { mProfile = nclx; }
  207. heif_color_profile_nclx* mProfile;
  208. friend class Image;
  209. };
  210. class Image
  211. {
  212. public:
  213. Image() = default;
  214. Image(heif_image* image);
  215. // throws Error
  216. void create(int width, int height,
  217. enum heif_colorspace colorspace,
  218. enum heif_chroma chroma);
  219. // throws Error
  220. void add_plane(enum heif_channel channel,
  221. int width, int height, int bit_depth);
  222. heif_colorspace get_colorspace() const noexcept;
  223. heif_chroma get_chroma_format() const noexcept;
  224. int get_width(enum heif_channel channel) const noexcept;
  225. int get_height(enum heif_channel channel) const noexcept;
  226. int get_bits_per_pixel(enum heif_channel channel) const noexcept;
  227. int get_bits_per_pixel_range(enum heif_channel channel) const noexcept;
  228. bool has_channel(enum heif_channel channel) const noexcept;
  229. const uint8_t* get_plane(enum heif_channel channel, int* out_stride) const noexcept;
  230. uint8_t* get_plane(enum heif_channel channel, int* out_stride) noexcept;
  231. // throws Error
  232. void set_nclx_color_profile(const ColorProfile_nclx&);
  233. // throws Error
  234. ColorProfile_nclx get_nclx_color_profile() const;
  235. heif_color_profile_type get_color_profile_type() const;
  236. // throws Error
  237. std::vector<uint8_t> get_raw_color_profile() const;
  238. void set_raw_color_profile(heif_color_profile_type type,
  239. const std::vector<uint8_t>& data);
  240. bool is_premultiplied_alpha() const noexcept;
  241. void set_premultiplied_alpha(bool is_premultiplied_alpha) noexcept;
  242. class ScalingOptions
  243. {
  244. };
  245. // throws Error
  246. Image scale_image(int width, int height,
  247. const ScalingOptions& options = ScalingOptions()) const;
  248. private:
  249. std::shared_ptr<heif_image> m_image;
  250. friend class Context;
  251. };
  252. class EncoderDescriptor
  253. {
  254. public:
  255. static std::vector<EncoderDescriptor>
  256. get_encoder_descriptors(enum heif_compression_format format_filter,
  257. const char* name_filter) noexcept;
  258. std::string get_name() const noexcept;
  259. std::string get_id_name() const noexcept;
  260. enum heif_compression_format get_compression_format() const noexcept;
  261. // DEPRECATED: typo in function name
  262. bool supportes_lossy_compression() const noexcept;
  263. // DEPRECATED: typo in function name
  264. bool supportes_lossless_compression() const noexcept;
  265. // throws Error
  266. Encoder get_encoder() const;
  267. bool supports_lossy_compression() const noexcept;
  268. bool supports_lossless_compression() const noexcept;
  269. private:
  270. EncoderDescriptor(const struct heif_encoder_descriptor* descr) : m_descriptor(descr)
  271. {}
  272. const struct heif_encoder_descriptor* m_descriptor = nullptr;
  273. };
  274. class EncoderParameter
  275. {
  276. public:
  277. std::string get_name() const noexcept;
  278. enum heif_encoder_parameter_type get_type() const noexcept;
  279. bool is_integer() const noexcept;
  280. // Returns 'true' if the integer range is limited.
  281. bool get_valid_integer_range(int& out_minimum, int& out_maximum);
  282. bool is_boolean() const noexcept;
  283. bool is_string() const noexcept;
  284. std::vector<std::string> get_valid_string_values() const;
  285. private:
  286. EncoderParameter(const heif_encoder_parameter*);
  287. const struct heif_encoder_parameter* m_parameter;
  288. friend class Encoder;
  289. };
  290. class Encoder
  291. {
  292. public:
  293. // throws Error
  294. Encoder(enum heif_compression_format format);
  295. // throws Error
  296. void set_lossy_quality(int quality);
  297. // throws Error
  298. void set_lossless(bool enable_lossless);
  299. std::vector<EncoderParameter> list_parameters() const noexcept;
  300. void set_integer_parameter(const std::string& parameter_name, int value);
  301. int get_integer_parameter(const std::string& parameter_name) const;
  302. void set_boolean_parameter(const std::string& parameter_name, bool value);
  303. bool get_boolean_parameter(const std::string& parameter_name) const;
  304. void set_string_parameter(const std::string& parameter_name, const std::string& value);
  305. std::string get_string_parameter(const std::string& parameter_name) const;
  306. void set_parameter(const std::string& parameter_name, const std::string& parameter_value);
  307. std::string get_parameter(const std::string& parameter_name) const;
  308. private:
  309. Encoder(struct heif_encoder*) noexcept;
  310. std::shared_ptr<heif_encoder> m_encoder;
  311. friend class EncoderDescriptor;
  312. friend class Context;
  313. };
  314. // ==========================================================================================
  315. // IMPLEMENTATION
  316. // ==========================================================================================
  317. inline Context::Context()
  318. {
  319. heif_context* ctx = heif_context_alloc();
  320. m_context = std::shared_ptr<heif_context>(ctx,
  321. [](heif_context* c) { heif_context_free(c); });
  322. }
  323. inline void Context::read_from_file(const std::string& filename, const ReadingOptions& /*opts*/)
  324. {
  325. Error err = Error(heif_context_read_from_file(m_context.get(), filename.c_str(), NULL));
  326. if (err) {
  327. throw err;
  328. }
  329. }
  330. inline void Context::read_from_memory(const void* mem, size_t size, const ReadingOptions& /*opts*/)
  331. {
  332. Error err = Error(heif_context_read_from_memory(m_context.get(), mem, size, NULL));
  333. if (err) {
  334. throw err;
  335. }
  336. }
  337. inline void Context::read_from_memory_without_copy(const void* mem, size_t size, const ReadingOptions& /*opts*/)
  338. {
  339. Error err = Error(heif_context_read_from_memory_without_copy(m_context.get(), mem, size, NULL));
  340. if (err) {
  341. throw err;
  342. }
  343. }
  344. inline int64_t heif_reader_trampoline_get_position(void* userdata)
  345. {
  346. Context::Reader* reader = (Context::Reader*) userdata;
  347. return reader->get_position();
  348. }
  349. inline int heif_reader_trampoline_read(void* data, size_t size, void* userdata)
  350. {
  351. Context::Reader* reader = (Context::Reader*) userdata;
  352. return reader->read(data, size);
  353. }
  354. inline int heif_reader_trampoline_seek(int64_t position, void* userdata)
  355. {
  356. Context::Reader* reader = (Context::Reader*) userdata;
  357. return reader->seek(position);
  358. }
  359. inline heif_reader_grow_status heif_reader_trampoline_wait_for_file_size(int64_t target_size, void* userdata)
  360. {
  361. Context::Reader* reader = (Context::Reader*) userdata;
  362. return reader->wait_for_file_size(target_size);
  363. }
  364. static struct heif_reader heif_reader_trampoline =
  365. {
  366. 1,
  367. heif_reader_trampoline_get_position,
  368. heif_reader_trampoline_read,
  369. heif_reader_trampoline_seek,
  370. heif_reader_trampoline_wait_for_file_size
  371. };
  372. inline void Context::read_from_reader(Reader& reader, const ReadingOptions& /*opts*/)
  373. {
  374. Error err = Error(heif_context_read_from_reader(m_context.get(), &heif_reader_trampoline,
  375. &reader, NULL));
  376. if (err) {
  377. throw err;
  378. }
  379. }
  380. inline int Context::get_number_of_top_level_images() const noexcept
  381. {
  382. return heif_context_get_number_of_top_level_images(m_context.get());
  383. }
  384. inline bool Context::is_top_level_image_ID(heif_item_id id) const noexcept
  385. {
  386. return heif_context_is_top_level_image_ID(m_context.get(), id);
  387. }
  388. inline std::vector<heif_item_id> Context::get_list_of_top_level_image_IDs() const noexcept
  389. {
  390. int num = get_number_of_top_level_images();
  391. std::vector<heif_item_id> IDs(num);
  392. heif_context_get_list_of_top_level_image_IDs(m_context.get(), IDs.data(), num);
  393. return IDs;
  394. }
  395. inline heif_item_id Context::get_primary_image_ID() const
  396. {
  397. heif_item_id id;
  398. Error err = Error(heif_context_get_primary_image_ID(m_context.get(), &id));
  399. if (err) {
  400. throw err;
  401. }
  402. return id;
  403. }
  404. inline ImageHandle Context::get_primary_image_handle() const
  405. {
  406. heif_image_handle* handle;
  407. Error err = Error(heif_context_get_primary_image_handle(m_context.get(), &handle));
  408. if (err) {
  409. throw err;
  410. }
  411. return ImageHandle(handle);
  412. }
  413. inline ImageHandle Context::get_image_handle(heif_item_id id) const
  414. {
  415. struct heif_image_handle* handle;
  416. Error err = Error(heif_context_get_image_handle(m_context.get(), id, &handle));
  417. if (err) {
  418. throw err;
  419. }
  420. return ImageHandle(handle);
  421. }
  422. #if 0
  423. inline Context Context::wrap_without_releasing(heif_context* ctx) {
  424. Context context;
  425. context.m_context = std::shared_ptr<heif_context>(ctx,
  426. [] (heif_context*) { /* NOP */ });
  427. return context;
  428. }
  429. #endif
  430. inline struct ::heif_error heif_writer_trampoline_write(struct heif_context* ctx,
  431. const void* data,
  432. size_t size,
  433. void* userdata)
  434. {
  435. Context::Writer* writer = (Context::Writer*) userdata;
  436. (void) ctx;
  437. //Context context = Context::wrap_without_releasing(ctx);
  438. //return writer->write(context, data, size);
  439. return writer->write(data, size);
  440. }
  441. static struct heif_writer heif_writer_trampoline =
  442. {
  443. 1,
  444. &heif_writer_trampoline_write
  445. };
  446. inline void Context::write(Writer& writer)
  447. {
  448. Error err = Error(heif_context_write(m_context.get(), &heif_writer_trampoline, &writer));
  449. if (err) {
  450. throw err;
  451. }
  452. }
  453. inline void Context::write_to_file(const std::string& filename) const
  454. {
  455. Error err = Error(heif_context_write_to_file(m_context.get(), filename.c_str()));
  456. if (err) {
  457. throw err;
  458. }
  459. }
  460. inline ImageHandle::ImageHandle(heif_image_handle* handle)
  461. {
  462. if (handle != nullptr) {
  463. m_image_handle = std::shared_ptr<heif_image_handle>(handle,
  464. [](heif_image_handle* h) { heif_image_handle_release(h); });
  465. }
  466. }
  467. inline bool ImageHandle::is_primary_image() const noexcept
  468. {
  469. return heif_image_handle_is_primary_image(m_image_handle.get()) != 0;
  470. }
  471. inline int ImageHandle::get_width() const noexcept
  472. {
  473. return heif_image_handle_get_width(m_image_handle.get());
  474. }
  475. inline int ImageHandle::get_height() const noexcept
  476. {
  477. return heif_image_handle_get_height(m_image_handle.get());
  478. }
  479. inline bool ImageHandle::has_alpha_channel() const noexcept
  480. {
  481. return heif_image_handle_has_alpha_channel(m_image_handle.get()) != 0;
  482. }
  483. inline bool ImageHandle::is_premultiplied_alpha() const noexcept
  484. {
  485. return heif_image_handle_is_premultiplied_alpha(m_image_handle.get()) != 0;
  486. }
  487. inline int ImageHandle::get_luma_bits_per_pixel() const noexcept
  488. {
  489. return heif_image_handle_get_luma_bits_per_pixel(m_image_handle.get());
  490. }
  491. inline int ImageHandle::get_chroma_bits_per_pixel() const noexcept
  492. {
  493. return heif_image_handle_get_chroma_bits_per_pixel(m_image_handle.get());
  494. }
  495. inline int ImageHandle::get_ispe_width() const noexcept
  496. {
  497. return heif_image_handle_get_ispe_width(m_image_handle.get());
  498. }
  499. inline int ImageHandle::get_ispe_height() const noexcept
  500. {
  501. return heif_image_handle_get_ispe_height(m_image_handle.get());
  502. }
  503. // ------------------------- depth images -------------------------
  504. // TODO
  505. // ------------------------- thumbnails -------------------------
  506. inline int ImageHandle::get_number_of_thumbnails() const noexcept
  507. {
  508. return heif_image_handle_get_number_of_thumbnails(m_image_handle.get());
  509. }
  510. inline std::vector<heif_item_id> ImageHandle::get_list_of_thumbnail_IDs() const noexcept
  511. {
  512. int num = get_number_of_thumbnails();
  513. std::vector<heif_item_id> IDs(num);
  514. heif_image_handle_get_list_of_thumbnail_IDs(m_image_handle.get(), IDs.data(), num);
  515. return IDs;
  516. }
  517. inline ImageHandle ImageHandle::get_thumbnail(heif_item_id id)
  518. {
  519. heif_image_handle* handle;
  520. Error err = Error(heif_image_handle_get_thumbnail(m_image_handle.get(), id, &handle));
  521. if (err) {
  522. throw err;
  523. }
  524. return ImageHandle(handle);
  525. }
  526. inline Image ImageHandle::decode_image(heif_colorspace colorspace, heif_chroma chroma,
  527. const DecodingOptions& /*options*/)
  528. {
  529. heif_image* out_img;
  530. Error err = Error(heif_decode_image(m_image_handle.get(),
  531. &out_img,
  532. colorspace,
  533. chroma,
  534. nullptr)); //const struct heif_decoding_options* options);
  535. if (err) {
  536. throw err;
  537. }
  538. return Image(out_img);
  539. }
  540. inline std::vector<heif_item_id> ImageHandle::get_list_of_metadata_block_IDs(const char* type_filter) const noexcept
  541. {
  542. int nBlocks = heif_image_handle_get_number_of_metadata_blocks(m_image_handle.get(),
  543. type_filter);
  544. std::vector<heif_item_id> ids(nBlocks);
  545. int n = heif_image_handle_get_list_of_metadata_block_IDs(m_image_handle.get(),
  546. type_filter,
  547. ids.data(), nBlocks);
  548. (void) n;
  549. //assert(n==nBlocks);
  550. return ids;
  551. }
  552. inline std::string ImageHandle::get_metadata_type(heif_item_id metadata_id) const noexcept
  553. {
  554. return heif_image_handle_get_metadata_type(m_image_handle.get(), metadata_id);
  555. }
  556. inline std::string ImageHandle::get_metadata_content_type(heif_item_id metadata_id) const noexcept
  557. {
  558. return heif_image_handle_get_metadata_content_type(m_image_handle.get(), metadata_id);
  559. }
  560. inline std::vector<uint8_t> ImageHandle::get_metadata(heif_item_id metadata_id) const
  561. {
  562. size_t data_size = heif_image_handle_get_metadata_size(m_image_handle.get(),
  563. metadata_id);
  564. std::vector<uint8_t> data(data_size);
  565. Error err = Error(heif_image_handle_get_metadata(m_image_handle.get(),
  566. metadata_id,
  567. data.data()));
  568. if (err) {
  569. throw err;
  570. }
  571. return data;
  572. }
  573. inline ColorProfile_nclx::ColorProfile_nclx()
  574. {
  575. mProfile = heif_nclx_color_profile_alloc();
  576. }
  577. inline ColorProfile_nclx::~ColorProfile_nclx()
  578. {
  579. heif_nclx_color_profile_free(mProfile);
  580. }
  581. inline heif_color_primaries ColorProfile_nclx::get_color_primaries() const
  582. { return mProfile->color_primaries; }
  583. inline heif_transfer_characteristics ColorProfile_nclx::get_transfer_characteristics() const
  584. { return mProfile->transfer_characteristics; }
  585. inline heif_matrix_coefficients ColorProfile_nclx::get_matrix_coefficients() const
  586. { return mProfile->matrix_coefficients; }
  587. inline bool ColorProfile_nclx::is_full_range() const
  588. { return mProfile->full_range_flag; }
  589. inline void ColorProfile_nclx::set_color_primaries(heif_color_primaries cp)
  590. { mProfile->color_primaries = cp; }
  591. inline void ColorProfile_nclx::set_color_primaties(heif_color_primaries cp)
  592. { set_color_primaries(cp); }
  593. inline void ColorProfile_nclx::set_transfer_characteristics(heif_transfer_characteristics tc)
  594. { mProfile->transfer_characteristics = tc; }
  595. inline void ColorProfile_nclx::set_matrix_coefficients(heif_matrix_coefficients mc)
  596. { mProfile->matrix_coefficients = mc; }
  597. inline void ColorProfile_nclx::set_full_range_flag(bool is_full_range)
  598. { mProfile->full_range_flag = is_full_range; }
  599. inline Image::Image(heif_image* image)
  600. {
  601. m_image = std::shared_ptr<heif_image>(image,
  602. [](heif_image* h) { heif_image_release(h); });
  603. }
  604. inline void Image::create(int width, int height,
  605. enum heif_colorspace colorspace,
  606. enum heif_chroma chroma)
  607. {
  608. heif_image* image;
  609. Error err = Error(heif_image_create(width, height, colorspace, chroma, &image));
  610. if (err) {
  611. m_image.reset();
  612. throw err;
  613. }
  614. else {
  615. m_image = std::shared_ptr<heif_image>(image,
  616. [](heif_image* h) { heif_image_release(h); });
  617. }
  618. }
  619. inline void Image::add_plane(enum heif_channel channel,
  620. int width, int height, int bit_depth)
  621. {
  622. Error err = Error(heif_image_add_plane(m_image.get(), channel, width, height, bit_depth));
  623. if (err) {
  624. throw err;
  625. }
  626. }
  627. inline heif_colorspace Image::get_colorspace() const noexcept
  628. {
  629. return heif_image_get_colorspace(m_image.get());
  630. }
  631. inline heif_chroma Image::get_chroma_format() const noexcept
  632. {
  633. return heif_image_get_chroma_format(m_image.get());
  634. }
  635. inline int Image::get_width(enum heif_channel channel) const noexcept
  636. {
  637. return heif_image_get_width(m_image.get(), channel);
  638. }
  639. inline int Image::get_height(enum heif_channel channel) const noexcept
  640. {
  641. return heif_image_get_height(m_image.get(), channel);
  642. }
  643. inline int Image::get_bits_per_pixel(enum heif_channel channel) const noexcept
  644. {
  645. return heif_image_get_bits_per_pixel(m_image.get(), channel);
  646. }
  647. inline int Image::get_bits_per_pixel_range(enum heif_channel channel) const noexcept
  648. {
  649. return heif_image_get_bits_per_pixel_range(m_image.get(), channel);
  650. }
  651. inline bool Image::has_channel(enum heif_channel channel) const noexcept
  652. {
  653. return heif_image_has_channel(m_image.get(), channel);
  654. }
  655. inline const uint8_t* Image::get_plane(enum heif_channel channel, int* out_stride) const noexcept
  656. {
  657. return heif_image_get_plane_readonly(m_image.get(), channel, out_stride);
  658. }
  659. inline uint8_t* Image::get_plane(enum heif_channel channel, int* out_stride) noexcept
  660. {
  661. return heif_image_get_plane(m_image.get(), channel, out_stride);
  662. }
  663. inline void Image::set_nclx_color_profile(const ColorProfile_nclx& nclx)
  664. {
  665. Error err = Error(heif_image_set_nclx_color_profile(m_image.get(), nclx.mProfile));
  666. if (err) {
  667. throw err;
  668. }
  669. }
  670. // throws Error
  671. inline ColorProfile_nclx Image::get_nclx_color_profile() const
  672. {
  673. heif_color_profile_nclx* nclx = nullptr;
  674. Error err = Error(heif_image_get_nclx_color_profile(m_image.get(), &nclx));
  675. if (err) {
  676. throw err;
  677. }
  678. return ColorProfile_nclx(nclx);
  679. }
  680. inline heif_color_profile_type Image::get_color_profile_type() const
  681. {
  682. return heif_image_get_color_profile_type(m_image.get());
  683. }
  684. // throws Error
  685. inline std::vector<uint8_t> Image::get_raw_color_profile() const
  686. {
  687. auto size = heif_image_get_raw_color_profile_size(m_image.get());
  688. std::vector<uint8_t> profile(size);
  689. heif_image_get_raw_color_profile(m_image.get(), profile.data());
  690. return profile;
  691. }
  692. inline void Image::set_raw_color_profile(heif_color_profile_type type,
  693. const std::vector<uint8_t>& data)
  694. {
  695. const char* profile_type = nullptr;
  696. switch (type) {
  697. case heif_color_profile_type_prof:
  698. profile_type = "prof";
  699. break;
  700. case heif_color_profile_type_rICC:
  701. profile_type = "rICC";
  702. break;
  703. default:
  704. throw Error(heif_error_code::heif_error_Usage_error,
  705. heif_suberror_Unspecified,
  706. "invalid raw color profile type");
  707. break;
  708. }
  709. Error err = Error(heif_image_set_raw_color_profile(m_image.get(), profile_type,
  710. data.data(), data.size()));
  711. if (err) {
  712. throw err;
  713. }
  714. }
  715. inline bool Image::is_premultiplied_alpha() const noexcept
  716. {
  717. return heif_image_is_premultiplied_alpha(m_image.get()) != 0;
  718. }
  719. inline void Image::set_premultiplied_alpha(bool is_premultiplied_alpha) noexcept
  720. {
  721. heif_image_set_premultiplied_alpha(m_image.get(), is_premultiplied_alpha);
  722. }
  723. inline Image Image::scale_image(int width, int height,
  724. const ScalingOptions&) const
  725. {
  726. heif_image* img;
  727. Error err = Error(heif_image_scale_image(m_image.get(), &img, width, height,
  728. nullptr)); // TODO: scaling options not defined yet
  729. if (err) {
  730. throw err;
  731. }
  732. return Image(img);
  733. }
  734. inline std::vector<EncoderDescriptor>
  735. EncoderDescriptor::get_encoder_descriptors(enum heif_compression_format format_filter,
  736. const char* name_filter) noexcept
  737. {
  738. int maxDescriptors = 10;
  739. int nDescriptors;
  740. for (;;) {
  741. const struct heif_encoder_descriptor** descriptors;
  742. descriptors = new const heif_encoder_descriptor* [maxDescriptors];
  743. nDescriptors = heif_context_get_encoder_descriptors(nullptr,
  744. format_filter,
  745. name_filter,
  746. descriptors,
  747. maxDescriptors);
  748. if (nDescriptors < maxDescriptors) {
  749. std::vector<EncoderDescriptor> outDescriptors;
  750. outDescriptors.reserve(nDescriptors);
  751. for (int i = 0; i < nDescriptors; i++) {
  752. outDescriptors.push_back(EncoderDescriptor(descriptors[i]));
  753. }
  754. delete[] descriptors;
  755. return outDescriptors;
  756. }
  757. else {
  758. delete[] descriptors;
  759. maxDescriptors *= 2;
  760. }
  761. }
  762. }
  763. inline std::string EncoderDescriptor::get_name() const noexcept
  764. {
  765. return heif_encoder_descriptor_get_name(m_descriptor);
  766. }
  767. inline std::string EncoderDescriptor::get_id_name() const noexcept
  768. {
  769. return heif_encoder_descriptor_get_id_name(m_descriptor);
  770. }
  771. inline enum heif_compression_format EncoderDescriptor::get_compression_format() const noexcept
  772. {
  773. return heif_encoder_descriptor_get_compression_format(m_descriptor);
  774. }
  775. inline bool EncoderDescriptor::supportes_lossy_compression() const noexcept
  776. {
  777. return heif_encoder_descriptor_supports_lossy_compression(m_descriptor);
  778. }
  779. inline bool EncoderDescriptor::supports_lossy_compression() const noexcept
  780. {
  781. return heif_encoder_descriptor_supports_lossy_compression(m_descriptor);
  782. }
  783. inline bool EncoderDescriptor::supportes_lossless_compression() const noexcept
  784. {
  785. return heif_encoder_descriptor_supports_lossless_compression(m_descriptor);
  786. }
  787. inline bool EncoderDescriptor::supports_lossless_compression() const noexcept
  788. {
  789. return heif_encoder_descriptor_supports_lossless_compression(m_descriptor);
  790. }
  791. inline Encoder EncoderDescriptor::get_encoder() const
  792. {
  793. heif_encoder* encoder;
  794. Error err = Error(heif_context_get_encoder(nullptr, m_descriptor, &encoder));
  795. if (err) {
  796. throw err;
  797. }
  798. return Encoder(encoder);
  799. }
  800. inline Encoder::Encoder(enum heif_compression_format format)
  801. {
  802. heif_encoder* encoder;
  803. Error err = Error(heif_context_get_encoder_for_format(nullptr, format, &encoder));
  804. if (err) {
  805. throw err;
  806. }
  807. m_encoder = std::shared_ptr<heif_encoder>(encoder,
  808. [](heif_encoder* e) { heif_encoder_release(e); });
  809. }
  810. inline Encoder::Encoder(struct heif_encoder* encoder) noexcept
  811. {
  812. m_encoder = std::shared_ptr<heif_encoder>(encoder,
  813. [](heif_encoder* e) { heif_encoder_release(e); });
  814. }
  815. inline EncoderParameter::EncoderParameter(const heif_encoder_parameter* param)
  816. : m_parameter(param)
  817. {
  818. }
  819. inline std::string EncoderParameter::get_name() const noexcept
  820. {
  821. return heif_encoder_parameter_get_name(m_parameter);
  822. }
  823. inline enum heif_encoder_parameter_type EncoderParameter::get_type() const noexcept
  824. {
  825. return heif_encoder_parameter_get_type(m_parameter);
  826. }
  827. inline bool EncoderParameter::is_integer() const noexcept
  828. {
  829. return get_type() == heif_encoder_parameter_type_integer;
  830. }
  831. inline bool EncoderParameter::get_valid_integer_range(int& out_minimum, int& out_maximum)
  832. {
  833. int have_minimum_maximum;
  834. Error err = Error(heif_encoder_parameter_get_valid_integer_range(m_parameter,
  835. &have_minimum_maximum,
  836. &out_minimum, &out_maximum));
  837. if (err) {
  838. throw err;
  839. }
  840. return have_minimum_maximum;
  841. }
  842. inline bool EncoderParameter::is_boolean() const noexcept
  843. {
  844. return get_type() == heif_encoder_parameter_type_boolean;
  845. }
  846. inline bool EncoderParameter::is_string() const noexcept
  847. {
  848. return get_type() == heif_encoder_parameter_type_string;
  849. }
  850. inline std::vector<std::string> EncoderParameter::get_valid_string_values() const
  851. {
  852. const char* const* stringarray;
  853. Error err = Error(heif_encoder_parameter_get_valid_string_values(m_parameter,
  854. &stringarray));
  855. if (err) {
  856. throw err;
  857. }
  858. std::vector<std::string> values;
  859. for (int i = 0; stringarray[i]; i++) {
  860. values.push_back(stringarray[i]);
  861. }
  862. return values;
  863. }
  864. inline std::vector<EncoderParameter> Encoder::list_parameters() const noexcept
  865. {
  866. std::vector<EncoderParameter> parameters;
  867. for (const struct heif_encoder_parameter* const* params = heif_encoder_list_parameters(m_encoder.get());
  868. *params;
  869. params++) {
  870. parameters.push_back(EncoderParameter(*params));
  871. }
  872. return parameters;
  873. }
  874. inline void Encoder::set_lossy_quality(int quality)
  875. {
  876. Error err = Error(heif_encoder_set_lossy_quality(m_encoder.get(), quality));
  877. if (err) {
  878. throw err;
  879. }
  880. }
  881. inline void Encoder::set_lossless(bool enable_lossless)
  882. {
  883. Error err = Error(heif_encoder_set_lossless(m_encoder.get(), enable_lossless));
  884. if (err) {
  885. throw err;
  886. }
  887. }
  888. inline void Encoder::set_integer_parameter(const std::string& parameter_name, int value)
  889. {
  890. Error err = Error(heif_encoder_set_parameter_integer(m_encoder.get(), parameter_name.c_str(), value));
  891. if (err) {
  892. throw err;
  893. }
  894. }
  895. inline int Encoder::get_integer_parameter(const std::string& parameter_name) const
  896. {
  897. int value;
  898. Error err = Error(heif_encoder_get_parameter_integer(m_encoder.get(), parameter_name.c_str(), &value));
  899. if (err) {
  900. throw err;
  901. }
  902. return value;
  903. }
  904. inline void Encoder::set_boolean_parameter(const std::string& parameter_name, bool value)
  905. {
  906. Error err = Error(heif_encoder_set_parameter_boolean(m_encoder.get(), parameter_name.c_str(), value));
  907. if (err) {
  908. throw err;
  909. }
  910. }
  911. inline bool Encoder::get_boolean_parameter(const std::string& parameter_name) const
  912. {
  913. int value;
  914. Error err = Error(heif_encoder_get_parameter_boolean(m_encoder.get(), parameter_name.c_str(), &value));
  915. if (err) {
  916. throw err;
  917. }
  918. return value;
  919. }
  920. inline void Encoder::set_string_parameter(const std::string& parameter_name, const std::string& value)
  921. {
  922. Error err = Error(heif_encoder_set_parameter_string(m_encoder.get(), parameter_name.c_str(), value.c_str()));
  923. if (err) {
  924. throw err;
  925. }
  926. }
  927. inline std::string Encoder::get_string_parameter(const std::string& parameter_name) const
  928. {
  929. const int max_size = 250;
  930. char value[max_size];
  931. Error err = Error(heif_encoder_get_parameter_string(m_encoder.get(), parameter_name.c_str(),
  932. value, max_size));
  933. if (err) {
  934. throw err;
  935. }
  936. return value;
  937. }
  938. inline void Encoder::set_parameter(const std::string& parameter_name, const std::string& parameter_value)
  939. {
  940. Error err = Error(heif_encoder_set_parameter(m_encoder.get(), parameter_name.c_str(),
  941. parameter_value.c_str()));
  942. if (err) {
  943. throw err;
  944. }
  945. }
  946. inline std::string Encoder::get_parameter(const std::string& parameter_name) const
  947. {
  948. const int max_size = 250;
  949. char value[max_size];
  950. Error err = Error(heif_encoder_get_parameter(m_encoder.get(), parameter_name.c_str(),
  951. value, max_size));
  952. if (err) {
  953. throw err;
  954. }
  955. return value;
  956. }
  957. inline void Context::set_primary_image(ImageHandle& new_primary_image_handle)
  958. {
  959. Error err = Error(heif_context_set_primary_image(m_context.get(),
  960. new_primary_image_handle.get_raw_image_handle()));
  961. if (err) {
  962. throw err;
  963. }
  964. }
  965. inline Context::EncodingOptions::EncodingOptions()
  966. {
  967. // TODO: this is a bit hacky. It would be better to have an API function to set
  968. // the options to default values. But I do not see any reason for that apart from
  969. // this use-case.
  970. struct heif_encoding_options* default_options = heif_encoding_options_alloc();
  971. *static_cast<heif_encoding_options*>(this) = *default_options; // copy over all options
  972. heif_encoding_options_free(default_options);
  973. }
  974. inline ImageHandle Context::encode_image(const Image& img, Encoder& encoder,
  975. const EncodingOptions& options)
  976. {
  977. struct heif_image_handle* image_handle;
  978. Error err = Error(heif_context_encode_image(m_context.get(),
  979. img.m_image.get(),
  980. encoder.m_encoder.get(),
  981. &options,
  982. &image_handle));
  983. if (err) {
  984. throw err;
  985. }
  986. return ImageHandle(image_handle);
  987. }
  988. inline ImageHandle Context::encode_thumbnail(const Image& image,
  989. const ImageHandle& master_image_handle,
  990. Encoder& encoder,
  991. const EncodingOptions& options,
  992. int bbox_size)
  993. {
  994. struct heif_image_handle* thumb_image_handle;
  995. Error err = Error(heif_context_encode_thumbnail(m_context.get(),
  996. image.m_image.get(),
  997. master_image_handle.get_raw_image_handle(),
  998. encoder.m_encoder.get(),
  999. &options,
  1000. bbox_size,
  1001. &thumb_image_handle));
  1002. if (err) {
  1003. throw err;
  1004. }
  1005. return ImageHandle(thumb_image_handle);
  1006. }
  1007. inline void Context::assign_thumbnail(const ImageHandle& thumbnail_image,
  1008. const ImageHandle& master_image)
  1009. {
  1010. Error err = Error(heif_context_assign_thumbnail(m_context.get(),
  1011. thumbnail_image.get_raw_image_handle(),
  1012. master_image.get_raw_image_handle()));
  1013. if (err) {
  1014. throw err;
  1015. }
  1016. }
  1017. inline void Context::add_exif_metadata(const ImageHandle& master_image,
  1018. const void* data, int size)
  1019. {
  1020. Error err = Error(heif_context_add_exif_metadata(m_context.get(),
  1021. master_image.get_raw_image_handle(),
  1022. data, size));
  1023. if (err) {
  1024. throw err;
  1025. }
  1026. }
  1027. inline void Context::add_XMP_metadata(const ImageHandle& master_image,
  1028. const void* data, int size)
  1029. {
  1030. Error err = Error(heif_context_add_XMP_metadata(m_context.get(),
  1031. master_image.get_raw_image_handle(),
  1032. data, size));
  1033. if (err) {
  1034. throw err;
  1035. }
  1036. }
  1037. }
  1038. #endif