Bug 150940

Summary: Gradient color interpolation incorrect for colors with alpha (need to interpolate premultiplied colors)
Product: WebKit Reporter: tmjenox
Component: CSSAssignee: Sam Weinig <sam>
Status: RESOLVED FIXED    
Severity: Normal CC: 7raivis, alexwriter2003, bramus, calum.p.m.smith, darin, dino, gilmoreorless, Hironori.Fujii, jonlee, philip, rik, sam, simon.fraser, tym46383, webkit-bug-importer, zyuzin.vitaly
Priority: P2 Keywords: InRadar
Version: Safari 9   
Hardware: All   
OS: All   
See Also: https://bugs.webkit.org/show_bug.cgi?id=212442
Bug Depends on: 234492, 234653    
Bug Blocks:    
Attachments:
Description Flags
example
none
Enable premultiplied interpolation for CSS gradients by default none

tmjenox
Reported 2015-11-05 13:06:04 PST
Currently the following gradients produce different results despite they should render the same: - opaque black to transparent black - opaque black to transparent white - opaque black to transparent anything All transparent anythings are in fact the same color, a clear color, no matter what the underlying RGB components say. It seems all four components are currently linearly interpolated, resulting in a very odd gradient -- the second one has a semitransparent gray in the middle. For semitransparent endpoint colors we have the same issue: their RBG components affect the interpolated colors too much, in an unnatural way. No matter in which color space colors are interpolated, their components should be weighted according to their alpha component. Firefox seems to use the following weighted approach, producing a much more visually appealing gradient: float r3 = (r1 * a1 * (1.0 - fraction) + r2 * a2 * fraction) / ((1.0 - fraction) * a1 + fraction * a2); float g3 = (g1 * a1 * (1.0 - fraction) + g2 * a2 * fraction) / ((1.0 - fraction) * a1 + fraction * a2); float b3 = (b1 * a1 * (1.0 - fraction) + b2 * a2 * fraction) / ((1.0 - fraction) * a1 + fraction * a2); float a3 = a1 * (1.0 - fraction) + a2 * fraction;
Attachments
example (249 bytes, text/html)
2020-04-11 10:40 PDT, Alexey Proskuryakov
no flags
Enable premultiplied interpolation for CSS gradients by default (1.55 KB, patch)
2021-12-23 16:37 PST, Sam Weinig
no flags
Simon Fraser (smfr)
Comment 1 2015-11-05 21:23:22 PST
This is because we don't interpolate gradients in non-premultiplied colors, because CG can't do this yet.
tmjenox
Comment 2 2015-11-06 03:17:46 PST
What do you mean by 'CG can't do this yet'? It is obviously possible... (In reply to comment #1) > This is because we don't interpolate gradients in non-premultiplied colors, > because CG can't do this yet.
Darin Adler
Comment 3 2015-11-06 08:22:12 PST
The OS X and iOS graphics framework, Core Graphics, that WebKit uses to draw on those operating systems has a gradient feature that does not have a mode where it properly handles this. If we wanted to fix this problem in WebKit without waiting for the Core Graphics we would have to write a new gradient implementation that bypasses the Core Graphics Framework. Our plan is to instead ask Apple to add this feature to the Core Graphics framework.
tmjenox
Comment 4 2015-11-06 08:37:58 PST
(In reply to comment #3) > The OS X and iOS graphics framework, Core Graphics, that WebKit uses to draw > on those operating systems has a gradient feature that does not have a mode > where it properly handles this. If we wanted to fix this problem in WebKit > without waiting for the Core Graphics we would have to write a new gradient > implementation that bypasses the Core Graphics Framework. Our plan is to > instead ask Apple to add this feature to the Core Graphics framework. Ah, I see. So is this a known/confirmed issue? One may argue for both approaches of drawing such a gradient. How does the collaboration with Apple work in such scenarios? Who even decides who's right and who's wrong? Is there a specification on how these gradients should be drawn?
Darin Adler
Comment 5 2015-11-06 08:49:10 PST
(In reply to comment #4) > So is this a known/confirmed issue? Yes. Simon personally contacted the team at Apple responsible for Core Graphics, a while back, to let them know about this issue.
Simon Fraser (smfr)
Comment 6 2015-11-06 08:52:44 PST
(In reply to comment #4) > How does the collaboration with Apple work in such scenarios? Who even > decides who's right and who's wrong? Is there a specification on how these > gradients should be drawn? This is specified by CSS: <https://drafts.csswg.org/css-images/#gradients> "with the interpolation taking place in premultiplied RGBA space" but that text is expected to change once Mac and iOS can support interpolation in non-premultiplied.
tmjenox
Comment 7 2015-11-06 09:49:27 PST
> "with the interpolation taking place in premultiplied RGBA space" > but that text is expected to change once Mac and iOS can support > interpolation in non-premultiplied. Mh, I'm a little confused now as I'm not quite familiar with this terminology. Is interpolation in premultiplied RGBA what we are seeing now or what would be the correct thing to do? Why would that text change once Core Graphics decides to ship a fix for this bug?
Simon Fraser (smfr)
Comment 8 2015-11-06 10:38:33 PST
(In reply to comment #7) > > "with the interpolation taking place in premultiplied RGBA space" > > > but that text is expected to change once Mac and iOS can support > > interpolation in non-premultiplied. > > Mh, I'm a little confused now as I'm not quite familiar with this > terminology. Is interpolation in premultiplied RGBA what we are seeing now > or what would be the correct thing to do? That's what you're seeing now. Transparent red in premultiplied color just becomes transparent, so any time you interpolate from it you end up with grayish intermediate values. > Why would that text change once Core Graphics decides to ship a fix for this bug? Because all browsers would then be able to interpolate in non-premultiplied color, and the CSS working group would change the text (at least for the next level of the spec).
tmjenox
Comment 9 2015-11-06 10:58:58 PST
> > Mh, I'm a little confused now as I'm not quite familiar with this > > terminology. Is interpolation in premultiplied RGBA what we are seeing now > > or what would be the correct thing to do? > > That's what you're seeing now. Transparent red in premultiplied color just > becomes transparent, so any time you interpolate from it you end up with > grayish intermediate values. Sorry if this is really obvious and I am missing something, but that makes only little sense to me. I am currently seeing this behavior in Safari: [opaque black (0,0,0,1)] => [semitransparent dark red (128,0,0,0.5)] => [transparent red (255,0,0,0)] (all components interpolated linearly) However, I think it should look like this: (and it does in Firefox) [opaque black (0,0,0,1)] => [semitransparent black (0,0,0,0.5)] => [transparent black (0,0,0,0)] (color components weighted with alpha) Your description ("so any time you interpolate from it you end up with grayish intermediate values") sounds like the latter is what you call interpolation in premultiplied RGBA, however you are also stating that what I am currently seeing is interpolation in premultiplied RGBA... Could you please clear this up? Which of the two examples is interpolated in premultiplied RGBA? And how is the other method called?
Simon Fraser (smfr)
Comment 10 2016-04-01 13:13:13 PDT
*** Bug 156105 has been marked as a duplicate of this bug. ***
Radar WebKit Bug Importer
Comment 11 2016-04-01 13:59:08 PDT
Binyamin
Comment 12 2017-01-11 11:30:54 PST
Any progress with this?
Alexey Proskuryakov
Comment 13 2020-04-11 10:38:52 PDT
*** Bug 210365 has been marked as a duplicate of this bug. ***
Alexey Proskuryakov
Comment 14 2020-04-11 10:40:22 PDT
Philip Jägenstedt
Comment 15 2020-04-16 01:48:25 PDT
This issue was mentioned to me while interviewing web developers about browser compat issues. I found this test in web-platform-tests which I think covers the behavior and is failing only in Safari: https://wpt.fyi/results/css/css-images/gradients-with-transparent.html?run_id=488890002&run_id=483120004&run_id=505970001 Is this still blocked on Core Graphics not supporting it?
Philip Jägenstedt
Comment 16 2020-04-16 01:58:57 PDT
I also found bug 200208, which is about the specific failure I found.
Darin Adler
Comment 17 2020-04-16 09:46:14 PDT
(In reply to Philip Jägenstedt from comment #15) > Is this still blocked on Core Graphics not supporting it? Yes.
Fujii Hironori
Comment 18 2021-12-21 13:43:40 PST
*** This bug has been marked as a duplicate of bug 234492 ***
Sam Weinig
Comment 19 2021-12-21 17:43:57 PST
Keeping this open for a moment, since we still have not enabled it yet. We need to decide what perf cost is acceptable for older platforms, and if we should add any additional optimizations like all opaque checking or the extension of that Dan suggested in https://bugs.webkit.org/show_bug.cgi?id=234492#c19.
Sam Weinig
Comment 20 2021-12-23 16:37:11 PST
Created attachment 447917 [details] Enable premultiplied interpolation for CSS gradients by default
EWS
Comment 21 2021-12-23 20:24:49 PST
Committed r287419 (245554@main): <https://commits.webkit.org/245554@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 447917 [details].
Note You need to log in before you can comment on or make changes to this bug.