-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Functions for composing colors #21
Comments
I concur we should add color combinators. Their choice and implementation should be done carefully, however. In particular, to account for the human perception of colors, blending ought to be done in a linear color space (e.g., sRGB with a linear transfer function) and not directly on the coordinates of a color model like RGB or HSV. The Colour Haskell library can serve as a good source of inspiration, although the explanations in the documentation could use better clarity. Porter's 1984 paper "Composing Digital Images" is also a classic and gives historical names to some of the combinators suggested above. Skia itself offers several blend modes and implements several color spaces we should be able to leverage (without getting crazy ourselves). I'm not particularly convinced about adding the selector to access the coordinates. There are definitely legitimate use cases, but it would leave users with the complex task of doing such calculations, and would also not be on par with the treatment we are giving to graphics (which cannot be destructured). If we pick the right choice of basic color combinators, on top of those combinators users could build theirs when occasionally needed, perfectly following PyTamaro's spirit. |
I knew about the Haskell
I don't really understand yet why one needs to gamma-correct before mixing two colors. E.g., why is taking the weighted average of all the color's components, with code similar to the following, not appropriate? def blend(w: float, ca: Color, cb: Color) -> Color:
return hsv_color(
hsv_hue(ca) * w + hsv_hue(cb) * (1 - w),
hsv_saturation(ca) * w + hsv_saturation(cb) * (1 - w),
hsv_value(ca) * w + hsv_value(cb) * (1 - w),
color_opacity(ca) * w + color_opacity(cb) * (1 - w)
) Maybe once I read the Porter paper this will clear up that need to transform to a color space that's different? |
Currently we have functions to create colors (e.g.,
hsv_color
), and we have graphics function that use colors, but we have no function that combine colors.I suggest to add functions to access the components (of different color spaces) of a Color:
rgb_red(color: Color) -> int
rgb_green(color: Color) -> int
rgb_blue(color: Color) -> int
hsv_hue(color: Color) -> float
hsv_saturation(color: Color) -> float
hsv_value(color: Color) -> float
hsl_hue(color: Color) -> float
(the same ashsv_hue
)hsl_saturation(color: Color) -> float
(NOT the same ashsv_saturation
)hsl_lightness(color: Color) -> float
color_opacity(color: Color) -> int
These functions would allow it for users to create their own color combinators and converters.
Moreover, similar to having a
beside
,above
, andoverlay
, in addition tocompose
, we should have a couple of key high-level color combinators:blend(weightA: float, colorA: Color, colorB: Color) -> Color
-- this mixes the two colors (within the HSV color space to produce nice results) -- this can be used to do nice gradientsdarken(factor: float, color: Color) -> Color
-- this produces a darker/brighter version (not sure about the name) by multiplying the lightnesstranslucent(alpha: int, color: Color) -> Color
-- this produces a more or less transparent/opaque version of the given colorCurrently, if we want to create a function that takes a color, but we want to then produce multiple shades of that color (e.g., to produce a darker/briger version for shadows or highlights), we cannot do that. We have to pass the components of the color around (e.g., hue, saturation, lightness), with is counter to the idea of having a type for colors.
The text was updated successfully, but these errors were encountered: