facelessuser / coloraide

A library to aid in using colors
https://facelessuser.github.io/coloraide
MIT License
195 stars 12 forks source link

Compositing: channel values use reverse premultiplication #241

Closed facelessuser closed 2 years ago

facelessuser commented 2 years ago

Composition currently works fine as long as you evaluate the values from bottom to top (bottom being the absolute base background, and top being the color layered on the very top), but there is a slight issue.

Premultiplication is applied to every color during composition. Specifically, source-over should be associative, but currently isn't. What this means is that if you group the colors in a way that is not bottom to top (the default when applying the composition to a list of colors) you will get a different answer. Whether all PorterDuff operations are associative I do not know for certain, but it recently came to my attention that source-over should be, and currently isn't.

Why does it not work? This occurs simply because we forget to undo the premultiplication. When evaluating from bottom to top, you'd never know something was wrong. Try to do something complex like isolate a few colors, apply some opacity and apply them on top of another color, you will get a very different result compared to browsers.

Simply remembering to undo premultiplication completely solves this issue.

On a side note, we should clamp any alpha value returned by PorterDuff that exceeds the normal limits. This is also that occurs in browsers that we do not do. It is noticeable when comparing the lighter operation.