Repository navigation
Conversation
The shoulder of the AgX curve was capped at linear 1.0, so a PQ or HLG export could never place highlights above the 203 nit reference white that colorout maps 1.0 to. Users had to pull exposure down and lose the mid-tone placement AgX was tuned for. Raise the target white limit to 50 (5000%, about 10000 nits) while keeping the 50-100% soft range, so SDR edits are unchanged. The curve math already handles a shoulder ending above 1; the graph now scales its y axis to fit and adds guides above 100%. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Hf5bYk6AYsiHXNmKFEr15
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Hf5bYk6AYsiHXNmKFEr15
With HDR headroom, target white is easier to reason about as display luminance than as a percentage of reference white. Add a "show target white in nits" toggle under the slider. It only changes the slider's display factor and unit (203 nits per 100%), so typed values are taken in nits too and the stored params are unchanged. The choice is kept in conf, and the curve graph's guide labels follow it. Labels are now placed top-down and skipped when they would overlap, so the guides squeezed together below a raised shoulder no longer print on top of each other. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Hf5bYk6AYsiHXNmKFEr15
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Hf5bYk6AYsiHXNmKFEr15
With HDR headroom, "target white" is the curve's peak output rather than the reference white, which stays at 203 nits. The label is kept so existing shortcuts, translations and the manual still match; the tooltip now says what the slider controls and how it maps to nits. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Hf5bYk6AYsiHXNmKFEr15
HLG is encoded through the BT.2100 1000 nit OOTF, so a target white above about 493% is not rolled off by the curve but clipped flat in dt_hdr_hlg_encode(). Nothing told the user this was happening. Show the warning icon on the target white slider when the export profile is HLG and the target white exceeds the HLG peak, refresh it when the export profile changes, and mention the limit in the tooltip. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Hf5bYk6AYsiHXNmKFEr15
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Hf5bYk6AYsiHXNmKFEr15
468fedc to
d70d2e3
Compare
|
@nicknezis : You have created a set of PR with the same goal, supporting HDR. In each PR you have a description and I think I understand them. But can you please give me an explanation of the full picture, what is your goal at the end? What's are you trying to achieve/fix on the HDR side? This would help me for the review. TIA. |
Thanks for asking, and sorry for landing six PRs at once without a map. Here is the whole picture. The goal Take a raw, edit it once, and export it both as a normal SDR file and as an HDR file (PQ or HLG) that uses the extra brightness of an HDR screen, with no exposure hacks and without changing the history per target. Later, the same mechanism should allow gain-map exports (one file that looks right on SDR and HDR screens) and HDR display in the darkroom. What is broken today #22516 fixed the PQ/HLG encoding so that 1.0 in the pipe is the 203 nit reference white (BT.2408). That is correct, but it means anything above reference white has to come out of the tone mapper as values above 1.0, and none of our tone mappers really do that:
Before #22516 people worked around this by pulling exposure down by several EV, which is the hack I wanted to get rid of. The PRs, grouped by what they fix
Each one is based on master and can be reviewed and merged on its own. #22661 and #22669 both touch AgX, so whichever goes in second will need a rebase. #22661 was the first, simpler step: a manual slider. kofa73's review of #22669 showed that AgX's curve maths was built for a white of at most 1.0, so pushing target white well above 100% (above about 600 nits) makes the shoulder fall back to a shape that steepens near the top. The Blender-style rework in #22669 avoids that by keeping the curve on 0..1 and adding the HDR step after it. The large values #22661 allows would run into the same problem. So I think #22669 is the better route for AgX, and #22661 is worth keeping only if a manual peak (without the output option) is wanted. I'm happy to close #22661, or cut it down to what still makes sense on top of #22669, whichever you prefer. Where it goes next (not in these PRs)
Suggested review order #22669 first, since it carries the design. Then #22662 (independent). Then #22668 and #22667, which are small. #22661 last, or closed, depending on what you think of the above. |
|
@nicknezis : Thanks, I'm starting to understand, still some question. You said :
But if I understand well taking the description on Sigmoid PR #22668 you still need to tweak the "target white" to get a proper export in "Rec2020 PQ". So you don't really ensure the "edit it once" and export SDR & HDR ? If this is true maybe we can design an automatic way of supporting that ? |
@TurboGit You're right about #22668: on its own it only raises sigmoid's limit, so you would still set target white by hand for each target. The same is true of #22661 for AgX. Those two are the manual part. The automatic way is #22669, and it is what makes "edit once" work:
The option is off by default, and existing edits are migrated with it off, so nobody's images change. If you would rather have it on by default for new edits, or set by a preference, I'm happy to do that. That is the main design choice I'd like your view on. Given that, I don't think #22661 and #22668 are needed for the HDR workflow any more. They only matter for someone who wants a fixed peak typed in by hand, and for AgX that path also has the shoulder problem kofa73 found above about 600 nits. I'd suggest focusing review on #22669 and closing #22661 and #22668, unless you see a use for the manual sliders. |
|
Ok, the fog is starting to dissipate :)
Do you think this makes sense? Let's continue the design before changing code at the moment, I really need to get a clear view of all this which is probably not yet the case at the moment. Thanks for your patience. |
|
@nicknezis what PR's do we need to pull so that we can test the whole thing. I have some HDR images, PQ and otherwise, that I can test with. |
@TurboGit Yes, it makes sense, and I agree we should settle the design before more code. Here is how I'd refine your proposal, plus the points I think still need a decision. 1. Agreed: the export decides, not a toggle in each module The user picks an HDR output profile (and a peak for PQ), and the tone mappers adapt on their own. No per-module tick box. That is a better UX than what #22669 has now. 2. The hidden setting should be a number, not a boolean The tone mapper needs to know how much room there is above reference white, not just "HDR yes/no":
So I'd carry a "headroom" value on the pipe: output peak / 203 nits. It is 1 for every SDR output, so for SDR nothing changes. The pipe already has this in #22669 ( 3. Where it is set
4. Existing edits (the main open question) Some users already make HDR exports by hand: sigmoid or filmic with target white above 100%, or the old negative exposure trick. If tone mappers start following the headroom unconditionally, those edits would change on their next HDR export. Options:
I lean towards (a), since it never changes an existing image, but I'd like your view. 5. What target white means afterwards I'd keep target white as the SDR value the user edits (100% by default), and let the module scale it to the headroom for HDR output. The slider keeps working for SDR, and one edit gives both. 6. Which tone mappers
Modules placed after the tone mapper would also need a check that nothing clips at 1.0 when the headroom is above 1. 7. Previewing HDR on an SDR screen With an SDR display, the darkroom renders at headroom 1, so the HDR scopes in #22662 would show the SDR signal. To judge an HDR export on an SDR screen, the scopes would need the export's headroom. That could be a scope option later; it doesn't block the rest. Proposed next step If this matches what you have in mind, I'll rework #22669 to (1) drop the per-module toggles, (2) move the PQ peak into the export module, and (3) implement whichever of 4a/4b you prefer, for AgX and sigmoid first, with filmic as a follow-up. #22661 and #22668 (the manual sliders) would then no longer be needed. |
#22666 (has been merged) |
|
I think all is clear now, and I'm happy to see that we have a good design coming.
I think we are good now and your new proposal is sounds to me. |
@TurboGit Thanks, that's very helpful. I've reworked #22669 to this design:
Filmic will follow in its own PR. With this in, #22661 (AgX manual slider) and #22668 (sigmoid manual slider) aren't needed for HDR export, so I'll close them unless you see a use for them. |
agx: target white above 100% for HDR output
Branch:
nicknezis:agx-hdr-target-whiteSummary
AgX capped target white at 100%, which is the 203 nit reference white of a PQ or HLG export, so HDR exports could not hold highlights above SDR white without a negative exposure hack. Target white can now go up to 5000% (about 10000 nits), and the curve graph rescales with guides at 1x to 32x. An optional "show target white in nits" toggle displays and accepts the value in nits, for example 1000 nits instead of 493%. The tooltip explains that target white is the peak output brightness. A warning icon appears on the slider when the export profile is HLG and the value is above about 493%, because HLG clips at its 1000 nit nominal peak.
Referenced issue
Follows #22516, which fixed #20562 by putting PQ reference white at 203 nits. That left AgX's 100% cap at 203 nits, so it could no longer reach HDR highlights.
Related: #20562
Related: #17710
Checklist
src/tests/integration/where the pixelpipe is touched, ordarktable-clias a headless smoke test._(), new preferences are registered indata/darktableconfig.xml.in.RELEASE_NOTES.mdentry was added (only needed if fixing an issue in a release). Do not reference GitHub issues.Test instructions
Done so far:
git rebase --exec 'cmake --build build' master)darktable-cliPQ export of a synthetic -10 to +8 EV ramp: 203 nits lands at PQ code 148 and 1000 nits at code 192Not verified: OpenCL, real raws, macOS and Windows. The default params and existing edits are unchanged, since only the upper limit moved.
AI assistance
The code, commit messages and this description were written with Claude Code. I reviewed the diff.