Mapping to output gamut

Curiously, ASTM E308-01 AND IEC 61966-2-1 specify the whitepoint as CIE 1931 XYZ. Hmm. IEC 61966-2-1 defines two matrices with different precisions.
IEC 61966-2-1 (first hit preview in google)
One with four decimal points for converting from XYZ to 8-bit sRGB and one for higher bit depth sRGB with 7 decimal points (F8 and F8’).

Wikipedia is not the best source. Not saying this particular entry is wrong — I am not checking for you :stuck_out_tongue: — but I have seen incorrect numbers and misinformation in colour-related articles.

I recall Elle pointing out that Bruce had an error in his transform docs.

@KelSolaar has an account on this forum. :wink:

Some OKLab conversions, including tone mapping using OKLab L:


From HDR input:

2 Likes

Looks great! Especially for the simplicity of the approach. Benefits a lot from swapping out CIELch(ab) to OKLch.

Note that you cannot compare them directly, as tone mapping is always done using the ‘native L’ of the space.

Fun explorations! And good progress so far :smiley:

I have been thinking about the topic as well and I see a need for being very specific in what boundaries we want to map to and from!

Do we have any upstream promises from modules coming before the output gamut mapping in pipeline?

I can say what sigmoid gives as a promise.
All pixels will always stay within [black target, white target) of the chosen linear working profile.

This means that you always now the theoretical max C! The damping curve can then be computed from this theoretical max and applied to all pixels without any if-else logic → should keep the results more consistent over large sets of images!

Hmmm… The difference you see may come from the tone mapping, which I only added because we have HDR input. Without that, I see pretty much no difference – but I’m not really sensitive to colour, I’m afraid.

This left side of this image comes from OKLab, the right from CIELab. Chroma is compressed when it exceeds 90% of the max allowed by sRGB:

Amplified differences:

Same here (left is OKLab, right is CIELab):

Amplified differences:

With LUV, the differences (due to the pink shift) are noticeable even for me. :slight_smile:

1 Like

@kofa At a glance, using an uncalibrated display, Oklab looks more uniform. Could you please flip the left and right-hand sides for comparison?

fwiw, this is how vkdt handles explicitly requested gamut bounds and chromaticity changes:

this is the input from a playraw:


(note that it’s a screengrab colourmanaged for my display that is slightly > srgb but colours are still out of gamut here)

and this is what it looks like if i desaturate (it follows lines of constant hue, nonlinear):


(so what looked red in clipped is actually a bit orange)

and this is the image with gamut restricted to rec709 (note that the sat parameter is still at 1.0 here):

and increasing chromaticity from here will “squish” the colours near the specified gamut boundary, by moving the less saturated colours more:

i haven’t been very successful when experimenting with OKLab, especially the far out of gamut and hdr cases yielded funny results if i remember correctly.

Feel free to compare them. Chroma compression starts at 70 or 90% of the gamut maximum (see the filename).

CIELAB:


CIELUV:


OKLAB:


CIELAB:


CIELUV:


OKLAB:


Good progress doesn’t equal done :wink:
The most important part is to get once feet wet and figure out what the problem is and why it happens. Finding a solution might be the easy part sometimes!

That said, I think many of the very tricky examples actually suffer from clipping already in color calibration or color balance rgb. Those might need a scene-referred input gamut mapping to smoothly fit the full observable camera gamut into the darktable working gamut. Or make all editing modules support Infinite gamut, i.e. allow for negative rgb values, but that is probably a larger more cumbersome task!

Note that all I did is reducing chroma at constant luminance. sRGB gamut clipping demonstrates multiple approaches (allowing modifications to luma), and uses maths instead of brute-forcing the gamut boundary.

1 Like

Isn’t there any fancy filter / script in gmic land that does things like this ?
It has oklab as well IIRC (but otherwise it does very little with colour management. It assumes sRGB or linear rgb for anything rgb related.
Doesn’t mean you can somehow explain it the boundaries for it to map something.

Would be interesting for me to have something that can open a linear rec2020 file and ‘map the colours’ BEFORE it gets converted to sRGB, to prevent detail / saturation clipping.

That’s what I’m trying to do. I convert to unbounded linear sRGB, and then manage C to get all sRGB coordinates between 0 and 1. In GradualChromaDampeningLchBasedGamutMapper I never clip, just ‘compress colours’ (gradually reduce C).

To my knowledge, nothing in g’mic. No native support for reading profiles embedded within an image either, which might make things tricky depending on what you want to test.

If you only plan to load image data, do some transforms, then output to display sRGB (or output to a generic file which doesn’t need to be sRGB) then it’s at least possible. I happen to also be a business java programmer amongst other things, so I could translate this stuff to g’mic. May not be worth the effort though!

I agree. This is just my playground, and uses brute force instead of maths and brains. I think sRGB gamut clipping would be much more useful.

1 Like

Heh, just to clarify, it’s not that I think this stuff is worthless (quite the opposite!) only that you’re probably already more than able to do what you want here. Having it in g’mic too is likely overkill.

1 Like

I didn’t take it to mean that. It’s just highly inefficient, but for me a valuable learning tool - especially when the brute-forcing reveals something to me that causes me to slap myself on the forehead (‘that’s so obvious, how could I miss that?’). :smiley:

1 Like