cmm: Make log_100 and log_316 TFs symmetric#826
cmm: Make log_100 and log_316 TFs symmetric#826kennylevinsen wants to merge 1 commit intomahkoh:masterfrom
Conversation
log_100 and log_316 has the treshold implemented in the inverse EOTF, but missing from the EOTF. This causes black from a client buffer to be elevated to 0.01 and 0.00316 respectively, which can be seen in wl-colortest as having the black brightness tile become grey as you switch through the TFs. Add the threshold to the EOTF so that 0 means black.
| return pow(vec3(10), vec3(2.0) * (c - vec3(1.0))); | ||
| return mix( | ||
| vec3(0.0), | ||
| pow(vec3(10), vec3(2.0) * (c - vec3(1.0))), | ||
| greaterThan(c, vec3(0.0)) | ||
| ); |
There was a problem hiding this comment.
I feel like this should just clamp(c, 0.0, 1.0) like the other SDR transfer functions.
There was a problem hiding this comment.
The problem is that when c is zero, pow(vec3(10), vec3(2.0) * (c - vec3(1.0))) yields 0.01, so a clamp wouldn't help.
The approach is similar to compound_power_2_4. and matches what is done in their respective inverse EOTF's (a mix over greaterThanEqual(c, vec3(0.01)) and greaterThanEqual(c, vec3(sqrt(10)/1000)), respectively).
There was a problem hiding this comment.
The problem I see with your current code is that it creates a discontinuity at 0. I.e. E=0 maps to O=0 but E=epsilon maps to O=0.01. For a single black tile that would be fine, but I'm not sure if it would be fine for a gradient or any image that just so happens to have a black pixel.
There was a problem hiding this comment.
The step in log_316 is small enough that it is unlikely to matter, but log100 clearly shows the discontinuity in the gradient (images below).
Searching around a bit I don't see a whole lot of implementations to reference, but the fix matches gstreamer and the color-science python package. moxcms does neither and instead uses the midpoint to minimize the maximum error. Not a whole lot of support out there for these TFs though, so don't really have much in way of a benchmark or convention...
There was a problem hiding this comment.
If we want to use 0 as the fixed point, which is what all other EOTFs do right now, then maybe applying an affine function could work:
vec3 eotf_log100(vec3 c) {
c = clamp(c, 0.0, 1.0);
c = pow(vec3(10), vec3(2.0) * (c - vec3(1.0)));
return (c - vec3(0.01)) / vec3(1.0 - 0.01);
}
vec3 inv_eotf_log100(vec3 c) {
c = clamp(c, 0.0, 1.0);
c = c * vec3(1.0 - 0.01) + vec3(0.01);
return vec3(1.0) + log2(c) / vec3(log2(10)) / vec3(2.0);
}However, I'd prefer to standardize these things in https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/staging/color-management/appendix.md.



log_100 and log_316 has the treshold implemented in the inverse EOTF, but missing from the EOTF. This causes black from a client buffer to be elevated to 0.01 and 0.00316 respectively, which can be seen in wl-colortest as having the black brightness tile become grey as you switch through the TFs.
Add the threshold to the EOTF so that 0 means black.