Skip to content

jpegrutils: set use_base_cg for Apple gain maps - #484

Open
tejas-dbx-public wants to merge 2 commits into
google:mainfrom
tejas-dbx-public:apple-gainmap-use-base-cg
Open

tejas-dbx-public wants to merge 2 commits into
google:mainfrom
tejas-dbx-public:apple-gainmap-use-base-cg

Conversation

@tejas-dbx-public

@tejas-dbx-public tejas-dbx-public commented Sep 23, 2026 •

Copy link
Copy Markdown

The Apple decode path in getMetadataFromXMP() (added in #385) returns early without setting use_base_cg, so it stays false.

Decoding is unaffected. But re-encoding the decoded base image, gain map, and metadata through uhdr_enc_set_compressed_image + uhdr_enc_set_gainmap_image fails in JpegR::encodeJPEGR:

For gainmap application space to be alternate image space, gainmap image is expected
to contain alternate image color space in the form of ICC. The ICC marker in gainmap
jpeg is missing.

use_base_cg == false tells the encoder the gain map is applied in an alternate color space and must carry its own ICC profile. Apple gain-map images don't have one. Apple applies the gain map in the base image's color space, so use_base_cg should be true, which is what the ISO and Adobe XMP paths already set.

In practice this shows up when an app resizes an Apple HDR JPEG while preserving its gain map (for example ImageMagick's UHDR: coder): the transcode fails instead of producing a smaller Ultra HDR JPEG.

Decoded output doesn't change. Apple gain-map images carry no ICC, so applyGainMap resolves the gain map's gamut to the base's, and both gamut-conversion paths are identity whichever way use_base_cg is set. I confirmed that decoding both Apple fixtures to linear HDR gives byte-identical output with and without this change. Only the encode check is affected.

Test

JpegRTest.decodeApple now also asserts use_base_cg for both Apple fixtures (apple_gainmap_old.jpg, apple_gainmap_new.jpg), and round-trips each one: it re-encodes the decoded base image, gain map and metadata through uhdr_enc_set_compressed_image + uhdr_enc_set_gainmap_image, then decodes the result. Without this change the re-encode fails with the ICC error above; with it, both fixtures pass. The full ultrahdr_unit_test suite passes (1093 tests).

Related discussion: #365.

The Apple decode path in getMetadataFromXMP() returns early without setting
use_base_cg, so it stays false. Decoding is unaffected, but re-encoding the
decoded base image, gain map and metadata (e.g. to resize an Apple HDR JPEG)
then fails in encodeJPEGR with "ICC marker in gainmap jpeg is missing":
use_base_cg == false tells the encoder the gain map lives in an alternate color
space and must carry its own ICC profile, which Apple gain-map images do not.

Apple applies the gain map in the base image's color space, so set
use_base_cg = true, matching the ISO and Adobe XMP paths.

Test: decodeApple now asserts use_base_cg for both Apple fixtures (it fails
without this change).
Re-encode the decoded base image, gain map and metadata with
uhdr_enc_set_compressed_image + uhdr_enc_set_gainmap_image and check the
result decodes. Without the use_base_cg fix this fails because the Apple
gain-map image has no ICC profile.
@gregbenz

Copy link
Copy Markdown
Contributor

@tejas-dbx-public Thanks for clarifying on the other PR, and for adding the round-trip tests for both Apple samples. That covers the failure I had in mind. This updated change looks good to me.

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.

2 participants