Tone mapping and gamut compression articles

OK. Some gamut compression charts.
We are rotating in 30-degree steps around the D65 white point xy coordinates, so each of these contains 12 groups of bands.
For each angle and Y luminance value:

  • we take the xy coordinates at the edge of the Rec2020 gamut (this is determined via a simple search), and note its distance from the white point (maxDistanceRec2020)
  • Then, we shorten that distance according to a fixed multiplier; each chart has its own, starting from 40% and going up to 100%, in steps of 10%. We treat this as a kind of ‘saturation’. distance = saturation * maxDistanceRec2020
  • Then we calculate the x and y of the unmapped pixel:
    x = cos(alpha) * distance + D65_WP_x
    y = sin(alpha) * distance + D65_WP_y
  • We convert this xyY into XYZ, then to Rec709RGB, and clamp the components to [0, 1], to demonstrate the naive approach. These values form the first line in the band.
  • Then we take maxDistanceRec709, the max. distance for the given angle for the Rec709 space (again, determined via a search).
  • We calculate ratioToMax709Distance = distance / maxDistanceRec709
  • We pass it through a curve that’s linear until 0.8, and smoothly converges to 1 above that. This gives us compressedRec709RatioFromMax.
  • We calculate compressedDistance = maxRec709Distance * compressedRec709RatioFromMax. If the original distance was less than 80% of the maximum, it remains unchanged; otherwise, it gets compressed more and more, but will never exceed the max. distance.
  • Then we calculate the x and y of the mapped pixel:
    x = cos(alpha) * compressedDistance + D65_WP_x
    y = sin(alpha) * compressedDistance + D65_WP_y
  • We convert this xyY into XYZ, then to Rec709RGB, and clamp the components to [0, 1]. These values form the second line in the band.
  • The third line in the band is simply Rec2020 at 30% saturation, as that saturation never needs compression. It’s included as a hue reference.
  • The fourth, monochromatic line indicates the extent of the compression, 1 - compressedDistance / distanceRec2020. Black means no compression.

Right. So, here are the charts (from 40%, as 30% needs no compression):

Rec2020 at 40% (only one of the greens needs some compression):

At 50%:

At 60%:

At 70%:

At 80%:

At 90%:

And at 100%:

If you have good wide-gamut (but not HDR, so Y should not exceed 1) input files, I’d appreciate them, to check how this behaves with real-world images. Flowers (maybe @ggbutcher ?), hummingbirds, whatever.

Thanks for reading, if you got here. :slight_smile:

4 Likes