Web color is still broken
webcolorisstillbroken.com
webcolorisstillbroken.com
It’s a bit of a chicken and egg problem that we can really only fix by allowing content to explicitly opt-in to linear working color profiles. And sadly that’s not going to solve everything either: while a linear profile is good for color interpolation, sRGB encoding is ideal for brightness interpolation. You’re stuck choosing between ugly red-green interpolation and nice white-black (sRGB) or between nice red-green and ugly white-black (linear). There are some more complex color spaces that do try to be the best of everything here, but I’m not aware of any browser or OS providing support for working with these perceptual color spaces.
A similar problem comes up when trying to manage color gamut on screens and systems that are intentionally blown out to look vivid, vibrant, shiny… looking at you Samsung phones. Any properly color-managed image there looks incredibly dull compared to the bright defaults you’ve grown accustomed to. If we take 0xff red to mean “full sRGB red”, that’s much less bright these days than if we just assume it means “as red as the screen will go.” It’s much like how TVs are (hopefully were?) set in the store in bright shiny mode to induce you to buy them, not set to reproduce colors accurately.
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)The 0.5 sRGB grey (aka 50%, 0x7f or 0x80) is right smack at the grey value most people would pick as the halfway point between black and white.
A linear 0.5 grey is way off from that, I think way too bright, but I’m about 10 months off working on this and to be honest this is one of those things like east/west or left/right that I can never remember without working out the math on a piece of paper. Too bright or too dark for sure, not at all a medium grey.
It took my team a long time to not think of linear and sRGB interpolation in terms of good vs. bad, right vs. wrong, modern vs. legacy, etc. There are good uses for interpolating in both color spaces, and an a variety of others like HSL, HSV, CMY, perceptual spaces. Sorry for continuing the problem. There’s no ugly color space; they all have good uses.
You are right though that schemes like sRGB are a better fit for perceptual brightness. As you say the slider works the way people expect it to and you don’t need so many gray levels. 8 bit linear light shows posterization at some levels and is shaded too finely at others. If you want good results with linear light and common tools you need 16 bits of grey.
Chicken-and-egg problems have to be resolved one step at a time. Implementing color-interpolation is a possible first step.
OKLab and OKLCH coming soon to CSS4 near you:
https://www.w3.org/TR/css-color-4/#resolving-oklab-oklch-val...
Note this is a part of what the "Color Spaces and Functions" area of Interop 2022 (https://webkit.org/blog/12288/working-together-on-interop-20...) contains. See https://wpt.fyi/interop-2022?feature=interop-2022-color for the current status.
This is a problem on a lot of HDR-capable consumer monitors, even expensive factory calibrated ones from Dell. They often lack any form of sRGB clamp resulting in exactly this problem when viewing an sRGB signal. AMD has a setting in their GPU driver control panel that can do this on the GPU without needing the user to provide an ICC profile. The Nvidia driver has a hidden API to do this, requiring the use of third party software to take advantage of.[1]
TVs are a little better in this regard. My Samsung TV has an "Auto" option for color gamut that correctly identifies DCI-P3 and sRGB signals and clamps them accordingly. But the default setting was "native" which made sRGB content look really bad.
And the ones that don't almost universally lock you out of all other color settings when enabling it, often even including brightness. It's ridiculous.
Also, thanks for the shoutout :)
I remember when the Pixel 2 came out, there was a minor kerfuffle over it defaulting to using sRGB. It got overshadowed a bit due to some of the more severe issues people ran into with the early batch, but it still apparently got enough of a backlash for them to patch it shortly after to update to a compromise between what I think it called "natural" and "vivid". At the time, I had never paid much attention to color profiles, so my roommate suggested I enable sRGB (which was in the developer settings on the original Pixel) for a week and see if I preferred it. It turns out I do actually prefer it, so now I've used it on whichever phone I've had since then!
TVs and monitors are pretty bad as well, but at least more wide-gamut source material is becoming available and calibration to DCI-P3 or Rec.709 is starting to become a selling point.
"Color gradients are supposed to be equally bright around the midpoint"
This is false. Nobody mandates this.
There is no "correct" way to do it, every one of them is arbitrary (although some do look better than others and the suggested method is better than the default linear interpolation).
It is completely analogous to smoothing curve in animation - it's about what sort of interpolation mechanism you use.
If there would be a standard for specific perceptually pleasing gradient, then one could claim "does not follow standard X".
The point of the article is usually abslutely correct, though: "The correct way to process sRGB data is to convert it to linear RGB values first, then process it, then convert it back to sRGB if required."
The issue with this is that the human eye perceives brightness slightly differently at different frequencies (and combinations of frequencies) so the perceived brightness of the gradient may appear non linear. That isn't to say that the browser generated gradient is perceived in this way, it is generally even more non linear in its perceived brightness.
Focusing on the luminosity is only half of the battle.
For nice looking gradients that are pleasing to design with, generally for aesthetic reasons you also want the perceived color saturation to be interpolated in a predictable way.
For reference, here is a nice example of an approach to find a nice looking mixing function: https://bottosson.github.io/posts/oklab/
As you can see, preserving luminance means you get a restricted range of gradients to choose from.
The possible colors produced by a display remain a cube in a linear colorspace, which is a convex object, so all gradients remain available.
So there _is_ a natural interpretation of linear interpolation between two colors in physics. Concretely: Imagine two lamps with the two colors and the same brightness. You start with one fully turned up and the other fully turned down. Then you increase the one while you turn down the other keeping the brightness constant.
I say this as a software engineer with a MSc in physics and a computer graphics/traditional graphics afficinado :) - not to boast with my eminence as that would be silly on this site but just that I've given a long and hard thought on this matter over the years.
Also, this argument makes total sense in isolation, but you still have no good reason for the gradient rendering on the web to stay as it is. It doesn’t look nicer or have any benefit other than backwards compatibility. This is the whole point of the article.
To be clear, when I say "based on physics" I mean "a value that can be computed from first principles, based on a specific model".
For example the spectrum of a black body radiation can be said to be based on physics.
Gradient is a mathematical entity.
A "correct" gradient cannot be computed from first principles, nor does the article specify any specific model to use. There is no "correct" gradient. We can define some spec for a gradient and say "is according to spec" or "is not according to spec".
Gradient is an interpolation between two triplets using some function.
With gradient, in R3, we have two elements, a,b, and our task is to define a path g(t) from point a to point b so that g(0) = a and g(1) = b;
The trivial way to do this is by way of linear interpolation
g(t) = a * (1-t) + b * t
however this has lots of aesthetic pathologies. The work around gradients is about finding the most pleasing g(t).
If we start from the philosophical point of view that all smooth curves are based on intuition and inspiration from physics you are free to do so but this will summon an angry horde of mathematicians and computational geometry experts.
"This is the whole point of the article."
I think the point of the article was
1. Gradient rendering does not respect the spec
2. Any color computations should be done in linear color spaces
The points are valid, but the motivational paragraph about gradients was more misleading than correct (IMO) hence my critical response above.
The 'eye sensitivity response' mode is a color space. But it has problems. Notably, it can represent a lot of impossibly pure colors (because e.g. your red detectors have a lot of overlap with green so pure red acitivation is impossible). More relevantly, a linear interpretation of this system does not match what people see. Perceived brightness is close to logarithmic. If the cell has double the activation, that looks like a constant increase in brightness.
Finally, the way we see color depends on the context, mostly the ambient light. This is largely (but not completely) captured by the idea of color-temperature / a white point. But there are also optical illusion effects around brightness and color.
The spectral response of the L and M cones mostly overlaps and our perception of color relies heavily on “adversarial” transformations in the brain.
The result is a very different effective spectral response superficially resembling RGB bandpass filters except the red channel takes negative values (!) at some wavelengths:
https://en.m.wikipedia.org/wiki/CIE_1931_color_space
The negative values can be thought of as requiring additional anti-red (green+blue) to render the correct color.
The CIEXYZ color space was invented to address the negative values and also conveniently separate luminance from color information. It is widely used today to do color space transformations since it represents standard human color vision in a reasonably convenient and intuitive way.
On a side note, wide band RGB or Bayer filters used in digital cameras are a poor match for the CIE 1931 standard observer effective band pass filters (even ignoring the negative red values). They would result in low saturation colors if mapped directly to a full-gamut RGB colorspace. Conveniently or coincidentally they work well when directly mapped to a limited gamut sRGB color space. Narrower bandpass filters approximating the CIE1931 curves look correct when mapped to a wide gamut like rec.2020. The point is you cannot make simple assumptions about RGB colors at any point in the process.
The biggest problem we have today however is many systems are not aware of colorspaces and assume that RGB values are an absolute and invariant encoding of color.
https://www.w3.org/TR/SVG11/painting.html#ColorInterpolation...
edit: An other mode of interpolation that is missing even from the spec is using premultiplied alpha. It would be essential to correctly render upscaled transparent raster images, where you don't want to see the "color" of the fully transparent pixels to leak through when it gets interpolated with a neighboring opaque pixel.
I'd say the transparency assertions are more dubious. There's a zillion ways to superimpose a color on an image and the one they suggest isn't even more consistently useful than the others, let alone 'correct.'
I'm with you, there are ways that I think color mixing should be done but I would never say that mine is "right". That's silly, it's art.
I think color mixing should be done using HSI colorspace (luminosity replaced with intensity defined as the sum of all light power outputs) with HS defined as per HSL/HSV and interpolation between any two colors done by a line drawn between the coordinates. The reason for this is that in my applications I use spotlights so obviously "total brightness" is way more important than "display lightness". It's just physics, and no right or wrong about it, it's a different display kind.
This is "correct", the colorspace is explicitly constructed to be used in this way such that each step is perceptually even. But it also isn't necessarily what people want, to me "fade from red to cyan" automatically goes through white because of course it does... but what people usually mean is they want the hue to spin around at fairly constant saturation (ignoring that the direction of rotation matters) because it looks good. Red to orange to yellow to green looks vastly nicer in a gradient than going a direct path through white.
That all said (mostly because I find it bizarre and fascinating even after a lot of study), the arguments in the OP are not about whether a given gradient is objectively right but rather whether they match the spec. Things should match the spec...
Also agree "should match spec" is always a valid argument.
To repeat, and be clear, my critique was about what the page says "Physically correct color gradients..". This should have been "according to spec you should compute a gradient this way, and this is what your browser does...".
Value (bright vs dark) is more important than anything else. If you were picking foreground and background colors for text whether or not it is readable depends on the difference in values, not the hues.
Any image should be meaningful if seen in black and white, not just for color blind individuals but for normal sighted individuals too. The Ansel Adams zone system is good for thinking about this, even for non-photographic images. He identifies 11 major bands of value which are about as many shades as you are going to get in a bad print or viewing environment, say with a thermal printer or newsprint.
In a top quality print and viewing environment however each of those zones except the most extreme is able to show meaningful detail. Of course an image can choose to not use certain zones but generically I’d say the ideal image looks good under bad circumstances but under good circumstances it has something to delight the eye in all the zones. (Reference art from Pokémon often has well-thought out uses of value because it has to play across various media.)
I feel like if you can do that math you understand a ton. Including why red and blue mixed is purple =) The integrals you need are at the bottom.
- Why is there a "white locus"? How much does my hue shift under different color temperatures (ignoring CRI, which I suggest you do for now)
- With what math can I reproduce a color using three other colors in combination?
The chemicals that pick up light respond to different wavelengths differently. However, if they get excited, they are a [1] (as far as I think we understand). So a single phosphor can't tell anything about the wavelength other than a probability distribution.
Then you take three probability distributions and identify a single unique color in our heads for it. And that's why every color-space ultimately has three parameters, it's all just different projections and mappings but physically there's really just a spatially isolated signal that tells you which of three phosphors were hit and how much, and then a ratio to downsample it to a perceptual color.
And then you look at the overlap and see how for wavelengths you see as blue, the "blue" phosphor is only about as active as the "green" phosphor (which are confusing misnomers anyway) but your brain sees both being active equally as "blue". And then that "red" secondary hump gets hit when the wavelength moves from blue towards violet -- activating the "red" phosphor and making vision into a wheel.
It was always one of those "this is obvious until I think about it" moments when I wondered why 400nm and 700nm aren't ends of a spectrum in our vision rather than a wheel, there's no obvious theoretical reason for it I think. It's just a possibly pure coincidence of that "red" phosphor having a second hump.
It's nice to do the conversion for real a few times with example colors or black body radiation. Seeing how this works a little closely makes a bunch of stuff like imaginary colors make sense biologically with saturating certain phosphors.
I like Rainbow Dash’s tail in My little pony because the artist chose to let the brightness vary but did it deliberately so it is meaningful in color and B&W.
This is the main reason I like it for my spotlights, it's way weirder if the apparent brightness of the spot changed as it went through a rainbow at fixed saturation (or from unsaturated to fully saturated even). Instead, I make it so that for secondary colors each individual emitter is half as bright by keeping the sum(R,G,B) constant (if it's RGB) as one of the main parameters. It's a tradeoff, it definitely only gets half as bright for the secondary colors. I think this is for the best in practice, otherwise white would be thrice as bright again, the software limit makes more sense to me than bouncing spot brightnesses.
For computer display colors, I don't think I am an expert enough to speak to it. I know about spotlight color schemes because that's what I build =)
http://www.handprint.com/HP/WCL/color2.html#combocolor
But he's just probably talking about how "green-yellow" wavelenghts contribute much more to lightness perception ?
See "Catch #3" here:
https://entropymine.com/imageworsener/gamma/
And you can sometimes get even better results using a sigmoidized colorspace. See:
https://legacy.imagemagick.org/Usage/filter/nicolas/#detaile...
Maybe a fancier model like oklab would outperform it for this specific case, but only in quality, not performance oklab is more expensive to convert to/from compared to sRGB, which is usually free as your backbuffer and textures are usually sRGB.
That's just because their wording is imprecise. If you replace color gradient with "perceptually linear hue gradient", which I think is strongly implied, then that would be 100% correct. Hue is a color coordinate completely independent from others like lightness, in a perceptually uniform color space.
But you're on point - there's no right way to do it. Not because of it's a matter of taste or something (it's not). Problem is, there's currently no perceptually uniform color models! All models are uniform in some range but fail in various scenarios; human perception is still largely unexplored. As a result, getting it "equally bright" in different viewing conditions with varying intensities is an impossible task, especially when you know nothing about viewing conditions. You have to narrow it down to "good enough in common scenarios". Models like OKLab are trying to do exactly that.
> Physically correct color gradients (as you would get, for example, along an out of focus edge between colors) are equally bright around the midpoint,
So I think there is an argument that using a linear color space is more correct.
About a decade ago I was hearing that web-safe color was effectively obsolete. Today Firefox chokes on P3 color, and Chrome doesn't appear to care at all about display color profiles.
I recently launched a website that had a fire-engine red background and was expected to have a rotating animation above the fold (https://worldparkinsonsday.com). Even once we got the animation synced perfectly between Chrome and Safari, it turned out that iOS Safari was rendering the video differently. Eventually I gave up and replaced a 128kb mp4 video with a 5mb transparent animated GIF. Shameful.
And I had this lil' fellah on my desk smiling at me the whole time https://100soft.shop/collections/dumpster-fire/products/dump...
Its intentional sabotage by Apple at this point on behalf of MPEG-LA, it seems.
On another day Apple is working on behalf of MPEG-LA when its VVC patent pool doesn't even include Apple.
I think the real correct solution would have been a Lottie animation, but there was no time to train the fx guys.
First I figure out which edges of the video will have website background next to them. Some video edges won't need any if the video itself is touching the side of the webpage.
Inside the video, do either or both of these two things:
a) Make the background of the video the same as the background of the website (impossible for live action, useful for product spin-arounds / pull-apart animations)
b) Place a gradient layer over the video to make the edges of the video that meet the website content blend into the website's background color. The gradient should go from transparent to the website's color.
Render out the video.
Now comes the part where people usually get frustrated. The video either doesn't blend in with the website's background, or only blends in on certain browsers. (This is due to a combination of the video losing color information when it is rendered and due to the whole web color spacing issues the Original Post goes into.
Now to fix it: Place a css/svg gradient over the <video> element itself that also goes from transparent to the website's color.
Why put the original gradient over the video?
Two reasons:
1. Depending on the css/svg gradient shape and stopping points, some browsers will render a hard edge through the gradient, allowing the border of the video to still be seen. Human eyes are great at seeing very minute changes in brightness/color when they're next to each other, especially when they're arranged in a straight line. Baking a gradient into the video itself actually helps out the css/svg gradient to hide the video's edge
2. Rendering a colored transparent gradient inside a video actually lowers the amount of colors in the final video, leading to a smaller file size and faster loading time. If the user's aren't actually going to see the original colours, there's no point rendering out the original video and all its much larger amount of color information if the user's aren't going to see it.
Example time:
Here's the last website I achieved this effect on: https://myoresearch.com/en-au
(Yes I'm aware there are some other issues with the website, but this is more to demonstrate the video effect itself)
The normal versions have a white point of 50 and the ok versions have a white point of 65, which is the same as sRGB[2].
[1]: https://wpt.fyi/results/css/css-color?label=stable&label=mas...
The SVG color space definition is the exception here, browsers can do better in that area. Still, it's silly to expect browsers to change the way their color system works and go against the expectations of color blending for web developers just to tick a correctness box.
Make a time machine and take it up with Microsoft en Mozilla in the early 2000s if you want the default color system to work differently. Write a patch for Chrome/Firefox/WebKit to implement the SVG spec if you're so passionate about this. People generally don't care about this stuff, they want the result to look Good Enough™ and that's exactly what the current implementation does. I don't think any browser maker will put in the effort to do much about this "problem".
"Never underestimate the value of a 'good-enough' solution"
I commenting as a multi-decade programmer, but alas I know nothing about color ! Even though I've dabbled in graphics here and there in my career. (this is just for background)
My main point is that, as "technical person" with NO skin in the game. I can honestly say I can't see the difference, or if I can, why one is better or not. Not saying it should not be fixed, but if I am a sample of the "ignorant majority" that don't know about colors should this bother me ? Or bother me more ?
I hope I'm not offending the "experts in this field" just saying, your clueless audience(me) don't even know what is wrong :)
But I can see the difference. For "my browser" visual image, I can kind of see "vertical pillars" in the middle which which reminds me of times where we had not many colors in our palette.
Moreover, if looking at red and moving on horizontal axis - it is same red and after only some distance it starts to change. The correct color mixing for me looks better - the colors start to change instantly and more smoothly.
Here's an example: https://incoherency.co.uk/interest/colour.html
And here's a screenshot of how it looks on my browser (Firefox 99.0, Ubuntu 20.04 LTS): https://img.incoherency.co.uk/3812
The square is a different colour to the page background colour despite having the same RGB value (#0cf4c7) but they look different. No amount of changing the colour mode selection in GIMP can fix this.
I opened the screenshot in GIMP and used the colour picker tool to see what colour my #0cf4c7 has turned into, and in the screenshot image it is #67f1c7.
Strangely, when I draw the screenshot in the browser, its colours stay the same, so obviously there is something you can do to the PNG that will make it render the colours you chose.
I remember reading a Firefox bug report about this, and the response was that the person's monitor colour calibration must be wrong, which makes no sense to me since even if the monitor colour calibration was wrong, I'd except it to apply to both the page and the image equally.
EDIT: This one: https://bugzilla.mozilla.org/show_bug.cgi?id=621474 - from 12 years ago.
Color mgmt by browsers is, when it is applied, only applied to images (neither videos nor "CSS colors", broadly speaking). I'd bet you have an ICC profile associated with your monitor.
Did you use some browser extension for eye protection or dark mode?
I think you need to investigate Firefox and how it is using your GPU. Maybe try disabling WebRender? https://support.mozilla.org/gl/questions/1345186
gfx.color_management.force_srgb
in about:config makes the rectangle disappear. I don't have the slightest idea what is going on tho.- No colorspace metadata (software should assume sRGB)
- Built-in sRGB format chunk
- gAMA chunks
- cHRM chunks
- ICC profile chunks
IMO v4 ICC profiles are the modern and best way to encode colorspace info. The problem is not all software uses any or all of these.
ffmpeg for example decodes all of these chunks but does not actually use any of it. It even assumes by default PNGs are encoded with rec.701 gamma (common for legacy video). This is why PNG->x264 conversion with ffmpeg has weird colors unless you encode the PNGs with gamma ~2.0 instead of the sRGB standard ~2.2.
Gimp shows a color of that hex the same as Firefox's square. The Chrome color is much paler in comparison. There's no color profile set for the monitor.
the Photos app on Windows 11 renders it as 01f4c7. almost 0 red. (although come to think of it, maybe the Windows 11 Photos app is an embedded browser, lol)
There's an article with a much more sympathetic approach:
https://www.joshwcomeau.com/css/make-beautiful-gradients/
Not sure if this is trolling or not, but the closing HTML tag misses a > :)
Colorjs.io doesn't address most problems the website highlights.
There are 3 issues highlighted: color mixing, transparency and scaling.
The second is entirely subjective and I prefer what browsers do. Scaling is irrelevant (the issue is not explained) to color handling.
https://caniuse.com/?search=Houdini
Listen — I’m not really sure what your problem is and I don’t really care. I have no interest in “winning” a conversation. If you’re just going to push goal posts in different directions to try and find some way you feel righter than me despite my having done nothing besides making several specific, one-sentence, topical points, then I yield the remainder of my time for you to go ahead and do that by yourself.
And I agree with the author about his reasoning that sRGB is compressed data. An audio equivalent is the Mel scale https://en.wikipedia.org/wiki/Mel_scale
They were not really common in the Western (maybe more so in vinyls, but I don't collect that) but it's such a pain in ass when I was collecting Japanese CDs from 80's.
sRGB color is not the perfect color space, but in general it's better for UI than using linear color, which the author seems to be advocating for. The web is primarily UI. Not only that, but sRGB is the color space of probably 95% or more of devices, and of all low end computer monitors. sRGB is designed to balance perceptual linearity with encoding cost. It's very cheap to encode, and perceptual-enough that you can store a channel in 8 bits with high quality (linear value needs 16 bits to be comparable, and it's still worse unless you use half floats instead of unorm. It's common to go as low as 5 bit sRGB channels for albedo in computer graphcis.)
I am a graphics engineer, I've had a lot of colleagues learn the aphorism "don't do math in linear" once they get first burned.
> Unfortunately, by calling it a "color space", we've misled the vast majority of developers into believing that you can do math on sRGB colors
That belief is an over-correction in my opinion. The examples that the author shows are all about achieving physically correct lighting. The Rubik's cube image blended with 25% white doesn't look physically plausible because it's not being done in linear color.
But the goal with UI is visibility, not physical plausibility. If you want to cover something with a UI element at 50% transparency, you want 50% of the UI and 50% of the background, not a physical model of some transparent medium.
sRGB does however suck for defining gradients, but I think that's more to do with it being RGB. For this what I generally advocate is a luma/chroma model. Other posters have mentioned Oklab which is great, though even plain YCbCr will get you 80% of the way there while being cheap to convert to. You still want to do that in gamma/perceptual space though, not linear. The author didn't show gradients between white and black. Gradients between colors of 2 different luminances look awful in linear^.
However I totally agree with the author on zoom. Web browsers should be doing zoom/image resampling in linear space. Images shouldn't qualitatively change based on their zoom level.
^ https://external-preview.redd.it/voeyOYu6Ds-fLLU7nR4kABmFgUE...
I'm not sure what you mean by this. I work with game engines and everything is calculated with linear color. Not only anything else would be completely physically inaccurate, it would be unfeasible for modern HDR rendering which supports extreme dynamic ranges with physical units (ie 100000 lux sun).
Maybe you work with mobile devices, where they still haven't fully moved to HDR?
You work with 100,000 lux sun? Damn! We did physical values for sun/moon lighting when I did flight simulator stuff but that painfully required full float rendertargets, which is fine when you can tell Uncle Sam the minspec gpu is a 1080, but unacceptable for console and mobile.
Anyway we do full linear HDR for the 3D scene of course, as it's simulating physical light transport. Though not exact sun/moon values as we want to do half float rendertargets.
The UI does compositing in SDR sRGB.
Some of our textures are tinted with this rather cursed lab model I cooked up for speed, which is gamma encoded srgb linearly transformed so that 'l' = average of rgb and 'chroma' is rgb equally weighted but placed 120 degrees apart in the unit circle. Was designed to make HSV transforms linear operations (ie matrix multiply) and have great performance with acceptable quality with not too many imaginary colors. Nicer color spaces were too expensive, and it works good enough to make the artists like it.
I don't believe it is yet implemented in browsers, but I know Chrome at least is working on it.
But sRGB spec does specify a color space ! And these numbers do have a meaning - the unreasonableness is with people's assumptions.
The issue here seems to be rather that developers and users, when hearing "space", assume a linear, Euclidean space, except color spaces are usually none of these !
But I don't really see what other word could be used here instead of "space" ?
----
A related issue (and potentially a fix) :
In 2015 developers (and users) could (usually) just stay blissfully ignorant of colorimetry and assume sRGB everywhere.
Today, with wider gamut screens becoming common even in non-professional monitors ("HDR"), and non-Apple OSes starting to get proper support for non-sRGB specs, sRGB cannot be assumed everywhere.
So learning some colorimetry might be a pre-requisite for comptetence now.
(Except for Web text colors, IIRC they're still limited to 8 bit per color = 256 values, sRGB ?)
Has this been discussed at the appropriate standards bodies and conferences?
I couldn't disagree more. Browsers and modern web development style keep kicking out tried and tested technologies in favour of newer alternatives that are objectively inferior. This is not a good thing if you're interested in an attractive, functional WWW.
In this case we stopped using real images prepared by real graphic designers and digital artists using real graphics software and we substituted rounded corners and gradients and web fonts and scalable line art graphics. You can argue about whether this has advantages by reducing data sizes or cutting costs through allowing developers with bland toolkits based on "flat design" to do styling work instead of hiring experts. What you can't seriously dispute is that those new techniques render really badly in some or all of the major browsers and now many sites look bad unnecessarily and some become harder to use as well.
I suppose the original author is a zealot for linear SRGB, but that might change once he encounters a black and white gradient interpolated in linear.
However we know that most users will prioritise other aspects, such as functionality or security, over aesthetics. If the advantages of a nice design are purely cosmetic and don't also improve factors like the usability of an app or the credibility of a marketing site then that's probably going to be less important than missing some key feature the user wants or lacking the network effects that existing products in the market have established or convincing a potential customer that you're trustworthy before they had over their card details.
Not trying to be negative, I just can't think of any and that would be excellent evidence that it does matter. Just bringing up a list of the top 200 web sites and they are the reference gallery of visually terrible sites.
Both types of bank offer similar basic accounts and services. Interest rates and fees also tend to be similar at the moment.
What does separate them is that the established "big names" almost universally have terrible online banking and mobile apps while the newer alternatives tend to focus on these facilities (I think some of them don't even have physical branches) and they have slick, modern UIs aimed squarely at younger generations and the digital native market.
I don't have any hard data to cite but the number of younger people I see using these services suggests they are having some significant success at breaking into even such a heavily regulated and competitive market.
But the airquotes around "fix" are precisely because it's not "broken", it's simply "how it's implemented". Plan accordingly.
> ...we stopped using real images prepared by real graphic designers ...allowing developers with bland toolkits based on "flat design" to do styling work instead of hiring experts.
Yeah that's a separate issue and rings of No True Scotsman-ism.
> What you can't seriously dispute is that those new techniques render really badly in some or all of the major browsers and now many sites look bad unnecessarily and some become harder to use as well.
Pretty sure that is disputable. "Many sites" do look bad, but if you're claiming this is because of browser sRGB colour handling then you're gonna have to cite a source or do more than claim the high ground.
I do. When I'm building web stuff professionally, there's a laundry list of CSS features (often quite basic ones) that it would be very convenient to use but I often don't because I know they will look terrible in production for a significant proportion of users. But that's unfortunate.
Yeah that's a separate issue and rings of No True Scotsman-ism.
Separate perhaps but I don't see how Now True Scotsman applies here. There certainly are professional developers who also have significant knowledge of things like colour theory and graphic design. You're talking to one. But those are separate skill sets, not normally required or expected for most development work. I don't think it's plausibly deniable that web development today frequently relies on someone who designed some toolkit, probably using basic CSS effects for almost all the visuals, instead of hiring an in-house designer. And I don't think it's plausibly deniable that today's WWW is much more homogenous and dare I say boring in appearance than the WWW of 10 or 20 years ago. There are usability advantages that come from some types of consistency but does everything really have to be so same-y?
"Many sites" do look bad, but if you're claiming this is because of browser sRGB colour handling then you're gonna have to cite a source or do more than claim the high ground.
It's not just the sRGB handling. I'm talking about a bigger picture. Some popular browsers had antialiasing glitches that made rounded corners done with CSS look like low-res pixellated junk for years when `border-radius` was first a thing. Try applying CSS transforms to anything using fonts or SVGs today and you can still see horrendous rendering artifacts in some browsers, and even worse if you're animating as well. Of course the fonts themselves render completely differently on different platforms even without any transforms applied and sometimes that has a material effect on important aspects like accessibility or even basic legibility. Gradients over large areas have horrible banding in some browsers because they don't use basic dithering techniques that every real graphics program has used since about the 1980s. The list of browser rendering glitches that any halfway decent creative software has avoided for a very long time is long and frustrating to read.
> but I don't see how Now True Scotsman applies here.
"Real" designers, using "real" software, hiring "experts", etc. Because "no true designer would X...". There is absolutely genuine expertise in this domain but, much like development, it isn't a profession. It's not even a trade. Anyone who says they're a designer (or developer), is. For better and (usually) worse.
EDIT: nevermind, I see it now. The square in the last few images is slightly green when CSS is scaling it.
On Linux, when I force Chrome to use sRGB (chrome://flags/#force-color-profile) it makes the colors identical to Firefox's. It doesn't seem to make a difference on MacOS though, the colors are always identical there
A better example would be to use HSL or LAB for the gradients (Red->Green):
background: linear-gradient(to right, hsl(0, 100%, 50%), hsl(120, 100%, 50%));
background: linear-gradient(to right, lab(50% 128 128), lab(50% -128 128));
background: linear-gradient(to right, lab(50% 128 128), lab(100% -128 128));
The two different LAB values for "green" show that if you're just changing Lightness, you'll get a darker share of green. The RGB green needs 100% Lightness.HSL produces the same output as an RGB gradient, which is wrong, as only L should be modified.
LAB works only in safari, and although the result is slightly different, it's still incorrect, probably due to my conversion
My ad hoc expectation would be that I get a linear interpolation of perceived brightness, saturation, and color independent of how I specified the color to interpolate. Or maybe even better a path of minimal perceived color difference with uniform perceived color difference along the path which is probably at least slightly different from interpolating brightness, saturation, and color independently.
Some values don’t exist. Some might have multiple values in another space
So yes, LAB will produce more perceptually uniform gradients than RGB, but browsers are exacerbating the problems of RGB gradients by not implementing them properly.
Shameless plug: https://www.joshwcomeau.com/css/make-beautiful-gradients/
Nature doesn't work in terms of how much red, green and blue it needs to mix on the canvas. Sure, it's great and intuitive to represent colors on digital systems, but that's it. Light in nature works in terms of hue/tint along a continuous spectrum, brightness and saturation.
Color spaces such as HSV/HSL model these concepts much better than any RGB algorithm, and doing math with them produces results that actually make mathematical sense. YUV also takes human color perception into account. It's not a coincidence that most of the smart lights usually use HSV/HSL color spaces, and most of the cameras opt for YUV* based color spaces.
The value of your nominal R,G,B number is the result of using the original "intensity" (brightness or similar) and then raise it to the power of gamma (typically 1/2.2). The purpose of this is to give more "bits" around lower end (darker end) where human eyes are more sensitive [1]. If we don't do gamma and have relatively low bit depth (like your typical 8-bit), it's very easy to produce banding at dark gradient areas.
Up to this point, there is nothing wrong.
However, if you want to average two colors (which affects almost all the operations that can happen on bitmap images, including gradient, blending, resizing, blurring, etc...), the correct way, just like real-world physics, is to average them in original linear form/value; but most of applications/implementations, as shown in this page, are just averaging their nominal "gamma'd" values.
[1] There is often a common belief to say that the introducing of gamma space historically was because of how CRT screen used to work (the relationship between electricity intensity and brightness etc.). But most of in-depth articles about this topic say that's just a coincidence.
Say you blend red and green, such as by having a red ( rgb(255,0,0) ) div, and putting a div that is green with 50% transparency over it ( rgba(0,255,0,.5) ).
Now, make a checkerboard pattern of red and green divs. Look at it from far away enough that it appears as a solid color. (easier if you make each div occupy one pixel, while trying to avoid any antialiasing) You could also use something like frosted glass to blur it.
Do they appear the same color?
I would not expect it to appear as a bright yellow, but a rather dark yellow. (but not so dark as it appears brown)
Mixing black and white dots to produce a grey was a pretty common trick when we did not have enough colors in our computers decades ago. But when I step back to lose the perception of the texture, why do I still see a very different grey than the center-grey with the same overall brightness?
I can't even say which one is brighter/darker (my answer changes when I look with a different mindset).
You can visually test your display calibration with [1], but you should ensure that the image is displayed 1:1, which might not be the case with your browser and hiDPI settings.
[1] http://www.lagom.nl/lcd-test/gamma_calibration.php#gamma-tes...
I wrote a simple primer on color profiles [1] a while back which makes mention of state of custom color profiles on the web. I do wonder what result you'd get if you blended images with different color profiles on a web page as browsers can view non sRGB based image content.
[1]: https://blog.oxplot.com/understanding-color-management/
I used the proper black background/white text override in my settings for a while, it was a great improvement on the sites where it worked. But it broke too many sites.
Not really sure how we've managed to regress so far on the ideal of having webpages just provide content and letting the browser render it as appropriate. Oh well, readerview it is I guess.
I grew up using an IBM 8513 VGA monitor connected to a PS/2. That's the mental model I use when thinking about color; to my brain, the default grey color (value 7) is "right in the middle" between what I think of as black and white.
What modern colorspace most closely maps to the color space I grew up with?
anyway, I think the "correct" scaling is at the very least objectionable. from a numeric point of view, it whould mix in gray, but from a visual poin of view we do preceive the outer box as darker because non linearity in dislpay and perception.
I can barely perceive a brightness difference between the two areas. Meanwhile, scaling the gamma-encoded image results in a severely wrong result where the outside is far darker than the inside.
Also, the apparent color changes depending on the zoom level - at anything other than 100% zoom, the effects described above disappear and the outer square appears darker than the inner one (although not uniformly). This may be linked to the bug that causes the browser to scale the image incorrectly.
Your monitor likely has a 6-bit panel and uses FRC to emulate an 8-bit display. This tends to cause content-dependent flickering and other temporal artifacts.
Incorrect.
While large regions of homogeneous color should indeed retain their brightness, thin one-dimensional structures are supposed to become darker and disappear gradually as the image is scaled down.
This is what happens when you move far away from an object, which is what "zoom-out" or "downscale" is all about. The total amount of light that you receive from an object decreases with the square of the distance.
EDIT: This is in the context of the image shown in the article, which is a gradient image consisting in light lines over black background. Of course, if you have thin black lines on white background, they will become ligter upon downscaling. In practice, on a real image, some parts will become darker and others lighter, depending on their particular textures.
But those pixels are also larger and the ratio (amount of light in image) : (number of pixels in image) should not change.
The author of the OP is complaining that when you take an image and rescale it, its overall average brightness changes.
I don’t want you to control my experience: Maybe I like having weird colors; maybe I’m color blind and need alternative colors; maybe I don’t want color at all and want a web experience that is text centric.
The model of the web is backwards and it makes browsers ridiculously over-complicated because they’re software designed to tel other people control my experience navigating and consuming information.
Give me the information and keep your colors and layout and scripts and ads and …
The problem is that the web as currently constituted allows (encourages) the web page author to dictate my experience and my browser will mostly obey.
I’d prefer that there be no such thing as “pages”, just “information”, and that all display decisions would be made by software I completely control.
avoid this kind of flaming pit of fun gaming and consult with the person (know and trust). Opticians are great for this in my experience. They actually should point out to you the truth.
There's an entire field of colour management that Microsoft, Linux, and Google are carefully ignoring. They'll occasionally stumble upon ICC colour spaces, HDR, or 10-bit, but they make sure to break everything even worse and leave it like that forever.
Sigh... I have gone on the same rant annually since about 2010, starting on Slashdot. Most recently on YCombinator News in 2021. It's a whole new year, time to repeat my rant and pray to the IT gods that someone at Microsoft or Google stumbles upon this:
The current year is 2022. The future. We have these amazing display technologies such as OLED, HDR, and quantum dots. In this sci-fi fantasy world I cannot do any of the following:
- Send a photo in any format better than an SDR sRGB JPEG in the general case, such as an email attachment, document, or chat message. These are 30 year old standards, by the way.
- Send a photo in any format and expect colour reproduction to be even vaguely correct. Wide-gamut is especially pointless. It is near certain that the colours will be stretched to the monitor gamut in an unmanaged way. People will look either like clowns or zombies depending on the remote display device, operating system, software, and settings.
- Send a photo in 10-bit and expect an improvement in image quality when displayed.
- Expect any industry-wide take-up of any new image encoding format. It is a certainty that each vendor will do their "own thing", refuse to even acknowledge the existence of their competitors, and guarantee that whatever they come up with will be relegated to the dustbin of history. Remind me... can ANY software written by Microsoft or Google save a HEIF/HEIC file? No... because it's an "Apple" format. Even most Microsoft software can't read or write their own JPEG-XR format, let alone Google or Apple. Netflix developed AVIF but I'm yet to see it taken up by any mainstream system. Etc...
New in 2022:
- Display HDR on Linux.
- Display HDR even vaguely correctly on Windows. I mean, good try, but simply clipping highlights without even attempting to implement tone mapping is just plain wrong.
- Use a colour calibrator device on Windows 11, which totally broke this functionality.
- Use a colour calibrator device for calibrating a HDR display. I have a device that can measure up to 2000 nits. Can I use this calibrate my HDR OLED laptop display? No. That's not an option.
- Turn on HDR in Windows 11 and not have it cause a downside such as restricting the display gamut to sRGB.
- Use HDR in any desktop application for GUI controls.
- Use colour management for any desktop application for GUI controls that isn't an Electron application -- the only platform that does this vaguely correctly under Windows by default.
Things have even regressed over the last few years! Windows 10 Photo viewer could do colour management -- badly. It would show an unmanaged picture at first, and then overwrite it with the colour managed picture a bit later, so you get colour flickering as you scroll through your photos. Okay, fine, at least it was trying. Windows 11 does not try. It just assumes 8-bit sRGB for everything.
Similarly, the 14 year old WPF framework supported wide gamut, 16-bit linear compositing, and HDR. The "latest & greatest" Win UI 3 framework... 8-bit SDR sRGB only.
> Wide-gamut is especially pointless. It is near certain that the colours will be stretched to the monitor gamut in an unmanaged way.
This is also the manufacturer's fault. Some wide gamut displays don't even have sRGB emulation, and pretty much every wide gamut display defaults to their native gamut even in 8-bit mode, which is virtually never the right thing to do. sRGB emulation naturally reduces contrast, which is generally already very poor in all but the highest end PC monitors. To add insult to injury, the 10-bit / HDR (these are technically independent, but generally coupled in monitors) mode is complete shit in virtually every PC monitor advertised with HDR support. So you spend money on a display device that is designed essentially in exact opposition to its capabilities and your needs.
(Naturally, reviewers tend to ignore all of these problems apart from HDR actually being pointless with the current state of PC monitor tech; many praise the "vibrant colors" this gives you. Of course, everyone looks like they got sunburn, but who cares. Vibrant! Vivid! Saturated! The reddest reds money can buy! The greyest blacks! The most washed out shadows! Amazing! 8/10! Recommend! Buy now through my affiliate link!)
Then why have a wide gamut display!?!
The whole point is that you have a greater capability. It should be on all the time, not just when doing "professional image editing" or whatever. There SHOULD be no downside!
Similarly with HDR -- it is literally a superset of SDR, so then why are there endless support form complaints about it causing issues when enabled!? It SHOULD just work! Instead, early versions in Windows 10 would shift the desktop by 1/2 a pixel and cause blurring. Or darken the desktop. Or more recently force everything to sRGB, including colour-managed applications light Adobe Photoshop or Lightroom.
The correct thing to do is for each display to always be running in native gamut mode. The whole concept of in-display colour space emulation is absurd[1]. Instead, the display should feed back its native gamut to the operating system, which should then take care of tone mapping via either software or the GPU hardware. This almost happens now. Displays have EDID metadata that include the "coordinates" of their colour primaries. Windows even picks this up! Aaaaand then ignores it, and even strips out the information in newer SDKs like Win UI 3, because... I don't even know.
[1] Ideally, GPUs should be doing tonemapping under OS control, but to avoid banding this would need 12-bit or even higher output to the display. This would take too much bandwidth, so instead displays do tone mapping using LUTs with as many as 14-bits. Except that these LUTs are 1D and control over them is totally broken...
(though IIRC none - aside for black & white medical monitors - had better than 8 bit per color in hardware until "HDR in screens" showed up - IIRC also the PlayStation 3 and some games had a 10 bit per color mode that caused a lot of compatibility problems for hardly any benefit ?)
- but (non-Apple) OS support has been abysmal until recently,
and you probably need to pay a technician to use a probe to calibrate your screen anyway, so only some work environments would bother to set them up correctly ?
----
[1] Dolby PQ only needs 12 bits for up to 10k cd/m² ?
https://www.avsforum.com/threads/smpte-webinar-dolby-vision-...
I don't think any of the current TN/IPS/etc. PC monitors with HDR have 10 bit panels. HDR is achieved generally through sheer imagination (most) and less commonly through more or less (rare) rough local dimming, not by actually having a panel capable of anything close to HDR contrast ratios.
Also, all of this is about liquid crystals (and the electronics controlling them), but cathode ray tubes, plasmas, and light emitting diodes have quite different characteristics...
I would be surprised if nobody had made yet (professional ?) non-CRT PC monitors capable of more than 256 values discrimination ?! (Not even Apple ?!? Or at least some super-expensive, but still commercial (= non-experimental) displays ?)
Also, I guess a similar benefit might be achieved by using more than 3 primaries : who was it already that used a 4th "yellow" subpixel in their (IIRC) diode displays ?
(Though it's still not clear to me why more displays aren't using the standard (at least in Charge Coupled Devices) 2x2 Bayer Filter with double green, rather than a 3x1 one ? Too much reliance on Windows' ClearType hack working properly ? But why in TVs too ??)
Yes
> I would be surprised if nobody had made yet (professional ?) non-CRT PC monitors capable of more than 256 values discrimination ?! (Not even Apple ?!? Or at least some super-expensive, but still commercial (= non-experimental) displays ?)
They exist, but it's limited to the high-end. E.g. Apple's XDR display has a 10-bit panel and FALD.
Reference-class monitors are generally of the "dual film" type, which essentially means that the panel is two LCDs on top of each other, one being used to control only brightness of a given pixel, and the other for brightness and color.
> (Though it's still not clear to me why more displays aren't using the standard (at least in Charge Coupled Devices) 2x2 Bayer Filter with double green, rather than a 3x1 one ? Too much reliance on Windows' ClearType hack working properly ? But why in TVs too ??)
Non-standard pixel layouts are common in OLEDs, e.g. RGBW, weird pyramids and un-even subpixel sizes (I'm assuming due to differing phosphor efficiencies). These all lead to poor text and UI clarity, as one would expect. (It's worth pointing out that OLEDs, being LEDs at their heart, have inherently lacking linearity which is why most of their brightness range is covered by digital modulation)
RGB subpixels require the fewest number of subpixels, which also means reduced brightness loss due to LCD structures. Going to Bayer would mean 33 % more pixels for the same display, except it's dimmer (increasing pixel pitch by 50 % horizontally does not make up for halving it vertically), more expensive to make and also dimmer because now you have two green dots per pixel, so they need to be half as bright, throwing away more of the backlight, and the drivers now need to perform with inhomogenous pixels -- without an obvious upside.
The reason color camera sensors tend to use Bayer filters is - I think - because green contributes most to perceived brightness, so doubling the sensor area for green means halving green's contribution to luma noise. This problem does not exist in displays.
IIRC cathode rays aren't. Plasma-fluorescent ?
Are liquid crystals even used in big screens with something else than a diode backlight these days ? (Maybe cheap ones still use plasma-fluorescent ?)
----
Ooh, right, silly me, for displays green light being human-efficient is backwards !
So you need less than 1/3 of green subpixels, rather than more ! (Anyone tried that yet ?)
A website is an interface, not your own personal fiefdom to grow your portfolio.
There is nothing wrong with this because now the browser can decide how to convert it. So the title should be: browsers still use linear color space.