imgrs

✨ Effects API

Complete reference for shadow, glow, and blending effects.

Shadow Effects

img.drop_shadow(offset_x, offset_y, blur_radius, shadow_color)

Add a drop shadow behind the image.

Parameters:

Returns: Image (larger than original to accommodate shadow)

Example:

# Classic drop shadow
shadowed = img.drop_shadow(
    offset_x=10,
    offset_y=10,
    blur_radius=15.0,
    shadow_color=(0, 0, 0, 128)  # Semi-transparent black
)

# Soft shadow
soft = img.drop_shadow(5, 5, 25.0, (0, 0, 0, 100))

# Hard shadow
hard = img.drop_shadow(8, 8, 2.0, (0, 0, 0, 200))

# Colored shadow
colored = img.drop_shadow(15, 15, 20.0, (255, 0, 0, 100))  # Red shadow

Canvas expansion:


img.inner_shadow(offset_x, offset_y, blur_radius, shadow_color)

Add an inner shadow (shadow inside the image edges).

Parameters:

Returns: Image (same size as original)

Example:

# Inner shadow for depth
inset = img.inner_shadow(
    offset_x=5,
    offset_y=5,
    blur_radius=10.0,
    shadow_color=(0, 0, 0, 180)
)

# Top-left inner shadow
top_shadow = img.inner_shadow(-3, -3, 8.0, (0, 0, 0, 150))

# Emboss-like effect
embossed = img.inner_shadow(2, 2, 5.0, (0, 0, 0, 100))

Use cases:


img.glow(blur_radius, glow_color, intensity)

Add a glow effect around the image.

Parameters:

Returns: Image (larger than original)

Example:

# Soft white glow
glowing = img.glow(
    blur_radius=20.0,
    glow_color=(255, 255, 255, 255),
    intensity=0.8
)

# Colored neon glow
neon = img.glow(15.0, (0, 255, 255, 255), 1.0)  # Cyan

# Subtle glow
subtle = img.glow(10.0, (255, 255, 0, 255), 0.5)  # Yellow

# Intense glow
intense = img.glow(25.0, (255, 0, 255, 255), 1.5)  # Magenta

Canvas expansion:


Blending Effects

img.blend_with(other, mode, opacity)

Blend image with another using advanced blend modes.

Parameters:

Returns: Image (blended result)

Example:

from imgrs import Image, BlendMode

background = Image.open("background.jpg")
overlay = Image.open("overlay.png")

# Different blend modes
multiply = background.blend_with(overlay, BlendMode.MULTIPLY, 0.8)
screen = background.blend_with(overlay, BlendMode.SCREEN, 0.6)
overlay_blend = background.blend_with(overlay, BlendMode.OVERLAY, 0.7)
difference = background.blend_with(overlay, BlendMode.DIFFERENCE, 1.0)

img.overlay_with(overlay, mode, opacity, position)

Overlay an image using advanced blending with positioning.

Parameters:

Returns: Image (overlayed result)

Example:

# Center overlay
centered = background.overlay_with(watermark, "normal", 0.5)

# Positioned overlay
positioned = background.overlay_with(watermark, "multiply", 0.8, position=(50, 100))

# Corner watermark
corner = background.overlay_with(watermark, "screen", 0.3, position=(10, 10))

Blend Mode Reference

Mode Description Use Case
normal Standard alpha blending Default compositing
multiply Multiply colors (darker) Shadows, darkening
screen Screen colors (lighter) Highlights, lightening
overlay Multiply/screen based on base Contrast enhancement
soft_light Soft dodge/burn Soft lighting effects
hard_light Hard dodge/burn Dramatic lighting
color_dodge Lighten with color Bright highlights
color_burn Darken with color Deep shadows
darken Keep darker pixels Darkening effects
lighten Keep lighter pixels Lightening effects
difference Color difference Special effects
exclusion Similar to difference High contrast

Effect Combinations

Layered Effects

# Drop shadow + glow
enhanced = (img
    .drop_shadow(8, 8, 15.0, (0, 0, 0, 120))
    .glow(10.0, (255, 255, 255, 255), 0.6))

UI Button Effect

def create_button(text_img):
    """Create a button with depth."""
    return (text_img
        .drop_shadow(0, 3, 5.0, (0, 0, 0, 100))  # Bottom shadow
        .inner_shadow(0, -1, 3.0, (255, 255, 255, 50)))  # Top highlight

button = create_button(label_img)

Neon Sign Effect

def neon_sign(img, color=(0, 255, 255, 255)):
    """Create neon glow effect."""
    return (img
        .glow(25.0, color, 1.0)
        .glow(15.0, color, 0.8)
        .glow(8.0, color, 1.2))

neon = neon_sign(text_img)

Shadow Parameters Guide

Offset Guidelines

# Natural shadow (bottom-right)
offset_x=10, offset_y=10

# Top shadow (light from bottom)
offset_x=0, offset_y=-5

# Right shadow
offset_x=8, offset_y=0

# No offset (centered shadow/glow)
offset_x=0, offset_y=0

Blur Radius Guidelines

# Sharp shadow (close to object)
blur_radius=2.0

# Medium blur (natural)
blur_radius=10.0

# Soft shadow (far from object)
blur_radius=25.0

# Very diffuse
blur_radius=50.0

Shadow Color Guidelines

# Natural shadow (black with transparency)
shadow_color=(0, 0, 0, 128)

# Soft shadow (more transparent)
shadow_color=(0, 0, 0, 80)

# Hard shadow (more opaque)
shadow_color=(0, 0, 0, 200)

# Colored shadow (creative)
shadow_color=(100, 50, 150, 120)  # Purple

Effect Presets

Realistic Drop Shadow

def realistic_shadow(img):
    return img.drop_shadow(
        offset_x=12,
        offset_y=12,
        blur_radius=20.0,
        shadow_color=(0, 0, 0, 100)
    )

Floating Effect

def floating_effect(img):
    return img.drop_shadow(
        offset_x=0,
        offset_y=15,
        blur_radius=30.0,
        shadow_color=(0, 0, 0, 80)
    )

Neon Glow

def neon_glow(img, color=(0, 255, 255, 255)):
    return img.glow(
        blur_radius=20.0,
        glow_color=color,
        intensity=1.2
    )

Embossed Look

def emboss_effect(img):
    return img.inner_shadow(
        offset_x=3,
        offset_y=3,
        blur_radius=5.0,
        shadow_color=(0, 0, 0, 150)
    )

Performance Notes

Effect Complexity Notes
drop_shadow() O(n×m×r²) Blur is expensive
inner_shadow() O(n×m×r²) Similar to drop shadow
glow() O(n×m×r²) Blur is expensive
blend_with() O(n×m) Fast pixel operations
overlay_with() O(n×m) Fast pixel operations

Tips:


Common Use Cases

Photo Enhancement

# Add subtle depth
enhanced = img.drop_shadow(5, 5, 10.0, (0, 0, 0, 60))

Logo/Icon Effects

# Make logo pop
logo = (logo
    .drop_shadow(8, 8, 15.0, (0, 0, 0, 120))
    .glow(10.0, (255, 255, 255, 255), 0.5))

Text Effects

# Glowing text
glowing_text = text_img.glow(15.0, (255, 200, 0, 255), 1.0)

# Embossed text
embossed_text = text_img.inner_shadow(2, 2, 3.0, (0, 0, 0, 180))

UI Elements

# Pressed button (inner shadow)
pressed = button.inner_shadow(0, 2, 4.0, (0, 0, 0, 120))

# Floating card (drop shadow)
card = content.drop_shadow(0, 5, 20.0, (0, 0, 0, 100))

Compositing & Blending

# Photo compositing
foreground = Image.open("subject.png")
background = Image.open("scene.jpg")
composited = background.overlay_with(foreground, "normal", 1.0, position=(100, 50))

# Color grading with blend modes
warm_overlay = Image.new("RGB", (800, 600), (255, 200, 150))
graded = photo.blend_with(warm_overlay, "overlay", 0.3)

# Texture overlay
texture = Image.open("paper_texture.jpg")
textured = image.blend_with(texture, "multiply", 0.4)

# Double exposure effect
layer1 = Image.open("portrait.jpg")
layer2 = Image.open("landscape.jpg")
double_exposure = layer1.blend_with(layer2, "screen", 0.7)

See Also: