# 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:

- `composite()`: Render layer to PIL Image

- `numpy()`: Get pixel data as NumPy array

- `topil()`: Convert to PIL Image

- `has_mask()`: Check if layer has a mask

- `has_clip_layers()`: Check if layer has clipping mask

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)
  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

    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.

  delete_layer() → Self

    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

    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

    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

    Returns True if the layer has a mask.

    Returns:

      bool

  has_origination() → bool

    Returns True if the layer has live shape properties.

    Returns:

      bool

  has_pixels() → bool

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

    Returns:

      bool

  has_stroke() → bool

    Returns True if the shape has a stroke.

  has_vector_mask() → bool

    Returns True if the layer has a vector mask.

    Returns:

      bool

  property height: int

    Height of the layer.

    Returns:

      int

  is_group() → bool

    Return True if the layer is a group.

    Returns:

      bool

  is_visible() → bool

    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

    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

    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

    Deprecated: Use group.append(layer) instead.

    Parameters:

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

  move_up(offset: int = 1) → Self

    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

    Next sibling of this layer.

  numpy(channel: str | None = None, real_mask: bool = True) → ndarray | None

    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

    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

  property right: int

    Right coordinate.

    Returns:

      int

  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

    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.

  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)

  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)

  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

    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) → tuple[int, int, int, int]

    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.

    Returns:

      tuple of four int

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

    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

    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

    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)

  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

    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)

  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)

  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)

  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 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:

      - `psd_tools.constants.TextType.POINT` for point type text

          (also known as character type)

      - `psd_tools.constants.TextType.PARAGRAPH` for paragraph type text

          (also known as area type)

      - None if text type cannot be determined or information is unavailable

    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 warp: DescriptorBlock | None

    Warp configuration.