iop/basecurve: add ACES-like modes, JzAzBz saturation and gamut mapping#20320
iop/basecurve: add ACES-like modes, JzAzBz saturation and gamut mapping#20320Christian-Bouhon wants to merge 10 commits intodarktable-org:masterfrom
Conversation
dbc808d to
4a6dfb5
Compare
|
I just saw that you've been working on the project. Sorry if my last push overwrote some of your maintenance fixes. I've finalised the implementation of the JzAzBz adaptive shoulder extension and CPU/GPU parity. The mathematical logic is now complete on my end. |
|
Thank you for this detailed analysis! I have taken note of all your comments regarding coding style (alignment, one parameter per line, and spaces). I will work on the code this weekend to apply all these corrections and publish the updates. |
TurboGit
left a comment
There was a problem hiding this comment.
I have finally tested this a bit, some comments:
- I have on the console a bunch of :
34,4786 /home/obry/dev/builds/c-darktable/x86_64-linux-gnu-default/src/src/iop/basecurve.c:3000 gui_init: trying to add widget that already has a parent to box (#1)
-
When I change the "color look" it resets to 100% the "look opacity".
-
I'm wondering if the target gamut should not be Rec 2020 by default?
|
Also this PR introduces a regression on the The new report is: So 44885 different pixels in CPU compared to GPU instead of 9772. |
I finally found a typo. In color_conversion.h, we have this matrix: // XYZ to Rec.2020 conversion matrix coefficients and a small error in the basecurve.c file |
Hello, Regarding the name without capital letters, I noticed that this was not applied in French. I adapt the fr.po file and create a new pr or link it to this one. |
|
After updating my CM_BC work branch from the master branch, as mentioned in the commit, I had to replace these two lines in basecurve.c: |
This sounds really wrong to me. We don't do that in any other sliders. If the user needs this it must be done manually, because some other people may be quite annoyed by having to go back to the control for reset to the previously set value. |
Yes, see 4e6d1b8. See that only
|
As parameters for OpenCK kernels must be presented as 'pointer-to-value' we use compound literals for readability.
d9f8555 to
bed486a
Compare
bed486a to
ac32cab
Compare
|
A very quick test with some thoughts I'd get rid of the kinematics in the names and just use ACES and the other It would be nice to set a curve in ACES and then switch to the other without the curve resetting so that you can compare the difference. Do we need a basecurve scene referred workflow? Should that be included in this PR? Does scene referred basecurve need a tone mapper at the end of the pipe? I think yes because being scene referred the edits can drive the image out of the 0 - 1 range, but maybe not enabled by default? The following error messages repeat when I open/change image |
TurboGit
left a comment
There was a problem hiding this comment.
You still have a huge amount of error on the console:
10,9565 /home/obry/dev/builds/c-darktable/x86_64-linux-gnu-default/src/src/iop/basecurve.c:2998 gui_init: trying to add widget that already has a parent to box (#1)
10,9565 /home/obry/dev/builds/c-darktable/x86_64-linux-gnu-default/src/src/iop/basecurve.c:3012 gui_init: trying to add widget that already has a parent to box (#1)
It looks like you are trying to add a widgets two times. Maybe the box containing the widget and the box itself? (just a wild guess as I haven't looked at the code yet).
And you still are setting "look opacity" to 100% when change "color look". This is not consistent with current UI.
I don't see why and your example about blending is exactly the point. When you change the blend mode the opacity is not changed. Again this is not OK and not consistent, I'd prefer to have the "look opacity" to keep it's value and that is the user responsibility to change it if needed. |
So, if I understand correctly, you want this layout, for example.
|
Yes exactly that. Sorry if it was not clear. |
TurboGit
left a comment
There was a problem hiding this comment.
There is an issue with OpenCL, take the test 0078, it used to give:
Test 0078-basecurve-fusion
Image mire1.cr2
CPU & GPU version differ by 9772 pixels
CPU vs. GPU report :
----------------------------------
Max dE : 3.50957
Avg dE : 0.00152
Std dE : 0.02891
----------------------------------
Pixels below avg + 0 std : 99.65 %
Pixels below avg + 1 std : 99.65 %
Pixels below avg + 3 std : 99.67 %
Pixels below avg + 6 std : 99.69 %
Pixels below avg + 9 std : 99.73 %
----------------------------------
Pixels above tolerance : 0.00 %
Expected CPU vs. current CPU report :
----------------------------------
Max dE : 0.97390
Avg dE : 0.00023
Std dE : 0.00912
----------------------------------
Pixels below avg + 0 std : 99.91 %
Pixels below avg + 1 std : 99.91 %
Pixels below avg + 3 std : 99.91 %
Pixels below avg + 6 std : 99.92 %
Pixels below avg + 9 std : 99.93 %
----------------------------------
Pixels above tolerance : 0.00 %
OK
And with this PR we have:
Test 0078-basecurve-fusion
Image mire1.cr2
CPU & GPU version differ by 44885 pixels
CPU & GPU large difference > 10000
CPU vs. GPU report :
----------------------------------
Max dE : 18.79237
Avg dE : 0.01460
Std dE : 0.18322
----------------------------------
Pixels below avg + 0 std : 98.39 %
Pixels below avg + 1 std : 98.49 %
Pixels below avg + 3 std : 99.23 %
Pixels below avg + 6 std : 99.69 %
Pixels below avg + 9 std : 99.80 %
----------------------------------
Pixels above tolerance : 0.13 %
Expected CPU vs. current CPU report :
----------------------------------
Max dE : 0.97390
Avg dE : 0.00023
Std dE : 0.00912
----------------------------------
Pixels below avg + 0 std : 99.91 %
Pixels below avg + 1 std : 99.91 %
Pixels below avg + 3 std : 99.91 %
Pixels below avg + 6 std : 99.92 %
Pixels below avg + 9 std : 99.93 %
----------------------------------
Pixels above tolerance : 0.00 %
OK
As you can see the CPU code gives the same result as previous version but the CPU vs GPU has a larger difference.
Note that I have multiple tests where basecure is used where this happens. So definitely a regression on the OpenCL code.
|
Hello,,
Personally, I would not use the term ACES because I do not use the full curve. Internal comments retain all technical references (Narkowicz 2016, Narkowicz/Filiberto 2021) for greater transparency. I have also implemented an adaptive JzAzBz shoulder curve that acts before it to preserve more detail in highlights and a smoother progression.
OK, I'll include it in the PR.
Thanks for pointing that out. I've corrected the code so that it's always enabled. For your information, it wasn't enabled if the gamut compression function wasn't used.
Fixed bug between the two workflows: legacy and scene.
It is implemented as follows
Implemented via last_workflow_mode. Switching between the two curves preserves all slider and curve values for direct comparison. Reset only occurs when switching from display mode to scene-referenced mode.
It is implemented as follows : Here is the latest log without errors. Greetings from Luberon, |
|
The CPU vs GPU diff is not fixed: Also the "scale for graph" slider is missing. |
97c0cb2 to
a39cb1b
Compare
Hello,
Indeed, I put it back for the legacy workflow. |


This PR modernizes the basecurve module to improve its scene-referred capabilities while ensuring perfect backward compatibility for display-referred workflows.
Key Improvements
1. Scene-Referred Mode (ACES-like/Narkowicz):
◦ New Flow: Implements a perceptual tone mapping pipeline: Signal Analysis -> Matrix-based Looks -> Exposure Normalization -> Perceptual Tone Mapping -> RGB Reconstruction.
◦ Tone Mapping: Added ACES-like and Narkowicz perceptual models for better highlight roll-off and contrast control compared to standard curves.
◦ Looks: Added 3x3 RGB matrix-based "Looks" (Portrait, Sky, etc.) with a mix slider.
2. Color & Gamut Integrity:
◦ Perceptual Saturation (JzAzBz): Improved "UCS saturation balance" to compress highlight saturation while boosting shadows for better visual density.
◦ Hue Correction: New color rotation slider with selective desaturation to eliminate common color drifts (skin tones, blues).
◦ Gamut Securing: Introduced a multi-space gamut engine (sRGB, Adobe RGB, Rec2020) and a specific Anti-Magenta Algorithm (Highlights Protection): Implementation of a selective highlight desaturation logic. When luminance exceeds the threshold (0.8), the compression factor is biased to be 10% stronger on the blue channel compared to red and green.
◦ Goal: This specifically targets the common "magenta shift" in overexposed skies or artificial blue lights, ensuring they desaturate towards white rather than shifting hue.
3. Ergonomics & Compatibility:
◦ Backward Compatibility: Display-referenced processing (classic mode) remains untouched.
◦ UI: Curve graph can now be resized with the mouse.
◦ Introspection: Bumped to version 7.