Hacker News new | past | comments | ask | show | jobs | submit login
What every coder should know about gamma (2016) (johnnovak.net)
154 points by scq on July 4, 2021 | hide | past | favorite | 50 comments



Sorry to be off-topic but I dislike the "what every X should know" or "X everyone should know" headlines. Do some searching on hn.algolia.com on different variations and suddenly there is a lot of stuff that you were supposed to know about already that you most likely don't.

Everyone thinks that their own favorite subject is the most important and should be mandatory reading in their broader field. I believe these headlines build unnecessary imposter syndrome and general bad feels.


I disagree. I read the article because it nudged me, even though I probably don't really need to know the contents right this moment.

If the title had been "What some coders may need to know about gamma, but definitely no worries if not"... I probably wouldn't have read it. To me, the anxious muddle of qualifiers would have suggested a lack of confidence and focus that would bode poorly for the clarity and helpfulness of the contents.

When people are so insecure about their abilities that they feel threatened by the notion that they may not know something they should know, I think that's something for them to work on within themselves, not something the world needs to tiptoe around to keep them comfortable.

As an aside, I have occasionally had coworkers who have had important things to say, but they have forced me to struggle way harder than necessary to understand what those things are, because they are terrified of explicitly saying that their work revealed someone else's assumptions or practices to be flawed. This is especially an affliction of young women, who often seem to think that it is their (and everyone's) moral obligation to be exquisitely sensitive to all possible negative ways that a communication could be perceived, no matter how fragile or unreasonable. As a result, they are morally against directly correcting anyone else's ideas, and will freak out if anyone else prefers to be more direct.


While I agree about the tiptoe part I have an instinctive negative reaction to the nudge argument. I do not see a clear difference between "What every X should know about Y", "Programmers hate this one weird gamma trick" and "top 10 crazy gamma hacks". Sure, it might make more people read the article, but that is just clickbait.

My point was mostly that the title was clickbaity and (IMO) incorrent. There are some things that I think all programmers should know, but it's not much at all. I just wish HN level articles would be more descriptive in their titles. I don't need the nudge, I'll read what interests me.


It's worth distinguishing "clickbait" that takes you to brain-rotting junk versus taking you to an informative essay. Is the latter really a problem?


I guess it could be "what you need to know about gamma if you work on graphics"


Partly agree partly not

It is not really required to memorize these stuff anyway. Just the idea of it gives you a broader perspective.

One of the reasons I come to HN and read these things. They add some knowlegde to me, even though I cannot list them or their exact properties, I get to be familiar with the topic.


Titles on HN that I would be happy if I never saw again:

"What every X should know about Y"

"X considered harmful"

"An opinionated version of X"


"an opinionated opinion about opinions"


"What every X should know about Y considered harmful, an opinionated version of Z"


It’s probably useful to know that scales that may appear linear at first sight may actually not be, and then you have to be careful operating on it.

For example, ever notice how sweet lemonade may become sour when you dilute it with water 1:4? That really doesn’t make sense, since water isn’t sour. But perhaps sweetness and sourness have different gamma curves, changing the relative perception when operating on some value.


True, and I agree.

Every coder that deals with graphics in some contexts should know Gamma. That knowledge would have been useful I think once in my professional career and only because of some specific stuff.

There's no hard/fast rule, but there are several more important things that coders in general should know before Gamma.


This is a fantastic article, but one nitpick:

> 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.

That's not true at all -- fonts are mostly designed for high-resolution printing where gamma is essentially irrelevant.

Fonts in small sizes can look overly thin on computer screens when rendered "correctly" as black-on-white because 1) bright white surrounding a black letter can "bleed" into it in our vision, 2) we've become accustomed to comparatively bold fonts in computer interfaces and so fonts designed for print look thin by comparison, and 3) when stems are less than a pixel wide and therefore render as gray, this also introduces contrast problems (less of a problem on retina screens).

None of these have anything to do with gamma. However, changing the gamma used in rendering actually does work as a "hack" to make letterforms darker with more contrast -- but it's actually entirely incorrect.

Also with regarding small fonts, font designers have long known that the smaller a font is, the thicker its strokes should be proportionally, so some fonts come in optical sizes. "Text" or "book" weights are "normal", while "display" designed for larger sizes is thinner, and the occasional "small text" size is even thicker (often intended for classified listings, historically).

If you look at typefaces actually designed primarily for computer screens rather than print, like Georgia and Verdana, you'll see they are indeed thicker, much like "small text" fonts.


Looking at the examples of incorrect compositing and scaling, which results in unnatural color bands and hue transitions, look a lot like the AI Generative Art floating around these days. I wager these trained image generators are completely ignoring color spaces and producing composited nonsense a lot of the time.


It's a good post but IMHO does still conflate several things. The problem with "gamma" is that it's such an overloaded term.

1st. Human vision is not linear but is more sensitive to changes in low brightness conditions where a small change in input results in large change in perception. This is the so called "Stevens power law". The blog calls the perceptiply linear gradient ramp "gamma encoded" when it's really just adjusting for the non linearity of the human vision and employs "inverse of Stevens power law".

2nd. Because of the human sensitivity to differences in dark tones, a linear encoding when using limited bandwidth (i.e. 8 bits per color Channel) would allocate too many bits for the bright colors (that humans can't distinguish so well) and too little for the dark tones. The normal scheme is here is to encode the image using a "gamma" function that allocates the bits in a non linear fashion. This isn't often a simple gamma per se but a color space such as sRGB but the idea is the same.

3rd old CRT monitors had a characteristic behaviour so that 50% of input signal strength would not result in 50% of light emissions. this non linearity was also called "gamma". Modern LCDs etc panels then replicate this functionality for compatibility purposes.

However I believe the software/display circuitry these days correct for the display gamma so that if you write 0x808080 you'd indeed get 50% of light emission from the display. That means that the 2 really sort of interesting "gammas" are the encoding/decoding for storage and for producing changes in brightness that the human vision will perceive linearly.

Ps. I find that because of this overloading of the term gamma there's a lot of confusion and often if the result is correct it's by accident. I in fact prefer to call the whole thing "gamma incorrection" rather than correction since it's almost never correct in the whole software stack unless by accident. ;-)


> the software/display circuitry these days correct for the display gamma so that if you write 0x808080 you'd indeed get 50% of light emission from the display

That's precisely what I'm observing on my phone. The grayscale gradients, and downsampled checkerboard, images from the article look correct with gamma=1.0


This turned out to be more interesting than I thought. Gradients and blurs are common in UI design. The Figma app actually does blurs wrong, while Chrome/CSS renders them correctly. This is good to know.


Same here. Useful article, for sure. It's funny most of us have seen, even used, done of this terminology without having a clear idea what it actually means.

I am going to disagree with that chrome, or any browser, for that matter, renders blurs correctly.

In fact, I'd go as far as say that CSS blur filters are embarrassingly low quality. One of these days I am going to finally say fuck it just use canvas on top of my whatever I have to blur.


What I meant was that at least CSS blurs in Chrome don't have that "dark" effect that you get from poor color management. https://twitter.com/graycoding/status/1411679670001569793


From the screenshot, it looks like a compositing issue. I'm guessing Figma does compositing in gamma space while Chrome does it in linear space.


Minute physics did a great video on this topic a while back: https://youtu.be/LKnqECcg6Gw


Did instagram fix it after this video? It should have gotten some attention.


I'm really looking forward to read this article, I've longed for an article about this for a long time. The problem becomes noticeable when for instance comparing colors on web apps with different screens. The colors can look different on the different screens, or if you use color profiles then the colors look different on apps that support it vs. apps that don't support it.

To my surprise the New Relic NRQL editor in light mode which heavily relies on highlighting for editing is hardly usable on my dated LCD screen which doesn't have a color profile I guess. (Safari supports color profiles actually) Luckily there's now the dark mode option...


Colour gamuts, colour profiles, and the translation between them is a whole other topic which this article barely touches on.


> gamma

Oh, that gamma.

I thought he meant the gamma function.


... or options trading, or the rays


The important thing to know is that Gamma is just an optimization step for low gamut color spaces. Ideally, you would just work with linear CIE RGB values and forget all about Gamma. Unfortunately you still have relics like sRGB around, so you cannot just ignore it, but you really should not read an article about gamma, you should read a book about colorimetry.

For example: https://mitpress.mit.edu/books/color-sciences


You would never want to ignore it. Gamma is about perceptual intensity, which follows a power law, as opposed to physical intensity (counting photons). That's why it's an "optimization" in the first place. Even in a magical world where all colors were represented with infinite-precision rational numbers, you'd still want to use a power law every time you wanted to display a gradient.


Perceptually-uniform color spaces such as CIE L*a*b* (and especially more modern alternatives, such as Oklab [1]) are better for gradients. This page has a simple demo: https://raphlinus.github.io/color/2021/01/18/oklab-critique....

This Observable notebook goes into more detail: https://observablehq.com/@mattdesl/perceptually-smooth-multi...

Gamma is more or less a poor man's perceptual color space, but I don't think it's very useful for that nowadays. There are much better options for image processing that requires perceptual uniformity (which is not everything, e.g. blurring is usually better done in linear RGB), and when you don't need that, I'm not aware of much reason to use it other than limited precision and sRGB being a ubiquitous device color space.

[1] https://bottosson.github.io/posts/oklab/


Depends on what you mean by "display". If you are talking about a monitor, sure, do whatever magic works best in there. But otherwise I prefer to work in a mathematical vector space and ignore it. Raytracing software for example can just ignore it as long as renderers understand the image format it outputs.


Indeed, but reading this I definitely get the sense this would all be easier if that was left to displays at the end of the chain, rather than be present in how the information is encoded on disk.

Can obviously understand how we ended up here.


Right. The second issue is that the example grayscale ramps in the page lack a color profile as well, and depending on how you're looking at them (monitor and, sadly, which browser/version) you'll get different results.

On my current high-gamut display the uncorrected images look almost linear, while the gamma-corrected ones have too much black (exactly the opposite of what the page is intended to show).


New HDR standards, Rec.709/Rec.2020 still have that same gamma ramp so I wouldn’t call it a relic.


I'd say most HDR contents are using PQ rather than gamma ( https://en.m.wikipedia.org/wiki/Perceptual_quantizer ), and some are using HLG.


Yes and PQ use was standardized in Rec.2100. Still non-linear output :)


It’s linear output; the PQ is just the “down the wire” encoding, and the display undoes it back to linear photon light.


I don’t understand what you mean here. On the last engine I worked on, PQ encoding was done in a shader in the last rendering pass, which then ended up copied into the back buffer. That’s what I call output.

Did we miss a magical hardware feature somewhere so that we could have kept output linear and just let the hardware do its thing ?


Is there actually a mapping to downsample colors so that the mapped colors are visible on any screen? (Assuming there is a minimal common intersection on the color space)


"Any screen" means sRGB, I guess. So sure, there are plenty of ways to map CIE XYZ into sRGB, if that is what you are asking.


What about gamma in rendering pipelines that use floats for high dynamic range?


In an ideal world, why would you use gamma there? Especially in a rendering pipeline using vectors (= linear) is better. And floats give you the range and precision you need. If you use CIE XYZ instead of CIE RGB, then the Y channel corresponds to luminosity, a float value for luminosity should cover any range any hardware can handle.


You'd use gamma to convert it to the limited rgba8888 scheme. Or maybe with hdr monitors some sort of 10 or 12 bit scheme. Either way you'll need to cut out information, because a light with value 1029 and a shade with value 3 in the same picture won't bode well without some gamma correction and cutoff.


Why would you not just let the output hardware handle that sort of stuff? It really depends on the hardware what it can output and what not.


How does the hardware know what I want to adjust my range for?


Well you don't want to adjust your range, you give it the actual values. The hardware then does its best to show them.

Anything else would be image processing, which is fine, but I don't see why you would need "Gamma" for that.


Back and forth sRGB conversion is builtin to the texture sampling and frame buffer output pipelines.


You don't need gamma when you have floats.

We use gamma in order to emulate human sensibility that is logarithmic, lot linear. Most machine sensors work in the linear space, they are either linear or linearized around a specific point(like most cameras).

Human senses adapt continuously to the strength of the signal. Your eardrum has muscles that become more rigid with loud sounds and decouple it. Your eyes have pupils that contract and let much less light to pass. Half pupil's diameter means 4 times less light, not linearly but as a power of two.

Then the sensors itself reduce the signal again. If you look at a bright thing in sunlight for two seconds and then look away you see a "shadow" of the bright object because the specific part of the retina has adapted to the level of sunlight and automatically subtracts the brightness in this region.

Neurons itself work logarithmically. The hairs in the ears reacts proportionally less than the signal itself. The chemical diffusion of to cells is also proportional to itself. That is they work in the logarithmic (or the inverse, exponential if you want to recover the original signal).

The reason float works is because float encoding is logarithmic. But there is a problem, 16 float bits is not standard and it is very limited. You need 32 bit floats per image channel and that is wasteful.

Adobe raw format(dng) created a 16 bit float. But if you do something, do it well, use 32 bits like the Gimp does. The great thing about 32 bits is that you could combine multiple exposures in a single image and that way you are not wasting so much resources because instead of 3 or 4 pictures(each for a different exposure), you just have one with almost the same info.


Gamma is about outputting to the monitor. HDR or not, the pipeline should be linear and the output converted to whatever the display needs.


Some people will understand those concepts better with examples:

Imagine you are in the Sahara desert at night with no lights out there in new moon. You fire a candle so you can see. Your vision adapts to the candle illumination that is 1 lumen. Let's call it one unit of illumination.

You can see things around. That is your sensibility is capable of seeing things in very dark conditions. Your sensibility is very high.

Now imagine that you are in a room at night, the illumination could be thousands of times bigger than with the candle, so your vision sensibility must be thousands of times smaller.

No you get out outside in Sahara desert at 12 AM in July and the illumination is millions or hundreds of millions of times stronger than with the candle. Your vision's sensibility must be hundreds of millions of times smaller.

Our senses adapt dynamically to the signal level. That is sensibility becomes inversely proportional to the signal level itself, starting from a given threshold of minimal signal we could perceive.

In a high dynamic range(a big range in illumination or sound levels) we can use logarithms to model that behavior. In a low dynamic range, we can use gamma or ulaw(in sound).


Sahara desert = Desert desert. Does not make sense. I learned that here on HN


12:00 a.m. is midnight ;)




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: