Color Blending

Colorium provides powerful color blending capabilities for creating new colors by combining existing ones. This guide covers all blending operations.

Basic Blending

Simple Linear Blend

The most common blending method using a ratio.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from colorium import Color, RED, BLUE, WHITE, YELLOW

# Equal blend (50/50)
purple = RED.blend(BLUE, 0.5)
print(purple.to_hex_string())  # #7F007F

# Different ratios
pink = RED.blend(WHITE, 0.7)   # 70% white
orange = RED.blend(YELLOW, 0.4) # 40% yellow

# Custom colors
color1 = Color(255, 100, 50)
color2 = Color(50, 100, 255)
result = color1.blend(color2, 0.3)

Blend with Opacity

Blending preserves opacity.

1
2
3
4
5
6
7
8
from colorium import Color

color1 = Color(255, 0, 0, 0.5)   # Semi-transparent red
color2 = Color(0, 0, 255, 0.5)   # Semi-transparent blue

# Blend with opacity
result = color1.blend(color2, 0.5)
print(result.opacity)  # 0.5 (average of opacities)

Advanced Blending

Multiple Color Blend

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from colorium import Color

def blend_colors(colors, ratios):
    """Blend multiple colors with custom ratios"""
    if len(colors) != len(ratios):
        raise ValueError("Number of colors must match ratios")

    total_r = total_g = total_b = 0
    total_ratio = sum(ratios)

    for color, ratio in zip(colors, ratios):
        weight = ratio / total_ratio
        total_r += color.red * weight
        total_g += color.green * weight
        total_b += color.blue * weight

    return Color(int(total_r), int(total_g), int(total_b))

# Blend three colors
colors = [Color(255, 0, 0), Color(0, 255, 0), Color(0, 0, 255)]
ratios = [0.4, 0.3, 0.3]
result = blend_colors(colors, ratios)

Gradient Generation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from colorium import Color

def create_gradient(start_color, end_color, steps=10):
    """Create a smooth gradient between two colors"""
    gradient = []
    for i in range(steps):
        ratio = i / (steps - 1)
        color = start_color.blend(end_color, ratio)
        gradient.append(color)
    return gradient

def multi_stop_gradient(colors, steps_per_segment=10):
    """Create a gradient with multiple color stops"""
    if len(colors) < 2:
        return colors

    result = []
    for i in range(len(colors) - 1):
        segment = create_gradient(colors[i], colors[i+1], steps_per_segment)
        if i > 0:
            segment = segment[1:]  # Avoid duplicate stops
        result.extend(segment)

    return result

# Simple gradient
gradient = create_gradient(
    Color(255, 0, 0),
    Color(0, 0, 255),
    10
)

# Multi-stop gradient
rainbow_colors = [
    Color(255, 0, 0),    # Red
    Color(255, 165, 0),  # Orange
    Color(255, 255, 0),  # Yellow
    Color(0, 255, 0),    # Green
    Color(0, 0, 255),    # Blue
    Color(75, 0, 130)    # Indigo
]
rainbow = multi_stop_gradient(rainbow_colors, 8)

Blending Modes

Weighted Blend

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from colorium import Color

def weighted_blend(color1, color2, weight1=0.5, weight2=0.5):
    """Blend with custom weights for each color"""
    total = weight1 + weight2
    r = (color1.red * weight1 + color2.red * weight2) / total
    g = (color1.green * weight1 + color2.green * weight2) / total
    b = (color1.blue * weight1 + color2.blue * weight2) / total
    a = (color1.opacity * weight1 + color2.opacity * weight2) / total

    return Color(int(r), int(g), int(b), a)

# More weight on first color
result = weighted_blend(
    Color(255, 0, 0),
    Color(0, 0, 255),
    weight1=0.7,
    weight2=0.3
)

Screen Blend

1
2
3
4
5
6
7
8
9
from colorium import Color

def screen_blend(color1, color2):
    """Screen blending mode (lighter result)"""
    r = 255 - ((255 - color1.red) * (255 - color2.red) / 255)
    g = 255 - ((255 - color1.green) * (255 - color2.green) / 255)
    b = 255 - ((255 - color1.blue) * (255 - color2.blue) / 255)

    return Color(int(r), int(g), int(b))

Multiply Blend

1
2
3
4
5
6
7
8
9
from colorium import Color

def multiply_blend(color1, color2):
    """Multiply blending mode (darker result)"""
    r = (color1.red * color2.red) / 255
    g = (color1.green * color2.green) / 255
    b = (color1.blue * color2.blue) / 255

    return Color(int(r), int(g), int(b))

Overlay Blend

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from colorium import Color

def overlay_blend(color1, color2):
    """Overlay blending mode"""
    def overlay_channel(c1, c2):
        if c1 < 128:
            return (2 * c1 * c2) / 255
        else:
            return 255 - (2 * (255 - c1) * (255 - c2) / 255)

    r = overlay_channel(color1.red, color2.red)
    g = overlay_channel(color1.green, color2.green)
    b = overlay_channel(color1.blue, color2.blue)

    return Color(int(r), int(g), int(b))

Practical Examples

Color Palette Generation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from colorium import Color, from_string

def generate_palette(base_color, count=5):
    """Generate a monochromatic palette"""
    palette = []
    for i in range(count):
        lightness = 0.2 + (i / (count - 1)) * 0.6
        color = base_color.clone()
        color.lightness = lightness
        palette.append(color)
    return palette

def generate_complementary_palette(base_color, count=3):
    """Generate complementary palette"""
    hsl = base_color.to_hsl()
    from colorium import from_hsl

    palette = []
    for i in range(count):
        hue = (hsl['h'] + i * 60) % 360
        color = from_hsl(hue, hsl['s'], hsl['l'])
        palette.append(color)
    return palette

# Create palettes
base = from_string("blue")
mono = generate_palette(base, 5)
comp = generate_complementary_palette(base, 6)

print("Monochromatic palette:")
for color in mono:
    print(f"  {color.to_hex_string()}")

print("\nComplementary palette:")
for color in comp:
    print(f"  {color.to_hex_string()}")

Theme Generation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
from colorium import Color, from_hsl

def generate_theme(base_color):
    """Generate a complete color theme"""
    hsl = base_color.to_hsl()
    from colorium import from_hsl

    # Complementary
    comp_hue = (hsl['h'] + 180) % 360
    complementary = from_hsl(comp_hue, hsl['s'], hsl['l'])

    # Analogous (30° apart)
    analogous = [
        from_hsl((hsl['h'] - 30) % 360, hsl['s'], hsl['l']),
        base_color,
        from_hsl((hsl['h'] + 30) % 360, hsl['s'], hsl['l'])
    ]

    # Triadic (120° apart)
    triadic = [
        from_hsl(hsl['h'], hsl['s'], hsl['l']),
        from_hsl((hsl['h'] + 120) % 360, hsl['s'], hsl['l']),
        from_hsl((hsl['h'] + 240) % 360, hsl['s'], hsl['l'])
    ]

    # Shades (different lightness)
    shades = [
        from_hsl(hsl['h'], hsl['s'], 0.2),
        from_hsl(hsl['h'], hsl['s'], 0.4),
        from_hsl(hsl['h'], hsl['s'], 0.6),
        from_hsl(hsl['h'], hsl['s'], 0.8)
    ]

    return {
        'base': base_color,
        'complementary': complementary,
        'analogous': analogous,
        'triadic': triadic,
        'shades': shades
    }

# Generate theme from red
theme = generate_theme(Color(255, 0, 0))

print("Theme:")
print(f"Base: {theme['base'].to_hex_string()}")
print(f"Complementary: {theme['complementary'].to_hex_string()}")
print("Analogous:")
for color in theme['analogous']:
    print(f"  {color.to_hex_string()}")

Gradient Examples

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from colorium import Color

def display_gradient(gradient):
    """Display a gradient as a color bar"""
    for color in gradient:
        bar = "█" * 10
        print(f"{color.to_hex_string()} {bar}")

# Warm to cool gradient
warm_to_cool = create_gradient(
    Color(255, 100, 0),
    Color(0, 100, 255),
    15
)

print("Warm to Cool:")
display_gradient(warm_to_cool)

# Pastel gradient
pastels = create_gradient(
    Color(255, 200, 200),
    Color(200, 200, 255),
    10
)

print("\nPastel Gradient:")
display_gradient(pastels)

# Vibrant gradient
vibrant = create_gradient(
    Color(255, 0, 0),
    Color(0, 255, 255),
    20
)

print("\nVibrant Gradient:")
display_gradient(vibrant)

Advanced Blending Techniques

Gaussian Blend

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from colorium import Color
import math

def gaussian_blend(color1, color2, center=0.5, spread=0.2):
    """Gaussian weighted blend"""
    def gaussian(x, mu, sigma):
        return math.exp(-((x - mu) ** 2) / (2 * sigma ** 2))

    # Sample multiple points and blend
    steps = 10
    result = Color(0, 0, 0)
    total_weight = 0

    for i in range(steps + 1):
        t = i / steps
        weight = gaussian(t, center, spread)
        sample = color1.blend(color2, t)

        result = Color(
            int(result.red + sample.red * weight),
            int(result.green + sample.green * weight),
            int(result.blue + sample.blue * weight)
        )
        total_weight += weight

    # Normalize
    result = Color(
        int(result.red / total_weight),
        int(result.green / total_weight),
        int(result.blue / total_weight)
    )

    return result

Perceptual Blend

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from colorium import Color
from colorium.converters import rgb_to_oklch, oklch_to_rgb

def perceptual_blend(color1, color2, ratio=0.5):
    """Blend in perceptual color space (OKLCH)"""
    # Convert to OKLCH
    oklch1 = rgb_to_oklch(color1.red, color1.green, color1.blue)
    oklch2 = rgb_to_oklch(color2.red, color2.green, color2.blue)

    # Interpolate in OKLCH space
    l = oklch1['l'] * (1 - ratio) + oklch2['l'] * ratio
    c = oklch1['c'] * (1 - ratio) + oklch2['c'] * ratio

    # Handle hue interpolation
    h1 = oklch1['h']
    h2 = oklch2['h']
    # Take shortest path around color wheel
    if abs(h2 - h1) > 180:
        if h2 > h1:
            h1 += 360
        else:
            h2 += 360
    h = (h1 * (1 - ratio) + h2 * ratio) % 360

    # Convert back to RGB
    rgb = oklch_to_rgb(l, c, h)
    return Color(rgb['r'], rgb['g'], rgb['b'])

Performance Tips

Batch Blending

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from colorium import Color

def batch_blend(base_color, target_colors, ratio=0.5):
    """Blend base color with multiple colors"""
    return [base_color.blend(color, ratio) for color in target_colors]

base = Color(100, 150, 200)
targets = [
    Color(255, 0, 0),
    Color(0, 255, 0),
    Color(0, 0, 255)
]

results = batch_blend(base, targets)
for original, blended in zip(targets, results):
    print(f"{original.to_hex_string()}{blended.to_hex_string()}")

Reuse Blend Results

1
2
3
4
5
6
# Good - reuse result
blended = color1.blend(color2, 0.5)
use_result(blended)

# Avoid - recalculate
use_result(color1.blend(color2, 0.5))

Next Steps


Previous: Color Filters Next: Color Distance →

On this page
22 sections