psd-tools
psd-tools is a Python package designed for working with Adobe Photoshop PSD and PSB files, enabling reading, writing, and manipulation of layer data and compositions. The current version is 1.15.0.post1, and it maintains an active release cadence with frequent updates and improvements. It provides functionalities for low-level file structure access, raw layer image export, and limited layer composition.
Common errors
-
ImportError: Advanced compositing features require optional dependencies. Install with: pip install 'psd-tools[composite]'
cause Attempting to use advanced compositing features (like vector masks, gradients, or layer effects) without installing the `composite` extra dependencies.fixInstall the optional dependencies: `pip install 'psd-tools[composite]'` -
KeyError: 'FillColor' (or similar KeyError for layer properties like 'FontSize', 'SmartObject', etc.)
cause The `psd-tools` library might not fully support parsing specific types of layer data or smart object properties, leading to missing keys when trying to access them.fixConsult the `psd-tools` documentation or GitHub issues to check for specific layer type support. If unsupported, you may need to access lower-level PSD structures or consider alternative methods for these specific properties. -
Error -3 while decompressing data: incorrect data check
cause This error typically indicates a corrupted PSD file or an issue during the decompression process of image data within the PSD.fixVerify the integrity of the PSD file. Try opening it in Photoshop to see if it's recoverable. If not, you might need a backup of the PSD or specialized PSD repair tools. -
Image conversion to PIL fails or produces unexpected results for certain layer types (e.g., 'type' layers, 'shape' layers)
cause `psd-tools` has limited support for rendering certain complex layer types (like type layers, shape layers, smart objects) directly into pixel data without Photoshop's engine.fixFor these layer types, `layer.composite()` might return `None` or an incomplete image. If direct pixel access is needed, ensure the PSD is saved with 'Maximize Compatibility' in Photoshop, which embeds a composite image.
Warnings
- breaking As of v1.12, advanced compositing features (vector shapes, gradients, layer effects) require optional dependencies ('aggdraw', 'scipy', 'scikit-image') to be explicitly installed via `pip install 'psd-tools[composite]'`. Basic compositing with NumPy still works without them.
- breaking In v1.11, layer creation APIs changed. Layers now require a valid `PSDImage` object and cannot be created as 'orphaned' layers or shared between multiple container objects.
- breaking The `compose` module was dropped in v1.10. Users should migrate to using the `composite` method for image composition.
- gotcha The iteration order for layers in a `PSDImage` object is from background to foreground by default. This is reversed from versions prior to 1.7.x.
- gotcha Compositing results from `psd-tools` may differ from Photoshop's rendering due to limited support for many layer effects and adjustment layers.
- gotcha Extracting images from 32-bit PSD files requires the Pillow library to be built with LITTLECMS or LITTLECMS2 support.
Install
-
pip install psd-tools -
pip install 'psd-tools[composite]'
Imports
- PSDImage
from psd_tools import PSDImage
Quickstart
import os
from psd_tools import PSDImage
# Create a dummy PSD for demonstration if it doesn't exist
dummy_psd_path = 'example.psd'
if not os.path.exists(dummy_psd_path):
# In a real scenario, you'd have an actual PSD file
# For this example, we'll just demonstrate the API calls.
# Creating a valid PSD requires more complex operations
# than a simple placeholder here.
print(f"Please create a dummy '{dummy_psd_path}' file to run this quickstart.")
print("Example: a small Photoshop file with a few layers.")
else:
psd = PSDImage.open(dummy_psd_path)
# Print basic info
print(f"Opened PSD: {psd}")
# Composite the entire PSD and save as PNG
composite_image = psd.composite()
composite_image.save('example.png')
print(f"Saved composite image to example.png")
# Iterate through layers and save each as a separate PNG
for i, layer in enumerate(psd):
print(f"Layer {i}: {layer.name} (Type: {layer.kind})")
if layer.is_pixel_layer() and layer.visible:
layer_image = layer.composite()
if layer_image:
layer_image.save(f'{layer.name.replace(" ", "_")}.png')
print(f"Saved layer '{layer.name}' to {layer.name.replace(" ", "_")}.png")