Repository navigation
imageio: write peak luminance metadata for PQ JPEG XL, HEIF and PNG exports - #22666
Conversation
|
Output CICP should already be written for HEIF and PNG (as with AVIF and JXL), IMHO one can (or should be able to) skip writing the chromaticities and white point explicitly... I.e. one should aim to keep those writers as similar as possible wrt HDR workflow, perhaps factor as much common code out as possible... |
The AVIF and HEIF writers each carried their own copy of the PQ EOTF and the same MaxCLL/MaxFALL loop. Move the loop into dt_imageio_pq_light_level(), built on dt_hdr_pq_decode() from common/hdr-transfer.h, so every writer that needs the PQ content peak measures it the same way. NaN samples decode to black and Inf to the PQ maximum, as the old isfinite() check guaranteed, so the written levels do not change. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vw9xh7zRjZCUynr6FAuohP
PQ exports left intensity_target at 0, so libjxl recorded its default of 10000 nits and viewers tone mapped every image as if it reached the top of the PQ range. Measure the content peak with the helper the AVIF and HEIF writers use for MaxCLL and store it as the intensity target. HLG is relative and keeps libjxl's default. Fixes darktable-org#22663 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vw9xh7zRjZCUynr6FAuohP
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vw9xh7zRjZCUynr6FAuohP
3bdab96 to
b59d60e
Compare
Thanks, agreed. CICP is already written by all four writers, and the mdcv/mDCV I added carried nothing new: its primaries and white point repeated CICP, and its peak was the same MaxCLL already in clli/cLLI. I've dropped both, so HEIF and PNG are back to CICP + content light level, the same as AVIF. I've also factored the measurement out. AVIF and HEIF each had their own PQ EOTF and MaxCLL/MaxFALL loop; that now lives in PNG keeps its own measurement because it only sees the quantized 8/16-bit output, not the float buffer. I can route it through the shared decode too if you'd prefer. The PR is now 3 commits: the shared helper, the JXL intensity target, and the release note. |
Summary
PQ exports to JPEG XL had no intensity target, so libjxl recorded 10000 nits and viewers tone mapped every image as if it reached the top of the PQ range. The JPEG XL writer now measures the brightest sample and stores it as the intensity target. The measurement is shared: the AVIF and HEIF writers each had their own copy of the PQ EOTF and the MaxCLL/MaxFALL loop, which now live in one helper,
dt_imageio_pq_light_level(), built ondt_hdr_pq_decode(). The levels they write are unchanged. HLG output is untouched, since HLG is relative.An earlier revision also wrote mastering display metadata (HEIF mdcv, PNG mDCV). It was dropped after review: its primaries and white point only repeated the CICP signaling every writer already emits, and its peak was the MaxCLL already in clli/cLLI.
Referenced issue
Fixes #22663
Checklist
src/tests/integration/where the pixelpipe is touched, ordarktable-clias a headless smoke test._(), new preferences are registered indata/darktableconfig.xml.in. (none added)RELEASE_NOTES.mdentry was added (only needed if fixing an issue in a release). Do not reference GitHub issues.Test instructions
Export any image with a PQ Rec2020 or PQ P3 output profile to JPEG XL, HEIF and AVIF:
What I ran:
darktable-clion a synthetic linear ramp peaking at 4x reference white (812 nits), with PQ Rec2020, PQ P3 and HLG Rec2020.jxlinforeads back an intensity target of 812 nits for both PQ variants and none for HLG. AVIF and HEIF still report MaxCLL 812 and MaxFALL 406 after the refactor, the same values as before it. Built with libjxl 0.7.0, libheif 1.17.6, libavif 1.0.4, no warnings, each commit built on its own.Not verified: how macOS, Chrome or other viewers render the intensity target; writing the HEIF file itself, since the test machine's libheif has no HEVC encoder (the clli values are from the debug log).
AI assistance
Written with Claude Code (an AI coding agent), which made the code change and ran the darktable-cli and metadata checks listed above. [Nick: add what you checked yourself.]