Skip to content

Conversation

@ram-mohan
Copy link

@ram-mohan ram-mohan commented Apr 6, 2025

Gain map technology offers a way to create an image (henceforth referred
as derived image) from one base input image and a secondary input image
called as a gainmap input image. Reconstruction is done by applying the
gain map to the base image according to iso 21496-1 section 6.

This change provides API to read, write base input image, gain map input
image, gain map metadata. Third party applications can make use of this
API to render only base image or reconstruct the derived image and
render the same.

By default these API is disabled and can be enabled at configure time
using option -DWITH_EXPERIMENTAL_GAIN_MAP=1

TODO: add plugins for encoding, decoding uhdr images

@ram-mohan ram-mohan force-pushed the master branch 2 times, most recently from dce9a85 to 7440574 Compare April 6, 2025 20:09
std::shared_ptr<ImageItem> get_primary_image(bool return_error_image);

#if WITH_EXPERIMENTAL_GAIN_MAP
std::shared_ptr<ImageItem> get_gain_map_image() { return m_gain_map_image; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only works if there is only a single gain map in the file. The gain map should probably be stored in the ImageItem like the alpha image or the depth map.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the review, As indicated, i have moved the gainmap info inside ImageItem

#if WITH_EXPERIMENTAL_GAIN_MAP
std::shared_ptr<ImageItem> get_gain_map_image() { return m_gain_map_image; }

std::shared_ptr<ImageMetadata> get_gain_map_metadata();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, the gain map metadata has to be part of ImageItem to work correctly when there are several images in a file.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@farindk
Copy link
Contributor

farindk commented Apr 7, 2025

Thank you. Note that there is also some work for this in #1121.

I will have a closer look at this when we switched to the v1.20.x branch and can do API additions.

@farindk
Copy link
Contributor

farindk commented Apr 7, 2025

Gain map technology offers a way to create an image (henceforth referred
as derived image) from one base input image and a secondary input image
called as a gainmap input image. Reconstruction is done by applying the
gain map to the base image according to iso 21496-1 section 6.

This change provides API to read, write base input image, gain map input
image, gain map metadata. Third party applications can make use of this
API to render only base image or reconstruct the derived image and
render the same.

By default these API is disabled and can be enabled at configure time
using option -DWITH_EXPERIMENTAL_GAIN_MAP=1

TODO: add plugins for encoding, decoding uhdr images
@Tom94
Copy link

Tom94 commented Jan 22, 2026

Hi there, just wanted to check in on the progress of this. I realize that gain maps can already be decoded as generic auxiliary images, but I don't think it's possible to read gain map metadata without this PR's tmap item support (please let me know if I am wrong) -- that feature alone would already be very useful. Thank you!

@fxthomas
Copy link

fxthomas commented Feb 2, 2026

I rebased it on v1.21.2 here: https://github.com/fxthomas/libheif/tree/pr/1503-gain-maps-v1.21.2

A couple of warts in the API so far (I haven't touched most of the original branch, just moved things around when needed following changes in libheif master):

  • I'm not sure about truncating the version field of the tmap metadata, it seems to me that it would be more future-proof to just copy the whole structure without modification.
  • It looks like having a proper API for handling derived images (dimg boxes) might be something to look into for the future, since this is something that is common across several sub-formats.
  • There are several hard-coded things that might need some configurable options : the encoded bit depth is hardcoded to 10-bits, and it is currently not possible to store a full ICC profile to the new tmap derived image (only nclx), unlike some other HEIC images I've found in the wild.

I verified that it is possible to re-encode an input HEIC+gain map file into a new HEIC+gain map file with almost identical data (the "except" is because of re-compression of the original decompressed data) and that both display identically on an HDR display.

@Tom94
Copy link

Tom94 commented Feb 2, 2026

I'm not sure about truncating the version field of the tmap metadata, it seems to me that it would be more future-proof to just copy the whole structure without modification.

To make things worse, I encountered heic images in the wild whose tmap metadata doesn't have the version field (start directly with the ISO gainmap metadata). And I don't know of a good, spec-compliant way to check for this automatically. (One might consider checking the size for 62 or 142, but the ISO standard permits padding at the end of the metadata which makes that approach ambiguous... works in practice on all images I tried, though.) Long story short: 100% agree with leaving this up to the consumer.

@fxthomas
Copy link

fxthomas commented Feb 3, 2026

After checking : the version I have access to (ISO/DIS 21496-1:2024 draft, which I unfortunately cannot link to here because ISO is not public access...) seems to mandate the presence of the version field. In my version this field also contains a struct of 2 big endian int16 values (which matches images generated by iOS devices, for example), but the original PR truncates a single uint8 value (an older revision of the draft?).

Either way all things do point towards leaving interpretation outside of libheif (and not just for tmap but for all derived images in general which follow the same principles).

@Tom94
Copy link

Tom94 commented Feb 3, 2026

Yes, the two big endian int16 values are always included. What I am saying is that some heic files (notably ones from my iPhone) include an additional uint8 version (the one being skipped in this PR), whereas other heic files don't include the uint8 (notably from Hasselblad cameras).

@fxthomas
Copy link

fxthomas commented Feb 3, 2026

some heic files (notably ones from my iPhone) include an additional uint8 version (the one being skipped in this PR)

Ah, I found it elsewhere! ISO/IEC 23008-12 describes the structure of HEIF/HEIC files and the latest version describes how ISO 21496 is supposed to be implemented in those containers.

While I only have a draft (I cannot check if it is still the case in the published version), the version I have has an uint8 version field marked as mandatory, which is then followed by the struct described in ISO 21496. I'm still in favor of just returning the whole data, but this explains why the PR truncated the field originally.

@Tom94
Copy link

Tom94 commented Feb 3, 2026

Ooooh, thank you very much for the pointer! (Yet another document to purchase...) That at least settles which of the heic images are compliant.

I'm still in favor of just returning the whole data, but this explains why the PR truncated the field originally.

FWIW, also still agreeing. Even if only for users to be able to read non-standard metadata.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants