diff --git a/CMakePresets.json b/CMakePresets.json index bbe8b49abe..3662e7537c 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -54,6 +54,7 @@ "WITH_VVDEC_PLUGIN" : "OFF", "WITH_VVENC" : "ON", "WITH_VVENC_PLUGIN" : "OFF", + "WITH_EXPERIMENTAL_GAIN_MAP" : "OFF", "WITH_REDUCED_VISIBILITY" : "OFF", "WITH_HEADER_COMPRESSION" : "ON", @@ -110,6 +111,7 @@ "WITH_VVDEC_PLUGIN" : "ON", "WITH_VVENC" : "ON", "WITH_VVENC_PLUGIN" : "ON", + "WITH_EXPERIMENTAL_GAIN_MAP" : "OFF", "WITH_REDUCED_VISIBILITY" : "ON", "WITH_HEADER_COMPRESSION" : "ON", @@ -148,6 +150,7 @@ "WITH_UVG266" : "OFF", "WITH_VVDEC" : "OFF", "WITH_VVENC" : "OFF", + "WITH_EXPERIMENTAL_GAIN_MAP" : "OFF", "WITH_REDUCED_VISIBILITY" : "ON", "WITH_HEADER_COMPRESSION" : "OFF", diff --git a/libheif/CMakeLists.txt b/libheif/CMakeLists.txt index e8d7e0dce9..290b27f4d1 100644 --- a/libheif/CMakeLists.txt +++ b/libheif/CMakeLists.txt @@ -249,6 +249,10 @@ if (ENABLE_EXPERIMENTAL_MINI_FORMAT) mini.cc) endif () +if (WITH_EXPERIMENTAL_GAIN_MAP) + target_compile_definitions(heif PUBLIC WITH_EXPERIMENTAL_GAIN_MAP=1) +endif () + write_basic_package_version_file(${PROJECT_NAME}-config-version.cmake COMPATIBILITY ExactVersion) install(TARGETS heif EXPORT ${PROJECT_NAME}-config diff --git a/libheif/api/libheif/heif.cc b/libheif/api/libheif/heif.cc index de275a9d3a..01c5eeabe5 100644 --- a/libheif/api/libheif/heif.cc +++ b/libheif/api/libheif/heif.cc @@ -657,6 +657,124 @@ struct heif_error heif_context_get_primary_image_ID(struct heif_context* ctx, he } +#if WITH_EXPERIMENTAL_GAIN_MAP + +struct heif_error heif_image_handle_get_gain_map_image_handle( + const struct heif_image_handle* handle, struct heif_image_handle** gain_map_handle) { + if (!gain_map_handle) { + return {heif_error_Usage_error, heif_suberror_Null_pointer_argument, + "NULL gain_map_handle passed to heif_image_handle_get_gain_map_image_handle()"}; + } + + std::shared_ptr gain_map_image = handle->image->get_gain_map(); + if (!gain_map_image) { + Error err(heif_error_Usage_error, heif_suberror_Nonexisting_item_referenced, + "base image handle is not associated with a gain map image"); + return err.error_struct(handle->image.get()); + } + + *gain_map_handle = new heif_image_handle(); + (*gain_map_handle)->image = gain_map_image; + (*gain_map_handle)->context = handle->context; + + return Error::Ok.error_struct(handle->image.get()); +} + +size_t heif_image_handle_get_gain_map_metadata_size(const struct heif_image_handle* handle) { + std::shared_ptr metadata = handle->image->get_gain_map_metadata(); + + if (metadata) { + // Ignore unsigned int(8) version = 0; field of ToneMapImage syntax + size_t sz = metadata->m_data.size(); + return sz > 0 ? (sz - 1) : 0; + } + + return 0; +} + +struct heif_error heif_image_handle_get_gain_map_metadata(const struct heif_image_handle* handle, + void* out_data) { + if (!out_data) { + return {heif_error_Usage_error, heif_suberror_Null_pointer_argument, + "NULL out_data passed to heif_image_handle_get_gain_map_metadata()"}; + } + + std::shared_ptr metadata = handle->image->get_gain_map_metadata(); + if (!metadata) { + Error err(heif_error_Invalid_input, heif_suberror_No_item_data, + "base image handle is not associated with a gain map image"); + return err.error_struct(handle->image.get()); + } + + uint8_t version = 0xff; + size_t pos = 0; + std::vector& buffer = metadata->m_data; + + if (pos >= buffer.size()) { + Error err(heif_error_Invalid_input, heif_suberror_End_of_data); + return err.error_struct(handle->image.get()); + } + version = buffer[pos++]; + if (version != 0) { + Error err(heif_error_Invalid_input, heif_suberror_Unsupported_data_version, + "Box[tmap] has unsupported version"); + return err.error_struct(handle->image.get()); + } + + memcpy(out_data, buffer.data() + pos, buffer.size() - pos); + + return heif_error_success; +} + +struct heif_error heif_image_handle_get_derived_image_nclx_color_profile( + const struct heif_image_handle* handle, struct heif_color_profile_nclx** out_data) { + if (!out_data) { + return {heif_error_Usage_error, heif_suberror_Null_pointer_argument, + "NULL out_data passed to heif_image_handle_get_derived_image_nclx_color_profile()"}; + } + + auto nclx_profile = handle->image->get_derived_img_color_profile_nclx(); + if (!nclx_profile) { + Error err(heif_error_Color_profile_does_not_exist, heif_suberror_Unspecified); + return err.error_struct(handle->image.get()); + } + + Error err = nclx_profile->get_nclx_color_profile(out_data); + + return err.error_struct(handle->image.get()); +} + +size_t heif_image_handle_get_derived_image_raw_color_profile_size( + const struct heif_image_handle* handle) { + auto profile_icc = handle->image->get_color_profile_icc(); + if (profile_icc) { + return profile_icc->get_data().size(); + } else { + return 0; + } +} + +struct heif_error heif_image_handle_get_derived_image_raw_color_profile( + const struct heif_image_handle* handle, void* out_data) { + if (!out_data) { + return {heif_error_Usage_error, heif_suberror_Null_pointer_argument, + "NULL out_data passed to heif_image_handle_get_derived_image_raw_color_profile()"}; + } + + auto raw_profile = handle->image->get_derived_img_color_profile_icc(); + if (raw_profile) { + memcpy(out_data, raw_profile->get_data().data(), raw_profile->get_data().size()); + } else { + Error err(heif_error_Color_profile_does_not_exist, heif_suberror_Unspecified); + return err.error_struct(handle->image.get()); + } + + return Error::Ok.error_struct(handle->image.get()); +} + +#endif + + int heif_context_is_top_level_image_ID(struct heif_context* ctx, heif_item_id id) { const std::vector> images = ctx->context->get_top_level_images(true); @@ -3442,6 +3560,121 @@ struct heif_error heif_context_encode_image(struct heif_context* ctx, } +#if WITH_EXPERIMENTAL_GAIN_MAP + +struct heif_error heif_context_encode_gain_map_image( + struct heif_context* ctx, const struct heif_image_handle* base_image_handle, + struct heif_encoder* encoder, const struct heif_image* gain_map_image, + const struct heif_encoding_options* input_options, const uint8_t* gain_map_metadata, + int gain_map_metadata_len, const struct heif_color_profile_nclx* derived_image_nclx, + struct heif_image_handle** out_image_handle) { + if (!encoder) { + return Error(heif_error_Usage_error, heif_suberror_Null_pointer_argument) + .error_struct(ctx->context.get()); + } + + if (gain_map_metadata_len <= 0) { + return Error(heif_error_Invalid_input, heif_suberror_Invalid_parameter_value) + .error_struct(ctx->context.get()); + } + + if (out_image_handle) { + *out_image_handle = nullptr; + } + + // --- write tmap item + std::vector metadata; + metadata.push_back(0); // version = 0 + for (int i = 0; i < gain_map_metadata_len; i++) { + metadata.push_back(gain_map_metadata[i]); + } + heif_item_id tmap_item_id = -1; + ctx->context->add_tmap_item(metadata, tmap_item_id); + + std::vector> properties; + + // --- write ISPE property for tmap item + std::shared_ptr ispe = std::make_shared(); + ispe->set_size(base_image_handle->image->get_ispe_width(), + base_image_handle->image->get_ispe_height()); + + properties.push_back(ispe); + + // --- write PIXI property for tmap item + // TODO: this assumes the base image is 8 bit and derived image is 10 bit. Have to handle the + // other way where the base image is hdr and derived image is sdr + std::shared_ptr pixi = std::make_shared(); + pixi->add_channel_bits(10); + pixi->add_channel_bits(10); + pixi->add_channel_bits(10); + + properties.push_back(pixi); + + // --- write COLR property for tmap item + if (derived_image_nclx != nullptr) { + std::shared_ptr colr = std::make_shared(); + auto derived_img_nclx_profile = std::make_shared(); + derived_img_nclx_profile->set_colour_primaries(derived_image_nclx->color_primaries); + derived_img_nclx_profile->set_transfer_characteristics( + derived_image_nclx->transfer_characteristics); + derived_img_nclx_profile->set_matrix_coefficients(derived_image_nclx->matrix_coefficients); + derived_img_nclx_profile->set_full_range_flag(derived_image_nclx->full_range_flag); + colr->set_color_profile(derived_img_nclx_profile); + + properties.push_back(colr); + } + // set tmap item properties + for (auto& propertyBox : properties) { + int index = + ctx->context->get_heif_file()->get_ipco_box()->find_or_append_child_box(propertyBox); + ctx->context->get_heif_file()->get_ipma_box()->add_property_for_item_ID( + tmap_item_id, + Box_ipma::PropertyAssociation{propertyBox->is_essential(), uint16_t(index + 1)}); + } + + heif_encoding_options options; + set_default_encoding_options(options); + if (input_options != nullptr) { + copy_options(options, *input_options); + } + + auto gainmap_encoding_result = ctx->context->encode_image(gain_map_image->image, encoder, options, + heif_image_input_class_gain_map); + if (gainmap_encoding_result.error) { + return gainmap_encoding_result.error.error_struct(ctx->context.get()); + } + + std::shared_ptr gain_map_image_item = *gainmap_encoding_result; + Error error = + ctx->context->link_gain_map(base_image_handle->image, gain_map_image_item, tmap_item_id); + if (error != Error::Ok) { + return error.error_struct(ctx->context.get()); + } + + if (out_image_handle) { + *out_image_handle = new heif_image_handle; + (*out_image_handle)->image = std::move(gain_map_image_item); + (*out_image_handle)->context = ctx->context; + } + + // --- generate altr box + auto altr_box = std::make_shared(); + altr_box->set_short_type(fourcc("altr")); + altr_box->set_group_id(ctx->context->get_heif_file()->get_unused_item_id()); + + std::vector ids; + ids.push_back(tmap_item_id); + ids.push_back(base_image_handle->image->get_id()); + + altr_box->set_item_ids(ids); + ctx->context->get_heif_file()->add_entity_group_box(altr_box); + + return heif_error_success; +} + +#endif + + struct heif_error heif_context_encode_grid(struct heif_context* ctx, struct heif_image** tiles, uint16_t columns, diff --git a/libheif/api/libheif/heif.h b/libheif/api/libheif/heif.h index 7d969f1d2e..4c88c384bb 100644 --- a/libheif/api/libheif/heif.h +++ b/libheif/api/libheif/heif.h @@ -884,6 +884,13 @@ typedef uint32_t heif_brand2; */ #define heif_brand2_1pic heif_fourcc('1','p','i','c') +/** + * HEIF tone map brand (`tmap`). + * + * This is a compatible brand indicating the file contains a gainmap image. + */ +#define heif_brand2_tmap heif_fourcc('t', 'm', 'a', 'p') + // input data should be at least 12 bytes LIBHEIF_API heif_brand2 heif_read_main_brand(const uint8_t* data, int len); @@ -1453,6 +1460,42 @@ struct heif_error heif_image_handle_get_auxiliary_image_handle(const struct heif heif_item_id auxiliary_id, struct heif_image_handle** out_auxiliary_handle); +#if WITH_EXPERIMENTAL_GAIN_MAP + +// ------------------------- gain map images ------------------------- + +// Get the gain map image associated with the main image. If no gain map image is available, this +// method will return error. +LIBHEIF_API +struct heif_error heif_image_handle_get_gain_map_image_handle( + const struct heif_image_handle* handle, struct heif_image_handle** gain_map_handle); + +// Get the gain map metadata size associated with the main image. If no gain map image is available, +// this method will return 0 +LIBHEIF_API +size_t heif_image_handle_get_gain_map_metadata_size(const struct heif_image_handle* handle); + +// Get the gain map metadata associated with the main image. if no gain map image is available, this +// method will return error +LIBHEIF_API +struct heif_error heif_image_handle_get_gain_map_metadata(const struct heif_image_handle* handle, + void* out_data); + +// Get nclx color profile for derived image +LIBHEIF_API +struct heif_error heif_image_handle_get_derived_image_nclx_color_profile( + const struct heif_image_handle* handle, struct heif_color_profile_nclx** out_data); + +// Get raw color profile for derived image +LIBHEIF_API +size_t heif_image_handle_get_derived_image_raw_color_profile_size( + const struct heif_image_handle* handle); + +LIBHEIF_API +struct heif_error heif_image_handle_get_derived_image_raw_color_profile( + const struct heif_image_handle* handle, void* out_data); + +#endif // ------------------------- metadata (Exif / XMP) ------------------------- @@ -2621,6 +2664,22 @@ LIBHEIF_API int heif_encoder_descriptor_supportes_lossless_compression(const struct heif_encoder_descriptor*); + +#if WITH_EXPERIMENTAL_GAIN_MAP + +// Compress the gain map image and write metadata. +// Returns a handle to the coded image in 'out_image_handle' unless out_image_handle = NULL. +LIBHEIF_API +struct heif_error heif_context_encode_gain_map_image( + struct heif_context* ctx, const struct heif_image_handle* base_image_handle, + struct heif_encoder* encoder, const struct heif_image* gain_map_image, + const struct heif_encoding_options* input_options, const uint8_t* gain_map_metadata, + int gain_map_metadata_len, const struct heif_color_profile_nclx* derived_image_nclx, + struct heif_image_handle** out_image_handle); + +#endif + + #ifdef __cplusplus } #endif diff --git a/libheif/api/libheif/heif_plugin.h b/libheif/api/libheif/heif_plugin.h index 3a438bfc94..533a1ebc92 100644 --- a/libheif/api/libheif/heif_plugin.h +++ b/libheif/api/libheif/heif_plugin.h @@ -129,6 +129,9 @@ enum heif_image_input_class heif_image_input_class_alpha = 2, heif_image_input_class_depth = 3, heif_image_input_class_thumbnail = 4 +#if WITH_EXPERIMENTAL_GAIN_MAP + , heif_image_input_class_gain_map = 5 +#endif }; diff --git a/libheif/context.cc b/libheif/context.cc index ab1cbb00a7..67d61f5869 100644 --- a/libheif/context.cc +++ b/libheif/context.cc @@ -337,10 +337,12 @@ Error HeifContext::interpret_heif_file() m_top_level_images.clear(); m_primary_image.reset(); - // --- reference all non-hidden images std::vector image_IDs = m_heif_file->get_item_IDs(); +#if WITH_EXPERIMENTAL_GAIN_MAP + bool check_tmap_item = m_heif_file->get_ftyp_box()->has_compatible_brand(heif_brand2_tmap); +#endif for (heif_item_id id : image_IDs) { auto infe_box = m_heif_file->get_infe_box(id); @@ -807,6 +809,12 @@ Error HeifContext::interpret_heif_file() // these item types should have data return err; } +#if WITH_EXPERIMENTAL_GAIN_MAP + else if (check_tmap_item && item_type == fourcc("tmap")) { + // this also should have data + return err; + } +#endif else { // anything else is probably something that we don't understand yet continue; @@ -831,6 +839,41 @@ Error HeifContext::interpret_heif_file() } img_iter->second->add_metadata(metadata); } +#if WITH_EXPERIMENTAL_GAIN_MAP + if (check_tmap_item && item_type == fourcc("tmap")) { + std::vector image_references = iref_box->get_references(id, fourcc("dimg")); + // "'tmap' item MUST be associated with 2 references to images" + // "'tmap' item first entry is expected to be referencing primary image" + // "'tmap' item reference entries MUST not be duplicate" + // "'tmap' item references MUST be pointing to valid image items" + if ((int)image_references.size() == 2 && + image_references[0] == m_heif_file->get_primary_image_ID() && + image_references[1] != image_references[0] && + m_all_images.find(image_references[0]) != m_all_images.end() && + m_all_images.find(image_references[1]) != m_all_images.end()) { + std::shared_ptr baseItem = m_all_images.find(image_references[0])->second; + std::shared_ptr gainmapItem = m_all_images.find(image_references[1])->second; + + baseItem->set_gain_map(gainmapItem); + + baseItem->add_metadata(metadata); // gain map metadata + + auto ipma = m_heif_file->get_ipma_box(); + auto ipco = m_heif_file->get_ipco_box(); + auto derived_image_colr = ipco->get_property_for_item_ID(id, ipma, fourcc("colr")); + auto colr = std::dynamic_pointer_cast(derived_image_colr); + auto nclx = + std::dynamic_pointer_cast(colr->get_color_profile()); + if (nclx) { + baseItem->set_derived_img_color_profile(nclx); + } + auto raw = std::dynamic_pointer_cast(colr->get_color_profile()); + if (raw) { + baseItem->set_derived_img_color_profile(raw); + } + } + } +#endif } } @@ -1170,6 +1213,29 @@ create_alpha_image_from_image_alpha_channel(const std::shared_ptr& data, heif_item_id& item_id) { + auto tmap_infe = m_heif_file->add_new_infe_box(fourcc("tmap")); // gain map metadata + tmap_infe->set_item_name("GMap"); + item_id = tmap_infe->get_item_ID(); + + m_heif_file->append_iloc_data(item_id, data, 0); + + return Error::Ok; +} + + +Error HeifContext::link_gain_map(const std::shared_ptr& primary_image, + const std::shared_ptr& gain_map_image, + const heif_item_id tmap_id) { + m_heif_file->add_iref_reference(tmap_id, fourcc("dimg"), + {primary_image->get_id(), gain_map_image->get_id()}); + + return Error::Ok; +} +#endif + + Result> HeifContext::encode_image(const std::shared_ptr& pixel_image, struct heif_encoder* encoder, const struct heif_encoding_options& in_options, diff --git a/libheif/context.h b/libheif/context.h index 3f4f0bc3e7..48e86c8af0 100644 --- a/libheif/context.h +++ b/libheif/context.h @@ -47,6 +47,7 @@ class StreamWriter; class ImageItem; +class ImageMetadata; // This is a higher-level view than HeifFile. // Images are grouped logically into main images and their thumbnails. @@ -147,6 +148,14 @@ class HeifContext : public ErrorBuffer Result add_pyramid_group(const std::vector& layers); +#if WITH_EXPERIMENTAL_GAIN_MAP + Error add_tmap_item(const std::vector& metadata, heif_item_id& item_id); + + Error link_gain_map(const std::shared_ptr& primary_image, + const std::shared_ptr& gain_map_image, const heif_item_id tmap_id); +#endif + + // --- region items void add_region_item(std::shared_ptr region_item) diff --git a/libheif/file.cc b/libheif/file.cc index 8a678bf92a..e725f4db0b 100644 --- a/libheif/file.cc +++ b/libheif/file.cc @@ -192,6 +192,9 @@ void HeifFile::set_brand(heif_compression_format format, bool miaf_compatible) m_ftyp_box->set_minor_version(0); m_ftyp_box->add_compatible_brand(heif_brand2_mif1); m_ftyp_box->add_compatible_brand(heif_brand2_heic); +#if WITH_EXPERIMENTAL_GAIN_MAP + m_ftyp_box->add_compatible_brand(heif_brand2_tmap); +#endif break; case heif_compression_AV1: @@ -199,6 +202,9 @@ void HeifFile::set_brand(heif_compression_format format, bool miaf_compatible) m_ftyp_box->set_minor_version(0); m_ftyp_box->add_compatible_brand(heif_brand2_avif); m_ftyp_box->add_compatible_brand(heif_brand2_mif1); +#if WITH_EXPERIMENTAL_GAIN_MAP + m_ftyp_box->add_compatible_brand(heif_brand2_tmap); +#endif break; case heif_compression_VVC: @@ -352,6 +358,9 @@ Error HeifFile::parse_heif_file() !m_ftyp_box->has_compatible_brand(heif_brand2_1pic) && #if ENABLE_EXPERIMENTAL_MINI_FORMAT !(m_ftyp_box->get_major_brand() == heif_brand2_mif3) && +#endif +#if WITH_EXPERIMENTAL_GAIN_MAP + !(m_ftyp_box->get_major_brand() == heif_brand2_tmap) && #endif !m_ftyp_box->has_compatible_brand(heif_brand2_jpeg)) { std::stringstream sstr; diff --git a/libheif/image-items/image_item.cc b/libheif/image-items/image_item.cc index 549880b610..76dbaf2e51 100644 --- a/libheif/image-items/image_item.cc +++ b/libheif/image-items/image_item.cc @@ -386,6 +386,17 @@ Error ImageItem::encode_to_item(HeifContext* ctx, auto infe_box = ctx->get_heif_file()->add_new_infe_box(get_infe_type()); heif_item_id image_id = infe_box->get_item_ID(); set_id(image_id); +#if WITH_EXPERIMENTAL_GAIN_MAP + if (input_class == heif_image_input_class_gain_map) { + if (encoder->plugin->compression_format != heif_compression_HEVC && + encoder->plugin->compression_format != heif_compression_AV1) { + return Error(heif_error_Encoder_plugin_error, heif_suberror_Unsupported_codec); + } + infe_box->set_item_name("GMap"); + infe_box->set_hidden_item(true); + } +#endif + ctx->get_heif_file()->append_iloc_data(image_id, codedImage.bitstream, 0); @@ -646,7 +657,13 @@ void ImageItem::add_color_profile(const std::shared_ptr& image, const heif_color_profile_nclx* target_heif_nclx, ImageItem::CodedImageData& inout_codedImage) { +#if WITH_EXPERIMENTAL_GAIN_MAP + if (input_class == heif_image_input_class_normal || + input_class == heif_image_input_class_thumbnail || + input_class == heif_image_input_class_gain_map) { +#else if (input_class == heif_image_input_class_normal || input_class == heif_image_input_class_thumbnail) { +#endif auto icc_profile = image->get_color_profile_icc(); if (icc_profile) { auto colr = std::make_shared(); diff --git a/libheif/image-items/image_item.h b/libheif/image-items/image_item.h index 5f0d2b2bbc..8a9fdb3256 100644 --- a/libheif/image-items/image_item.h +++ b/libheif/image-items/image_item.h @@ -82,12 +82,14 @@ class ImageItem : public ErrorBuffer virtual Result> read_bitstream_configuration_data() const { return std::vector{}; } - void clear() - { + void clear() { m_thumbnails.clear(); m_alpha_channel.reset(); m_depth_channel.reset(); m_aux_images.clear(); +#if WITH_EXPERIMENTAL_GAIN_MAP + m_gain_map_image.reset(); +#endif } HeifContext* get_context() { return m_heif_context; } @@ -264,6 +266,44 @@ class ImageItem : public ErrorBuffer } } +#if WITH_EXPERIMENTAL_GAIN_MAP + // --- gain map + + const std::shared_ptr& get_gain_map() const { return m_gain_map_image; } + + std::shared_ptr get_gain_map_metadata() { + if (m_gain_map_image != nullptr) { + for (auto it : m_metadata) { + if (it->item_type == "tmap") { + return it; + } + } + } + return nullptr; + } + + const std::shared_ptr& get_derived_img_color_profile_nclx() const { + return m_derived_img_color_profile_nclx; + } + + const std::shared_ptr& get_derived_img_color_profile_icc() const { + return m_derived_img_color_profile_icc; + } + + void set_gain_map(std::shared_ptr img) { m_gain_map_image = std::move(img); } + + void set_derived_img_color_profile(const std::shared_ptr& profile) { + auto icc = std::dynamic_pointer_cast(profile); + if (icc) { + m_derived_img_color_profile_icc = std::move(icc); + } + + auto nclx = std::dynamic_pointer_cast(profile); + if (nclx) { + m_derived_img_color_profile_nclx = std::move(nclx); + } + }; +#endif // --- metadata @@ -417,10 +457,18 @@ class ImageItem : public ErrorBuffer std::string m_aux_image_type; std::vector> m_aux_images; +#if WITH_EXPERIMENTAL_GAIN_MAP + std::shared_ptr m_gain_map_image; +#endif + std::vector> m_metadata; std::shared_ptr m_color_profile_nclx; std::shared_ptr m_color_profile_icc; +#if WITH_EXPERIMENTAL_GAIN_MAP + std::shared_ptr m_derived_img_color_profile_nclx; + std::shared_ptr m_derived_img_color_profile_icc; +#endif bool m_miaf_compatible = true; diff --git a/libheif/plugins/encoder_aom.cc b/libheif/plugins/encoder_aom.cc index 9c01a50eb4..c16ea30b0c 100644 --- a/libheif/plugins/encoder_aom.cc +++ b/libheif/plugins/encoder_aom.cc @@ -1073,7 +1073,12 @@ struct heif_error aom_encode_image(void* encoder_raw, const struct heif_image* i if (nclx && (input_class == heif_image_input_class_normal || +#if WITH_EXPERIMENTAL_GAIN_MAP + input_class == heif_image_input_class_thumbnail || + input_class == heif_image_input_class_gain_map)) { +#else input_class == heif_image_input_class_thumbnail)) { +#endif aom_error = aom_codec_control(&codec, AV1E_SET_COLOR_PRIMARIES, nclx->color_primaries); CHECK_ERROR aom_error = aom_codec_control(&codec, AV1E_SET_MATRIX_COEFFICIENTS, nclx->matrix_coefficients); CHECK_ERROR; aom_error = aom_codec_control(&codec, AV1E_SET_TRANSFER_CHARACTERISTICS, nclx->transfer_characteristics); CHECK_ERROR; diff --git a/libheif/plugins/encoder_kvazaar.cc b/libheif/plugins/encoder_kvazaar.cc index 9db79a6c2d..6acb35b723 100644 --- a/libheif/plugins/encoder_kvazaar.cc +++ b/libheif/plugins/encoder_kvazaar.cc @@ -567,7 +567,12 @@ static struct heif_error kvazaar_encode_image(void* encoder_raw, const struct he if (nclx && (input_class == heif_image_input_class_normal || +#if WITH_EXPERIMENTAL_GAIN_MAP + input_class == heif_image_input_class_thumbnail || + input_class == heif_image_input_class_gain_map)) { +#else input_class == heif_image_input_class_thumbnail)) { +#endif config->vui.colorprim = nclx->color_primaries; config->vui.transfer = nclx->transfer_characteristics; config->vui.colormatrix = nclx->matrix_coefficients; diff --git a/libheif/plugins/encoder_rav1e.cc b/libheif/plugins/encoder_rav1e.cc index 6a0ca759ab..7e0fbac8ca 100644 --- a/libheif/plugins/encoder_rav1e.cc +++ b/libheif/plugins/encoder_rav1e.cc @@ -550,7 +550,12 @@ struct heif_error rav1e_encode_image(void* encoder_raw, const struct heif_image* if (nclx && (input_class == heif_image_input_class_normal || +#if WITH_EXPERIMENTAL_GAIN_MAP + input_class == heif_image_input_class_thumbnail || + input_class == heif_image_input_class_gain_map)) { +#else input_class == heif_image_input_class_thumbnail)) { +#endif if (rav1e_config_set_color_description(rav1eConfig.get(), (RaMatrixCoefficients) nclx->matrix_coefficients, (RaColorPrimaries) nclx->color_primaries, diff --git a/libheif/plugins/encoder_x265.cc b/libheif/plugins/encoder_x265.cc index d4e1b01682..2544873d6f 100644 --- a/libheif/plugins/encoder_x265.cc +++ b/libheif/plugins/encoder_x265.cc @@ -806,7 +806,12 @@ static struct heif_error x265_encode_image(void* encoder_raw, const struct heif_ if (nclx && (input_class == heif_image_input_class_normal || +#if WITH_EXPERIMENTAL_GAIN_MAP + input_class == heif_image_input_class_thumbnail || + input_class == heif_image_input_class_gain_map)) { +#else input_class == heif_image_input_class_thumbnail)) { +#endif { std::stringstream sstr;