Linearly interpolating pixels that are in a gamma encoded color space
twitter.com
twitter.com
But in, say, Photoshop the gamma is still wrong, unless you switch to 32-bit space, which produces huge files and removes access to most filters. You don't need 32-bit precision for proper gamma. You just need gamma correction when combining/interpolating/blending color values. Alas. Ignorance is pervasive.
I heard explanations how it'd be slow, or doesn't matter, or what am I talking about, all ultimately variations of "works as coded, won't fix".
There are clearly people at Adobe who are aware of the issue in some capacity, and their efforts have weird specifics, such as... they noticed text anti-aliasing looks weird, so they added an Advanced Control called "Blend Text Colors Using Gamma" option in Color Settings. The bizarre thing is that none of this is specific to text. It's just that text has many small complex shape edges, and you notice it more on text (like Carmack noticed it on the star field). They didn't fix vector art rendering, for example. And the option default is not even the correct gamma for a document, but 1.45 which makes no sense at all. They just "eyed it" and went with it.
There's also a Blend RGB Colors Using Gamma option which is disabled by default. If you enable it, it corrects SOME operations, but not others, with no rhyme or reason. However, you can't really tweak those yourself, because if you do, the settings are not saved per document, they're global. So if you tweak them... then ALL Photoshop files you open will look wrong, because they were originally made for another configuration of these settings. Which leaves you with 32-bit color channels. I have Actions that convert an image to 32-bit to scale, and back to 8/16-bit, just so it's gamma corrected.
It's... a f***ing mess.
"Photoshop antialiases text using γ=1.42 by default, and this indeed seems to yield the best looking results (middle image). The reason for this is that most fonts have been designed for gamma-incorrect font rasterizers, hence if you use linear space (correctly), then the fonts will look thinner than they should."
https://blog.johnnovak.net/2016/09/21/what-every-coder-shoul...
So even if a font is designed with incorrect gamma, it might still not be the best to render it with incorrect gamma, as you might use different background and foreground colors to the designer of the font.
AFAIK freetype has the option to enable "stem thickening" to consistently correct for incorrectly designed fonts regardless of colors being used for rendering.
Stu was able to get linear compositing into AE, but I think PS had already evolved into more of a graphics tool than a photo tool. They added 32bpcc and HDR, but it's for specialty workflows, not general use.
Fully embracing linear light would change almost every part of PS—everything from blend modes to the built-in filters were written for perceptually encoded values that don't go over 1.0. Even today, Curves works with 32bpcc, but only shows you the 0–1 portion.
It’s called something like “Blend in Gamma: 1.0”. The default is 2.2 of course.
The annoying thing is that it can’t be done per image, so if you chnage it, it breaks the blending of any image you load made by someone who doesn’t have that setting enabled.
I occassionally walk around our studio and audit this setting is set correctly for all our VFX artists because they are the ones who will see incorrect results compared to in-engine if they use the wrong setting here.
And they're right. But there's an entire flip side of this coin, called Linear is Not Always The Answer.
Are you dealing with the behavior of light? Then you should be a linear colorspace.
But if you're performing artistic operations or other things that need to look right to a human, this is not what you want. What you actually want is a perceptually-uniform colorspace. Linear RGB is most definitely _not_ perceptually uniform! It's in fact, much worse than sRGB!
sRGB for all its flaws is at least roughly perceptually uniform for grey tones, a kind of "poor man's perceptual space". Color mixing, gradients, etc etc all work much better in a uniform space.
I've fallen in love with Oklab as a colorspace. (https://bottosson.github.io/posts/oklab/ ), which has in practice provided excellent results.
Light? Use linear rgb. Human vision? Use Oklab.
Of course you use gamma so that you have a more perceptually correct colorspace, mostly because 8 bit isn't enough accuracy to represent correctly the various shades of black the eye can percieve. Or because it's easier to make a perceptually linear gradient in gamma space.
But the blending in gamma space looks WRONG. It isn't perceptually correct! Try blending at 50% pure white and pure black and the grey you obtain is the wrong one, far too dark. Surely this cannot be what people want.
I wish he had included an example screenshot or video clip of what’s wrong with them.
This is probably the issue he is referring to.
frame=0: 1 0 0 0
frame=1: 0 1 0 0
frame=2: 0 0 1 0
frame=3: 0 0 0 1
Values are in lumens. Now let's do it half as fast: frame=0: 1 0 0 0
frame=1: 0.5 0.5 0 0
frame=2: 0 1 0 0
frame=3: 0 0.5 0.5 0
frame=4: 0 0 1 0
frame=5: 0 0 0.5 0.5
frame=6: 0 0 0 1
When the impulse falls between two pixels, the amount of light should be distributed over those two pixels, so that the total amount emitted stays the same. However, we use a nonlinear encoding to map these physical values to numbers, which is called gamma compression. So in case of an 8-bit encoding, if 1 lumen is mapped to 255, then 0.5 lumen would correspond to a value of say 186, instead of 128. The display hardware uses the reverse of this mapping to emit the intended amount of light from each display pixel, so everything works fine as long as gamma is accounted for in the whole pipeline.However, if you have a gamma-compressed image, you must be careful when doing any transformations on this image in the digital domain, because the pixel values live in a non-linear space, and this must be taken into account when transforming them!
E.g. let's say we have our 0.5 pixel/frame animation from above, encoded with gamma=0.45:
frame=0: 255 0 0 0
frame=1: 186 186 0 0
frame=2: 0 255 0 0
frame=3: 0 186 186 0
frame=4: 0 0 255 0
frame=5: 0 0 186 186
frame=6: 0 0 0 255
And in post-processing you resize this video to 0.5x of the original size, with software that naïvely blends the pixel values when shrinking the image: frame=0: 128 0
frame=1: 186 0
frame=2: 128 0
frame=3: 93 93
frame=4: 0 128
frame=5: 0 186
frame=6: 0 128
Oops! The intensity is no longer constant, which is going to be visible as twinkling when viewing the video.Wikipedia has a static test image for gamma here https://en.wikipedia.org/wiki/File:Gamma_correction_test_pic...
If you look in the green section, you can see the background is a checkerboard of (0, 0, 0) black and (0, 255, 0) green. Because of gamma, this is not equivalent to (0, 127, 0).
The 2.6, 2.2, 1.8 sections are supposed to blend with the background if that's the gamma that your image-to-screen pipeline uses. (Including the browser's PNG decoder, the browser's painting and compositing, the desktop's painting and compositing, anything goofy the GPU drivers do, and all the goofy stuff monitors do)
Looks like my cheapo 2010 LCD's gamma changes greatly depending on viewing angle. Ugh :S
The bookmarklet for anyone who is interested:
javascript:void(document.body.style.imageRendering='pixelated')
Gamma encoding is only really necessary to optimize around the limitations of 8-bit color channels. So, load sRGB888 convert to linear 32-bit floats, do linear algebra, convert back to sRGB888, store the results.
And 16 bit floats are plenty, so that's a good option as long as the hardware won't do something dumb with them that makes them slower.
I guess ideally you'd reallocate the sign bit to the mantissa, and maybe an exponent bit too.
A gamma of 2.2 puts that '15' at 0.2% brightness, and the '20' at 0.4% brightness.
An 8 bit linear representation would make that '20' square the minimum brightness above zero. The next step up would be roughly the '30' square.
So yes, the gamma curve is very necessary. Even 12 bit linear would be a bad idea. So 14 or 16 minimum. And adding HDR is something like 2 bits with gamma and 8 bits without.