@@ -657,6 +657,86 @@ struct heif_error heif_context_get_primary_image_ID(struct heif_context* ctx, he
657657}
658658
659659
660+ #if WITH_EXPERIMENTAL_GAIN_MAP
661+ heif_error heif_context_get_gain_map_image_handle (heif_context* ctx, heif_image_handle** img) {
662+ if (!img) {
663+ Error err (heif_error_Usage_error, heif_suberror_Null_pointer_argument);
664+ return err.error_struct (ctx->context .get ());
665+ }
666+
667+ std::shared_ptr<ImageItem> gain_map_image = ctx->context ->get_gain_map_image ();
668+ if (!gain_map_image) {
669+ Error err (heif_error_Invalid_input, heif_suberror_No_item_data);
670+ return err.error_struct (ctx->context .get ());
671+ }
672+
673+ *img = new heif_image_handle ();
674+ (*img)->image = std::move (gain_map_image);
675+ (*img)->context = ctx->context ;
676+
677+ return Error::Ok.error_struct (ctx->context .get ());
678+ }
679+
680+ // As per ISO/IEC 23008-12, Support for tone map derived items and other improvements, Section:
681+ // Tone-map derivation, A 'tmap' derived item shall be associated with a 'colr' item property. This
682+ // need not be cicp but also icc. TODO: Add support for handling raw (icc) color profile
683+ struct heif_error heif_context_get_tmap_nclx_color_profile (
684+ struct heif_context * ctx, struct heif_color_profile_nclx ** out_data) {
685+ if (!out_data) {
686+ Error err (heif_error_Usage_error, heif_suberror_Null_pointer_argument);
687+ return err.error_struct (ctx->context .get ());
688+ }
689+
690+ Error err = ctx->context ->get_tmap_color_profile (out_data);
691+ return err.error_struct (ctx->context .get ());
692+ }
693+
694+ size_t heif_context_get_gain_map_metadata_size (struct heif_context * ctx) {
695+ std::shared_ptr<ImageMetadata> metadata = ctx->context ->get_gain_map_metadata ();
696+
697+ if (metadata) {
698+ // Ignore unsigned int(8) version = 0 field of ToneMapImage syntax
699+ size_t sz = metadata->m_data .size ();
700+ return sz > 0 ? (sz - 1 ) : 0 ;
701+ }
702+
703+ return 0 ;
704+ }
705+
706+ struct heif_error heif_context_get_gain_map_metadata (struct heif_context * ctx, void * out_data) {
707+ if (!out_data) {
708+ Error err (heif_error_Usage_error, heif_suberror_Null_pointer_argument);
709+ return err.error_struct (ctx->context .get ());
710+ }
711+
712+ std::shared_ptr<ImageMetadata> metadata = ctx->context ->get_gain_map_metadata ();
713+ if (!metadata) {
714+ Error err (heif_error_Invalid_input, heif_suberror_No_item_data);
715+ return err.error_struct (ctx->context .get ());
716+ }
717+
718+ uint8_t version = 0xff ;
719+ size_t pos = 0 ;
720+ std::vector<uint8_t >& buffer = metadata->m_data ;
721+
722+ if (pos >= buffer.size ()) {
723+ Error err (heif_error_Invalid_input, heif_suberror_End_of_data);
724+ return err.error_struct (ctx->context .get ());
725+ }
726+ version = buffer[pos++];
727+ if (version != 0 ) {
728+ Error err (heif_error_Invalid_input, heif_suberror_Unsupported_data_version,
729+ " Box[tmap] has unsupported version" );
730+ return err.error_struct (ctx->context .get ());
731+ }
732+
733+ memcpy (out_data, buffer.data () + pos, buffer.size () - pos);
734+
735+ return heif_error_success;
736+ }
737+ #endif
738+
739+
660740int heif_context_is_top_level_image_ID (struct heif_context * ctx, heif_item_id id)
661741{
662742 const std::vector<std::shared_ptr<ImageItem>> images = ctx->context ->get_top_level_images (true );
@@ -3442,6 +3522,117 @@ struct heif_error heif_context_encode_image(struct heif_context* ctx,
34423522}
34433523
34443524
3525+ #if WITH_EXPERIMENTAL_GAIN_MAP
3526+ struct heif_error heif_context_encode_gain_map_image (
3527+ struct heif_context * ctx, const struct heif_image * alternate_image,
3528+ const struct heif_image_handle * base_image_handle, struct heif_encoder * encoder,
3529+ const struct heif_encoding_options * input_options, const uint8_t * gain_map_metadata,
3530+ int gain_map_metadata_len, const struct heif_color_profile_nclx * derived_image_nclx,
3531+ struct heif_image_handle ** out_image_handle) {
3532+ if (!encoder) {
3533+ return Error (heif_error_Usage_error, heif_suberror_Null_pointer_argument)
3534+ .error_struct (ctx->context .get ());
3535+ }
3536+
3537+ if (out_image_handle) {
3538+ *out_image_handle = nullptr ;
3539+ }
3540+
3541+ if (gain_map_metadata_len <= 0 ) {
3542+ return Error (heif_error_Invalid_input, heif_suberror_Invalid_parameter_value)
3543+ .error_struct (ctx->context .get ());
3544+ }
3545+
3546+ // --- write tmap item
3547+ std::vector<uint8_t > metadata;
3548+ metadata.push_back (0 ); // version = 0
3549+ for (int i = 0 ; i < gain_map_metadata_len; i++) {
3550+ metadata.push_back (gain_map_metadata[i]);
3551+ }
3552+ heif_item_id tmap_item_id = -1 ;
3553+ ctx->context ->add_tmap_item (metadata, tmap_item_id);
3554+
3555+ std::vector<std::shared_ptr<Box>> properties;
3556+
3557+ // --- write ISPE property for tmap item
3558+ std::shared_ptr<Box_ispe> ispe = std::make_shared<Box_ispe>();
3559+ ispe->set_size (base_image_handle->image ->get_ispe_width (),
3560+ base_image_handle->image ->get_ispe_height ());
3561+
3562+ properties.push_back (ispe);
3563+
3564+ // --- write PIXI property for tmap item
3565+ // TODO: this assumes the base image is 8 bit and derived image is 10 bit. Have to handle the
3566+ // other way where the base image is hdr and derived image is sdr
3567+ std::shared_ptr<Box_pixi> pixi = std::make_shared<Box_pixi>();
3568+ pixi->add_channel_bits (10 );
3569+ pixi->add_channel_bits (10 );
3570+ pixi->add_channel_bits (10 );
3571+
3572+ properties.push_back (pixi);
3573+
3574+ // --- write COLR property for tmap item
3575+ if (derived_image_nclx != nullptr ) {
3576+ std::shared_ptr<Box_colr> colr = std::make_shared<Box_colr>();
3577+ auto target_nclx_profile = std::make_shared<color_profile_nclx>();
3578+ target_nclx_profile->set_colour_primaries (derived_image_nclx->color_primaries );
3579+ target_nclx_profile->set_transfer_characteristics (derived_image_nclx->transfer_characteristics );
3580+ target_nclx_profile->set_matrix_coefficients (derived_image_nclx->matrix_coefficients );
3581+ target_nclx_profile->set_full_range_flag (derived_image_nclx->full_range_flag );
3582+ colr->set_color_profile (target_nclx_profile);
3583+
3584+ properties.push_back (colr);
3585+ }
3586+ // set item properties
3587+ for (auto & propertyBox : properties) {
3588+ int index =
3589+ ctx->context ->get_heif_file ()->get_ipco_box ()->find_or_append_child_box (propertyBox);
3590+ ctx->context ->get_heif_file ()->get_ipma_box ()->add_property_for_item_ID (
3591+ tmap_item_id,
3592+ Box_ipma::PropertyAssociation{propertyBox->is_essential (), uint16_t (index + 1 )});
3593+ }
3594+
3595+ heif_encoding_options options;
3596+ set_default_encoding_options (options);
3597+ if (input_options != nullptr ) {
3598+ copy_options (options, *input_options);
3599+ }
3600+
3601+ auto gainmap_encoding_result = ctx->context ->encode_image (
3602+ alternate_image->image , encoder, options, heif_image_input_class_gain_map);
3603+ if (gainmap_encoding_result.error ) {
3604+ return gainmap_encoding_result.error .error_struct (ctx->context .get ());
3605+ }
3606+
3607+ std::shared_ptr<ImageItem> gain_map_image = *gainmap_encoding_result;
3608+ Error error = ctx->context ->link_gain_map (base_image_handle->image , gain_map_image, tmap_item_id);
3609+ if (error != Error::Ok) {
3610+ return error.error_struct (ctx->context .get ());
3611+ }
3612+
3613+ if (out_image_handle) {
3614+ *out_image_handle = new heif_image_handle;
3615+ (*out_image_handle)->image = std::move (gain_map_image);
3616+ (*out_image_handle)->context = ctx->context ;
3617+ }
3618+
3619+ // --- generate altr box
3620+ auto altr_box = std::make_shared<Box_EntityToGroup>();
3621+ altr_box->set_short_type (fourcc (" altr" ));
3622+ altr_box->set_group_id (ctx->context ->get_heif_file ()->get_unused_item_id ());
3623+
3624+ std::vector<heif_item_id> ids;
3625+ ids.push_back (tmap_item_id);
3626+ ids.push_back (base_image_handle->image ->get_id ());
3627+
3628+ altr_box->set_item_ids (ids);
3629+ ctx->context ->get_heif_file ()->add_entity_group_box (altr_box);
3630+
3631+ return heif_error_success;
3632+ }
3633+ #endif
3634+
3635+
34453636struct heif_error heif_context_encode_grid (struct heif_context * ctx,
34463637 struct heif_image ** tiles,
34473638 uint16_t columns,
0 commit comments