psd_tools.composite
Composite module for layer rendering and blending.
This subpackage provides the rendering engine for compositing PSD layers into raster images. It implements Photoshop’s blend modes, layer effects, and vector shape rasterization.
Note: This module requires optional dependencies. Install with:
pip install 'psd-tools[composite]'
Or using uv:
uv sync --extra composite
The composite extra includes:
aggdraw: For vector path and bezier curve rasterizationscipy: For advanced image processing operationsscikit-image: For morphological operations in effects
Key modules:
psd_tools.composite.composite: Main compositing functionspsd_tools.composite.blend: Blend mode implementationspsd_tools.composite.effects: Layer effects (stroke, shadow, etc.)psd_tools.composite.vector: Vector shape and path renderingpsd_tools.composite.paint: Fill rendering (gradients, patterns)
Example usage:
from psd_tools import PSDImage
psd = PSDImage.open('document.psd')
# Composite entire document to PIL Image
image = psd.composite()
image.save('output.png')
# Composite specific layer
layer_image = psd[0].composite()
The compositing engine uses NumPy arrays for efficient pixel manipulation and supports all of Photoshop’s standard blend modes including multiply, screen, overlay, soft light, and more.
Performance considerations:
Compositing can be memory-intensive for large documents
Vector shapes require aggdraw for accurate rendering
Some effects have limited support compared to Photoshop
This module provides layer rendering and compositing functionality.
Installation: Requires optional dependencies:
pip install psd-tools[composite]
Or with uv:
uv sync --extra composite
Composite Functions
- psd_tools.composite.composite(group: Layer | PSDImage, color: float | tuple[float, ...] | ndarray = 1.0, alpha: float | ndarray = 0.0, viewport: tuple[int, int, int, int] | None = None, layer_filter: Callable | None = None, force: bool = False, as_layer: bool = False) tuple[ndarray, ndarray, ndarray][source]
Composite layers and return NumPy arrays.
This function composites the given layer or document into NumPy arrays representing color, shape, and alpha channels. It applies layer blending, effects, masks, and clipping according to the PSD specification.
- Parameters:
group – Layer or PSDImage to composite
color – Initial backdrop color (0.0-1.0, default: 1.0). Can be a scalar float applied to all channels, a tuple of per-channel values, or an ndarray.
alpha – Initial backdrop alpha (0.0-1.0, default: 0.0). Can be scalar or ndarray.
viewport – Bounding box (left, top, right, bottom) to composite. If None, uses layer bounds
layer_filter – Optional callable(layer) -> bool to filter which layers to composite
force – If True, force re-rendering of all layers including vector shapes and fills
as_layer – If True, treat the group as a layer (apply blend mode to backdrop)
- Returns:
color: RGB/CMYK/Grayscale values in range [0.0, 1.0]
shape: Layer shape/coverage mask in range [0.0, 1.0]
alpha: Composite alpha channel in range [0.0, 1.0]
- Return type:
Tuple of (color, shape, alpha) as float32 ndarrays with shape (height, width, channels)
Examples
>>> from psd_tools import PSDImage >>> psd = PSDImage.open('example.psd') >>> color, shape, alpha = composite(psd) >>> # Apply custom backdrop >>> color, shape, alpha = composite(psd, color=(1.0, 0.0, 0.0), alpha=1.0) >>> # Force re-render vector layers >>> color, shape, alpha = composite(psd, force=True) >>> # Composite only visible layers >>> color, shape, alpha = composite(psd, layer_filter=lambda l: l.visible)
Note
Requires optional composite dependencies (aggdraw, scipy, scikit-image) for vector shape rendering, gradient fills, and layer effects.
Adjustment layers have limited support.
Text rendering is not supported (text layers show as raster if available).
- psd_tools.composite.composite_pil(layer: Layer | PSDImage, color: float | tuple[float, ...] | ndarray, alpha: float | ndarray, viewport: tuple[int, int, int, int] | None, layer_filter: Callable | None, force: bool, as_layer: bool = False, apply_icc: bool = True) Image | None[source]
Composite layers and return a PIL Image.
This function composites the given layer or document into a PIL Image, applying blend modes, effects, and color management.
- Parameters:
layer – Layer or PSDImage to composite
color – Initial backdrop color (0.0-1.0). Can be scalar, tuple, or ndarray
alpha – Initial backdrop alpha (0.0-1.0). Can be scalar or ndarray
viewport – Bounding box (left, top, right, bottom) to composite. If None, uses layer bounds
layer_filter – Optional callable to filter which layers to composite. Should return True to include
force – If True, force re-rendering of all layers (ignore cached pixels)
as_layer – If True, apply layer blend modes (default: False for document-level compositing)
apply_icc – If True, apply ICC profile color correction (default: True)
- Returns:
PIL Image with composited result, or None if viewport is empty
Note
Requires optional composite dependencies (aggdraw, scipy, scikit-image)
LAB and Duotone color modes have limited blending support
Alpha channel handling varies by color mode
Blend Modes
Blend mode implementations.
This module implements Photoshop’s blend modes for compositing layers. Blend modes determine how a layer’s colors interact with the layers beneath it. Each function implements the mathematical formula for a specific blend mode.
The blend functions operate on NumPy arrays with normalized float32 values (0.0-1.0) representing pixel color channels. They follow Adobe’s PDF Blend Mode specification.
Blend mode categories:
Normal modes:
- normal: Source replaces backdrop (no blending)
Darken modes:
- darken: Selects darker of source and backdrop
- multiply: Multiplies colors (darkens)
- color_burn: Darkens backdrop to reflect source
- linear_burn: Similar to multiply but more extreme
- darker_color: Selects darker color (non-separable)
Lighten modes:
- lighten: Selects lighter of source and backdrop
- screen: Inverted multiply (lightens)
- color_dodge: Brightens backdrop to reflect source
- linear_dodge: Same as addition (Add blend mode)
- lighter_color: Selects lighter color (non-separable)
Contrast modes:
- overlay: Combination of multiply and screen
- soft_light: Soft version of overlay
- hard_light: Hard version of overlay
- vivid_light: Combination of color dodge and burn
- linear_light: Combination of linear dodge and burn
- pin_light: Replaces colors based on brightness
- hard_mix: Posterizes to primary colors
Inversion modes:
- difference: Absolute difference between colors
- exclusion: Similar to difference but lower contrast
Component modes (non-separable):
- hue: Preserves luminosity and saturation, replaces hue
- saturation: Preserves luminosity and hue, replaces saturation
- color: Preserves luminosity, replaces hue and saturation
- luminosity: Preserves hue and saturation, replaces luminosity
Implementation details:
Separable blend modes process each color channel independently
Non-separable modes convert to HSL color space first
All functions expect normalized float32 arrays (0.0-1.0 range)
Division by zero is protected with small epsilon values
Example usage:
import numpy as np
from psd_tools.composite.blend import multiply, screen
# Create backdrop and source colors (normalized)
backdrop = np.array([0.5, 0.3, 0.8], dtype=np.float32)
source = np.array([0.7, 0.6, 0.2], dtype=np.float32)
# Apply blend mode
result = multiply(backdrop, source)
# Result: [0.35, 0.18, 0.16]
The BLEND_FUNC dictionary maps BlendMode
enums to their corresponding functions for easy lookup during compositing.
- psd_tools.composite.blend.divide(Cb: ndarray, Cs: ndarray) ndarray[source]
Looks at the color information in each channel and divides the blend color from the base color.
- psd_tools.composite.blend.hard_mix(Cb: ndarray, Cs: ndarray) ndarray[source]
Adds the red, green and blue channel values of the blend color to the RGB values of the base color. If the resulting sum for a channel is 255 or greater, it receives a value of 255; if less than 255, a value of 0. Therefore, all blended pixels have red, green, and blue channel values of either 0 or 255. This changes all pixels to primary additive colors (red, green, or blue), white, or black.
- psd_tools.composite.blend.linear_light(Cb: ndarray, Cs: ndarray) ndarray[source]
Burns or dodges the colors by decreasing or increasing the brightness, depending on the blend color. If the blend color (light source) is lighter than 50% gray, the image is lightened by increasing the brightness. If the blend color is darker than 50% gray, the image is darkened by decreasing the brightness.
- psd_tools.composite.blend.non_separable(k: str = 's')[source]
Wrap non-separable blending function for CMYK handling.
- psd_tools.composite.blend.pin_light(Cb: ndarray, Cs: ndarray) ndarray[source]
Replaces the colors, depending on the blend color. If the blend color (light source) is lighter than 50% gray, pixels darker than the blend color are replaced, and pixels lighter than the blend color do not change. If the blend color is darker than 50% gray, pixels lighter than the blend color are replaced, and pixels darker than the blend color do not change. This is useful for adding special effects to an image.
- psd_tools.composite.blend.vivid_light(Cb: ndarray, Cs: ndarray) ndarray[source]
Burns or dodges the colors by increasing or decreasing the contrast, depending on the blend color. If the blend color (light source) is lighter than 50% gray, the image is lightened by decreasing the contrast. If the blend color is darker than 50% gray, the image is darkened by increasing the contrast.
The blend module implements Photoshop’s blend modes following the Adobe PDF specification. All blend functions operate on normalized float32 NumPy arrays.
Vector Rendering
Vector shapes and path operations for compositing.
- psd_tools.composite.vector.draw_stroke(layer)[source]
Draw a stroke.
Requires aggdraw for bezier curve rasterization.
- psd_tools.composite.vector.draw_vector_mask(layer)[source]
Draw a vector mask.
Requires aggdraw for bezier curve rasterization.
Vector shape and path rendering using aggdraw for bezier curve rasterization.
Effects Rendering
Layer effects rendering.
This module implements rendering for Photoshop layer effects (also known as layer styles). Effects are non-destructive visual enhancements applied to layers such as strokes, shadows, glows, and overlays.
Note: Effects rendering requires scikit-image. Install with:
pip install 'psd-tools[composite]'
Currently supported effects:
Stroke: Outline around layer shape or pixels - Supports solid color, gradient, and pattern fills - Position: inside, outside, or centered - Limited compared to Photoshop’s full implementation
Partially supported or limited effects:
Drop shadow, inner shadow, outer glow, inner glow
These may render but with reduced accuracy
The main function draw_stroke_effect() handles stroke rendering by:
Extracting the layer’s alpha channel or shape mask
Applying morphological operations (dilation/erosion) based on stroke size and position
Filling the stroke region with the specified paint (solid color, gradient, pattern)
Returning the rendered stroke as a NumPy array
Implementation notes:
Effects are image-based rather than vector-based, which may differ from Photoshop
For layers with vector paths, ideally strokes should be drawn geometrically
Some effect parameters may not be fully supported
Complex effect combinations may not render identically to Photoshop
Example usage (internal):
from psd_tools.composite.effects import draw_stroke_effect
# Called during layer compositing
viewport = (0, 0, 100, 100) # Region to render
shape = layer_alpha_channel # NumPy array
desc = stroke_descriptor # Effect parameters
color, alpha = draw_stroke_effect(viewport, shape, desc, psd)
The effects system integrates with the main compositing pipeline and is automatically applied when rendering layers that have effects enabled.
Layer effects rendering including strokes, shadows, and glows. Requires scikit-image for morphological operations.