v0.4.0

Blend Modes

A blend mode combines the image (the base, A) with a blend layer (B). The layer can be a hex color, a NumPy array the same size as the image (a gradient, a texture, another photo) or anything that broadcasts to it. Every mode takes an optional opacity from 0 to 1. Below, all 14 modes blend #e8743b into the same three photos. Hover a result to see the base photo.Press and hold a result to see the base photo.

Base Photos

The unedited photos that every blend mode below is applied to.

Older man in a white hanbok and black gat hat by a paper window
hanbok-portrait
Gyeonghoeru pavilion reflected in its pond at sunrise
palace-pond
Rows of colorful lotus lanterns over a temple courtyard
lotus-lanterns

Darken Group

The result is never lighter than the base. White is neutral.

Darken

image.darken("#e8743b") min(A, B)
Darken with #e8743b on the hanbok-portrait photobase
hanbok-portrait
Darken with #e8743b on the palace-pond photobase
palace-pond
Darken with #e8743b on the lotus-lanterns photobase
lotus-lanterns

Multiply

image.multiply("#e8743b") A * B
Multiply with #e8743b on the hanbok-portrait photobase
hanbok-portrait
Multiply with #e8743b on the palace-pond photobase
palace-pond
Multiply with #e8743b on the lotus-lanterns photobase
lotus-lanterns

Color Burn

image.color_burn("#e8743b") 1 - (1 - A) / B
Color Burn with #e8743b on the hanbok-portrait photobase
hanbok-portrait
Color Burn with #e8743b on the palace-pond photobase
palace-pond
Color Burn with #e8743b on the lotus-lanterns photobase
lotus-lanterns

Linear Burn

image.linear_burn("#e8743b") A + B - 1
Linear Burn with #e8743b on the hanbok-portrait photobase
hanbok-portrait
Linear Burn with #e8743b on the palace-pond photobase
palace-pond
Linear Burn with #e8743b on the lotus-lanterns photobase
lotus-lanterns

Lighten Group

The result is never darker than the base. Black is neutral.

Lighten

image.lighten("#e8743b") max(A, B)
Lighten with #e8743b on the hanbok-portrait photobase
hanbok-portrait
Lighten with #e8743b on the palace-pond photobase
palace-pond
Lighten with #e8743b on the lotus-lanterns photobase
lotus-lanterns

Screen

image.screen("#e8743b") 1 - (1 - A)(1 - B)
Screen with #e8743b on the hanbok-portrait photobase
hanbok-portrait
Screen with #e8743b on the palace-pond photobase
palace-pond
Screen with #e8743b on the lotus-lanterns photobase
lotus-lanterns

Color Dodge

image.color_dodge("#e8743b") A / (1 - B)
Color Dodge with #e8743b on the hanbok-portrait photobase
hanbok-portrait
Color Dodge with #e8743b on the palace-pond photobase
palace-pond
Color Dodge with #e8743b on the lotus-lanterns photobase
lotus-lanterns

Linear Dodge

image.linear_dodge("#e8743b") A + B
Linear Dodge with #e8743b on the hanbok-portrait photobase
hanbok-portrait
Linear Dodge with #e8743b on the palace-pond photobase
palace-pond
Linear Dodge with #e8743b on the lotus-lanterns photobase
lotus-lanterns

Contrast Group

Darken below mid-gray, lighten above it. 50% gray is neutral for most of these modes.

Overlay

image.overlay("#e8743b") 2AB if A <= 0.5, else 1 - 2(1 - A)(1 - B)
Overlay with #e8743b on the hanbok-portrait photobase
hanbok-portrait
Overlay with #e8743b on the palace-pond photobase
palace-pond
Overlay with #e8743b on the lotus-lanterns photobase
lotus-lanterns

Soft Light

image.soft_light("#e8743b") Pegtop soft light
Soft Light with #e8743b on the hanbok-portrait photobase
hanbok-portrait
Soft Light with #e8743b on the palace-pond photobase
palace-pond
Soft Light with #e8743b on the lotus-lanterns photobase
lotus-lanterns

Hard Light

image.hard_light("#e8743b") 2AB if B <= 0.5, else 1 - 2(1 - A)(1 - B)
Hard Light with #e8743b on the hanbok-portrait photobase
hanbok-portrait
Hard Light with #e8743b on the palace-pond photobase
palace-pond
Hard Light with #e8743b on the lotus-lanterns photobase
lotus-lanterns

Vivid Light

image.vivid_light("#e8743b") Color burn if B <= 0.5, else color dodge
Vivid Light with #e8743b on the hanbok-portrait photobase
hanbok-portrait
Vivid Light with #e8743b on the palace-pond photobase
palace-pond
Vivid Light with #e8743b on the lotus-lanterns photobase
lotus-lanterns

Linear Light

image.linear_light("#e8743b") A + 2B - 1
Linear Light with #e8743b on the hanbok-portrait photobase
hanbok-portrait
Linear Light with #e8743b on the palace-pond photobase
palace-pond
Linear Light with #e8743b on the lotus-lanterns photobase
lotus-lanterns

Pin Light

image.pin_light("#e8743b") Replace A depending on B
Pin Light with #e8743b on the hanbok-portrait photobase
hanbok-portrait
Pin Light with #e8743b on the palace-pond photobase
palace-pond
Pin Light with #e8743b on the lotus-lanterns photobase
lotus-lanterns

Opacity

Opacity mixes the blended result back with the original: overlay("#ff4f8b", opacity=...) on the palace-pond photo.

Overlay at opacity 0
opacity=0
Overlay at opacity 0.25
opacity=0.25
Overlay at opacity 0.5
opacity=0.5
Overlay at opacity 0.75
opacity=0.75
Overlay at opacity 1
opacity=1

Choosing a Blend Color

The same mode gives very different moods depending on the color: soft_light(color) on the hanbok-portrait photo.

Soft Light with #ff6b35
#ff6b35
Soft Light with #ffd23f
#ffd23f
Soft Light with #3bceac
#3bceac
Soft Light with #0ead69
#0ead69
Soft Light with #4361ee
#4361ee
Soft Light with #c42bd8
#c42bd8

Blending with Arrays

Pass a NumPy array instead of a hex string to blend per pixel. The creative effects examples use this for a vignette, a graduated filter and a double exposure.

h, w, _ = image.get_image_as_array().shape
t = np.linspace(0, 1, h)[:, np.newaxis, np.newaxis]  # 0 at the top, 1 at the bottom
gradient = (1 - t) * np.array([1.0, 0.6, 0.3]) + t    # orange fading to white

image.multiply(gradient)  # white is neutral for multiply