Skip to content

Compositing and Blending

Alpha compositing and blending are tied together under the umbrella of compositing. Each is just an aspect of the overall compositing of colors. Compositing simply controls how colors are resolved when they are layered on top of each other.

ColorAide implements both alpha compositing and blending as described in the Compositing and Blending Level 1 specification. Alpha composting is based on Porter Duff compositing. By default, the layer method is used to layer colors on top of each other applying the appropriate compositing, using the normal blend mode and the source-over Porter Duff operator by default.

Deprecated 4.0

compose method was deprecated in favor of the new layer method and will be removed at some future time.

New in 4.0

A new layer method was added which uses a more intuitive name and aligns with how multiple colors are handled in other similar APIs such as average(), interpolate(), etc.

Blending

Blending is the aspect of compositing that calculates the mixing of colors where the source element and backdrop overlap. Conceptually, the colors in the source element (top layer) are blended in place with the backdrop (bottom layer).

There are various blend modes, the most common is the normal blend mode which is the default blending mode for browsers. The normal blend mode simply returns the top layer's color when one is overlaid onto another.

But there are many blend modes that could be used, all of which yield different results. If we were to apply a multiply blend mode, we would get something very different:

When layering colors, the blend mode can be controlled separately in ColorAide. Below, we use the multiply example and replicate it in ColorAide. To apply various blend modes in ColorAide, simply call layer with a list of colors. Colors will be layered on top of each other where the left most color is on top and the right most color will be on the bottom.

>>> c1 = Color('#07c7ed')
>>> c2 = Color('#fc3d99')
>>> c1, c2
(color(srgb 0.02745 0.78039 0.92941 / 1), color(srgb 0.98824 0.23922 0.6 / 1))
>>> Color.layer([c1, c2], blend='multiply', space="display-p3")
color(display-p3 0.32281 0.23703 0.54084 / 1)
>>> c1 = Color('#07c7ed')
>>> c2 = Color('#fc3d99')
>>> c1, c2
(color(srgb 0.02745 0.78039 0.92941 / 1), color(srgb 0.98824 0.23922 0.6 / 1))
>>> Color.layer([c1, c2], blend='multiply', space="srgb")
color(srgb 0.02713 0.18668 0.55765 / 1)

Tip

layer() can output the results in any color space you need by setting out_space.

>>> Color.layer(['#07c7ed', '#fc3d99'], blend='multiply', space='srgb', out_space='hsl')
color(--hsl 221.95 0.90722 0.29239 / 1)

Display Differences

As some browsers apply compositing based on the display's current color space, we've provided examples in both sRGB and Display P3 so that the examples can be compared on different displays. Which of the above matches your browser?

ColorAide allows for layering any number of colors as well, simply list of as many colors as you like ordered from left to right, left being the top most color.

>>> c1 = Color('#07c7ed')
>>> c2 = Color('#fc3d99')
>>> c3 = Color('#f5d311')
>>> c1, c2, c3
(color(srgb 0.02745 0.78039 0.92941 / 1), color(srgb 0.98824 0.23922 0.6 / 1), color(srgb 0.96078 0.82745 0.06667 / 1))
>>> Color.layer([c1, c2, c3], blend='multiply', space="display-p3")
color(display-p3 0.3031 0.19729 0.15625 / 1)
>>> c1 = Color('#07c7ed')
>>> c2 = Color('#fc3d99')
>>> c3 = Color('#f5d311')
>>> c1, c2, c3
(color(srgb 0.02745 0.78039 0.92941 / 1), color(srgb 0.98824 0.23922 0.6 / 1), color(srgb 0.96078 0.82745 0.06667 / 1))
>>> Color.layer([c1, c2, c3], blend='multiply', space="srgb")
color(srgb 0.02606 0.15447 0.03718 / 1)

Lastly, if for any reason, it is desired to layer the colors with the blending step disabled (e.g. just run alpha compositing), then you can simply set blend to False.

multiply is just one of many blend modes that are offered in ColorAide, check out Blend Modes to learn about other blend modes.

Alpha Compositing

Alpha compositing or alpha blending is the process of combining one image with a background to create the appearance of partial or full transparency.

When dealing with layers, there are many possible ways to handle them:

Alpha Composition

Porter Duff compositing covers all possible configurations of layers. Many of these configurations can be useful for all sorts of operations, such as masking. While this library supports all of them, the most commonly used one is source-over which is used to implement simple alpha compositing to simulate semi-transparent layers on top of each other.

Given two colors layered on top of each other, ColorAide can replicate this behavior and determine the resultant color by applying alpha compositing. We will use the demonstration above and replicate the result in the example below by setting the source color to rgb(7 199 237 / 0.5) and the backdrop color to #fc3d99 and then running it through the layer method.

>>> c1 = Color('#07c7ed').set('alpha', 0.5)
>>> c2 = Color('#fc3d99')
>>> c1, c2
(color(srgb 0.02745 0.78039 0.92941 / 0.5), color(srgb 0.98824 0.23922 0.6 / 1))
>>> Color.layer([c1, c2], space="display-p3")
color(display-p3 0.63261 0.53855 0.75261 / 1)
>>> c1 = Color('#07c7ed').set('alpha', 0.5)
>>> c2 = Color('#fc3d99')
>>> c1, c2
(color(srgb 0.02745 0.78039 0.92941 / 0.5), color(srgb 0.98824 0.23922 0.6 / 1))
>>> Color.layer([c1, c2], space="srgb")
color(srgb 0.50784 0.5098 0.76471 / 1)

Display Differences

As some browsers apply compositing based on the display's current color space, we've provided examples in both sRGB and Display P3 so that the examples can be compared on different displays. Which of the above matches your browser?

While the average user will be content with the default alpha compositing, Porter Duff offers many other configurations. If desired, we can change the Porter Duff operator used and apply different composite logic. For instance, in this case we can get the resultant of the backdrop over the source color by setting the operator to destination-over. As the backdrop is fully opaque, we just get the backdrop color unaltered.

>>> c1 = Color('#07c7ed').set('alpha', 0.5)
>>> c2 = Color('#fc3d99')
>>> c1, c2
(color(srgb 0.02745 0.78039 0.92941 / 0.5), color(srgb 0.98824 0.23922 0.6 / 1))
>>> Color.layer([c1, c2], operator='destination-over', space="display-p3")
color(display-p3 0.91078 0.30832 0.59266 / 1)
>>> c1 = Color('#07c7ed').set('alpha', 0.5)
>>> c2 = Color('#fc3d99')
>>> c1, c2
(color(srgb 0.02745 0.78039 0.92941 / 0.5), color(srgb 0.98824 0.23922 0.6 / 1))
>>> Color.layer([c1, c2], operator='destination-over', space="srgb")
color(srgb 0.98824 0.23922 0.6 / 1)

You can also apply alpha compositing to multiple layers at once. Simply send in a list of colors of any length, and the colors will be layered on top of each other from right to left with the right most color being on the bottom of the stack and the left color (the source) being on the very top.

Here we are using the normal blend mode and 50% transparency on all the circles with an opaque white background. We will calculate the center color where all three layers overlap.

>>> c1 = Color('#07c7ed').set('alpha', 0.5)
>>> c2 = Color('#fc3d99').set('alpha', 0.5)
>>> c3 = Color('#f5d311').set('alpha', 0.5)
>>> bg = Color('white')
>>> c1, c2, c3, bg
(color(srgb 0.02745 0.78039 0.92941 / 0.5), color(srgb 0.98824 0.23922 0.6 / 0.5), color(srgb 0.96078 0.82745 0.06667 / 0.5), color(srgb 1 1 1 / 1))
>>> Color.layer([c1, c2, c3, bg], blend='normal', space="display-p3")
color(display-p3 0.64728 0.69051 0.76555 / 1)
>>> c1 = Color('#07c7ed').set('alpha', 0.5)
>>> c2 = Color('#fc3d99').set('alpha', 0.5)
>>> c3 = Color('#f5d311').set('alpha', 0.5)
>>> bg = Color('white')
>>> c1, c2, c3, bg
(color(srgb 0.02745 0.78039 0.92941 / 0.5), color(srgb 0.98824 0.23922 0.6 / 0.5), color(srgb 0.96078 0.82745 0.06667 / 0.5), color(srgb 1 1 1 / 1))
>>> Color.layer([c1, c2, c3, bg], blend='normal', space="srgb")
color(srgb 0.50588 0.67843 0.74804 / 1)

Lastly, if for any reason, it is desired to layer colors with alpha compositing disabled (e.g. just run blending), then you can simply set operator to False.

Check out Compositing Operators to learn about the many variations that are supported.

Complex Compositing

We've covered alpha compositing and blending and have demonstrated their use with simple two color examples and multi-layered examples, but what about different blend modes mixed with alpha compositing?

In this example, we will consider three circles, each with a unique color: #07c7ed, #fc3d99, and #f5d311. We apply 50% transparency to all the circles and place them on a white background. We then perform a multiply blend on all the circles but isolate them so the multiply blend does not apply to the background. The circles are all represented with CSS. We will now try and replicate the colors with ColorAide.

So in the code below, we work our way from the bottom of the stack to the top. Since the background is isolated from the multiply blending, in each region, we start by performing a normal blend on the bottom circle against the background. We then apply multiply blending on each color that is stacked on top. We've provided both the P3 and sRGB outputs to make it easy to compare in case your browser blends in one instead of the other.

>>> c1 = Color('#07c7ed').set('alpha', 0.5)
>>> c2 = Color('#fc3d99').set('alpha', 0.5)
>>> c3 = Color('#f5d311').set('alpha', 0.5)
>>> cw2 = Color.layer([c2, 'white'], blend='normal', space='display-p3')
>>> cw3 = Color.layer([c3, 'white'], blend='normal', space='display-p3')
>>> r1 = Color.layer([c2, cw3], blend='multiply', space='display-p3')
>>> r2 = Color.layer([c1, cw2], blend='multiply', space='display-p3')
>>> r3 = Color.layer([c1, cw3], blend='multiply', space='display-p3')
>>> r1, r2, r3
(color(display-p3 0.92621 0.59932 0.5132 / 1), color(display-p3 0.64701 0.57853 0.76151 / 1), color(display-p3 0.65654 0.81024 0.61627 / 1))
>>> Color.layer([c1, c2, cw3], blend='multiply', space='display-p3')
color(display-p3 0.62725 0.53003 0.49076 / 1)
>>> c1 = Color('#07c7ed').set('alpha', 0.5)
>>> c2 = Color('#fc3d99').set('alpha', 0.5)
>>> c3 = Color('#f5d311').set('alpha', 0.5)
>>> cw2 = Color.layer([c2, 'white'], blend='normal', space='srgb')
>>> cw3 = Color.layer([c3, 'white'], blend='normal', space='srgb')
>>> r1 = Color.layer([c2, cw3], blend='multiply', space='srgb')
>>> r2 = Color.layer([c1, cw2], blend='multiply', space='srgb')
>>> r3 = Color.layer([c1, cw3], blend='multiply', space='srgb')
>>> r1, r2, r3
(color(srgb 0.97463 0.56615 0.42667 / 1), color(srgb 0.5107 0.55157 0.77176 / 1), color(srgb 0.50365 0.81339 0.51451 / 1))
>>> Color.layer([c1, c2, cw3], blend='multiply', space='srgb')
color(srgb 0.50069 0.50399 0.41161 / 1)

Results may vary depending on the browser, but we can see (ignoring rounding differences) that the colors match up. This was performed on Chrome in macOS using a display that uses display-p3.

Color Meter

Blend Modes

Normal

The blending formula simply selects the source color.

Specified as 'normal'.


Multiply

The source color is multiplied by the destination color and replaces the destination. The resultant color is always at least as dark as either the source or destination color. Multiplying any color with black results in black. Multiplying any color with white preserves the original color.

Specified as 'multiply'.


Screen

Multiplies the complements of the backdrop and source color values, then complements the result. The result color is always at least as light as either of the two constituent colors. Screening any color with white produces white; screening with black leaves the original color unchanged. The effect is similar to projecting multiple photographic slides simultaneously onto a single screen.

Specified as 'screen'.


Overlay

Multiplies or screens the colors, depending on the backdrop color value. Source colors overlay the backdrop while preserving its highlights and shadows. The backdrop color is not replaced but is mixed with the source color to reflect the lightness or darkness of the backdrop.

Specified as 'overlay'.


Darken

Selects the darker of the backdrop and source colors. The backdrop is replaced with the source where the source is darker; otherwise, it is left unchanged.

Specified as 'darken'.


Lighten

Selects the lighter of the backdrop and source colors. The backdrop is replaced with the source where the source is lighter; otherwise, it is left unchanged.

Specified as 'lighten'.


Color Dodge

Brightens the backdrop color to reflect the source color. Painting with black produces no changes.

Specified as 'color-dodge'.


Color Burn

Darkens the backdrop color to reflect the source color. Painting with white produces no change.

Specified as 'color-burn'.


Hard Light

Multiplies or screens the colors, depending on the source color value. The effect is similar to shining a harsh spotlight on the backdrop.

Specified as 'hard-light'.


Soft Light

Darkens or lightens the colors, depending on the source color value. The effect is similar to shining a diffused spotlight on the backdrop.

Specified as 'soft-light'.


Difference

Subtracts the darker of the two constituent colors from the lighter color. Painting with white inverts the backdrop color; painting with black produces no change.

Specified as 'difference'.


Exclusion

Produces an effect similar to that of the Difference mode but lower in contrast. Painting with white inverts the backdrop color; painting with black produces no change.

Specified as 'exclusion'.


Hue

Creates a color with the hue of the source color and the saturation and luminosity of the backdrop color.

Specified as 'hue'.


Saturation

Creates a color with the saturation of the source color and the hue and luminosity of the backdrop color. Painting with this mode in an area of the backdrop that is a pure gray (no saturation) produces no change.

Specified as 'saturation'.


Luminosity

Creates a color with the luminosity of the source color and the hue and saturation of the backdrop color. This produces an inverse effect to that of the Color mode. This mode is the one you can use to create monochrome "tinted" image effects like the ones you can see in different website headers.

Specified as 'luminosity'.


Color

Creates a color with the hue and saturation of the source color and the luminosity of the backdrop color. This preserves the gray levels of the backdrop and is useful for coloring monochrome images or tinting color images.

Specified as 'color'.

Compositing Operators

Clear

No regions are enabled.

Source Destination Result
Source Destination Clear

Specified as 'clear'.

Copy

Only the source will be present.

Source Destination Result
Source Destination Copy

Specified as 'copy'.

Destination

Only the destination will be present.

Source Destination Result
Source Destination Destination

Specified as 'destination'.

Source Over

Source is placed over the destination.

Source Destination Result
Source Destination Source Over

Specified as 'source-over'.

Destination Over

Destination is placed over the source.

Source Destination Result
Source Destination Destination Over

Specified as 'destination-over'.

Source In

The source that overlaps the destination, replaces the destination.

Source Destination Result
Source Destination Source In

Specified as 'source-in'.

Destination In

Destination which overlaps the source, replaces the source.

Source Destination Result
Source Destination Destination In

Specified as 'destination-in'.

Source Out

Source is placed, where it falls outside of the destination.

Source Destination Result
Source Destination Source Out

Specified as 'source-out'.

Destination Out

Destination is placed, where it falls outside of the source.

Source Destination Result
Source Destination Destination Out

Specified as 'destination-out'.

Source Atop

Source which overlaps the destination, replaces the destination. Destination is placed elsewhere.

Source Destination Result
Source Destination Source Atop

Specified as 'source-atop'.

Destination Atop

Destination which overlaps the source replaces the source. Source is placed elsewhere.

Source Destination Result
Source Destination Destination Atop

Specified as 'destination-atop'.

XOR

Destination which overlaps the source replaces the source. Source is placed elsewhere.

Source Destination Result
Source Destination XOR

Specified as 'xor'.

Lighter

Display the sum of the source image and destination image.

Source Destination Result
Source Destination Lighter

Specified as 'lighter'.