psd_tools.api.layers

Layer module.

This module implements the high-level layer API for psd-tools, providing Pythonic interfaces for working with Photoshop layers. It defines the layer type hierarchy and common operations.

Key classes:

  • Layer: Base class for all layer types

  • GroupMixin: Mixin for layers that contain children (groups, documents)

  • Group: Folder/group layer containing other layers

  • PixelLayer: Regular raster layer with pixel data

  • TypeLayer: Text layer with typography information

  • ShapeLayer: Vector shape layer

  • SmartObjectLayer: Embedded or linked smart object

  • AdjustmentLayer: Non-destructive adjustment (curves, levels, etc.)

Layer hierarchy:

Layers are organized in a tree structure where groups can contain child layers. The GroupMixin provides iteration, indexing, and search capabilities:

# Iterate through all layers
for layer in psd:
    print(layer.name)

# Access by index
first_layer = psd[0]

# Check if layer is a specific type
if layer.kind == 'pixel':
    pixels = layer.numpy()

Common layer properties:

  • name: Layer name

  • visible: Visibility flag

  • opacity: Opacity (0-255)

  • blend_mode: Blend mode enum

  • bbox: Bounding box (left, top, right, bottom)

  • width, height: Dimensions

  • kind: Layer type string (‘pixel’, ‘group’, ‘type’, etc.)

  • parent: Parent layer or document

Layer operations:

Example usage:

from psd_tools import PSDImage

psd = PSDImage.open('document.psd')

# Access first layer
layer = psd[0]

# Modify layer properties
layer.visible = False
layer.opacity = 128
layer.name = "New Name"

# Get pixel data
pixels = layer.numpy()  # NumPy array
image = layer.topil()   # PIL Image

# Work with groups
for group in psd.descendants():
    if group.kind == 'group':
        print(f"Group: {group.name} with {len(group)} layers")

# Composite specific layer
rendered = layer.composite()
rendered.save('layer.png')

Layer types are automatically determined from the underlying PSD structures and exposed through the kind property for easy type checking.

Layer

class psd_tools.api.layers.Layer(parent: GroupMixin, record: LayerRecord, channels: ChannelDataList)[source]
property bbox: tuple[int, int, int, int]

(left, top, right, bottom) tuple.

property blend_mode: BlendMode

Blend mode of this layer. Writable.

Example:

from psd_tools.constants import BlendMode
if layer.blend_mode == BlendMode.NORMAL:
    layer.blend_mode = BlendMode.SCREEN
Returns:

BlendMode.

property bottom: int

Bottom coordinate.

Returns:

int

property clip_layers: list[Self]

Clip layers associated with this layer.

Returns:

list of layers

property clipping: bool

Clipping flag for this layer. Writable.

Returns:

bool

property clipping_layer: bool

Deprecated. Use clipping property instead.

composite(viewport: tuple[int, int, int, int] | None = None, force: bool = False, color: float | tuple[float, ...] | ndarray = 1.0, alpha: float | ndarray = 0.0, layer_filter: Callable | None = None, apply_icc: bool = True) Image | None[source]

Composite layer and masks (mask, vector mask, and clipping layers).

Parameters:
  • viewport – Viewport bounding box specified by (x1, y1, x2, y2) tuple. Default is the layer’s bbox.

  • force – Boolean flag to force vector drawing.

  • color – Backdrop color specified by scalar or tuple of scalar. The color value should be in [0.0, 1.0]. For example, (1., 0., 0.) specifies red in RGB color mode.

  • alpha – Backdrop alpha in [0.0, 1.0].

  • layer_filter – Callable that takes a layer as argument and returns whether if the layer is composited. Default is is_visible().

Returns:

PIL.Image.Image or None.

create_mask(image: Image, top: int | None = None, left: int | None = None, compression: Compression = Compression.RLE) Mask[source]

Create a pixel mask on this layer from a PIL Image.

If the image has an alpha channel (e.g. RGBA, LA), the alpha channel is used as the mask data. Otherwise the image is converted to grayscale (L mode). White (255) means fully unmasked, black (0) means fully masked.

Parameters:
  • image – Source Image for the mask.

  • top – Top offset of the mask. Defaults to the layer’s top.

  • left – Left offset of the mask. Defaults to the layer’s left.

  • compression – Compression algorithm for the mask data.

Returns:

The new Mask.

Raises:

ValueError – If the layer already has a mask.

delete_layer() Self[source]

Deprecated: Use layer.parent.remove(layer) instead.

property effects: Effects

Layer effects.

Returns:

Effects

property fill_opacity: int

Fill opacity of this layer in [0, 255] range. Writable.

Returns:

int

has_clip_layers(visible: bool = False) bool[source]

Returns True if the layer has associated clipping.

Parameters:

visible – If True, check for visible clipping layers.

Returns:

bool

has_effects(enabled: bool = True, name: str | None = None) bool[source]

Returns True if the layer has effects.

Parameters:
  • enabled – If True, check for enabled effects.

  • name – If given, check for specific effect type.

Returns:

bool

has_mask() bool[source]

Returns True if the layer has a mask.

Returns:

bool

has_origination() bool[source]

Returns True if the layer has live shape properties.

Returns:

bool

has_pixels() bool[source]

Returns True if the layer has associated pixels. When this is True, topil method returns PIL.Image.Image.

Returns:

bool

has_stroke() bool[source]

Returns True if the shape has a stroke.

has_vector_mask() bool[source]

Returns True if the layer has a vector mask.

Returns:

bool

property height: int

Height of the layer.

Returns:

int

is_group() bool[source]

Return True if the layer is a group.

Returns:

bool

is_visible() bool[source]

Layer visibility. Takes group visibility in account.

Returns:

bool

property kind: str

Kind of this layer, such as group, pixel, shape, type, smartobject, or psdimage. Class name without layer suffix.

Returns:

str

property layer_id: int

Layer ID.

Returns:

int layer id. if the layer is not assigned an id, -1.

property left: int

Left coordinate. Writable.

Returns:

int

lock(lock_flags: int = ProtectedFlags.COMPLETE) None[source]

Locks a layer accordind to the combination of flags.

Parameters:

lockflags – An integer representing the locking state

Example using the constants of ProtectedFlags and bitwise or operation to lock both pixels and positions:

layer.lock(ProtectedFlags.COMPOSITE | ProtectedFlags.POSITION)
property mask: Mask | None

Returns mask associated with this layer.

Returns:

Mask or None

move_down(offset: int = 1) Self[source]

Moves the layer down a certain offset within the group the layer is in.

Parameters:

offset – The number of positions to move the layer down (can be negative).

Raises:
  • ValueError – If layer has no parent or parent is not a group

  • IndexError – If the new index is out of bounds

Returns:

self

move_to_group(group: GroupMixin) Self[source]

Deprecated: Use group.append(layer) instead.

Parameters:

group – The group the current layer will be moved into.

move_up(offset: int = 1) Self[source]

Moves the layer up a certain offset within the group the layer is in.

Parameters:

offset – The number of positions to move the layer up (can be negative).

Raises:
  • ValueError – If layer has no parent or parent is not a group

  • IndexError – If the new index is out of bounds

Returns:

self

property name: str

Layer name. Writable.

Returns:

str

next_sibling(visible: bool = False) Self | None[source]

Next sibling of this layer.

numpy(channel: str | None = None, real_mask: bool = True) ndarray | None[source]

Get NumPy array of the layer.

Parameters:

channel – Which channel to return, can be ‘color’, ‘shape’, ‘alpha’, or ‘mask’. Default is ‘color+alpha’.

Returns:

numpy.ndarray or None if there is no pixel.

property offset: tuple[int, int]

(left, top) tuple. Writable.

Returns:

tuple

property opacity: int

Opacity of this layer in [0, 255] range. Writable.

Returns:

int

property origination: list[Origination]

Property for a list of live shapes or a line.

Some of the vector masks have associated live shape properties, that are Photoshop feature to handle primitive shapes such as a rectangle, an ellipse, or a line. Vector masks without live shape properties are plain path objects.

See psd_tools.api.shape.

Returns:

List of Invalidated, Rectangle, RoundedRectangle, Ellipse, or Line.

property parent: GroupMixinProtocol | None

Parent of this layer.

previous_sibling(visible: bool = False) Self | None[source]

Previous sibling of this layer.

property reference_point: tuple[float, float]

Reference point of this layer as (x, y) tuple in the canvas coordinates. Writable.

Reference point is used for transformations such as rotation and scaling.

Returns:

(x, y) tuple

remove_mask() None[source]

Remove the pixel mask from this layer.

Raises:

ValueError – If the layer does not have a mask.

property right: int

Right coordinate.

Returns:

int

property sheet_color: SheetColorType

Color label of this layer in the Photoshop layers panel. Writable.

Returns:

SheetColorType

property size: tuple[int, int]

(width, height) tuple.

Returns:

tuple

property stroke: Stroke | None

Property for strokes.

property tagged_blocks: TaggedBlocks

Layer tagged blocks that is a dict-like container of settings.

See psd_tools.constants.Tag for available keys.

Returns:

TaggedBlocks.

Example:

from psd_tools.constants import Tag
metadata = layer.tagged_blocks.get_data(Tag.METADATA_SETTING)
property top: int

Top coordinate. Writable.

Returns:

int

topil(channel: int | None = None, apply_icc: bool = True) Image | None[source]

Get PIL Image of the layer.

Parameters:
  • channel – Which channel to return; e.g., 0 for ‘R’ channel in RGB image. See ChannelID. When None, the method returns all the channels supported by PIL modes.

  • apply_icc – Whether to apply ICC profile conversion to sRGB.

Returns:

PIL.Image.Image, or None if the layer has no pixels.

Example:

from psd_tools.constants import ChannelID

image = layer.topil()
red = layer.topil(ChannelID.CHANNEL_0)
alpha = layer.topil(ChannelID.TRANSPARENCY_MASK)

Note

Not all of the PSD image modes are supported in PIL.Image.Image. For example, ‘CMYK’ mode cannot include alpha channel in PIL. In this case, topil drops alpha channel.

update_mask(image: Image, top: int | None = None, left: int | None = None, compression: Compression = Compression.RLE) Mask[source]

Update the pixel mask of this layer with a new image.

If the image has an alpha channel (e.g. RGBA, LA), the alpha channel is used as the mask data. Otherwise the image is converted to grayscale (L mode). White (255) means fully unmasked, black (0) means fully masked.

Parameters:
  • image – New source Image for the mask.

  • top – New top offset of the mask. Defaults to current mask top.

  • left – New left offset of the mask. Defaults to current mask left.

  • compression – Compression algorithm for the mask data.

Returns:

The updated Mask.

Raises:

ValueError – If the layer does not have a mask.

property vector_mask: VectorMask | None

Returns vector mask associated with this layer.

Returns:

VectorMask or None

property visible: bool

Layer visibility. Doesn’t take group visibility in account. Writable.

Returns:

bool

property width: int

Width of the layer.

Returns:

int

Artboard

class psd_tools.api.layers.Artboard(parent: GroupMixin, record: LayerRecord, channels: ChannelDataList)[source]

Artboard is a special kind of group that has a pre-defined viewbox.

property bbox: tuple[int, int, int, int]

(left, top, right, bottom) tuple.

property bottom: int

Bottom coordinate (computed from children, read-only).

property left: int

Left coordinate (computed from children, read-only).

property right: int

Right coordinate (computed from children, read-only).

property top: int

Top coordinate (computed from children, read-only).

Group

class psd_tools.api.layers.Group(parent: GroupMixin, record: LayerRecord, channels: ChannelDataList)[source]

Group of layers.

Example:

group = psd[1]
for layer in group:
    if layer.kind == 'pixel':
        print(layer.name)
property blend_mode: BlendMode

Blend mode of this layer. Writable.

property bottom: int

Bottom coordinate (computed from children, read-only).

property clipping: bool

Clipping flag for this layer. Writable.

Returns:

bool

composite(viewport: tuple[int, int, int, int] | None = None, force: bool = False, color: float | tuple[float, ...] | ndarray = 1.0, alpha: float | ndarray = 0.0, layer_filter: Callable | None = None, apply_icc: bool = True) Image | None[source]

Composite layer and masks (mask, vector mask, and clipping layers).

Parameters:
  • viewport – Viewport bounding box specified by (x1, y1, x2, y2) tuple. Default is the layer’s bbox.

  • force – Boolean flag to force vector drawing.

  • color – Backdrop color specified by scalar or tuple of scalar. The color value should be in [0.0, 1.0]. For example, (1., 0., 0.) specifies red in RGB color mode.

  • alpha – Backdrop alpha in [0.0, 1.0].

  • layer_filter – Callable that takes a layer as argument and returns whether if the layer is composited. Default is is_visible().

Returns:

PIL.Image.Image.

static extract_bbox(layers: Sequence[Layer] | GroupMixin, include_invisible: bool = False, include_clipping: bool = False) tuple[int, int, int, int][source]

Returns a bounding box for layers or (0, 0, 0, 0) if the layers have no bounding box.

Parameters:
  • layers – sequence of layers or a group.

  • include_invisible – include invisible layers in calculation.

  • include_clipping – include clipping layers in calculation. Defaults to False to match visible pixel bounds.

Returns:

tuple of four int

classmethod group_layers(parent: GroupMixin, layers: Sequence[Layer], name: str = 'Group', open_folder: bool = True) Self[source]

Deprecated: Use psdimage.create_group(layer_list, name) instead.

Parameters:
  • parent – The parent group to add the newly created Group object into.

  • layers – The layers to group. Can by any subclass of Layer

  • name – The display name of the group. Default to “Group”.

  • open_folder – Boolean defining whether the folder will be open or closed in photoshop. Default to True.

Returns:

A Group

Raises:

ValueError – If layers is empty

is_group() bool[source]

Return True if the layer is a group.

Returns:

bool

property left: int

Left coordinate (computed from children, read-only).

classmethod new(parent: GroupMixin, name: str = 'Group', open_folder: bool = True) Self[source]

Create a new Group object with minimal records and data channels and metadata to properly include the group in the PSD file.

Parameters:
  • name – The display name of the group. Default to “Group”.

  • open_folder – Boolean defining whether the folder will be open or closed in photoshop. Default to True.

  • parent – Optional parent folder to move the newly created group into.

Returns:

A Group object

Raises:

ValueError – If parent is None

property open_folder: bool

Returns True if the group is an open folder.

Returns:

bool

property right: int

Right coordinate (computed from children, read-only).

property top: int

Top coordinate (computed from children, read-only).

PixelLayer

class psd_tools.api.layers.PixelLayer(parent: GroupMixin, record: LayerRecord, channels: ChannelDataList)[source]

Layer that has rasterized image in pixels.

Example:

assert layer.kind == 'pixel':
image = layer.composite()
image.save('layer.png')
classmethod frompil(image: Image, parent: GroupMixin, name: str = 'Layer', top: int = 0, left: int = 0, compression: Compression = Compression.RLE, **kwargs: Any) PixelLayer[source]

Create a PixelLayer from a PIL image for a given psd file.

Parameters:
  • image – The Image object to convert to photoshop

  • psdimage – The target psdimage the image will be converted for.

  • name – The name of the layer. Defaults to “Layer”

  • top – Pixelwise offset from the top of the canvas for the new layer.

  • left – Pixelwise offset from the left of the canvas for the new layer.

  • compression – Compression algorithm to use for the data.

Returns:

A PixelLayer object

Raises:

TypeError – If image is not a PIL Image or parent is None

ShapeLayer

class psd_tools.api.layers.ShapeLayer(*args: Any)[source]

Layer that has drawing in vector mask.

property bbox: tuple[int, int, int, int]

(left, top, right, bottom) tuple.

property bottom: int

Bottom coordinate.

Returns:

int

property left: int

Left coordinate. Writable.

Returns:

int

property right: int

Right coordinate.

Returns:

int

property top: int

Top coordinate. Writable.

Returns:

int

SmartObjectLayer

class psd_tools.api.layers.SmartObjectLayer(parent: GroupMixin, record: LayerRecord, channels: ChannelDataList)[source]

Layer that inserts external data.

Use smart_object attribute to get the external data. See SmartObject.

Example:

import io
if layer.smart_object.filetype == 'jpg':
    image = Image.open(io.BytesIO(layer.smart_object.data))
property smart_object: SmartObject

Associated smart object.

Returns:

SmartObject.

TypeLayer

class psd_tools.api.layers.TypeLayer(*args: Any)[source]

Layer that has text and styling information for fonts or paragraphs.

Text is accessible at text property. Styling information for paragraphs is in engine_dict. Document styling information such as font list is is resource_dict.

Currently, textual information is read-only.

Example:

if layer.kind == 'type':
    print(layer.text)
    print(layer.engine_dict['StyleRun'])

    # Extract font for each substring in the text.
    text = layer.engine_dict['Editor']['Text'].value
    fontset = layer.resource_dict['FontSet']
    runlength = layer.engine_dict['StyleRun']['RunLengthArray']
    rundata = layer.engine_dict['StyleRun']['RunArray']
    index = 0
    for length, style in zip(runlength, rundata):
        substring = text[index:index + length]
        stylesheet = style['StyleSheet']['StyleSheetData']
        font = fontset[stylesheet['Font']]
        print('%r gets %s' % (substring, font))
        index += length
property document_resources: Dict

Resource set relevant to the document.

property engine_dict: Dict

Styling information dict.

property font_names: list[str]

List of PostScript font names used in this text layer.

Convenience shortcut for:

[font.postscript_name for font in layer.typesetting.fonts]
property resource_dict: Dict

Resource set.

property text: str

Text in the layer. Read-only.

Note

New-line character in Photoshop is ‘\r’.

property text_type: TextType | None

Text type. Read-only.

Returns:

See psd_tools.constants.TextType.

property transform: tuple[float, float, float, float, float, float]

Matrix (xx, xy, yx, yy, tx, ty) applies affine transformation.

property typesetting: TypeSetting

Structured typographic data.

Returns a TypeSetting object that provides Pythonic access to fonts, paragraphs, styled runs, and default styles without navigating raw engine data dicts.

Example:

ts = layer.typesetting
for paragraph in ts:
    print(paragraph.style.justification)
    for run in paragraph.runs:
        print(run.text, run.style.font_name, run.style.font_size)

See also: engine_dict, resource_dict for raw data.

property warp: DescriptorBlock | None

Warp configuration.