# Migrating to 1.12

psd-tools 1.12 makes composite dependencies optional to support more platforms and Python versions.

## Breaking Change: Optional Composite Dependencies

The main breaking change in version 1.12 is that advanced compositing features now require optional dependencies that must be explicitly installed.

What changed:

- Dependencies `aggdraw`, `scipy`, and `scikit-image` are now optional

- Basic compositing with NumPy continues to work without these dependencies

- Advanced features (vector masks, gradients, patterns, effects) require the composite extra

Migration steps:

If you use advanced compositing features, install with the composite extra:

    pip install 'psd-tools[composite]'

Or install the dependencies separately:

    pip install psd-tools aggdraw scipy scikit-image

What works without composite dependencies:

- Reading and writing PSD files

- Accessing layer information (names, dimensions, etc.)

- Extracting raw pixel data with NumPy

- Basic pixel layer compositing

- Using cached layer previews

What requires composite dependencies:

- Vector shape and stroke rendering

- Gradient fills

- Pattern fills

- Layer effects rendering (drop shadows, strokes, etc.)

Error handling:

If you try to use advanced features without the dependencies installed, you’ll see a clear error:

    ImportError: Advanced compositing features require optional dependencies.
    Install with: pip install 'psd-tools[composite]'

Why this change:

This change enables psd-tools to run on platforms where some composite dependencies are unavailable, particularly Python 3.14 on Windows where `aggdraw` is not yet available.

## Module Structure Changes

Version 1.12 includes some internal refactoring that generally doesn’t affect public APIs:

- The `PSD` class moved from `psd_tools.psd` to `psd_tools.psd.document` (still importable from `psd_tools.psd`)

- Utils module split into `registry` and `bin_utils` (internal change)

- Composite module reorganized for better type safety (internal change)

These changes maintain backward compatibility for public imports.

## Type Annotations

Version 1.12 adds comprehensive type annotations throughout the codebase. If you use type checkers like mypy, you may discover type errors in your code that were previously undetected. This is a good thing - the annotations help catch bugs earlier!

# Migrating to 1.11

psd-tools 1.11 introduces stronger type-safety via annotation and new public APIs for layer creation. Now the following approach is possible to create a new layered document:

    from PIL import Image
    from psd_tools import PSDImage

    image = Image.new("RGBA", (width, height))
    psdimage = PSDImage.new(mode='RGB', size=(640, 480), depth=8)
    layer = psdimage.create_pixel_layer(image, name="Layer 1", top=0, left=0, opacity=255)
    psdimage.save('new_image.psd')

Version 1.11 introduces some breaking changes.

Layer creation now disables orphaned layers. They must be given a valid PSDImage object.

version 1.11.x:

    image = Image.new("RGBA", (width, height))
    psdimage.create_pixel_layer(psdimage, image)

version 1.10.x:

    image = Image.new("RGBA", (width, height))
    PixelLayer.frompil(None, image, parent=None)

The same layer cannot be shared between multiple container objects.

version 1.11.x:

    layer = psdimage.create_pixel_layer(group, image)
    psdimage.append(layer)  # This won't duplicate the layer.

# Migrating to 1.10

psd-tools 1.10 has a few breaking changes.

Basic layer structure editing is supported in 1.10. You can add or remove a pixel layer, or change the grouping of layers.

psd-tools 1.10 drops compose module. Use composite instead.

version 1.10.x:

    image = psd.composite()
    layer_image = layer.composite()

# Migrating to 1.9

psd-tools 1.9 switches to NumPy based compositing.

version 1.8.x:

    psd = PSDImage.open(filename)
    image = psd.compose()
    layer = psd[0]
    layer_image = layer.compose()

version 1.9.x:

    psd = PSDImage.open(filename)
    image = psd.composite()
    layer = psd[0]
    layer_image = layer.composite()

NumPy array API is introduced:

    image = psd.numpy()
    layer_image = layer.numpy()

# Migrating to 1.8

There are major API changes in version 1.8.x.

Note

In version 1.8.0 - 1.8.7, the package name was psd_tools2.

## PSDImage

File open method is changed from load to `open()`.

version 1.7.x:

    psd = PSDImage.load(filename)
    with open(filename, 'rb') as f:
        psd = PSDImage.from_stream(f)

version 1.8.x:

    psd = PSDImage.open(filename)
    with open(filename, 'rb') as f:
        psd = PSDImage.open(f)

## Layers

Children of PSDImage or Group is directly accessible by iterator or indexing.

version 1.7.x:

    for layer in group.layers:
        print(layer)

    first_child = group.layers[0]

version 1.8.x:

    for layer in group:
        print(layer)

    first_child = group[0]

In version 1.8.x, the order of layers is reversed to reflect that the index should not change when a new layer is added on top.

## PIL export

Primary PIL export method is `compose()`.

version 1.7.x:

    image = psd.as_PIL()

    layer_image = compose(layer)
    raw_layer_image = layer.as_PIL()

version 1.8.x:

    image = psd.compose()

    layer_image = layer.compose()
    raw_layer_image = layer.topil()

## Low-level data structure

Data structures are completely rewritten to support writing functionality. See `psd_tools.psd` subpackage.

version 1.7.x:

    psd.decoded_data

version 1.8.x:

    psd._record

## Drop pymaging support

Pymaging support is dropped.