Open Bug 1248178 Opened 8 years ago Updated 2 years ago

Gradients colors should be interpolated in linear sRGB

Categories

(Core :: CSS Parsing and Computation, defect)

defect

Tracking

()

UNCONFIRMED

People

(Reporter: bugzilla.mozilla.org, Unassigned)

Details

Attachments

(1 file)

Attached file brown sludge.html
Originally brought this up in bug 1241717: The blending used to generate gradients does not seem to be physically correct. If you look at a chromacity diagram[1] then yellow sits between red and green. Yet the gradient creates a brown sludge instead.

I assume this is because blending happens in the non-linear (gamma curve) srgb space instead of linear rgb.

Depending on how one interprets the spec's wording - which says "linearly interpolated" - this could even be considered a spec-violation.


[1] https://upload.wikimedia.org/wikipedia/commons/6/60/Cie_Chart_with_sRGB_gamut_by_spigget.png
I think the issue here is that the gradient color space system used is actually not sRGB, but a linear RGBA system with individual, linear component interpolations of R, G and B values instead of combined components (=color), which would (roughly?) translate to (non-linear) sRGB'.

Should the spec be interpreted as transitioning from one color to another in linear sRGB, instead? What math would be needed for this?
It's possible that https://www.w3.org/TR/SVG/painting.html#ColorInterpolationProperties should apply to CSS gradients as it does to SVG gradients.
That said, css-images doesn't specify for gradient interpolation, but it does specify sRGB in https://drafts.csswg.org/css-images/#gradient-average-color , which I think ought to be the same as gradient interpolation.
> It's possible that https://www.w3.org/TR/SVG/painting.html#ColorInterpolationProperties should apply to CSS gradients as it does to SVG gradients.

Hrm, yes, that would allow the desired results to be achieved without changing current behavior.

> Should the spec be interpreted as transitioning from one color to another in linear sRGB, instead? What math would be needed for this?

Simply removing the gamma-curve part of sRGB before doing the interpolation, then converting back to gamma sRGB.

Although dbaron already linked to the svg spec, here's the wikipedia page on the math: https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation

Online tool (linked the wrong page in the other bug): http://davengrace.com/dave/cspace/

basically a gradient between #FF0000 #00FF00 should result in #BCBC00 at the midpoint and not #808000 to have the R and G subpixels at half power each.
I think we also need to keep in mind if using sRGB interpolation is supported by the graphics frameworks in use on different OSes, or if it needs to be emulated.

> Simply removing the gamma-curve part of sRGB before doing the interpolation,
> then converting back to gamma sRGB.
Like I said before, it's not done this way. the interpolation is done linearly on individual color component values, IIUC - it's not done in sRGB at all.
Summary: Gradients colors should be interpolated in linear RGB → Gradients colors should be interpolated in linear sRGB
> IIUC - it's not done in sRGB at all.

It's in sRGB (which includes the gamma curve), hence the dark mid-tones.

This is how it would look in linear sRGB: http://i.imgur.com/rwfm5J6.png

This is how it would look in CIE L*a*b*: http://i.imgur.com/wbwPYvt.png
I got that wrong, my imagemagick-fu is weak.

Let's try again:

sRGB,gamma: http://i.imgur.com/daoM2p3.png
sRGB,linear: http://i.imgur.com/WwPqYdT.png
 CIE L*a*b*: http://i.imgur.com/hg0RS86.png


I hope this displays properly on your browsers/image viewers, the PNG headers can contain their own color profiles and gamma values, which are ignored by some viewers and stuff like that.
I'm sure we're all familiar with the different colors spaces here and how they translate to output - examples aren't necessary :)
What I was saying is that, as far as I understood, it is a linear *component value* interpolation that is done currently, not a *color* interpolation in whatever preferred color space. i.e.: each component in RGBA is treated the same, with linear interpolation of the actual component values. Hopefully it's clear what I mean now.
Ah I see, that seems mostly like a semantic distinction to me because the interpolation is based on distance. And either you use an euclidean distance - thus interpolating individual components values - and just change to a different color space if you want a different interpolation or you use more complex interpolation algorithms that work in non-euclidean spaces.

Anyway, changing the default as I initially suggested probably isn't a good idea. While it would yield nicer hue transitions it would significantly affect luminosity-transitions, e.g. grey-grey gradients.
Unless the default was changed to LAB or some similar perceptual distance.

So I guess dbaron's suggestion might be the least invasive solution.
Good point on it affecting luminosity on grey transitions - those are extremely common on the web, and often not a point addressed in your typical chroma maps used to display color spaces.

IMHO, it's probably better to leave well enough alone here, and make the hue transition, if more accurate shifts are desired, the responsibility of the web designer for defining an extra mid-point or hinting (it's only very obvious in extreme cases, anyway). Unless of course the SVG approach is feasible and won't cause this luminance issue (but I'm guessing it would, too).

As an aside, there is talk on the www-style [css-color] @w3.org mailing list going on right now to define wider gamuts and deeper color spaces in CSS. Maybe you want to join the discussion there with your input?
Yeah, with the SVG approach you would have to pick between bad luminosity transitions vs. bad hue transitions if the choices are sRGB and linear sRGB.
> IMHO, it's probably better to leave well enough alone here, and make the hue transition, if more accurate shifts are desired, the responsibility of the web designer for defining an extra mid-point

I tried to manually create a rainbow by specifying a dozen HSL points. With fractional hue angle increments. The results weren't satisfactory. The interpolated points still dipped noticeably in saturation and brightness.

I guess I could automate it by creating hundreds of color stops via a CSS preprocessor, but at that point it's easier to embed a SVG data url with linear sRGB interpolation as background.

I still think CIELab would be much easier to work with to get perceptually nice results, but that hasn't gotten much support on the w3-style list either.
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: