In linear interpolation, there's too much white and not enough black. That's why gamma correction/sRGB exists after all: if you encode the linear value directly, you waste most of the space on white values you can barely tell apart.
In linear interpolation, there's too much white and not enough black. That's why gamma correction/sRGB exists after all: if you encode the linear value directly, you waste most of the space on white values you can barely tell apart.
sRGB: https://i.imgur.com/dbn3TM6.png Lab (linear): https://i.imgur.com/dCXzbF3.png
Please download the images and view in a proper image viewer. For some reason at least on my Windows machine Google Chrome adds horrible color banding to both images.
This is my code:
import imageio
import numpy as np
import colour
quantize_with_dither = lambda im: np.clip(im * (2**8-1) + np.random.uniform(size=im.shape), 0, 2**8-1).astype(np.uint8)
srgb_black = [0, 0, 0]
srgb_white = [1, 1, 1]
srgb_grad = np.linspace(srgb_black, srgb_white, 500) * np.ones((200, 1, 3))
imageio.imwrite("srgb.tif", quantize_with_dither(srgb_grad))
lab_black = colour.XYZ_to_Lab(colour.sRGB_to_XYZ(srgb_black))
lab_white = colour.XYZ_to_Lab(colour.sRGB_to_XYZ(srgb_white))
lab_grad = np.linspace(lab_black, lab_white, 500) * np.ones((200, 1, 3))
lab_grad_in_srgb = colour.XYZ_to_sRGB(colour.Lab_to_XYZ(lab_grad))
imageio.imwrite("lab.tif", quantize_with_dither(lab_grad_in_srgb))
I didn't trust imageio's correct handling of gamma/colorspaces so I just wrote out the raw sRGB coefficients as 8-bit TIFF and used imagemagick to convert to PNG, telling it that the input is in sRGB: magick convert lab.tif -set colorspace sRGB -depth 8 lab.png
magick convert srgb.tif -set colorspace sRGB -depth 8 srgb.pngGamma encoding is lin_to_srgb(c) = c*12.92 if c<=0.0031308 else 1.055*c**(1/2.4)-0.055. Since lin_to_srgb(0.214)=0.5, in a linear ramp, the middle gray (808080) pixel should occur about 20% of the way through.
https://i.imgur.com/jeM4RCu.png
top: linear_to_srgb(x)
middle: x
bottom: srgb_to_linear(x)