I was outside today, walking and taking photos, so only a small update.
I think yesterday night I was so tired that I goofed up; today I cannot reproduce a difference between debug and release build.
I’m checking the code to see what may cause the difference between darktable and Blender.
Suspects:
- curve
- matrices
- negative avoidance (‘guard-rail’-like code).
The curve is OK. I’ve dumped an x->y mapping of the darktable curve and copied it as a table into the original desmos plot (Power(P) Sigmoid | Desmos), setting it to the same params (no toe/shoulder length, contrast = 2.4, toe/shoulder power = 1.5, dynamic range +/- 10 EV (this is what Blender uses, I think, see here, internal gamma 2.2, so pivot x = 0.5 and y = pow(0.18, 1/2.2) = 0.4586), and got a perfect match:
. Actually, whether those are the exact params Blender uses or not is not that important; I wanted to check that given the same params, the Desmos curve calculations match the way my code works.
So I guess we can rule out the curve.
Checking the matrices is tricky, as in blender’s code D65 is used to calculate the matrices, if I understand correctly, while darktable runs in D50.
I’ve set the working space (darktable’s pipeline space, this is what arrives to the module as input) as Rec 2020 (it’s D50-based, so values are not exactly like yours).
The module is set to use Rec 2020 as the ‘base’ space.
The first step is pipeline → base, where I get the identity matrix, as expected.
Using rotate = [3.0, -1, -2.0], inset = [0.4, 0.22, 0.13]
(blender/release/datafiles/colormanagement/config.ocio at main · blender/blender · GitHub), Blender’s matrix looks like:
0.856627153315983, 0.0951212405381588, 0.0482516061458583,
0.137318972929847, 0.761241990602591, 0.101439036467562,
0.11189821299995, 0.0767994186031903, 0.811302368396859
My (D50) calculations give ‘similar’ values.
0.886298, 0.074611, 0.039091
0.209132, 0.723162, 0.067707
0.172641, 0.059884, 0.767475
If ‘restore purity’ is 1, the outgoing matrix is the same (rotations are always fully undone, something I inherited from darktable’s sigmoid module, where primaries were added by @flannelhead).
This is where I am now. I’ll try to check more during the weekend. If anyone can check the matrix calculation (I think it is fine, since I just reused sigmoid’s code), please do.
sigmoid, using those values I mentioned above (rotate = [3.0, -1, -2.0], inset = [0.4, 0.22, 0.13]), with preserve hue = 0, recover purity = 0%, base: Rec 2020 gives the following results:
agx:
With recover purity = 100% in both:
sigmoid:
agx:
(Note that agx is less contrasty and is set to cover a huge dynamic range in the screenshots above.)
What we do not (yet) have in darktable is the display-mapping transformation; if I understand that correctly, that would be in AgX_LUT_Gen/luminance_compenstation_srgb.py at main · EaryChow/AgX_LUT_Gen · GitHub. @Eary_Chow , could that be the missing step, or are you reasonably sure the matrices are wrong? @flannelhead , what do you think?