SRC(1)

โœจ NAME โœจ

okay so bestie, this is the man page for src โ€” a.k.a. the psd-tools docs, section 1 of the manual ๐ŸŽ€

psd-tools is a Python package for working with Adobe Photoshop PSD files, exactly as described in the spec over at https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/ ๐Ÿ’–


๐Ÿ’… INSTALLATION ๐Ÿ’…

Use pip to install the package, no cap:

pip install psd-tools

For the advanced layer compositing features (the fancy stuff, bestie), install with the composite extra:

pip install psd-tools[composite]

This pulls in optional dependencies โ€” aggdraw, scipy, scikit-image โ€” which are required for ๐Ÿ’ซ:

  • Vector shape and stroke rendering
  • Gradient and pattern fills
  • Layer effects rendering

Basic compositing operations work without these dependencies, by using cached previews or simple NumPy-based operations. lowkey huge ๐Ÿ™Œ

Note: In order to extract images from 32bit PSD files, PIL/Pillow must be built with LITTLECMS or LITTLECMS2 support (apt-get install liblcms2-2 or brew install little-cms2) ๐Ÿ™ˆ

๐Ÿฆ‹ GETTING STARTED ๐Ÿฆ‹

from psd_tools import PSDImage

psd = PSDImage.open('example.psd')
psd.composite().save('example.png')

for layer in psd:
    print(layer)
    image = layer.composite()

Check out the Usage documentation for more examples ๐Ÿ‘‘


๐Ÿ‘‘ FEATURES ๐Ÿ‘‘

Supported ๐Ÿ”ฅ:

  • Read and write of the low-level PSD/PSB file structure
  • Raw layer image export in NumPy and PIL format

Limited support (it's giving "we're working on it" ๐Ÿ˜ญ):

  • Composition of basic pixel-based layers
  • Composition of fill layer effects
  • Vector masks
  • Editing of some layer attributes such as layer name
  • Basic editing of pixel layers and groups, such as adding or removing a layer
  • Blending modes except for dissolve
  • Drawing of bezier curves

Not supported ๐Ÿ’€:

  • Editing of various layers such as type layers, shape layers, smart objects, etc.
  • Editing of texts in type layers
  • Composition of adjustment layers
  • Composition of many layer effects
  • Font rendering

๐ŸŒˆ Usage

๐Ÿ’ป Command line

The package provides command line tools to handle a PSD document:

psd-tools export <input_file> <output_file> [options]
psd-tools show <input_file> [options]
psd-tools debug <input_file> [options]
psd-tools -h | --help
psd-tools --version

Example โœจ:

psd-tools show example.psd  # Show the file content
psd-tools export example.psd example.png  # Export as PNG
psd-tools export example.psd[0] example-0.png  # Export layer as PNG

๐Ÿ“ธ Working with PSD document

The psd_tools.api package provides the user-friendly API to work with PSD files. PSDImage represents a PSD file ๐Ÿ’–

Open an image:

from psd_tools import PSDImage
psdimage = PSDImage.open('my_image.psd')

Most of the data structure in the psd-tools supports pretty printing in an IPython environment. it's so cute when it does that ๐Ÿฅน

In [1]: PSDImage.open('example.psd')
Out[1]:
PSDImage(mode=RGB size=101x55 depth=8 channels=3)
  [0] PixelLayer('Background' size=101x55)
  [1] PixelLayer('Layer 1' size=85x46)

Internal layers are accessible by iterator or indexing:

for layer in psdimage:
    print(layer)
    if layer.is_group():
        for child in layer:
            print(child)

child = psdimage[0][0]
Note: The iteration order is from background to foreground, which is reversed from version prior to 1.7.x. Use reversed(psd) to iterate from foreground to background. yes bestie, this trips everyone up ๐Ÿ™ˆ

The opened PSD file can be saved:

psdimage.save('output.psd')

If the PSD File's layer structure was updated, saving it will update the ImageData section. However, the rendered image is likely different from the Photoshop's rendering, due to the limited rendering support in psd_tools. not us being honest about our flaws ๐Ÿ’…


๐Ÿงš Working with Layers

There are various layer kinds in Photoshop, and each one is kind of a main character in its own way ๐ŸŒˆ

The most basic layer type is PixelLayer:

print(layer.name)
layer.kind == 'pixel'

Some of the layer attributes are editable, such as a layer name:

layer.name = 'Updated layer 1'

psd_tools experimentally supports the creation of a new PixelLayer from a PIL object โ€” the PIL image will be converted to the color mode of the PSD File given in parameter:

psdimage.create_pixel_layer(pil_image, name="Layer name")

To construct a layered PSD file from scratch (iconic behaviour, truly) โœจ:

psdimage = PSDImage.new(mode='RGB', size=(640, 480), depth=8)
layer = psdimage.create_pixel_layer(pil_image, name="Layer 1", top=0, left=0, opacity=255)
group = psdimage.create_group(name="Group 1")
group.append(layer)
psdimage.save('new_image.psd')

See the function documentation for further parameter explanations ๐Ÿ‘‘

Group has internal layers:

for layer in group:
    print(layer)

first_layer = group[0]

Create a new group object.:

group = psdimage.create_group(name="Group name")
group.append(layer)

TypeLayer is a layer with texts:

print(layer.text)

Typographic details such as fonts, character styles, and paragraph styles are available via the typesetting property. See typesetting for full API reference:

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

ShapeLayer draws a vector shape, and the shape information is stored in vector_mask and origination property. Other layers can also have shape information as a mask:

print(layer.vector_mask)
for shape in layer.origination:
    print(shape)

SmartObjectLayer embeds or links an external file for non-destructive editing. The file content is accessible via smart_object property:

import io
so = layer.smart_object
if so.detected_filetype in ('jpg', 'png'):
    # Use open(external_dir=...) when processing untrusted PSD files.
    with so.open() as f:
        image = Image.open(io.BytesIO(f.read()))

SolidColorFill, PatternFill, and GradientFill are fill layers that paint the entire region if there is no associated mask. Sub-classes of AdjustmentLayer represents layer adjustment applied to the composed image. See Adjustment layers ๐Ÿ’œ


๐Ÿ”ง Modifying the layer structure

The layer structure of a PSD object can be modified through methods emulating a python list. bestie it's literally just a list, go off ๐ŸŽ€

The internal model of the psd layer structure will be automatically updated. Moving a layer from a PSD to another will also automatically convert the PixelLayer to the target psd's color mode. auto-conversion?? slay โœจ

The following are valid for both PSDImage and Group objects:

Set an item:

group[0] = layer

Add a layer or layers to a group:

group.append(layer)
group.extend(layers)

Insert a layer to a specific index in the group:

group.insert(3, layer)

Remove a layer from the a group:

group.remove(layer)

Pop a layer from the group:

layer = group.pop()

Emptying a layer group:

group.clear()

Get the index of a layer in the group:

index = group.index(layer)

Count the occurrences of a layer in a group:

count = group.count(layer)

Move a given list of layers in a newly created Group. If no parent group is given in parameter, the new group will replace the first layer of the list in the PSD structure:

group = psdimage.create_group(layer_list=[layer1, layer2, ...], name="New Group")

Some operations are available for all Layer objects.

Delete a layer from its layer structure:

group.remove(layer)

Layers can be moved from a group to another:

target_group.append(layer)

Layers can be moved within the group to change their order:

layer.move_up() # Will send the layer upward in the group
layer.move_down() # Will send the layer downward in the group

๐Ÿ–ผ๏ธ Exporting data to PIL

Export the entire document as PIL.Image:

image = psd.composite()
image.save('exported.png')

Export a single layer including masks and clipping layers:

image = layer.composite()

Export layer and mask separately without composition:

image = layer.topil()
mask = layer.mask.topil()

To composite specific layers, such as layers except for texts, use layer_filter option:

image = psd.composite(
    layer_filter=lambda layer: layer.is_visible() and layer.kind != 'type')
Note: Advanced compositing features require optional dependencies. Install with: sh pip install psd-tools[composite] These dependencies (aggdraw, scipy, scikit-image) are needed for: - Vector shapes and strokes - Gradient and pattern fills - Layer effects Basic compositing works without them, by using cached previews or simple pixel-based operations. If a feature requires missing dependencies, an ImportError with installation instructions will be raised. Note that most layer effects are not supported. Adjustment layers have limited support (BrightnessContrast, Levels, Curves, Exposure, Invert, Posterize, Threshold). The compositing result may look different from Photoshop. ๐Ÿ˜ญ

๐Ÿ”ข Exporting data to NumPy

PSDImage or layers can be exported to NumPy array by numpy() method:

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

๐Ÿšš Migration Guide

๐ŸŒŸ v1.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. yeah we know, we know, deep breaths ๐Ÿ’€

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

okay so which of the cute lil features are the divas that literally cannot function without composite deps? ๐Ÿซถ

  • Vector shape and stroke rendering โœ๏ธ
  • Gradient fills ๐ŸŒˆ
  • Pattern fills ๐ŸŽ€
  • Layer effects rendering (drop shadows, strokes, etc.) ๐Ÿ’…

Error handling: bestie, if you try to serve advanced-feature looks without the deps installed, the package does not ghost you โ€” you get a crystal-clear error:

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

Why this change: because we want psd-tools to run on platforms where some composite dependencies straight-up don't exist โ€” especially Python 3.14 on Windows, where aggdraw is not yet available. so this keeps the whole thing alive instead of crashing the party. ๐Ÿ’€


Module Structure Changes ๐ŸŒธ

Version 1.12 did some internal glow-up refactoring that (mostly) doesn't touch the public APIs, promise:

  • The PSD class moved from psd_tools.psd to psd_tools.psd.document โ€” it's still importable from psd_tools.psd tho, so don't panic ๐Ÿซถ
  • Utils module got split into registry and bin_utils (internal change, nothing to see here)
  • Composite module got reorganized for better type safety (again: internal change)

These changes maintain backward compatibility for public imports. slay. ๐Ÿ‘‘

Type Annotations ๐ŸŽ€

Version 1.12 adds comprehensive type annotations throughout the codebase. so if you run type checkers like mypy, you might suddenly discover type errors in your own code that were previously undetected. and that is genuinely a good thing โ€” the annotations help catch bugs earlier! catching them early is highkey iconic. โญ

v1.11 โœจ

psd-tools 1.11 brings stronger type-safety via annotation, plus brand new public APIs for layer creation. so now this whole 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, so listen up bestie ๐Ÿ“ข

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.

v1.10 ๐Ÿ’œ

psd-tools 1.10 has a few breaking changes too.

Basic layer structure editing is supported in 1.10 โ€” you can add or remove a pixel layer, or change the grouping of layers. that's so cozy honestly. ๐Ÿงš

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

version 1.10.x:

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

v1.9 ๐Ÿฆ‹

psd-tools 1.9 switches to NumPy based compositing. big era.

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

v1.8 ๐Ÿ’–

There are major API changes in version 1.8.x. buckle up.

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(). (that's psd_tools.PSDImage.open for the record.)

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 are directly accessible by iterator or indexing. no more .layers middleman, we love direct communication. ๐Ÿ’…

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. the math is mathing. ๐Ÿงฎ

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. peep the psd_tools.psd subpackage.

version 1.7.x:

psd.decoded_data

version 1.8.x:

psd._record

Drop pymaging support ๐Ÿซถ

Pymaging support is dropped. it's gone, it's resting, we moved on.


Changelog ๐Ÿ“œ

1.17.4 (2026-06-24) ๐Ÿ”ฅ

  • [security] Guard against oversized memory allocation from failed channel decompression (CWE-789, related to GHSA-8q6g-vjhf-jp8m)
  • [api] Add max_alloc_bytes parameter to PSDImage.open() for an opt-in per-document allocation budget cap

1.17.3 (2026-06-22) ๐Ÿ›ก๏ธ

  • [security] Guard against uncontrolled memory allocation via crafted PSD canvas dimensions (GHSA-8q6g-vjhf-jp8m, #676)
  • [fix] Fix VirtualMemoryArray dimension computation for patterns (#672)
  • [fix] Fix smart object blank filetype field handling (#663)
  • [chore] Bump ruff to 0.15.18, pytest to 9.1.1, actions/checkout to v7

1.17.2 (2026-06-04) โญ

  • [fix] Disable Limited API for Windows Cython extension (#661)
  • [chore] Bump ruff from 0.15.14 to 0.15.15 (#659)

1.17.1 (2026-05-27) ๐Ÿ›ก๏ธ

  • [security] Fix path traversal in SmartObject.save() and open() (GHSA-2rmg-vrx8-9j2f, #657)
  • [chore] Bump ruff to 0.15.14, mypy to 2.1.0

1.17.0 (2026-05-11) ๐ŸŽจ

  • [composite] Add Hue/Saturation adjustment layer composite algorithm (#646)
  • [fix] Fix float32 safety in Hue/Saturation composite algorithm (#646)
  • [refactor] Use IO[bytes] instead of BinaryIO throughout the codebase (#647)
  • [fix] Fix mypy 2.0 strict-bytes errors in rle.py
  • [ci] Migrate pre-commit hooks to uv-local runners; expand ruff and mypy scope (#650)
  • [chore] Bump mypy to 2.0.0, ruff to 0.15.12, pre-commit to 4.6.0

1.16.0 (2026-04-24) ๐Ÿงš

  • [composite] Add adjustment layer compositing support and fix pass-through compositing logic (#628)
  • [fix] Fix fallback logic and density computation for user masks
  • [refactor] Refactor composite subpackage for type safety and stability (#640)
  • [docs] Update README and usage docs to reflect adjustment layer compositing support
  • [chore] Bump ruff to 0.15.11, mypy to 1.20.1

1.15.0.post1 (2026-04-14) ๐Ÿ™ˆ

  • [ci] Fix release packaging: version.py was not bumped in the v1.15.0 release PR, causing wheels to be built with the wrong version

1.15.0 (2026-04-14) ๐Ÿ’–

  • [api] Add layer_sized option to Mask.topil() for correct rendering of inverted masks (#622, fixes #389)
  • [fix] Graceful fallback for zero-length channel data (#621, fixes #398)
  • [fix] Make artboard background color color-mode aware (#620, fixes #395)
  • [fix] Normalize color space in composite paint to fix mixed-colorspace stroke error (#618, fixes #397)
  • [fix] Compute VectorMask.bbox from full Bรฉzier curve extent, not just anchors (#613)
  • [refactor] Extract color conversion math into psd_tools.color_convert module (#630)
  • [docs] Fix misleading ImageResource signature docstring (#624, fixes #375)
  • [ci] Add Python 3.14 free-threaded (cp314t) wheel support (#633)
  • [ci] Automate release tagging via pull_request closed event (#611)
  • [ci] Add stale issue/PR workflow (#615)
  • [chore] Bump pytest to 9.0.3, ruff to 0.15.10, actions/checkout to v6 (#625, #626, #627)

1.14.3 (2026-04-10) ๐Ÿ›ก๏ธ

  • [security] Upgrade Pygments to 2.20.0 to resolve ReDoS vulnerability (#609)
  • [fix] Don't add USER_LAYER_MASK when PSD mode already carries transparency (#608)
  • [chore] Bump Pillow from 12.1.1 to 12.2.0, mypy to 1.20.0, ruff to 0.15.9

1.14.2 (2026-03-19) โœจ

  • [fix] Detect transparency from negative layer_count in preview path (#595)

1.14.1 (2026-03-17) ๐ŸŒธ

  • [fix] Preserve alpha channel when compositing from layers (#593, fixes #592)
  • [chore] Bump ruff from 0.15.4 to 0.15.6, pypa/cibuildwheel from 3.3.1 to 3.4.0

1.14.0 (2026-03-03) ๐Ÿ‘‘

  • [api] Add PSDImage.background_color property for reading and writing document background color (#586)
  • [api] Add high-level typesetting API for TypeLayer text manipulation (#579)
  • [fix] Update contributing link from master to main branch (#580)
  • [chore] Bump sphinx-rtd-theme from 3.0.2 to 3.1.0, ruff from 0.15.2 to 0.15.4
  • [ci] Bump actions/upload-artifact from 6 to 7, actions/download-artifact from 7 to 8

1.13.1 (2026-02-27) ๐ŸŽ€

  • [psd] Fix TransferFunction curve values parsed as unsigned instead of signed shorts (#577)
  • [psd] Handle truncated MaskParameters data gracefully (#574, fixes #573)
  • [refactor] Drop Python <3.11 typing compatibility guards (#575)
  • [docs] Improve mask module documentation and index layout (#576)

1.13.0 (2026-02-26) ๐Ÿ’…

  • [api] Add Layer.sheet_color property for reading and writing Photoshop layer color labels (#546)
  • [api] Add Layer.create_mask(), remove_mask(), and update_mask() for pixel mask CRUD operations (#568)
  • [api] Auto-create layer masks from alpha channel in PixelLayer.frompil() (#568)
  • [api] Add Mask.disabled setter for toggling layer mask visibility (#568)

1.12.2 (2026-02-24) ๐Ÿฆ‹

  • [api] Fix bbox to exclude clipping layers by default; add include_clipping parameter to Group.extract_bbox() (#566, fixes #547)
  • [api] Fix UTF-16 surrogate pair handling for emoji in text layers (#551)
  • [security] Fix compression security issues (GHSA-24p2-j2jr-386w) (#549)
  • [ci] Fix least-privilege permissions in CI workflows (#550)
  • [ci] Add pre-commit hooks for linting, formatting, and type checking (#552)
  • [ci] Add Dependabot configuration for automated dependency updates (#555)
  • [dev] Extend mypy and ruff coverage to the tests directory (#554)
  • [docs] Clean up developer setup documentation (#553)
  • [chore] Bump Pillow from 11.3.0 to 12.1.1 (#563)
  • [chore] Bump attrs, ipykernel, mypy, pytest, and various GitHub Actions

1.12.1 (2025-12-05) โ„๏ธ

  • [api] Fix preview image mode when saving PSD files (#542)
  • [packaging] Upgrade aggdraw to >=1.4.1 for Python 3.14 Windows support (#543)

1.12.0 (2025-11-17) ๐ŸŒˆ

  • [packaging] Make composite dependencies optional via psd-tools[composite] extra (#525)
  • [api] Lazy-load advanced composite features (vector masks, gradients, effects) so we're not out here importing optional dependencies unless you actually need them ๐Ÿ’…
  • [api] Basic numpy-based compositing works without scipy, scikit-image, or aggdraw โœจ
  • [api] Composite functionality raises ImportError with installation instructions only when advanced features are used
  • [api] Handle missing composite dependencies gracefully in PSDImage.save() (#532) ๐Ÿซถ
  • [packaging] Move aggdraw, scipy, and scikit-image to optional dependencies
  • [packaging] Keep numpy as core dependency for raw pixel data access
  • [refactor] Move PSD class to dedicated document module (#530)
  • [refactor] Reorganize composite module structure and add type safety (#524)
  • [refactor] Split utils module into registry and bin_utils (#537)
  • [refactor] Create shared API utils module (#538)
  • [refactor] Improve type annotations and standardize imports (#539)
  • [api] Add comprehensive type annotations to psd_tools package (#536)
  • [tests] Add comprehensive type annotations to test suite (#534, #535)
  • [tests] Add CI testing without composite dependencies (#533)
  • [docs] Enhance package and module docstrings with comprehensive documentation (#531)
  • [docs] Update installation instructions for optional composite support (#527)
  • [docs] Convert README to Markdown (#527)
  • [ci] Fix CI status badge in README (#523)
  • [ci] Fix ReadTheDocs build by adding Self import fallback
  • [ci] Fix Python 3.10 mypy compatibility (#526)
  • [chore] Remove unused deprecated decorator (#529)
  • [chore] Remove redundant MANIFEST.in file (#528)
โš ๏ธ Breaking change: Users who rely on advanced composite features (vector masks, gradient fills, pattern fills, stroke effects) must now install with pip install 'psd-tools[composite]' or install the optional dependencies separately. Basic pixel layer compositing continues to work with just numpy. This change enables support for Python 3.14 on Windows and other platforms where composite dependencies may not be available. ๐Ÿ’€ yeah bestie it's real

๐ŸŒธ 1.11.1 (2025-11-17)

  • [ci] Disable Python 3.14 on Windows due to aggdraw unavailability (#521) ๐Ÿ˜ญ

๐ŸŽ€ 1.11.0 (2025-11-09)

  • [api] Add public APIs for layer and group creation (#517) ๐Ÿ”ฅ
  • [api] Type safety improvements (#516)
  • [api] Refactor psd_tools.api import dependencies (#515)
  • [api] Fix group blend mode returning None (#514)
  • [dev] Add Claude Code support (#511)
  • [api] Add type annotation to more APIs (#509, #510, #512)
  • [api] Add fill_opacity and reference_point attributes (#507, #508)
  • [psd] Improve pretty print of Subpath (#506)

๐Ÿ’– 1.10.13 (2025-10-02)

  • [docs] Fix incorrect method name in the usage (#504)
  • [api] Fix updated status flag (#503)
  • [api] Add tree traversal API (#502)
  • [psd] Fix crash when reading malformed Levels record (#501)

๐Ÿฆ‹ 1.10.12 (2025-09-25)

  • [api] Drop docopt dependency (#498)
  • [api] Remove unused imports (#497)
  • [api] Fix stacked clip layer handling (#496)

โœจ 1.10.11 (2025-09-24)

  • [tests] Drop python2 compatibility code (#494)
  • [api] Fix clip layer handling (#493)
  • [psd] Workaround CAI tagged block reconstruction (#492)

๐Ÿ“ 1.10.10 (2025-09-18)

  • [api] Fix clipping with stroke composite (#489)
  • [ci] Fix documentation build (#486, #487)
  • [ci] Introduce ABI3 wheels (#483, #485)
  • [api] Fix PyCMSError in composite (#484)
  • [api] Fix ImageMath deprecation warning (#482)

๐Ÿ’œ 1.10.9 (2025-08-07)

  • [psd] Allow linked layer version 8 (#476)

๐Ÿงš 1.10.8 (2025-06-06)

  • [ci] Update CI configuration (#471)
  • [psd] Workaround levels adjustment layer parsing (#470)
  • [psd] Support CAI, GenI, OCIO tagged blocks (#469)

๐ŸŒˆ 1.10.7 (2025-02-25)

  • [psd] Fix missing gradient method (#465)

๐Ÿ‘‘ 1.10.6 (2025-02-18)

  • [security] Update pillow dependency (#462) ๐Ÿ”’

๐ŸŒธ 1.10.5 (2025-02-18)

  • [security] Update pillow dependency (#461) ๐Ÿ”’

๐ŸŽ€ 1.10.4 (2024-11-25)

  • [api] Allow Path objects for PSDImage open (#452)

๐Ÿ’ซ 1.10.3 (2024-11-20)

  • [psd] Fix data corruption by irregular OSType (#449)
  • [api] Add type annotation to the high-level APIs (#448)

๐Ÿฆ‹ 1.10.2 (2024-10-23)

  • [api] Add channel info via DisplayInfo (#443)
  • [api] Support layer locking (#442)

โœจ 1.10.1 (2024-10-10)

  • [api] Fix artboard creation (#438)
  • [api] Fix layer conversion issue (#435)

๐Ÿ”ฅ 1.10.0 (2024-09-26)

  • [api] Support basic layer structure editing (#428)
  • [api] Drop deprecated compose module (#432)

๐Ÿ’– 1.9.34 (2024-07-01)

  • [api] Support text type property (#419)
  • [psd] Improve RLE decoding error handling (#417)

๐Ÿ“ 1.9.33 (2024-06-14)

  • [psd] Raise IO error instead of assertion (#413)
  • [api] Add a new property to SmartObject: transform_box (#412)
  • [ci] Migrate code formatter to ruff (#408)

๐ŸŒˆ 1.9.32 (2024-05-01)

  • [psd] Fix incorrect group divider handling (#399)

๐Ÿ’œ 1.9.31 (2024-02-26)

  • [psd] Reworked packbits/rle algorithms (#392)

๐Ÿงš 1.9.30 (2024-01-06)

  • [ci] Fix missing pyx file in sdist (#386)

๐Ÿ‘‘ 1.9.29 (2024-01-04)

  • [ci] Update CI configuration (#383)
  • [dev] Migrate the builder to pyproject.toml
  • [dev] Update linter and formatter to pysen
  • [dev] Deprecate tox
  • [psd] Add new color sheet (#380)
  • [psd] Fix transparency check (#370)

๐ŸŒธ 1.9.28 (2023-07-04)

  • [psd] Add alternate 8ELE signiture for 8BIM tagged block (#367)

๐ŸŽ€ 1.9.27 (2023-06-27)

  • [composite] Fix regression by #361 (#364)

๐Ÿ’ซ 1.9.26 (2023-06-21)

  • [composite] Read HSB colors in RGB and CMYK color modes (#361)
  • [ci] Update CI configuration (#362)

๐Ÿฆ‹ 1.9.25 (2023-06-19)

  • [composite] Fix hue, sat, and vivid light (#359)

โœจ 1.9.24 (2023-01-17)

  • [psd] Support float RGB values (#350)
  • [psd] Workaround stroke class ID (#346)
  • [ci] Update CI configuration (#347)
  • [composite] Fix group clipping (#336)

๐Ÿ”ฅ 1.9.23 (2022-09-26)

  • [api] Add bbox invalidation when toggling layer visibility (#334)

๐Ÿ’– 1.9.22 (2022-09-09)

  • [psd] Add support for v3 gradient map adjustment layer (#330)

๐Ÿ“ 1.9.21 (2022-06-18)

  • [api] Fix incorrect has_effects behavior (#322)
  • [composite] Improve blending numerical stability (#321)
  • [composite] Improve non-RGB modes and transparency (#319, @Etienne-Gautier)
  • [psd] Workaround assertion error in broken file (#320)

๐ŸŒˆ 1.9.20 (2022-05-16)

  • [ci] Update CI configuration (#313 #314)
  • [composite] Fix composite errors (#312)
  • [psd] Suppress vowv tagged blocks (#306)

๐Ÿ’œ 1.9.19 (2022-04-15)

  • [composite] Fix rasterized shape composite (#301 #302)

๐Ÿงš 1.9.18 (2021-08-20)

  • [api] Fix missing effect attributes (#284)
  • [package] Support additional platforms (i686, aarch64, universal2, win32)
  • [package] Drop py36 support

๐Ÿ‘‘ 1.9.17 (2021-01-15)

  • [api] Fix incorrect fill layer parse (fix #254)

๐ŸŒธ 1.9.16 (2020-09-24)

  • [package] Drop py27 and py35 support
  • [psd] Workaround Enum bug (fix #241)
  • [composite] Fix transparency issue (fix #242)
  • [composite] Fix mask disable flag (fix #243)
  • [api] Add workaround for creating PSB (fix #246)
  • [api] Fix incorrect adjustment parse (fix #247)

๐ŸŽ€ 1.9.15 (2020-07-17)

  • [composite] Fix ignored clip layers for groups.
  • [composite] Fix out-of-viewport stroke effect.

๐Ÿ’ซ 1.9.14 (2020-07-10)

  • [api] Bugfix for PSDImage composite layer_filter option.
  • [api] Bugfix for transparency and alpha distinction.
  • [psd] Rename COMPOSITOR_INFO.
  • [composite] Fix stroke effect target shape.

๐Ÿฆ‹ 1.9.13 (2020-05-25)

  • [api] Bugfix for PSDImage init internal.

โœจ 1.9.12 (2020-05-20)

  • [psd] Bugfix for CurvesExtraMarker read.

๐Ÿ”ฅ 1.9.11 (2020-05-01)

  • [composite] Fix layer check.

๐Ÿ’– 1.9.10 (2020-04-21)

  • [psd] Fix engine data parser.

๐Ÿ“ 1.9.9 (2020-03-30)

  • [composite] Fix stroke effect argument.

๐ŸŒˆ 1.9.8 (2020-03-18)

  • [composite] Fix incorrect fill opacity handling in compositing.
  • [composite] Fix incorrect alpha for patterns.

๐Ÿ’œ 1.9.7 (2020-03-17)

  • [composite] Fix path operation for merged components.
  • [composite] Fix vector mask compositing condition.

๐Ÿงš 1.9.6 (2020-03-16)

  • [composite] Fix incorrect alpha channel handling in composite.

๐Ÿ‘‘ 1.9.5 (2020-03-11)

  • [api] Add ignore_preview option to PSDImage.composite.
  • [composite] Improve stroke effect composition for vector masks.
  • [composite] Avoid crash when there is an erroneous subpath.
  • [composite] Workaround possible divide-by-zero warn in stroke composition.
  • [composite] Fix incorrect pattern transparency handling.
  • [composite] Fix ignored effects in direct group composition.
  • [composite] Fix incorrect opacity handling for clip layers.

๐ŸŒธ 1.9.4 (2020-03-11)

  • [compression] Security fix, affected versions are 1.8.37 - 1.9.3. ๐Ÿšจ

๐ŸŽ€ 1.9.3 (2020-03-10)

  • [composite] Fix memory corruption crash for pattern data in PSB files.
  • [psd] Add image data pretty printing.

๐Ÿ’ซ 1.9.2 (2020-03-03)

  • [psd] Add missing resource ID.
  • [psd] Fix pretty printing regression.
  • [psd] Fix big tag key for linked layers.
  • [psd] Support frgb tag.
  • [psd] Support sgrp metadata key.
  • [psd] Support patt tag.
  • [psd] Workaround unknown engine data.

๐Ÿฆ‹ 1.9.1 (2020-02-28)

  • [psd] Minor bugfix.

โœจ 1.9.0 (2020-02-26)

  • [composite] Implement NumPy-based compositing functionality.
  • [composite] Support blending modes other than dissolve.
  • [composite] Support blending in RGB, CMYK, Grayscale.
  • [api] Introduce NumPy array export method.
  • [api] Drop deprecated methods from v1.7.x such as as_PIL.
  • [api] Deprecate compose method.
  • [compression] Rename packbits to rle.
  • [compression] Improve RLE decode efficiency.
  • [tests] Additional compositing tests.

๐Ÿ”ฅ 1.8.38 (2020-02-12)

  • [composer] fix crash when gradient fill is in stroke.

๐Ÿ’– 1.8.37 (2020-02-07)

  • [compression] Remove packbits dependency and introduce cython implementation.
  • [deploy] Move CI provider from Travis-CI to Github Actions.
  • [deploy] Start distributing binary wheels.

๐Ÿ“ 1.8.36 (2019-12-26)

  • [psd] add safeguard for malformed global layer mask info parser.

๐ŸŒˆ 1.8.35 (2019-12-26)

  • [api] remove duplicate has_mask() definition.
  • [composer] fix empty effects check.

๐Ÿ’œ 1.8.34 (2019-11-28)

  • [api] fix compose() arguments.
  • [psd] fix attrs version dependency.

๐Ÿงš 1.8.33 (2019-11-28)

  • [api] add include_invisible option to Group.extract_bbox.
  • [psd] fix deprecated attrs api.

๐Ÿ‘‘ 1.8.32 (2019-11-28)

  • [psd] fix 16/32 bit file parsing bug introduced in 1.8.17.

๐ŸŒธ 1.8.31 (2019-11-27)

  • [psd] bugfix reading psb.
  • [psd] bugfix reading slices resource.
  • [security] so bestie, the dependency got bumped to pillow >= 6.2.0. stay safe out here ๐Ÿ’…

1.8.30 (2019-09-24)

  • [psd] we now do a little workaround so reading a less-than-4-byte int out of a malformed psd file doesn't ruin your whole day โœจ

1.8.29 (2019-09-10)

  • [composer] fixed the vector mask bbox situation when composing ๐ŸŽ€

1.8.28 (2019-09-09)

  • [api] Effects.__repr__() was being weird when the data was empty โ€” fixed, slay ๐Ÿ’–

1.8.27 (2019-08-29)

  • [api] PSDImage.open and PSDImage.save now accept the encoding param, iconic
  • [deploy] bugfix for the travis deployment condition ๐Ÿซถ

1.8.26 (2019-08-28)

  • [composer] group mask is supported now ๐Ÿ’ซ

1.8.25 (2019-08-07)

  • [api] the return type of PSDImage.color_mode got changed to enum ๐Ÿ‘‘
  • [api] reading of bitmap color mode is supported now
  • [api] the channel option is supported in the topil() method ๐ŸŒธ

1.8.24 (2019-07-25)

  • [composer] experimental support for commutative blending modes, very much a science moment ๐Ÿงช

1.8.23 (2019-06-24)

  • [composer] fixed clipping on alpha-less images
  • [composer] fixed the stroke effect for flat planes
  • [composer] workaround for insufficient knots
  • [composer] fix for custom color space ๐ŸŒˆ

1.8.22 (2019-06-19)

  • fixed the pass-through composing bug
  • fixed alpha blending in effects
  • fixed vector mask composition
  • experimental support for shape stroke โœจ
  • experimental support for stroke effect โœจ

1.8.21 (2019-06-18)

  • the effect property return type changed from str to enum
  • gradient quality got improved, lowkey a glow-up
  • fill opacity and layer opacity are supported now
  • added the tmln key in metadata setting ๐Ÿ’…

1.8.20 (2019-06-13)

  • gradient styles are supported now ๐ŸŽ€

1.8.19 (2019-06-11)

  • fixed the broken psd_tools.composer.vector module from 1.8.17 ๐Ÿ˜ญ
  • experimental support for color noise gradient
  • bugfix for clip masks
  • bugfix for CMYK composing

1.8.17 (2019-06-05)

  • moved the psd_tools.api.composer module over to the psd_tools.composer package
  • 19 blending modes are supported in the composer, no cap
  • fill opacity is supported
  • fixed image size when composing with masks
  • renamed TaggedBlockID to Tag
  • renamed ImageResourceID to Resource
  • added a bytes mixin to Enum constants
  • replaced Enum keys with raw values in psd_tools.psd.base.Dict classes ๐Ÿ’œ

1.8.16 (2019-05-24)

  • fixed broken group compose from 1.8.15
  • fixed missing pattern / gradient composition in vector stroke content ๐ŸŒธ

1.8.15 (2019-05-23)

  • coding style fix, we love a tidy moment
  • fixed the compose() bbox option ๐Ÿซถ

1.8.14 (2019-04-12)

  • added a dependency on aggdraw
  • bezier curves in vector masks are supported now
  • path operations are supported now
  • fixed compose(force=True) behavior
  • fixed the default background color in the composer
  • improved pattern overlay parameter support
  • fixed gradient map generation for a single stop โญ

1.8.13 (2019-04-05)

  • fixed the engine_data unknown tag format
  • fixed compose for extra alpha channels
  • workaround for a pillow 6.0.0 bug ๐Ÿ™ˆ

1.8.12 (2019-03-25)

  • added the apply_icc option in pil io โœจ

1.8.11 (2019-03-14)

  • introduced the terminology module
  • reduced memory use in read
  • added main testing ๐Ÿ’–

1.8.10 (2019-02-27)

  • fixed the PSB extn key size bug

1.8.9 (2019-02-21)

  • documentation updates
  • introduced the Artboard class ๐ŸŽ€

1.8.8 (2019-02-20)

  • reverted the package name back to psd_tools
  • prepared for merging into the main repo

1.8.7 (2019-02-15)

  • minor bugfix, tiny lil thing ๐Ÿฆ‹

1.8.6 (2019-02-14)

  • changed the _psd pointer in PSDImage
  • added the version property
  • fill effects are supported in the composer now ๐Ÿ’…

1.8.5 (2019-02-05)

  • changed the tagged block / image resource singleton accessor in the user API
  • added documentation on iterator order
  • fixed the export setting 1 big key config
  • fixed the computer info big key config ๐ŸŒธ

1.8.3 (2019-02-01)

  • added channel size checking in topil
  • added mlst metadata decoding
  • fixed the key collision issue in descriptor
  • performance improvement for packbit encoding/decoding
  • dropped the cython dependency in the travis config
  • implemented thumbnail, is_group, and parent methods in PSDImage ๐Ÿ‘‘

1.8.0 (2019-01-24)

  • major API changes, buckle up bestie
  • package name changed to psd_tools2
  • completely rewritten decoding subpackage psd_tools2.psd
  • improved composer functionality
  • file write support ๐Ÿ”ฅ
  • dropped the cython compression module, which makes the package pure-python
  • dropped pymaging support

1.7.30 (2019-01-15)

  • composer alpha blending fix
  • documentation fix

1.7.28 (2019-01-09)

  • cinf tagged block is supported now ๐Ÿ’ซ

1.7.27 (2018-12-06)

  • added the missing extra image resource block signatures

1.7.26 (2018-12-03)

  • moved the psd_tools tests under tests/psd_tools ๐ŸŽ€

1.7.25 (2018-11-27)

  • fixed alpha channel visibility of the composed image

1.7.24 (2018-11-21)

  • fixed the unit rectangle drawing size

1.7.23 (2018-11-20)

  • fixed ignored visibility in bbox calculation ๐ŸŒธ

1.7.22 (2018-10-12)

  • dropped py34 support
  • fixed the tobytes deprecation warning

1.7.21 (2018-10-10)

  • fixed the gradient descriptor bug ๐Ÿฆ‹

1.7.20 (2018-10-09)

  • fixed the coloroverlay bug
  • fixed the gradient angle bug
  • fixed the curves decoder bug

1.7.19 (2018-10-02)

  • fixed the descriptor decoder โœจ

1.7.18 (2018-09-26)

  • added shape rendering in compose()
  • added grayscale support ๐Ÿ’œ

1.7.17 (2018-09-21)

  • fixed the has_pixel() condition

1.7.16 (2018-08-29)

  • fixed fill opacity in compose()
  • workaround for broken PrintFlags ๐Ÿซถ

1.7.15 (2018-08-28)

  • fixed the color overlay issue in compose() ๐Ÿ’…

1.7.14 (2018-08-24)

  • fixed the verbose arg for python 3.7 compatibility

1.7.13 (2018-08-10)

  • fixed has_pixel() for partial channels
  • color overlay is supported in compose() now ๐ŸŒˆ

1.7.12 (2018-06-25)

  • fixed mask rendering in compose (Thanks @andrey-hider and @nkato) ๐Ÿ’–

1.7.11 (2018-06-11)

  • unicode bugfixes ๐ŸŽ€

1.7.10 (2018-06-06)

  • fixed descriptor decoding errors
  • minor bugfixes

1.7.9 (2018-06-05)

  • fixed UnicodeError in exif
  • workaround for irregular descriptor names
  • added undocumented extn tagged block decoding
  • moved the duplicated icc module to a subpackage
  • PIL rendering with extra alpha channels is supported now โœจ

1.7.8 (2018-05-29)

  • updated the documentation
  • fixed PEP8 compliance
  • renamed merge_layers to compose ๐Ÿฆ‹

1.7.7 (2018-05-02)

  • fixed the white background issue in as_PIL()

1.7.6 (2018-04-27)

  • added quality testing
  • fixed the disabled mask ๐Ÿ’…

1.7.5 (2018-04-25)

  • fixed the has_mask() condition
  • added mask composition in merge_layers()
  • fixed mask display ๐ŸŒธ

1.7.4 (2018-03-06)

  • fixed the infinity loop in print_tree() ๐Ÿ˜ญ

1.7.3 (2018-02-27)

  • added the vector origination API
  • fixed shape and vector mask identification
  • changed the enum name conversion
  • updated the docs โญ

1.7.2 (2018-02-14)

  • added the adjustments API
  • added the mask API
  • bugfix for tagged_blocks decoders ๐Ÿ’œ

1.7.1 (2018-02-08)

  • added the mask user API
  • added the layer coordinate user API
  • added the vector mask and vector stroke API
  • cleaned up the user API
  • added automatic descriptor conversion ๐Ÿซถ

1.7.0 (2018-01-25)

  • cleaned up the user API organization
  • removed the json encoder api
  • made cli a package main ๐Ÿ‘‘

1.6.7 (2018-01-17)

  • workaround for anaconda 2.7 pillow
  • bbox existence checkf ๐Ÿ™ˆ

1.6.6 (2018-01-10)

  • experimental clipping support in merge_layer()
  • reverted as_PIL() in AdjustmentLayer ๐Ÿ’ซ

1.6.5 (2017-12-22)

  • Small fix for erroneous unicode path name ๐ŸŽ€

1.6.4 (2017-12-20)

  • Add all_layers() method
  • Add _image_resource_blocks property
  • Add thumbnail() method โœจ

1.6.3 (2017-09-27)

  • documentation updates
  • github repository renamed to psd-tools2
  • AdjustmentLayer fix ๐ŸŒธ

1.6.2 (2017-09-13)

  • layer class structure reorganization
  • added the Effects API
  • added TypeLayer API methods ๐Ÿ’…

1.6 (2017-09-08)

  • PSDImage user API update
  • user API adds distinct layer types
  • Sphinx documentation ๐Ÿฆ‹

1.5 (2017-07-13)

  • implemented many decodings of image resources and tagged blocks
  • implemented EngineData text information
  • user API for getting mask and patterns
  • user API to calculate bbox for shape layers ๐Ÿ’œ

1.4 (2017-01-02)

  • Fixed reading of layer mask data (thanks Evgeny Kopylov)
  • Python 2.6 support is dropped
  • Python 3.6 support is added (thanks Leendert Brouwer)
  • extension is rebuilt with Cython 0.25.2 โญ

1.3 (2016-01-25)

  • fixed references decoding (thanks Josh Drake)
  • fixed PIL support for CMYK files (thanks Michael Wu)
  • optional C extension is rebuilt with Cython 0.23.4
  • Python 3.2 support is dropped; the package still works in Python 3.2, but the compatibility is no longer checked by tests, and so it can break in future
  • declare Python 3.5 as supported ๐ŸŽ€

1.2 (2015-01-27)

  • implemented extraction of embedded files (embedded smart objects) - thanks Volker Braun
  • optional C extension is rebuilt with Cython 0.21.2
  • hg mirror on bitbucket is dropped, sorry! ๐Ÿ˜ญ

1.1 (2014-11-17)

  • improved METADATA_SETTING decoding (thanks Evgeny Kopylov)
  • layer comps decoding (thanks Evgeny Kopylov)
  • improved smart objects decoding (thanks Joey Gentry)
  • user API for getting layer transforms and placed layer size (thanks Joey Gentry)
  • IPython import is deferred to speedup psd-tools.py command-line utility
  • _RootGroup.__repr__ is fixed
  • warning message building is more robust
  • optional C extension is rebuilt with Cython 0.21.1 โœจ

1.0 (2014-07-24)

  • Fixed reading of images with layer masks (thanks Evgeny Kopylov)
  • improved mask data decoding (thanks Evgeny Kopylov)
  • fixed synchronization in case of 8B64 signatures (thanks Evgeny Kopylov)
  • fixed reading of layers with zero length (thanks Evgeny Kopylov)
  • fixed Descriptor parsing (thanks Evgeny Kopylov)
  • some of the descriptor structures and tagged block constants are renamed (thanks Evgeny Kopylov)
  • PATH_SELECTION_STATE decoding (thanks Evgeny Kopylov)
  • the library is switched to setuptools; docopt is now installed automatically ๐Ÿ’–

0.10 (2014-06-15)

  • Layer effects parsing (thanks Evgeny Kopylov)
  • trailing null bytes are stripped from descriptor strings (thanks Evgeny Kopylov)
  • "Reference" and "List" descriptor parsing is fixed (thanks Evgeny Kopylov)
  • scalar descriptor values (doubles, floats, booleans) are now returned as scalars, not as lists of size 1 (thanks Evgeny Kopylov)
  • fixed reading of EngineData past declared length (thanks Carlton P. Taylor)
  • "background color" Image Resource parsing (thanks Evgeny Kopylov)
  • psd_tools.decoder.actions.Enum.enum field is renamed to psd_tools.decoder.actions.Enum.value (thanks Evgeny Kopylov)
  • code simplification โ€” constants are now bytestrings, exactly as they should have been all along (ty Evgeny Kopylov ๐Ÿ’–);
  • Python 3.4 is supported ๐Ÿ.

๐Ÿ’ซ 0.9.1 (2014-03-26)

  • merging of transparent layers got way better (thank you Vladimir Timofeev โœจ);
  • fixed layer merging and bounding box calculations for empty layers (thanks again Vladimir Timofeev ๐Ÿซถ);
  • the C extension is rebuilt with Cython 0.20.1.

๐ŸŒˆ 0.9 (2013-12-03)

  • the psd-tools.py command-line interface changed, and a 'debug' command was added ๐Ÿ”;
  • pretty-printing of internal structures, it's giving aesthetic;
  • pymaging support is fixed;
  • 'MeSa' is now allowed as a signature for image resource blocks (thanks Alexey Buzanov ๐Ÿ’…);
  • the psd_tools.debug.debug_view utility function is fixed;
  • Photoshop CC constants are added ๐Ÿ‘‘;
  • Photoshop CC vector origination data is decoded;
  • binary data is preserved if descriptor parsing fails (no data loss, we don't do that here);
  • more verbose logging for the PSD reader;
  • the channel data reader became more robust โ€” it now does not read past the declared channel length;
  • the psd-tools.py --version command is fixed;
  • lsdk tagged blocks parsing: this fixes some issues with layer grouping (thanks Ivan Maradzhyiski for the bug report and the patch ๐Ÿ’œ);
  • CMYK images support is added (thanks Alexey Buzanov, Guillermo Rauch and https://github.com/a-e-m for the help ๐ŸŽ€);
  • Grayscale images support is added (thanks https://github.com/a-e-m);
  • LittleCMS is now optional (but it is still required to get proper colors) โ€” so like, optional unless you want correct colors, bestie ๐Ÿ˜ญ.

๐Ÿฆ‹ 0.8.4 (2013-06-12)

  • Point and Millimeter types are added to UnitFloatType (thanks Doug Ellwanger โœจ).

๐ŸŒธ 0.8.3 (2013-06-01)

  • some issues with descriptor parsing are fixed (thanks Luke Petre).

๐Ÿ“ 0.8.2 (2013-04-12)

  • Python 2.x: reading data from file-like objects is fixed (thanks Pavel Zinovkin).

๐Ÿ’€ 0.8.1 (2013-03-02)

  • fixed parsing of layer groups without an explicit OPEN_FOLDER mark;
  • the Cython extension is rebuilt with Cython 0.18.

โญ 0.8 (2013-02-26)

  • descriptor parsing (thanks Oliver Zheng ๐Ÿ’–);
  • text (as string) is extracted from text layers (thanks Oliver Zheng);
  • improved support for optional building of the Cython extension.

๐Ÿงš 0.7.1 (2012-12-27)

  • a typo is fixed: LayerRecord.cilpping should be LayerRecord.clipping. Thanks Oliver Zheng ๐Ÿ™ˆ.

๐Ÿ’… 0.7 (2012-11-08)

  • highly experimental: basic layer merging is implemented (like, it's now possible to export a layer group to a PIL image);
  • Layer.visible no longer takes group visibility into account;
  • Layer.visible_global is the old Layer.visible;
  • psd_tools.user_api.combined_bbox made public;
  • Layer.width and Layer.height are removed (use layer.bbox.width and layer.bbox.height instead);
  • pil_support.composite_image_to_PIL is renamed to pil_support.extract_composite_image and pil_support.layer_to_PIL is renamed to pil_support.extract_layer_image so that pil_support and pymaging_support have the same API.

๐ŸŒŸ 0.6 (2012-11-06)

  • psd.composite_image() is renamed to psd.as_PIL();
  • Pymaging support: the psd.as_pymaging() and layer.as_pymaging() methods.

๐ŸŽ€ 0.5 (2012-11-05)

  • support for zip and zip-with-prediction compression methods is added;
  • support for 16/32bit layers is added;
  • an optional Cython extension for faster zip-with-prediction decompression;
  • other speed improvements ๐ŸŽ๏ธ.

๐Ÿซถ 0.2 (2012-11-04)

  • initial support for 16bit and 32bit PSD files: psd-tools v0.2 can read composite (merged) images for such files and extract information (names, dimensions, hierarchy, etc.) about layers and groups of 16/32bit PSD; extracting image data for distinct layers in 16/32bit PSD files is not supported yet;
  • better Layer.__repr__;
  • a bbox property for Group.

๐Ÿ“ 0.1.4 (2012-11-01)

Packaging is fixed in this release.

๐ŸŒˆ 0.1.3 (2012-11-01)

  • better support for 32bit images (still incomplete);
  • the reader is able to handle "global" tagged layer info blocks that were previously discarded.

โœจ 0.1.2 (2012-10-30)

  • warn about 32bit images;
  • transparency support for composite images.

๐Ÿ’œ 0.1.1 (2012-10-29)

Initial release (v0.1 had packaging issues).


๐Ÿ’– Contributing

Development happens at github: bug tracker https://github.com/psd-tools/psd-tools/issues. Feel free to submit bug reports https://github.com/psd-tools/psd-tools/issues/new or pull requests ๐Ÿซถ. Attaching an erroneous PSD file makes the debugging process faster. Such a PSD file might be added to the test suite.

The license is MIT.


๐Ÿงš Package design

The package consists of four major subpackages:

  1. psd_tools.psd <#module-psd_tools.psd>: the subpackage that reads/writes the low-level binary structure of the PSD/PSB file. The core data structures are built around attrs <https://www.attrs.org/en/stable/index.html#> classes that all implement read and write methods. Each data object tries to resemble the structure described in the specification https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/. Although documented, the specification https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/ is far from complete and some parts are even inaccurate. When psd-tools finds an unknown data structure, the package keeps such data as bytes in the parsed result ๐Ÿ™ˆ.
  2. psd_tools.api <#module-psd_tools.api>: the user-facing API that implements various easy-to-use methods which manipulate the low-level psd_tools.psd <#module-psd_tools.psd> data structures. This is the primary interface for most users ๐Ÿ‘‘.
  3. psd_tools.composite <#module-psd_tools.composite>: the rendering engine for layer compositing and blending. This subpackage implements blend modes, layer effects (drop shadows, strokes, etc.), and vector shape rasterization โœจ. It uses NumPy arrays for efficient pixel manipulation and includes optional dependencies (scipy, scikit-image, aggdraw) that must be installed via the composite extra.
  4. psd_tools.compression <#module-psd_tools.compression>: image compression codecs for raw data, RLE (Run-Length Encoding), and ZIP compression. The RLE codec includes a Cython-optimized implementation (_rle.pyx) that falls back to pure Python if not compiled, providing significant performance improvements for large files ๐ŸŽ๏ธ.

In the future, it might be good to implement the Photoshop API https://developer.adobe.com/photoshop/uxp/2022/ps_reference/ on top of the existing psd-tools API.


๐ŸŒธ Testing

In order to run tests, make sure PIL/Pillow is built with LittleCMS or LittleCMS2 support. For example, on Ubuntu, install the following packages:

apt-get install liblcms2-dev libjpeg-dev libfreetype6-dev zlib1g-dev

Then install psd-tools with development dependencies:

uv sync --group dev --extra composite

Finally, run tests:

uv run pytest

๐ŸŽ€ Documentation

Install documentation dependencies:

uv sync --group docs

Once installed, use the Makefile:

make docs

๐Ÿ”ฅ Release Process

Releases are automated via GitHub Actions ๐Ÿค–. Only maintainers with appropriate repository permissions can trigger releases. The following repository secrets must be configured:

  • RELEASE_WORKFLOW_TOKEN: a fine-grained PAT with contents: write, required so that the tag pushed by auto-tag.yml triggers the downstream release.yml workflow (the default GITHUB_TOKEN cannot do this).
  • PYPI_USERNAME / PYPI_PASSWORD: PyPI credentials for publishing.
  1. Decide the version number following PEP 440 https://peps.python.org/pep-0440/ based on the changes since the last release. The auto-tag workflow recognises these forms:
    • v1.2.3 โ€” standard release
    • v1.2.3a1, v1.2.3b1, v1.2.3rc1 โ€” pre-releases (alpha, beta, release candidate)
    • v1.2.3.post1 โ€” post-release
  2. Update the changelog: review git log since the last tag and summarize changes in docs/changelog.rst under the new version heading ๐Ÿ“.
  3. Create a release PR: create a branch named release/<version>, where <version> is one of the supported version forms listed above (e.g. release/v1.15.0, release/v1.15.0rc1, or release/v1.15.0.post1), commit the changelog update (and any version bumps), and open a PR against main. Merge it once approved. The branch name is how the auto-tag workflow identifies the version to tag ๐Ÿ”.
  4. Automated tagging and publishing: merging the release PR triggers the auto-tag workflow, which tags the exact merge commit that landed on main (using merge_commit_sha) and pushes the tag. This in turn triggers the release workflow, which:
    • builds wheels for all supported platforms (Linux, Windows, macOS including ARM)
    • generates release notes from git commits since the previous tag
    • creates a GitHub release with the auto-generated changelog
    • publishes the package to PyPI ๐Ÿš€
  5. Verify the release:

๐Ÿ’œ Acknowledgments

Great thanks to all the contributors https://github.com/psd-tools/psd-tools/graphs/contributors ๐Ÿซถ.


๐Ÿฆ‹ psd_tools

See Usage <> for examples.


๐Ÿ‘‘ PSDImage

class psd_tools.PSDImage(data: PSD <#psd_tools.psd.PSD>)

Photoshop PSD/PSB document ๐Ÿ“ธ.

The low-level data structure is accessible at PSDImage._record.

Example:

from psd_tools import PSDImage

psdimage = PSDImage.open('example.psd')
image = psdimage.composite()

for layer in psdimage:
    layer_image = layer.composite()

append(layer: Layer <#psd_tools.api.layers.Layer>) -> None

Add a layer to the end (top) of the group.

This operation rewrites the internal references of the layer. Adding the same layer will not create a duplicate ๐Ÿ‘€.

Parameters

  • layer โ€” the layer to add.

Raises

  • TypeError โ€” if the provided object is not a Layer instance.
  • ValueError โ€” if attempting to add a group to itself.

property background_color: float | tuple[float, ...] | None

Background color for the merged composite image. Writable โœ๏ธ.

When you set it, save() composites layers against an opaque backdrop of this color instead of a transparent one. It's giving major RGB-mode PSD files where the transparent areas should show up as a specific color (like white ๐Ÿฅ›) in the merged composite. obsessed with the utility tbh

Values live in the [0.0, 1.0] range, matching the composite() color parameter โ€” so:

  • RGB / Grayscale: 1.0 = white, 0.0 = black
  • CMYK: (0.0, 0.0, 0.0, 0.0) = white (no ink) ๐Ÿ–จ๏ธ

Use a scalar for uniform color, or a tuple for per-channel values. Set it to None for a transparent backdrop (the legacy behavior, bestie ๐Ÿ’…).

Documents created via new() have this set automatically from the color parameter. so convenient fr fr โœจ

Returns: float, tuple[float, ...], or None

Example:

psd = PSDImage.new('RGB', (640, 480), color=1.0)
psd.save('output.psd')  # White background, 3 channels (no alpha)

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

The minimal bounding box that contains all the visible layers ๐Ÿ‘‘ the tightest little hug around everything you can actually see.

Wanna grab the viewport bounding box instead? Use viewbox (psd_tools.api.psd_image.PSDImage.viewbox). And when the psd is empty, bbox is equal to the canvas bounding box โ€” yes, like an empty canvas still has a box ๐Ÿซถ

Returns: (left, top, right, bottom) tuple.

property bottom: int

Bottom coordinate ๐Ÿ‘ just the bottom, that's the whole vibe.

Returns: int

property channels: int

How many color channels the doc has ๐ŸŒˆ.

Returns: int

clear() -> None

Clears the group. poof ๐Ÿ’จ gone.

Heads up bestie, this operation rewrites the internal references of the layers โ€” so it's not just a cosmetic delete, it's a lil internal remix.

Returns: None

property color_mode: ColorMode

Document color mode, such as 'RGB' or 'GRAYSCALE' ๐ŸŽจ see ColorMode (psd_tools.constants.ColorMode).

Returns: ColorMode (psd_tools.constants.ColorMode)

property compatibility_mode: CompatibilityMode

Sets the compositing and layer organization compatibility mode. Writable ๐Ÿ‘€

This property checks whether the PSD file is compatible with specific authoring tools, such as Photoshop or CLIP Studio Paint. Different authoring tools may have different ways of handling layers, such as the use of clipping masks for groups. Default is Photoshop compatibility mode.

Returns: CompatibilityMode (psd_tools.constants.CompatibilityMode)

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

Composite the PSD image ๐Ÿ–ผ๏ธ the main character move where all your layers become one pretty picture.

Parameters

  • viewport โ€” Viewport bounding box specified by an (x1, y1, x2, y2) tuple. Default is the viewbox of the PSD.
  • ignore_preview โ€” Boolean flag for whether to skip compositing when a pre-composited preview is available.
  • force โ€” Boolean flag to force vector drawing.
  • color โ€” Backdrop color specified by a scalar or tuple of scalars. 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 the layer is composited. Default is is_visible().

Returns: PIL.Image.

count(layer: Layer) -> int

Counts the number of occurrences of a layer in the group ๐Ÿ”ข like a "how many of u are there" check.

Parameters

  • layer โ€” The layer to count.

create_group(layer_list: Iterable[Layer] | None = None, name: str = 'Group', opacity: int = 255, blend_mode: BlendMode = BlendMode.PASS_THROUGH, open_folder: bool = True) -> Group

Create a new group layer and add it to the PSDImage ๐ŸŽ€ fresh folder energy.

Example:

group = psdimage.create_group(name='New Group')
group.append(psdimage.create_pixel_layer(image, name='Layer in Group'))

Parameters

  • layer_list โ€” Optional list of layers to add to the group.
  • name โ€” Name of the new group.
  • opacity โ€” Opacity of the new layer (0-255).
  • blend_mode โ€” Blend mode of the new layer, default is BlendMode.PASS_THROUGH.
  • open_folder โ€” Whether the group is an open folder in the Photoshop UI.

Returns: The created Group (psd_tools.api.layers.Group) object.

create_pixel_layer(image: Image, name: str = 'Layer', top: int = 0, left: int = 0, compression: Compression = Compression.RLE, opacity: int = 255, blend_mode: BlendMode = BlendMode.NORMAL) -> PixelLayer

Create a brand new pixel layer and add it to the PSDImage โœจ.

Example:

psdimage = PSDImage.new("RGB", (640, 480))
layer = psdimage.create_pixel_layer(image, name='Layer 1')

Parameters

  • name โ€” Name of the new layer.
  • image โ€” PIL Image object.
  • top โ€” Top coordinate of the new layer.
  • left โ€” Left coordinate of the new layer.
  • compression โ€” Compression method for the layer image data.
  • opacity โ€” Opacity of the new layer (0-255).
  • blend_mode โ€” Blend mode of the new layer, default is BlendMode.NORMAL.

Returns: The created PixelLayer (psd_tools.api.layers.PixelLayer) object.

property depth: int

Pixel depth bits ๐Ÿ”.

Returns: int

descendants(include_clip: bool = True) -> Iterator[Layer]

Return a generator to iterate over all descendant layers ๐ŸŒณ the whole family tree.

Parameters

  • include_clip โ€” Whether to include clipping layers. Default is True.

Example:

# Iterate over all layers
for layer in psd.descendants():
    print(layer)

# Iterate over all layers in reverse order
for layer in reversed(list(psd.descendants())):
    print(layer)

extend(layers: Iterable[Layer]) -> None

Add a list of layers to the end (top) of the group โฌ†๏ธ.

This operation rewrites the internal references of the layers. and good news bestie: adding the same layer will not create a duplicate ๐Ÿ™…โ€โ™€๏ธ๐ŸŽ€

Parameters

  • layers โ€” The layers to add.

Raises

  • TypeError โ€” If the provided object is not a Layer instance.
  • ValueError โ€” If attempting to add a group to itself.

find(name: str) -> Layer | None

Returns the first layer found for the given layer name ๐Ÿ”Ž first match wins, no cap.

Parameters

  • name

findall(name: str) -> Iterator[Layer]

Return a generator to iterate over all layers with the given name ๐Ÿ“‹ everybody with that name, step forward.

Parameters

  • name

classmethod frompil(image: Image, compression: Compression = Compression.RLE, color: int | float | Sequence[int | float] | None = None) -> Self

Create a new layer-less PSD document from a PIL Image ๐Ÿฆ‹ starting from scratch, but make it PSD.

Parameters

  • image โ€” PIL Image object.
  • compression โ€” ImageData compression option. See Compression (psd_tools.constants.Compression).
  • color โ€” Background color for the compositing backdrop when saving. Accepts the same types as new() color. When set, save() will composite layers against an opaque backdrop of this color.

Returns: A PSDImage (psd_tools.api.psd_image.PSDImage) object.

has_preview() -> bool

Returns if the document has real merged data ๐Ÿ’พ. When True, topil() returns pre-composed data. no extra work needed, periodt.

has_thumbnail() -> bool

True if the PSDImage has a thumbnail resource ๐Ÿ–ผ๏ธโœจ.

property height: int

Document height ๐Ÿ“.

Returns: int

property image_resources: ImageResources

Document image resources ๐Ÿ—‚๏ธ. ImageResources (psd_tools.psd.image_resources.ImageResources) is a dict-like structure that keeps various document settings.

See psd_tools.constants.Resource (psd_tools.constants.Resource) for available keys ๐Ÿ”‘.

Returns: ImageResources (psd_tools.psd.image_resources.ImageResources)

Example:

from psd_tools.constants import Resource
version_info = psd.image_resources.get_data(Resource.VERSION_INFO)
slices = psd.image_resources.get_data(Resource.SLICES)

Image resources contain an ICC profile ๐Ÿ’– and here's literally how you export a PNG with the embedded ICC profile riding along:

from psd_tools.constants import Resource
icc_profile = psd.image_resources.get_data(Resource.ICC_PROFILE)
image = psd.compose(apply_icc=False)
image.save('output.png', icc_profile=icc_profile)

โœจ index(layer: Layer) -> int

Returns the index of the specified layer in the group. where is it bestie ๐Ÿ‘€

Parameters

  • layer โ€” The layer to find.

โœจ insert(index: int, layer: Layer) -> None

Insert the given layer at the specified index.

Heads up tho: this operation rewrites the internal references of the layer. ๐Ÿ”ง

Parameters

  • index โ€” The index to insert the layer at.
  • layer โ€” The layer to insert.

Raises

  • TypeError โ€” If the provided object is not a Layer instance.
  • ValueError โ€” If attempting to add a group to itself.

โœจ is_group() -> bool

Return True if this is a group. group chat behaviour fr fr ๐Ÿ’…

โœจ is_updated() -> bool

Returns whether the layer tree has been updated.

Returns

bool

โœจ is_visible() -> bool

Returns visibility of the element. are we showing up or are we hiding ๐Ÿ˜ญ

โœจ kind: str

Kind.

Returns

'psdimage'

โœจ left: int

Left coordinate.

Returns

0

โœจ name: str

Element name.

Returns

'Root'

โœจ new(mode: str, size: tuple[int, int], color: int | float | Sequence[int | float] = 0, depth: Literal[8, 16, 32] = 8, **kwargs: Any) -> Self

classmethod. Create a new PSD document. brand new blank canvas, main character energy โœจ

Parameters

  • mode โ€” The color mode to use for the new image.
  • size โ€” A tuple containing (width, height) in pixels.
  • color โ€” What color to use for the image. Default is black. Accepts a single integer (0-255 for 8-bit) or float in the [0.0, 1.0] range, or a sequence of per-channel values using the same ranges (e.g., 3 values for "RGB", 4 for "CMYK"). Mixed int/float sequences are allowed. The color is used both as the initial image data fill and as the background_color compositing backdrop when saving.
  • depth โ€” Bit depth (8, 16, or 32).

Returns

A PSDImage object.

โœจ numpy(channel: Literal['color', 'shape', 'alpha', 'mask'] | None = None) -> ndarray

Get NumPy array of the layer. numbers go brrr ๐Ÿงš

Parameters

  • channel โ€” Which channel to return, can be 'color', 'shape', 'alpha', or 'mask'. Default is 'color+alpha'.

Returns

numpy.ndarray

โœจ offset: tuple[int, int]

(left, top) tuple.

Returns

tuple

โœจ open(fp: IO[bytes] | str | bytes | PathLike, max_alloc_bytes: int | None = None, **kwargs: Any) -> Self

classmethod. Open a PSD document. let us in bestie ๐Ÿซถ

Parameters

  • fp โ€” filename or file-like object.
  • max_alloc_bytes โ€” optional per-document cap (bytes) on the buffer that composite()/numpy()/topil() allocate from the declared geometry; rendering raises ValueError if the estimate exceeds it. Defaults to the $PSD_TOOLS_MAX_ALLOC_BYTES env var (or psd_tools.api.utils.MAX_ALLOC_BYTES) when None.
  • encoding โ€” charset encoding of the pascal string within the file, default 'macroman'. Some psd files need explicit encoding option.

Returns

A PSDImage object.

โœจ parent: None

Parent of this layer.

โœจ pil_mode: str

PIL mode of the document.

โœจ pop(index: int = -1) -> Layer

Removes the specified layer from the list and returns it. gone but not forgotten ๐Ÿ’€

This operation rewrites the internal references of the layer.

Parameters

  • index โ€” The index of the layer to remove. Default is -1 (the last layer).

Raises

  • IndexError โ€” If the index is out of range.

Returns

The removed layer.

โœจ remove(layer: Layer) -> Self

Removes the specified layer from the group.

This operation rewrites the internal references of the layer.

Parameters

  • layer โ€” The layer to remove.

Raises

  • ValueError โ€” If the layer is not found in the group.

Returns

self

โœจ right: int

Right coordinate.

Returns

int

โœจ save(fp: IO[bytes] | str | bytes | PathLike, mode: str = 'wb', **kwargs: Any) -> None

Save the PSD file. Updates the ImageData section if the layer structure has been updated. lock it in ๐Ÿ”ฅ

Parameters

  • fp โ€” filename or file-like object.
  • encoding โ€” charset encoding of the pascal string within the file, default 'macroman'.
  • mode โ€” file open mode, default 'wb'.

โœจ size: tuple[int, int]

(width, height) tuple.

Returns

tuple

โœจ tagged_blocks: TaggedBlocks | None

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

See psd_tools.constants.Tag for available keys.

Returns

TaggedBlocks or None.

Example:

from psd_tools.constants import Tag
patterns = psd.tagged_blocks.get_data(Tag.PATTERNS1)

โœจ thumbnail() -> Image | None

Returns a thumbnail image in PIL.Image. When the file does not contain an embedded thumbnail image, returns None. no thumbnail = no vibes ๐Ÿ˜ญ

โœจ top: int

Top coordinate.

Returns

0

โœจ topil(channel: int | ChannelID | None = None, apply_icc: bool = True) -> Image | None

Get PIL Image.

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, or None if the composed image is not available.

โœจ version: int

Document version. PSD file is 1, and PSB file is 2.

Returns

int

โœจ viewbox: tuple[int, int, int, int]

Return bounding box of the viewport.

Returns

(left, top, right, bottom) tuple.

โœจ visible: bool

Visibility.

Returns

True

โœจ width: int

Document width.

Returns

int


๐Ÿฆ‹ psd_tools.api ๐Ÿฆ‹

High-level API for working with PSD/PSB files.

This subpackage provides the user-facing API for psd-tools, offering Pythonic interfaces for manipulating Photoshop documents. It wraps the low-level psd_tools.psd binary structures with convenient methods and properties.

The main entry point is PSDImage, which provides document-level operations. Individual layers are represented by various layer classes in psd_tools.api.layers.

Key modules:

  • psd_tools.api.psd_image: Main PSDImage class for document operations
  • psd_tools.api.layers: Layer type hierarchy (Layer, GroupMixin, etc.)
  • psd_tools.api.adjustments: Adjustment layer types
  • psd_tools.api.mask: Layer mask operations
  • psd_tools.api.shape: Vector shape and stroke operations
  • psd_tools.api.effects: Layer effects (shadows, glows, etc.)
  • psd_tools.api.pil_io: PIL/Pillow image I/O utilities
  • psd_tools.api.numpy_io: NumPy array I/O utilities

Example usage:

from psd_tools import PSDImage

# Open a PSD file
psd = PSDImage.open('document.psd')

# Access layers
for layer in psd:
    print(f"{layer.name}: {layer.kind}")

# Modify a layer
layer = psd[0]
layer.name = "New Name"
layer.opacity = 128

# Save changes
psd.save('modified.psd')

The API layer automatically reconstructs the layer tree from the flat list of layer records in the PSD file, establishing proper parent-child relationships for groups.

This module provides the high-level API for working with PSD files. It wraps the low-level psd_tools.psd structures with convenient Pythonic interfaces. Basically: the low-level stuff is giving raw bytes energy, and this module is here to make it actually cute to use. ๐Ÿ’…


๐Ÿ‘‘ PSDImage

class psd_tools.api.psd_image.PSDImage(data: psd_tools.psd.PSD)

A Photoshop PSD/PSB document, bestie. That's the whole vibe.

The low-level data structure is chillin' right there at PSDImage._record if you ever need to peek under the hood. โœจ

Example โ€” look at her go:

from psd_tools import PSDImage

psdimage = PSDImage.open('example.psd')
image = psdimage.composite()

for layer in psdimage:
    layer_image = layer.composite()

append(layer: psd_tools.api.layers.Layer) -> None

Add a layer to the end (top) of the group. Note that "end" here means the top of the stack, because PSD layer ordering has main character energy that way. ๐Ÿ™ƒ

This operation rewrites the internal references of the layer. Adding the same layer will not create a duplicate โ€” so no accidental clone situation, periodt.

Parameters

  • layer โ€” The layer to add.

Raises

  • TypeError โ€” If the provided object is not a Layer instance.
  • ValueError โ€” If attempting to add a group to itself.
The "group to itself" one? Yeah, don't. That's a ValueError and also just emotionally complicated. ๐Ÿ’€

property background_color: float | tuple[float, ...] | None

Background color for the merged composite image. Writable, so you can swap the vibe whenever.

When set, save() composites layers against an opaque backdrop of this color instead of a transparent one. Super useful for creating RGB-mode PSD files where transparent areas should show up as a specific color (e.g., white) in the merged composite. No more sad checkerboard reveal. ๐ŸŽ€

Values live in the [0.0, 1.0] range, matching the composite() color parameter:

  • RGB / Grayscale: 1.0 = white, 0.0 = black
  • CMYK: (0.0, 0.0, 0.0, 0.0) = white (no ink)

Use a scalar for uniform color or a tuple for per-channel values. Set to None for a transparent backdrop (that's the legacy behavior). Documents created via new() have this set automatically from the color parameter, so she comes pre-styled. ๐ŸŒˆ

Returns

float, tuple[float, ...], or None

Example:

psd = PSDImage.new('RGB', (640, 480), color=1.0)
psd.save('output.psd')  # White background, 3 channels (no alpha)

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

Minimal bounding box that contains all the visible layers. Tight, minimal, no wasted space. ๐Ÿ“

Use viewbox to get the viewport bounding box instead. When the psd is empty, bbox is equal to the canvas bounding box.

Returns

(left, top, right, bottom) tuple.

property bottom: int

Bottom coordinate.

Returns

int

property channels: int

Number of color channels.

Returns

int

clear() -> None

Clears the group. Everything gone, poof, empty canvas energy. ๐Ÿซง

This operation rewrites the internal references of the layers.

Returns

None

property color_mode: psd_tools.constants.ColorMode

Document color mode, such as 'RGB' or 'GRAYSCALE'. See psd_tools.constants.ColorMode for the whole roster. ๐Ÿ‘‘

Returns

psd_tools.constants.ColorMode

property compatibility_mode: psd_tools.constants.CompatibilityMode

Set the compositing and layer organization compatibility mode. Writable.

This property checks whether the PSD file is compatible with specific authoring tools, such as Photoshop or CLIP Studio Paint. Different authoring tools may have different ways of handling layers โ€” like the use of clipping masks for groups โ€” and honestly they're all a little opinionated. The default is Photoshop compatibility mode.

Returns

psd_tools.constants.CompatibilityMode

composite()

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

Composite the PSD image. This is the moment, this is the main event. ๐Ÿ”ฅ

Parameters

  • viewport โ€” Viewport bounding box specified by (x1, y1, x2, y2) tuple. Default is the viewbox of the PSD.
  • ignore_preview โ€” Boolean flag to whether skip compositing when a pre-composited preview is available.
  • 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.

count(layer: psd_tools.api.layers.Layer) -> int

Counts the number of occurrences of a layer in the group. Yes bestie, we're doing inventory. ๐Ÿงฎ

Parameters

  • layer โ€” The layer to count.

create_group()

create_group(layer_list: Iterable[psd_tools.api.layers.Layer] | None = None, name: str = 'Group', opacity: int = 255, blend_mode: psd_tools.constants.BlendMode = BlendMode.PASS_THROUGH, open_folder: bool = True) -> psd_tools.api.layers.Group

Create a new group layer and add it to the PSDImage. Folder? Created. Organized? Iconic. ๐ŸŽ€

Example:

group = psdimage.create_group(name='New Group')
group.append(psdimage.create_pixel_layer(image, name='Layer in Group'))

Parameters

  • layer_list โ€” Optional list of layers to add to the group.
  • name โ€” Name of the new group.
  • opacity โ€” Opacity of the new layer (0-255).
  • blend_mode โ€” Blend mode of the new layer, default is BlendMode.PASS_THROUGH.
  • open_folder โ€” Whether the group is an open folder in the Photoshop UI.

Returns

The created psd_tools.api.layers.Group object.

create_pixel_layer()

create_pixel_layer(image: Image, name: str = 'Layer', top: int = 0, left: int = 0, compression: psd_tools.constants.Compression = Compression.RLE, opacity: int = 255, blend_mode: psd_tools.constants.BlendMode = BlendMode.NORMAL) -> psd_tools.api.layers.PixelLayer

Create a new pixel layer and add it to the PSDImage. Fresh pixels, just dropped. โœจ

Example:

psdimage = PSDImage.new("RGB", (640, 480))
layer = psdimage.create_pixel_layer(image, name='Layer 1')

Parameters

  • name โ€” Name of the new layer.
  • image โ€” PIL Image object.
  • top โ€” Top coordinate of the new layer.
  • left โ€” Left coordinate of the new layer.
  • compression โ€” Compression method for the layer image data.
  • opacity โ€” Opacity of the new layer (0-255).
  • blend_mode โ€” Blend mode of the new layer, default is BlendMode.NORMAL.

Returns

The created psd_tools.api.layers.PixelLayer object.

property depth: int

Pixel depth bits.

Returns

int

descendants(include_clip: bool = True) -> Iterator[psd_tools.api.layers.Layer]

Return a generator to iterate over all descendant layers. The whole family tree, down to the tiniest grandchild layer. ๐ŸŒณ

Parameters

  • include_clip โ€” Whether to include clipping layers. Default is True.

Example:

# Iterate over all layers
for layer in psd.descendants():
    print(layer)

# Iterate over all layers in reverse order
for layer in reversed(list(psd.descendants())):
    print(layer)

extend(layers: Iterable[psd_tools.api.layers.Layer]) -> None

Add a list of layers to the end (top) of the group. Plural append, we're being efficient. ๐Ÿ’…

This operation rewrites the internal references of the layers. Adding the same layer will not create a duplicate.

Parameters

  • layers โ€” The layers to add.

Raises

  • TypeError โ€” If the provided object is not a Layer instance.
  • ValueError โ€” If attempting to add a group to itself.

find(name: str) -> psd_tools.api.layers.Layer | None

Returns the first layer found for the given layer name. First come, first served. ๐Ÿซถ

Parameters

  • name

findall(name: str) -> Iterator[psd_tools.api.layers.Layer]

Return a generator to iterate over all layers with the given name. Because duplicate layer names are absolutely a thing and we're not judging. ๐Ÿ™ˆ

Parameters

  • name

classmethod frompil()

frompil(image: Image, compression: psd_tools.constants.Compression = Compression.RLE, color: int | float | Sequence[int | float] | None = None) -> Self

Create a new layer-less PSD document from PIL Image. Just you and the canvas โ€” no layers, no drama. ๐Ÿฆ‹

Parameters

  • image โ€” PIL Image object.
  • compression โ€” the ImageData compression option, bestie. Go peep Compression for the deets. ๐Ÿ”ฅ
    • color โ€” the background color for the compositing backdrop when saving. Takes the exact same types as new()'s color. The moment you set it, save() will composite your layers against an opaque backdrop in that color. ๐Ÿ’…

Returns โ€” a PSDImage object. Iconic. โœจ


๐Ÿ’– has_preview() -> bool

Tells you if the document has real merged data. When it's True, topil() hands you pre-composed data instead of making you do the work. Slay. ๐Ÿซถ

๐ŸŽ€ has_thumbnail() -> bool

True if this PSDImage has a thumbnail resource. No thumbnail? Then it's False, simple as. ๐ŸŒธ

โญ property height: int

The document height, bestie.

Returns โ€” int

๐Ÿฆ‹ property image_resources: ImageResources

The document's image resources. ImageResources is a dict-like structure that keeps all your various document settings around.

See psd_tools.constants.Resource for the available keys. ๐Ÿ‘‘

Returns โ€” ImageResources (psd_tools.psd.image_resources.ImageResources)

Example:

from psd_tools.constants import Resource
version_info = psd.image_resources.get_data(Resource.VERSION_INFO)
slices = psd.image_resources.get_data(Resource.SLICES)

Image resources also contain an ICC profile. The following shows how to export a PNG file with the ICC profile embedded โ€” noted, bestie, write it down:

from psd_tools.constants import Resource
icc_profile = psd.image_resources.get_data(Resource.ICC_PROFILE)
image = psd.compose(apply_icc=False)
image.save('output.png', icc_profile=icc_profile)

๐Ÿ’… index(layer: Layer) -> int

Returns the index of the specified layer inside the group. ๐Ÿ”

Parameters

  • layer โ€” the layer to find, bestie.

๐ŸŒˆ insert(index: int, layer: Layer) -> None

Inserts the given layer at the specified index.

Heads up: this operation rewrites the internal references of the layer. It's not just vibes, it's structural. ๐Ÿ’€

Parameters

  • index โ€” the index to insert the layer at.
  • layer โ€” the layer to insert.

Raises

  • TypeError โ€” if the object you handed over is not a Layer instance.
  • ValueError โ€” if you're attempting to add a group to itself. Don't do that. ๐Ÿ™ˆ

๐Ÿงš is_group() -> bool

Returns True if this is a group. Periodt.

๐Ÿ’œ is_updated() -> bool

Tells you whether the layer tree has been updated, or not.

Returns โ€” bool

๐Ÿ“ is_visible() -> bool

Returns the visibility of the element. ๐Ÿ‘€

๐Ÿ‘‘ property kind: str

The kind, bestie.

Returns โ€” 'psdimage'

โœจ property left: int

The left coordinate.

Returns โ€” 0

๐ŸŒธ property name: str

The element name.

Returns โ€” 'Root'

๐ŸŽ€ classmethod new(mode: str, size: tuple[int, int], color: int | float | Sequence[int | float] = 0, depth: Literal[8, 16, 32] = 8, **kwargs: Any) -> Self

Creates a brand new PSD document. Fresh start energy. ๐Ÿฆ‹

Parameters

  • mode โ€” the color mode to use for the new image.
  • size โ€” a tuple containing (width, height) in pixels.
  • color โ€” what color to use for the image. Default is black. Accepts a single integer (0-255 for 8-bit) or a float in the [0.0, 1.0] range, or a sequence of per-channel values using the same ranges (e.g., 3 values for "RGB", 4 for "CMYK"). Mixed int/float sequences are allowed. The color is used both as the initial image data fill and as the background_color compositing backdrop when saving. ๐Ÿ’…
  • depth โ€” bit depth (8, 16, or 32).

Returns โ€” a PSDImage object. โœจ

๐Ÿซถ numpy(channel: Literal['color', 'shape', 'alpha', 'mask'] | None = None) -> ndarray

Gets you the 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

โญ property offset: tuple[int, int]

The (left, top) tuple.

Returns โ€” tuple

๐Ÿ’– classmethod open(fp: IO[bytes] | str | bytes | PathLike, max_alloc_bytes: int | None = None, **kwargs: Any) -> Self

Opens a PSD document. Come on in, the water's fine. ๐ŸŒŠ

Parameters

  • fp โ€” filename or file-like object.
  • max_alloc_bytes โ€” optional per-document cap (bytes) on the buffer that composite()/numpy()/topil() allocate from the declared geometry; rendering raises ValueError if the estimate exceeds it. Defaults to the $PSD_TOOLS_MAX_ALLOC_BYTES env var (or psd_tools.api.utils.MAX_ALLOC_BYTES) when None. โš ๏ธ
  • encoding โ€” charset encoding of the pascal string within the file, default 'macroman'. Some psd files need the explicit encoding option, no cap.

Returns โ€” a PSDImage object.

๐ŸŒˆ property parent: None

The parent of this layer. It's None, bestie โ€” root layers live parentless, main character energy. ๐Ÿ‘‘

๐Ÿ’œ property pil_mode: str

The PIL mode of the document.

๐Ÿ“ pop(index: int = -1) -> Layer

Removes the specified layer from the list and returns it. Popped and handed right back to you. ๐Ÿ’…

This operation rewrites the internal references of the layer.

Parameters

  • index โ€” the index of the layer to remove. Default is -1 (the last layer).

Raises โ€” IndexError โ€” if the index is out of range.

Returns โ€” the removed layer.

๐Ÿงš remove(layer: Layer) -> Self

Removes the specified layer from the group.

This operation rewrites the internal references of the layer too. Same vibe as insert() and pop().

Parameters

  • layer โ€” the layer to remove.

Raises โ€” ValueError โ€” if the layer is not found in the group.

Returns โ€” self

๐ŸŽ€ property right: int

The right coordinate.

Returns โ€” int

โœจ save(fp: IO[bytes] | str | bytes | PathLike, mode: str = 'wb', **kwargs: Any) -> None

Saves the PSD file. Updates the ImageData section if the layer structure has been updated. ๐Ÿ’พ

Parameters

  • fp โ€” filename or file-like object.
  • encoding โ€” charset encoding of the pascal string within the file, default 'macroman'.
  • mode โ€” file open mode, default 'wb'.

๐Ÿฆ‹ property size: tuple[int, int]

The (width, height) tuple.

Returns โ€” tuple

๐ŸŒธ property tagged_blocks: TaggedBlocks | None

Document tagged blocks, which is a dict-like container of settings.

See psd_tools.constants.Tag for the available keys.

Returns โ€” TaggedBlocks or None. It's literally tagging, bestie.

Example:

from psd_tools.constants import Tag
patterns = psd.tagged_blocks.get_data(Tag.PATTERNS1)

๐Ÿ’… thumbnail() -> Image | None

Returns a thumbnail image as a PIL.Image. When the file doesn't contain an embedded thumbnail image, it returns None. No thumbnail, no problem. ๐Ÿ™ˆ

โญ property top: int

The top coordinate.

Returns โ€” 0

๐Ÿ”ฅ topil(channel: int | ChannelID | None = None, apply_icc: bool = True) -> Image | None

Gets you a PIL Image.

Parameters

  • channel โ€” which channel to return; e.g., 0 for the 'R' channel in an 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, or None if the composed image is not available. ๐Ÿ˜ญ

๐Ÿ‘‘ property version: int

The document version. PSD file is 1, and PSB file is 2. iykyk. ๐ŸŽ€

Returns โ€” int

๐Ÿ’œ property viewbox: tuple[int, int, int, int]

Returns the bounding box of the viewport.

Returns โ€” (left, top, right, bottom) tuple.

๐ŸŒˆ property visible: bool

Visibility.

Returns โ€” True

๐Ÿซถ property width: int

The document width.

Returns โ€” int


For detailed layer types documentation, see psd_tools.api.layers. ๐Ÿ‘‘


โœจ psd_tools.api.adjustments โœจ

Adjustment and fill layers. The little glow-up layers, bestie. ๐Ÿ’–

Example:

if layer.kind == 'brightnesscontrast':
    print(layer.brightness)

if layer.kind == 'gradientfill':
    print(layer.gradient_kind)

๐ŸŽ€ Fill layers ๐ŸŽ€

So bestie, fill layers are basically ShapeLayer's cousin โ€” except this one might not have a vector mask attached at all. When that happens, the layer just spreads out and covers the whole entire canvas of the PSD document. Iconic behavior honestly. ๐Ÿ’…

Every fill layer out there inherits from FillLayer.

Example, because we love a demo:

if isinstance(layer, psd_tools.layers.FillLayer):
    image = layer.compose()

๐ŸŒˆ SolidColorFill ๐ŸŒˆ

class psd_tools.api.adjustments.SolidColorFill(*args: Any)

Just a solid color fill. Simple. Clean. Gorgeous. โœจ

Here's everything it comes with:

  • bbox: tuple[int, int, int, int] โ€” the (left, top, right, bottom) tuple, in that exact order, no cap.
  • blend_mode: BlendMode โ€” the blend mode of this layer. It's writable, so go off.

Example:

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

Returns a BlendMode.

  • bottom: int โ€” the bottom coordinate.

Returns an int.

  • clip_layers: list[Self] โ€” the clip layers chillin' with this layer.

Returns a list of layers.

  • clipping: bool โ€” the clipping flag for this layer. Writable, so you can flip it.

Returns a bool.

  • clipping_layer: bool โ€” โš ๏ธ deprecated. Please use the clipping property instead, bestie, we're moving on.
  • 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 โ€” composites the layer AND the masks (that's the mask, the vector mask, and the clipping layers, all of it).

Parameters, okay:

  • viewport โ€” the viewport bounding box, given as an (x1, y1, x2, y2) tuple. Defaults to the layer's bbox.
  • force โ€” boolean flag that forces vector drawing.
  • color โ€” the backdrop color, as a scalar or a tuple of scalars. It lives in [0.0, 1.0]. So like, (1., 0., 0.) is red in RGB color mode.
  • alpha โ€” the backdrop alpha, in [0.0, 1.0].
  • layer_filter โ€” a Callable that takes a layer as its argument and returns whether that layer gets composited or not. Default is is_visible().

Returns a PIL.Image.Image or None.

  • create_mask(image: Image, top: int | None = None, left: int | None = None, compression: Compression = Compression.RLE) -> Mask โ€” makes a pixel mask on this layer out of a PIL Image. ๐ŸŽจ

If the image has an alpha channel (like RGBA or LA), that alpha channel becomes the mask data. If not, the image gets converted to grayscale (L mode). White (255) means fully unmasked, black (0) means fully masked. That's the whole vibe.

Parameters:

  • image โ€” the source Image for the mask.
  • top โ€” the top offset of the mask. Defaults to the layer's top.
  • left โ€” the left offset of the mask. Defaults to the layer's left.
  • compression โ€” the compression algorithm for the mask data.

Returns the new Mask.

Raises ValueError โ€” if the layer already has a mask. One mask only, we don't do duplicates. ๐Ÿ’€

  • data: DescriptorBlock โ€” the color, in Descriptor(RGB).
  • delete_layer() -> Self โ€” deprecated, babe. Use layer.parent.remove(layer) instead.
  • effects: Effects โ€” the layer effects.

Returns Effects.

  • fill_opacity: int โ€” the fill opacity of this layer, in the [0, 255] range. Writable.

Returns an int.

  • has_clip_layers(visible: bool = False) -> bool โ€” returns True if the layer has clipping associated with it.

Parameters:

  • visible โ€” if True, it checks for visible clipping layers.

Returns a bool.

  • has_effects(enabled: bool = True, name: str | None = None) -> bool โ€” returns True if the layer has effects.

Parameters:

  • enabled โ€” if True, checks for enabled effects.
  • name โ€” if you pass one, it checks for that specific effect type.

Returns a bool.

  • has_mask() -> bool โ€” returns True if the layer has a mask.

Returns a bool.

  • has_origination() -> bool โ€” returns True if the layer has live shape properties.

Returns a bool.

  • has_pixels() -> bool โ€” returns True if the layer has pixels associated with it. When this one's True, the topil method hands you back a PIL.Image.Image.

Returns a 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 a bool.

  • height: int โ€” the height of the layer.

Returns an int.

  • is_group() -> bool โ€” returns True if the layer is a group.

Returns a bool.

  • is_visible() -> bool โ€” the layer's visibility, and yes it takes group visibility into account too.

Returns a bool.

  • kind: str โ€” the kind of this layer, like group, pixel, shape, type, smartobject, or psdimage. It's just the class name without the layer suffix.

Returns a str.

  • layer_id: int โ€” the layer ID.

Returns an int layer id โ€” and if the layer never got assigned an id, you get -1.

  • left: int โ€” the left coordinate. Writable.

Returns an int.

  • lock(lock_flags: int = ProtectedFlags.COMPLETE) -> None โ€” locks a layer according to the combination of flags you hand it.

Parameters:

  • lockflags โ€” an integer representing the locking state.

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

layer.lock(ProtectedFlags.COMPOSITE | ProtectedFlags.POSITION)
  • mask: Mask | None โ€” returns the mask associated with this layer.

Returns a Mask or None.

  • move_down(offset: int = 1) -> Self โ€” moves the layer down by a certain offset, within the group that the layer is in.

Parameters:

  • offset โ€” how many positions to move the layer down. It can be negative, go wild.

Raises:

  • ValueError โ€” if the layer has no parent, or the parent isn't 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, bestie.

Parameters:

  • group โ€” the group the current layer is gonna get moved into.
  • move_up(offset: int = 1) -> Self โ€” moves the layer up by a certain offset, within the group that the layer is in.

Parameters:

  • offset โ€” how many positions to move the layer up. Negative is allowed here too.

Raises:

  • ValueError โ€” if the layer has no parent, or the parent isn't a group.
  • IndexError โ€” if the new index is out of bounds.

Returns self.

  • name: str โ€” the layer name. Writable.

Returns a str.

  • next_sibling(visible: bool = False) -> Self | None โ€” the next sibling of this layer. That's it, that's the whole thing.
  • numpy(channel: str | None = None, real_mask: bool = True) -> ndarray | None โ€” grabs a NumPy array of the layer. ๐Ÿ“Š

Parameters:

  • channel โ€” which channel you want. Your options are 'color', 'shape', 'alpha', or 'mask'. Default is 'color+alpha'.

Returns numpy.ndarray, or None if there's just no pixel there.

  • offset: tuple[int, int] โ€” the (left, top) tuple. Writable.

Returns a tuple.

  • opacity: int โ€” the opacity of this layer, in the [0, 255] range. Writable.

Returns an int.

  • origination: list[Origination] โ€” the property that gives you a list of live shapes, or a line.

Some vector masks have live shape properties associated with them โ€” that's the Photoshop feature for handling primitive shapes like a rectangle, an ellipse, or a line. Vector masks without live shape properties? Those are just plain path objects. No glow-up.

See psd_tools.api.shape.

Returns a list of Invalidated, Rectangle, RoundedRectangle, Ellipse, or Line.

  • parent: GroupMixinProtocol | None โ€” the parent of this layer.

โœจ previous_sibling(visible: bool = False) -> Self | None

The previous sibling of this layer โ€” like, the layer that comes right before it in the same parent. Peek if you want bestie.

โœจ reference_point โ€” tuple[float, float]

Reference point of this layer, handed to you as an (x, y) tuple in canvas coordinates. Writable, so go off ๐Ÿ’…

The reference point is literally what transformations like rotation and scaling pivot around. That's it, that's the vibe.

Returns: an (x, y) tuple

โœจ remove_mask() -> None

Yeet the pixel mask off this layer.

Raises ValueError โ€” if the layer doesn't even have a mask to begin with ๐Ÿ˜ญ

โœจ right โ€” int

Right coordinate.

Returns: int

โœจ sheet_color โ€” SheetColorType

The color label of this layer, the one that shows up in the Photoshop layers panel. Writable, bestie.

Returns: SheetColorType

โœจ size โ€” tuple[int, int]

The (width, height) tuple. Classic.

Returns: tuple

โœจ stroke โ€” Stroke | None

Property for strokes. Simple as.

โœจ tagged_blocks โ€” TaggedBlocks

Layer tagged blocks, which is a dict-like container of settings. It's giving little treasure chest of layer config ๐ŸŽ€

See psd_tools.constants.Tag for which keys you can actually use.

Returns: TaggedBlocks

Example:

from psd_tools.constants import Tag
metadata = layer.tagged_blocks.get_data(Tag.METADATA_SETTING)

โœจ top โ€” int

Top coordinate. Writable, no cap.

Returns: int

โœจ topil(channel: int | None = None, apply_icc: bool = True) -> Image | None

Grab a PIL Image of the layer. This is the glow-up method fr fr โœจ

Parameters

  • channel โ€” which channel to hand back; e.g., 0 for the 'R' channel in an RGB image. See ChannelID. When it's 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 an alpha channel in PIL. In that case, topil drops the alpha channel. ๐Ÿ’€

โœจ update_mask(image: Image, top: int | None = None, left: int | None = None, compression: Compression = Compression.RLE) -> Mask

Update the pixel mask of this layer with a new image. Mask makeover era ๐Ÿงš

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 the current mask top.
  • left โ€” new left offset of the mask. Defaults to the current mask left.
  • compression โ€” compression algorithm for the mask data.

Returns: the updated Mask.

Raises ValueError โ€” if the layer does not have a mask. ๐Ÿ™ˆ

โœจ vector_mask โ€” VectorMask | None

Returns the vector mask associated with this layer.

Returns: VectorMask or None

โœจ visible โ€” bool

Layer visibility. Heads up โ€” this does not take group visibility into account. Writable.

Returns: bool

โœจ width โ€” int

Width of the layer.

Returns: int


๐Ÿฆ‹ PatternFill

class psd_tools.api.adjustments.PatternFill(*args: Any)

Pattern fill. That's the whole vibe, bestie โ€” a fill made of pattern ๐ŸŒธ

โœจ bbox โ€” tuple[int, int, int, int]

The (left, top, right, bottom) tuple.

โœจ blend_mode โ€” BlendMode

Blend mode of this layer. Writable, icon behavior.

Example:

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

Returns: BlendMode.

โœจ bottom โ€” int

Bottom coordinate.

Returns: int

โœจ clip_layers โ€” list[Self]

Clip layers associated with this layer.

Returns: list of layers

โœจ clipping โ€” bool

Clipping flag for this layer. Writable.

Returns: bool

โœจ clipping_layer โ€” bool

Deprecated. Use the clipping property instead. ๐Ÿ‘‘ (old news, bestie)

โœจ 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 the layer and its masks (the mask, vector mask, and clipping layers). This is where everything stacks up and slays ๐Ÿ”ฅ

Parameters

  • viewport โ€” viewport bounding box specified by an (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 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

Create a pixel mask on this layer from a PIL Image. Fresh mask, who dis ๐Ÿ’…

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. ๐Ÿ˜ญ one mask per layer, that's the rule.

โœจ data โ€” DescriptorBlock

Pattern in Descriptor(PATTERN).

โœจ delete_layer() -> Self

Deprecated: use layer.parent.remove(layer) instead. Bestie, the old way is giving ancient history ๐Ÿ™ˆ

โœจ effects โ€” Effects

Layer effects.

Returns: Effects

โœจ fill_opacity โ€” int

Fill opacity of this layer, in the [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. Sparkle check โœจ

Parameters

  • enabled โ€” if True, check for enabled effects.
  • name โ€” if given, check for a 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, the topil method returns a 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

โœจ height โ€” int

Height of the layer.

Returns: int

โœจ is_group() -> bool

Return True if the layer is a group. Found family energy ๐Ÿซถ

Returns: bool

โœจ is_visible() -> bool

Layer visibility. This one does take group visibility into account. Periodt.

  • Returns โ€” bool โœจ (that's the tail end of the property above, bestie, we're still in it ๐Ÿ’–)

  • kind (property ยท str) โ€” what vibe is this layer giving? Could be group, pixel, shape, type, smartobject, or psdimage ๐ŸŒˆ โ€” basically the class name with the Layer suffix chopped off.
    • Returns โ€” str
  • layer_id (property ยท int) โ€” the layer's ID number ๐Ÿชช
    • Returns โ€” the int layer id. If the layer was never assigned an id, you get -1 ๐Ÿ’€
  • left (property ยท int) โ€” left coordinate. Writable โœ๏ธ
    • Returns โ€” int
  • lock(lock_flags: int = ProtectedFlags.COMPLETE) -> None โ€” locks a layer according to whatever combo of flags you hand it ๐Ÿ”’
    • lockflags โ€” an integer representing the locking state
    • Example using the constants of ProtectedFlags and the bitwise or operation to lock both pixels and positions:
layer.lock(ProtectedFlags.COMPOSITE | ProtectedFlags.POSITION)
  • mask (property ยท Mask | None) โ€” returns the mask associated with this layer ๐ŸŽญ
    • Returns โ€” Mask or None
  • move_down(offset: int = 1) -> Self โ€” moves the layer down by a certain offset within the group it lives in โฌ‡๏ธ
    • offset โ€” the number of positions to move the layer down (can be negative)
    • Raises
      • ValueError โ€” if the layer has no parent, or its 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. โš ๏ธ
    • group โ€” the group the current layer will be moved into
  • move_up(offset: int = 1) -> Self โ€” moves the layer up by a certain offset within the group it lives in โฌ†๏ธ
    • offset โ€” the number of positions to move the layer up (can be negative)
    • Raises
      • ValueError โ€” if the layer has no parent, or its parent is not a group ๐Ÿ˜ญ
      • IndexError โ€” if the new index is out of bounds ๐Ÿ˜ฌ
    • Returns โ€” self
  • name (property ยท str) โ€” the layer name. Writable โœ๏ธ
    • Returns โ€” str
  • next_sibling(visible: bool = False) -> Self | None โ€” the next sibling of this layer, iykyk ๐Ÿ‘ฏ
  • numpy(channel: str | None = None, real_mask: bool = True) -> ndarray | None โ€” hands you a NumPy array of the layer ๐Ÿงฎ
    • channel โ€” which channel to return; can be 'color', 'shape', 'alpha', or 'mask'. Default is 'color+alpha'
    • Returns โ€” numpy.ndarray, or None if there's no pixel ๐Ÿ™ˆ
  • offset (property ยท tuple[int, int]) โ€” a (left, top) tuple. Writable โœ๏ธ
    • Returns โ€” tuple
  • opacity (property ยท int) โ€” opacity of this layer, in the [0, 255] range. Writable โœ๏ธ
    • Returns โ€” int
  • origination (property ยท list[Origination]) โ€” property for a list of live shapes or a line ๐ŸŸฆโญ•
    • Some of the vector masks have associated live shape properties โ€” that's the Photoshop feature for handling primitive shapes like a rectangle, an ellipse, or a line. Vector masks without live shape properties are plain path objects.
    • See psd_tools.api.shape.
    • Returns โ€” a list of Invalidated, Rectangle, RoundedRectangle, Ellipse, or Line.
  • parent (property ยท GroupMixinProtocol | None) โ€” the parent of this layer ๐Ÿซถ
  • previous_sibling(visible: bool = False) -> Self | None โ€” the previous sibling of this layer ๐Ÿ‘ฏ
  • reference_point (property ยท tuple[float, float]) โ€” the reference point of this layer as an (x, y) tuple in canvas coordinates. Writable โœ๏ธ
    • The reference point is what gets used for transformations like rotation and scaling ๐Ÿ”„
    • Returns โ€” an (x, y) tuple
  • remove_mask() -> None โ€” removes the pixel mask from this layer ๐Ÿงน
    • Raises ValueError โ€” if the layer doesn't have a mask
  • right (property ยท int) โ€” right coordinate โžก๏ธ
    • Returns โ€” int
  • sheet_color (property ยท SheetColorType) โ€” the color label of this layer in the Photoshop layers panel. Writable โœ๏ธ
    • Returns โ€” SheetColorType
  • size (property ยท tuple[int, int]) โ€” a (width, height) tuple ๐Ÿ“
    • Returns โ€” tuple
  • stroke (property ยท Stroke | None) โ€” property for strokes ๐Ÿ–Š๏ธ
  • tagged_blocks (property ยท TaggedBlocks) โ€” layer tagged blocks, which is a dict-like container of settings ๐Ÿ—‚๏ธ
    • See psd_tools.constants.Tag for the available keys.
    • Returns โ€” TaggedBlocks
    • Example:
from psd_tools.constants import Tag
metadata = layer.tagged_blocks.get_data(Tag.METADATA_SETTING)
  • top (property ยท int) โ€” top coordinate. Writable โœ๏ธ
    • Returns โ€” int
  • topil(channel: int | None = None, apply_icc: bool = True) -> Image | None โ€” hands you a PIL Image of the layer ๐Ÿ–ผ๏ธ
    • channel โ€” which channel to return; e.g. 0 for the 'R' channel in an RGB image. See ChannelID. When it's 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 can't include an alpha channel in PIL. In this case, topil drops the alpha channel ๐Ÿซ 
  • update_mask(image: Image, top: int | None = None, left: int | None = None, compression: Compression = Compression.RLE) -> Mask โ€” updates the pixel mask of this layer with a brand new image ๐Ÿ’…
    • If the image has an alpha channel (e.g. RGBA, LA), that alpha channel is used as the mask data. Otherwise the image gets converted to grayscale (L mode). White (255) means fully unmasked, black (0) means fully masked ๐Ÿ–ค๐Ÿค
    • image โ€” new source Image for the mask
    • top โ€” new top offset of the mask. Defaults to the current mask top
    • left โ€” new left offset of the mask. Defaults to the current mask left
    • compression โ€” compression algorithm for the mask data
    • Returns โ€” the updated Mask
    • Raises ValueError โ€” if the layer doesn't have a mask ๐Ÿ˜ญ
  • vector_mask (property ยท VectorMask | None) โ€” returns the vector mask associated with this layer โœจ
    • Returns โ€” VectorMask or None
  • visible (property ยท bool) โ€” layer visibility. Heads up: this does not take group visibility into account ๐Ÿ‘€. Writable โœ๏ธ
    • Returns โ€” bool
  • width (property ยท int) โ€” width of the layer ๐Ÿ“
    • Returns โ€” int

๐Ÿญ GradientFill

class psd_tools.api.adjustments.GradientFill(*args: Any)

Gradient fill, bestie ๐ŸŒˆ โ€” the exact kind of gradient moment that makes a design pop.

  • bbox (property ยท tuple[int, int, int, int]) โ€” a (left, top, right, bottom) tuple ๐Ÿ“ฆ
  • blend_mode (property ยท 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
  • bottom (property ยท int) โ€” bottom coordinate โฌ‡๏ธ
    • Returns โ€” int
  • clip_layers (property ยท list[Self]) โ€” clip layers associated with this layer โœ‚๏ธ
    • Returns โ€” list of layers
  • clipping (property ยท bool) โ€” clipping flag for this layer. Writable โœ๏ธ
    • Returns โ€” bool
  • clipping_layer (property ยท bool) โ€” Deprecated. Use the clipping property instead. โš ๏ธ

๐Ÿซถ composite(...) โ€” the group-hug method

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

This one composites layers and masks โ€” like, all of them: the mask, the vector mask, and the clipping layers. It's the whole squad showing up for the group photo. ๐Ÿ“ธ

Parameters

  • viewport โ€” the viewport bounding box, handed over as an (x1, y1, x2, y2) tuple. Default is the layer's bbox, obviously. ๐Ÿ’…
  • force โ€” a boolean flag that forces vector drawing. Yes queen, draw it anyway. โœจ
  • color โ€” the backdrop color, given as a scalar or a tuple of scalars. The color value lives in [0.0, 1.0]. For example, (1., 0., 0.) is red in RGB color mode. So specific, so iconic. ๐Ÿ“
  • alpha โ€” the backdrop alpha, in [0.0, 1.0].
  • layer_filter โ€” a Callable that takes a layer as its argument and returns whether that layer gets composited. Default is is_visible().

Returns

PIL.Image.Image or None.


๐ŸŽ€ create_mask(...) โ€” build a pixel mask out of a PIL Image

create_mask(image: Image, top: int | None = None, left: int | None = None,
            compression: Compression = Compression.RLE) -> Mask

Creates a pixel mask on this layer, sourced from a PIL Image. Lowkey magic.

If your image has an alpha channel (think RGBA, LA), then that alpha channel is used as the mask data. No alpha? Then the image gets converted to grayscale (L mode). And the vibes are: white (255) means fully unmasked, black (0) means fully masked. That's the whole scale, bestie. ๐Ÿค๐Ÿ–ค

Parameters

  • image โ€” the 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 โ€” the compression algorithm used for the mask data.

Returns

The brand-new Mask. โœจ

Raises

  • ValueError โ€” if the layer already has a mask. (One mask per layer, babes, that's the rule.)

๐ŸŒˆ property data: DescriptorBlock

Gradient in Descriptor(GRADIENT). That's the whole thing โ€” she's a DescriptorBlock.


๐Ÿ’€ delete_layer() -> Self

Deprecated: use layer.parent.remove(layer) instead. The old way, the flop way. Go use the new one. ๐Ÿ™ˆ


๐Ÿ’œ property effects: Effects

The layer effects.

Returns

Effects


โญ property fill_opacity: int

Fill opacity of this layer, in the [0, 255] range. Writable, so go ahead and tweak her.

Returns

int


๐Ÿ‘‘ property gradient_kind: str

The kind of gradient. It's exactly one of these, no in-between:

  • Linear
  • Radial
  • Angle
  • Reflected
  • Diamond

๐Ÿ’… has_clip_layers(visible: bool = False) -> bool

Returns True if the layer has associated clipping.

Parameters

  • visible โ€” if True, it checks specifically for visible clipping layers.

Returns

bool


โœจ has_effects(enabled: bool = True, name: str | None = None) -> bool

Returns True if the layer has effects. She's got the glow-up, fr.

Parameters

  • enabled โ€” if True, check for enabled effects.
  • name โ€” if given, check for a 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. And when this is True, the topil method returns PIL.Image.Image. Noted, bestie. ๐Ÿ“

Returns

bool


๐Ÿงš has_stroke() -> bool

Returns True if the shape has a stroke. Outlined and unbothered. ๐Ÿ’…


๐Ÿ’œ 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

Returns True if the layer is a group. Your little found family. ๐Ÿก

Returns

bool


๐Ÿ‘‘ is_visible() -> bool

Layer visibility. And here's the thing โ€” it takes group visibility into account. So if the group is hidden, her whole bloodline is hidden. Periodt.

Returns

bool


๐ŸŒˆ property kind: str

The kind of this layer, such as group, pixel, shape, type, smartobject, or psdimage. Basically the class name without the layer suffix. Love a consistent naming scheme. โœจ

Returns

str


๐Ÿ’… property layer_id: int

The layer ID.

Returns

int layer id โ€” but if the layer was never assigned an id, you get -1. Sad, but valid.


๐Ÿ“ property left: int

Left coordinate. Writable.

Returns

int


๐Ÿ”’ lock(lock_flags: int = ProtectedFlags.COMPLETE) -> None

Locks a layer according to the combination of flags you pass. (The param is listed as lockflags in the signature docs โ€” same thing, don't @ me.)

Parameters

  • lockflags โ€” an integer representing the locking state.

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

layer.lock(ProtectedFlags.COMPOSITE | ProtectedFlags.POSITION)

No one's moving her. Not today. ๐Ÿ’€


๐Ÿฆ‹ property mask: Mask | None

Returns the 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. She's stepping back, respectfully.

Parameters

  • offset โ€” the number of positions to move the layer down (and yes, it can be negative).

Raises

  • ValueError โ€” if the layer has no parent, or if the 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. Stop using the old one, I'm begging. ๐Ÿ™

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. Main character ascension arc. ๐Ÿ‘‘

Parameters

  • offset โ€” the number of positions to move the layer up (can be negative).

Raises

  • ValueError โ€” if the layer has no parent, or if the parent is not a group.
  • IndexError โ€” if the new index is out of bounds.

Returns

self


โญ property name: str

Layer name. Writable, so go name her something gorgeous.

Returns

str


๐Ÿ’œ next_sibling(visible: bool = False) -> Self | None

Next sibling of this layer. Simple as that. ๐Ÿซถ


๐Ÿงš numpy(channel: str | None = None, real_mask: bool = True) -> ndarray | None

Gets you a NumPy array of the layer. Nerd mode: activated. ๐Ÿค“โœจ

Parameters

  • channel โ€” which channel to return. Can be 'color', 'shape', 'alpha', or 'mask'. Default is 'color+alpha'.

Returns

numpy.ndarray, or None if there's no pixel.


๐ŸŒธ property offset: tuple[int, int]

(left, top) tuple. Writable.

Returns

tuple


๐ŸŒˆ property opacity: int

Opacity of this layer, in the [0, 255] range. Writable. Turn the drama all the way up or all the way down.

Returns

int


๐ŸŽ€ property origination: list[Origination]

A property for a list of live shapes, or a line.

Some of the vector masks have associated live shape properties, which are a Photoshop feature for handling primitive shapes like a rectangle, an ellipse, or a line. Vector masks without live shape properties are just plain path objects. Simple as.

See psd_tools.api.shape.

Returns

A list of Invalidated, Rectangle, RoundedRectangle, Ellipse, or Line.


๐Ÿ’œ property parent: GroupMixinProtocol | None

Parent of this layer. Your layer's layer-mom. ๐Ÿฅบ


๐Ÿฆ‹ previous_sibling(visible: bool = False) -> Self | None

Previous sibling of this layer. The one before her, iykyk.


โญ property reference_point: tuple[float, float]

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

The reference point is what gets used for transformations like rotation and scaling โ€” it's the little anchor everything pivots around. ๐ŸŒŸ

Returns

(x, y) tuple


๐Ÿ’€ remove_mask() -> None

Removes the pixel mask from this layer. Gone. Deleted. Not coming back. โœ‚๏ธ

Raises

  • ValueError โ€” if the layer does not have a mask. (Can't remove what was never there, bestie.)

๐Ÿ‘‘ property right: int

Right coordinate.

Returns

int


๐Ÿ“ property sheet_color: SheetColorType

The color label of this layer in the Photoshop layers panel. Writable โ€” yes, you can repaint the tab. ๐ŸŽจ

Returns

SheetColorType


๐ŸŒธ property size: tuple[int, int]

(width, height) tuple.

Returns

tuple


๐ŸŽ€ property stroke: Stroke | None

A property for strokes.

๐Ÿ’– tagged_blocks

property tagged_blocks: TaggedBlocks

Bestie, this is the layer's tagged blocks โ€” literally a dict-like lil container stuffed with settings. ๐Ÿ‘‘

Wanna know what keys you can pull from it? Go peek at psd_tools.constants.Tag.

Returns: TaggedBlocks โ†’ psd_tools.psd.tagged_blocks.TaggedBlocks

Example, because we love a demo:

from psd_tools.constants import Tag
metadata = layer.tagged_blocks.get_data(Tag.METADATA_SETTING)

๐Ÿ“ top

property top: int

Top coordinate. And yes, she's writable โ€” go off. โœจ

Returns: int


๐Ÿ–ผ๏ธ topil

topil(channel: int | None = None, apply_icc: bool = True) -> Image | None

Okay so this is the one that gets you an actual PIL Image of the layer. Main character behavior fr.

Parameters:

  • channel โ€” which channel do you want back? Like, 0 gives you the 'R' channel in an RGB image. See psd_tools.constants.ChannelID. Pass None and the method hands you back all the channels that PIL modes support.
  • apply_icc โ€” whether to apply ICC profile conversion to sRGB. ๐Ÿ’…

Returns: PIL.Image.Image, or None if the layer has no pixels. (no pixels = no vibes, sorry)

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 PSD image modes are supported by PIL.Image.Image. Like, 'CMYK' mode can't hold an alpha channel in PIL, periodt. So in that case topil just drops the alpha channel. ๐Ÿซ 

๐ŸŽญ update_mask

update_mask(image: Image, top: int | None = None, left: int | None = None, compression: Compression = Compression.RLE) -> Mask

Swap the pixel mask of this layer for a brand new image. Iconic.

If your image has an alpha channel (think RGBA, LA), that alpha channel becomes the mask data. No alpha? Then the image gets converted to grayscale (L mode). White (255) = fully unmasked ๐ŸŒˆ, black (0) = fully masked ๐Ÿ–ค.

Parameters:

  • image โ€” the new source Image for the mask.
  • top โ€” new top offset of the mask. Defaults to the current mask top.
  • left โ€” new left offset of the mask. Defaults to the current mask left.
  • compression โ€” compression algorithm for the mask data.

Returns: the updated Mask โ†’ psd_tools.api.mask.Mask

Raises ValueError โ€” if the layer doesn't have a mask. No mask, no update, that's just the rules bestie. ๐Ÿ˜ญ


๐Ÿฆ‹ vector_mask

property vector_mask: VectorMask | None

Returns the vector mask associated with this layer.

Returns: VectorMask โ†’ psd_tools.api.shape.VectorMask, or None


๐Ÿ‘€ visible

property visible: bool

Layer visibility. Heads up tho: this does not take group visibility into account. Writable.

Returns: bool


๐Ÿ“ width

property width: int

Width of the layer. Just the number, no drama.

Returns: int


โœจ Adjustment layers โœจ

So, adjustment layers apply image filtering to the composed result. Every single adjustment layer inherits from AdjustmentLayer.

Here's the thing: adjustment layers do not have pixels, and they're currently ignored in compose. So if you try to call topil on one, you always get None back. Not a bug, just how she is. ๐Ÿ’€

But just like any other layer, adjustment layers might have an associated mask or vector mask. And an adjustment can show up in other layers' clipping layers too. iykyk.

Example:

if isinstance(layer, psd_tools.layers.AdjustmentLayer):
    print(layer.kind)

๐ŸŽš๏ธ BrightnessContrast

class psd_tools.api.adjustments.BrightnessContrast(*args: Any)

Brightness and contrast adjustment.

  • property automatic: bool
  • property brightness: int
  • property contrast: int
  • property lab: bool
  • property mean: int
  • property use_legacy: bool
  • property vrsn: int

๐Ÿ“ˆ Curves

class psd_tools.api.adjustments.Curves(*args: Any)

Curves adjustment.

property data: Curves

Raw data.

Returns: Curves

property extra: Any


โ˜€๏ธ Exposure

class psd_tools.api.adjustments.Exposure(*args: Any)

Exposure adjustment.

property exposure: float

Exposure.

Returns: float

property exposure_offset: float

Exposure offset.

Returns: float

property gamma: float

Gamma.

Returns: float


๐ŸŽ›๏ธ Levels

class psd_tools.api.adjustments.Levels(*args: Any)

Levels adjustment.

Levels contain a list of LevelRecord. Yes bestie, a whole list.

property data: Levels

List of level records. The first record is the master. ๐Ÿ‘‘

Returns: Levels.

property master: LevelRecord

Master record.


๐ŸŒบ Vibrance

class psd_tools.api.adjustments.Vibrance(*args: Any)

Vibrance adjustment.

property saturation: int

Saturation.

Returns: int

property vibrance: int

Vibrance.

Returns: int


๐ŸŒˆ HueSaturation

class psd_tools.api.adjustments.HueSaturation(*args: Any)

Hue/Saturation adjustment.

HueSaturation contains a list of data. ๐Ÿ“

property colorization: tuple

Colorization.

Returns: tuple

property data: list

List of Hue/Saturation records.

Returns: list

property enable_colorization: int

Enable colorization.

Returns: int

property master: tuple

Master record.

Returns: tuple


โš–๏ธ ColorBalance

class psd_tools.api.adjustments.ColorBalance(*args: Any)

Color balance adjustment.

property highlights: tuple

Highlights.

Returns: tuple

property luminosity: int

Luminosity.

Returns: int

property midtones: tuple

Mid-tones.

Returns: tuple

property shadows: tuple

Shadows.

Returns: tuple


๐Ÿ–ค๐Ÿค BlackAndWhite

class psd_tools.api.adjustments.BlackAndWhite(*args: Any)

Black and white adjustment.

  • property blue: int
  • property cyan: int
  • property green: int
  • property magenta: int
  • property preset_file_name: str
  • property preset_kind: int
  • property red: int
  • property tint_color: Any
  • property use_tint: bool
  • property yellow: int

๐Ÿ“ธ PhotoFilter

class psd_tools.api.adjustments.PhotoFilter(*args: Any)

Photo filter adjustment.

  • property color_components: Any
  • property color_space: Any
  • property density: Any
  • property luminosity: Any

property xyz: bool

xyz.

Returns: bool


๐ŸŒ€ ChannelMixer

class psd_tools.api.adjustments.ChannelMixer(*args: Any)

Channel mixer adjustment.

  • property data: Any
  • property monochrome: Any

๐Ÿ” ColorLookup

class psd_tools.api.adjustments.ColorLookup(*args: Any)

Color lookup adjustment.


๐ŸŽจ Posterize

class psd_tools.api.adjustments.Posterize(*args: Any)

Posterize adjustment.

property posterize: int

Posterize value.

Returns: int


๐Ÿšช Threshold

class psd_tools.api.adjustments.Threshold(*args: Any)

Threshold adjustment.

property threshold: int

Threshold value.

Returns: int


๐ŸŽฏ SelectiveColor

class psd_tools.api.adjustments.SelectiveColor(*args: Any)

Selective color adjustment.

  • property data: Any
  • property method: Any

๐ŸŒ… GradientMap

class psd_tools.api.adjustments.GradientMap(*args: Any)

Gradient map adjustment.

  • property color_model: Any
  • property color_stops: Any
  • property dithered: Any
  • property expansion: Any
  • property gradient_name: Any

property interpolation: float

Interpolation between 0.0 and 1.0.

  • property length: Any
  • property max_color: Any
  • property min_color: Any
  • property mode: Any
  • property random_seed: Any
  • property reversed: Any
  • property roughness: Any
  • property show_transparency: Any
  • property transparency_stops: Any
  • property use_vector_color: Any

๐Ÿ’ซ psd_tools.api.effects

Effects module. Slay.

class psd_tools.api.effects.Effects(layer: LayerProtocol)

List-like effects.

Only present effects are kept. If it's not there, it's not there. ๐Ÿ™ˆ

property enabled: bool

Whether if all the effects are enabled.

Return type: bool

find(name: str, enabled: bool = True) -> Iterator[_Effect]

Iterate effect items by name.

Parameters:

  • name โ€” Effect name, e.g. DropShadow, InnerShadow, OuterGlow, InnerGlow, ColorOverlay, GradientOverlay, PatternOverlay, Stroke, BevelEmboss, or Satin.
  • enabled โ€” If true, only return enabled effects.

Return type: Iterator[Effect] โ†’ psd_tools.terminology.Key.Effect

property scale: float

Scale value.

๐Ÿฆ‹ DropShadow

bestie, say hi to DropShadow โ€” the psd_tools.api.effects baddie that makes your layer look like it's floating above everything else. main character energy fr fr. its constructor takes a descriptor and an image_resources:

class psd_tools.api.effects.DropShadow(descriptor: Descriptor, image_resources: ImageResources)

(and just so you know where those live: Descriptor is psd_tools.psd.descriptor.Descriptor and ImageResources is psd_tools.psd.image_resources.ImageResources โ€” noted once, applies everywhere below ๐Ÿ’…)

properties

  • angle float โ€” the angle value ๐Ÿ“
  • anti_aliased bool โ€” anti-aliased (the docs literally spell it "Angi-aliased", iconic typo, but the meaning is anti-aliased โœจ)
  • blend_mode bytes โ€” the effect blending mode
  • choke float โ€” choke level, in pixels
  • color Descriptor โ€” the color ๐ŸŽจ
  • contour Descriptor โ€” the contour configuration
  • distance float โ€” distance, in pixels
  • enabled bool โ€” whether the effect is enabled
  • layer_knocks_out bool โ€” layers are knocking out
  • name str โ€” the effect name
  • noise float โ€” noise level, in percent
  • opacity float โ€” layer effect opacity, in percentage
  • present bool โ€” whether the effect is present in the Photoshop UI
  • shown bool โ€” whether the effect is shown in the dialog
  • size float โ€” size, in pixels
  • use_global_light bool โ€” using global light
  • value Descriptor โ€” โš ๏ธ DEPRECATED ๐Ÿ’€ โ€” effect descriptor value. use the descriptor property instead, okay?

๐Ÿฉท InnerShadow

the shy sibling of DropShadow โ€” same energy, but it does its thing inside the layer. lowkey dramatic, highkey gorgeous. constructor:

class psd_tools.api.effects.InnerShadow(descriptor: Descriptor, image_resources: ImageResources)

properties

  • angle float โ€” the angle value ๐Ÿ“
  • anti_aliased bool โ€” angi-aliased ๐Ÿ‘€
  • blend_mode bytes โ€” the effect blending mode
  • choke float โ€” choke level, in pixels
  • color Descriptor โ€” the color
  • contour Descriptor โ€” the contour configuration
  • distance float โ€” distance, in pixels
  • enabled bool โ€” whether the effect is enabled
  • name str โ€” the effect name
  • noise float โ€” noise level, in percent
  • opacity float โ€” layer effect opacity, in percentage
  • present bool โ€” whether the effect is present in the Photoshop UI
  • shown bool โ€” whether the effect is shown in the dialog
  • size float โ€” size, in pixels
  • use_global_light bool โ€” using global light
  • value Descriptor โ€” โš ๏ธ DEPRECATED ๐Ÿ’€ โ€” effect descriptor value. use the descriptor property instead
ngl, notice how InnerShadow has no layer_knocks_out? that one's DropShadow-exclusive. don't go looking for it, it's not there ๐Ÿ™ˆ

โœจ OuterGlow

the glow that goes AROUND your layer, like a halo but make it fashion. constructor:

class psd_tools.api.effects.OuterGlow(descriptor: Descriptor, image_resources: ImageResources)

properties

  • angle float โ€” the angle value
  • anti_aliased bool โ€” angi-aliased (again ๐Ÿ˜ญ)
  • blend_mode bytes โ€” the effect blending mode
  • choke float โ€” choke level, in pixels
  • color Descriptor โ€” the color
  • contour Descriptor โ€” the contour configuration
  • dithered bool โ€” the dither flag
  • enabled bool โ€” whether the effect is enabled
  • glow_type bytes โ€” glow type
  • gradient Descriptor โ€” gradient configuration
  • name str โ€” the effect name
  • noise float โ€” noise level, in percent
  • offset Descriptor โ€” offset value, in a Pnt descriptor
  • opacity float โ€” layer effect opacity, in percentage
  • present bool โ€” whether the effect is present in the Photoshop UI
  • quality_jitter float โ€” quality jitter, in percent
  • quality_range float โ€” quality range, in percent
  • reversed bool โ€” reverse flag
  • shown bool โ€” whether the effect is shown in the dialog
  • size float โ€” size, in pixels
  • spread float โ€” spread level, in percent
  • type bytes โ€” gradient type, one of linear, radial, angle, reflected, or diamond ๐Ÿ’ซ
  • value Descriptor โ€” โš ๏ธ DEPRECATED ๐Ÿ’€ โ€” effect descriptor value. use the descriptor property instead

๐ŸŒธ InnerGlow

the inside-job glow. same glow energy, but it stays home. constructor:

class psd_tools.api.effects.InnerGlow(descriptor: Descriptor, image_resources: ImageResources)

properties

  • angle float โ€” the angle value
  • anti_aliased bool โ€” angi-aliased ๐Ÿซ 
  • blend_mode bytes โ€” the effect blending mode
  • choke float โ€” choke level, in pixels
  • color Descriptor โ€” the color
  • contour Descriptor โ€” the contour configuration
  • dithered bool โ€” the dither flag
  • enabled bool โ€” whether the effect is enabled
  • glow_source bytes โ€” elements source
  • glow_type bytes โ€” glow type
  • gradient Descriptor โ€” gradient configuration
  • name str โ€” the effect name
  • noise float โ€” noise level, in percent
  • offset Descriptor โ€” offset value, in a Pnt descriptor
  • opacity float โ€” layer effect opacity, in percentage
  • present bool โ€” whether the effect is present in the Photoshop UI
  • quality_jitter float โ€” quality jitter, in percent
  • quality_range float โ€” quality range, in percent
  • reversed bool โ€” reverse flag
  • shown bool โ€” whether the effect is shown in the dialog
  • size float โ€” size, in pixels
  • type bytes โ€” gradient type, one of linear, radial, angle, reflected, or diamond ๐Ÿ’ซ
  • value Descriptor โ€” โš ๏ธ DEPRECATED ๐Ÿ’€ โ€” effect descriptor value. use the descriptor property instead
bestie, spot the difference: InnerGlow has glow_source and OuterGlow has spread. they are NOT the same girl. iykyk ๐Ÿ™ˆ

๐ŸŽ€ ColorOverlay

just straight-up painting your layer a new color. simple, effective, slays every time. constructor:

class psd_tools.api.effects.ColorOverlay(descriptor: Descriptor, image_resources: ImageResources)

properties

  • blend_mode bytes โ€” the effect blending mode
  • color Descriptor โ€” the color
  • enabled bool โ€” whether the effect is enabled
  • name str โ€” the effect name
  • opacity float โ€” layer effect opacity, in percentage
  • present bool โ€” whether the effect is present in the Photoshop UI
  • shown bool โ€” whether the effect is shown in the dialog
  • value Descriptor โ€” โš ๏ธ DEPRECATED ๐Ÿ’€ โ€” effect descriptor value. use the descriptor property instead
eight properties, zero drama. ColorOverlay said "I keep it simple" and honestly? respect ๐Ÿ‘‘

๐ŸŒˆ GradientOverlay

ColorOverlay's louder cousin โ€” instead of one flat color you get a whole gradient situation. constructor:

class psd_tools.api.effects.GradientOverlay(descriptor: Descriptor, image_resources: ImageResources)

properties

  • aligned bool โ€” aligned
  • angle float โ€” the angle value
  • blend_mode bytes โ€” the effect blending mode
  • dithered bool โ€” the dither flag
  • enabled bool โ€” whether the effect is enabled
  • gradient Descriptor โ€” gradient configuration
  • name str โ€” the effect name
  • offset Descriptor โ€” offset value, in a Pnt descriptor
  • opacity float โ€” layer effect opacity, in percentage
  • present bool โ€” whether the effect is present in the Photoshop UI
  • reversed bool โ€” reverse flag
  • scale float โ€” the scale value
  • shown bool โ€” whether the effect is shown in the dialog
  • type bytes โ€” gradient type, one of linear, radial, angle, reflected, or diamond ๐ŸŒˆ
  • value Descriptor โ€” โš ๏ธ DEPRECATED ๐Ÿ’€ โ€” effect descriptor value. use the descriptor property instead

๐Ÿงš PatternOverlay

and last one for this batch โ€” patterns instead of colors or gradients. texture girlies, this is your moment. constructor:

class psd_tools.api.effects.PatternOverlay(descriptor: Descriptor, image_resources: ImageResources)

properties

  • aligned bool โ€” aligned
  • angle float โ€” the angle value
  • blend_mode bytes โ€” the effect blending mode

and that's where we're picking back up next part, bestie โ€” more PatternOverlay properties incoming, don't go anywhere ๐Ÿ’–

  • enabled: bool โ€” is this effect even on, bestie? yes/no, that's the whole vibe check.
  • linked: bool โ€” linked. that's it. that's the tea. ๐Ÿ’…
  • name: str โ€” the effect's name, obviously.
  • opacity: float โ€” layer effect opacity, measured in percentage.
  • pattern: Descriptor โ€” the pattern config, psd_tools.psd.descriptor.Descriptor style.
  • phase: Descriptor โ€” phase value in Point. yes, Point with a capital P, iconic.
  • present: bool โ€” does this effect show up in the Photoshop UI? that's the question.
  • scale: float โ€” scale value. ๐Ÿฆ‹
  • shown: bool โ€” whether the effect is shown in the dialog.
  • value: Descriptor โ€” deprecated, bestie, do NOT build your whole personality on this one.
Effect descriptor value. Use the descriptor property instead. like genuinely, use descriptor.

Stroke

class psd_tools.api.effects.Stroke(descriptor: Descriptor, image_resources: ImageResources)

okay so a stroke is justโ€ฆ an outline around your layer, and the way this class is giving so much detail about it โœจ here's everything it exposes:

  • angle: float โ€” angle value.
  • blend_mode: bytes โ€” effect blending mode.
  • color: Descriptor โ€” color. the Descriptor is psd_tools.psd.descriptor.Descriptor, no cap.
  • dithered: bool โ€” dither flag. ๐ŸŽ€
  • enabled: bool โ€” whether if the effect is enabled.
  • fill_type: bytes โ€” the fill type: SolidColor, Gradient, or Pattern.
  • gradient: Descriptor โ€” gradient configuration.
  • linked: bool โ€” linked.
  • name: str โ€” effect name.
  • offset: Descriptor โ€” offset value, sitting inside a Pnt descriptor.
  • opacity: float โ€” layer effect opacity in percentage.
  • overprint: bool โ€” overprint flag.
  • pattern: Descriptor โ€” pattern config.
  • phase: Descriptor โ€” phase value in Point.
  • position: bytes โ€” where the stroke sits: InsetFrame, OutsetFrame, or CenteredFrame. pick your fighter ๐Ÿ’…
  • present: bool โ€” whether if the effect is present in Photoshop UI.
  • reversed: bool โ€” reverse flag.
  • shown: bool โ€” whether if the effect is shown in dialog.
  • size: float โ€” size value.
  • type: bytes โ€” gradient type, and it's one of linear, radial, angle, reflected, or diamond.
  • value: Descriptor โ€” deprecated!!
Effect descriptor value. Use descriptor property instead. seriously bestie, the deprecated one is not the serve.

BevelEmboss

class psd_tools.api.effects.BevelEmboss(descriptor: Descriptor, image_resources: ImageResources)

the lil 3D-look effect, and the property list is lowkey enormous, buckle up ๐Ÿงš

  • altitude: float โ€” altitude value in angle.
  • angle: float โ€” angle value.
  • anti_aliased: bool โ€” anti-aliased. yes ma'am, smooth edges.
  • bevel_style: bytes โ€” bevel style, one of OuterBevel, InnerBevel, Emboss, PillowEmboss, or StrokeEmboss.
  • bevel_type: bytes โ€” bevel type, one of SoftMatte, HardLight, SoftLight.
  • contour: Descriptor โ€” contour configuration.
  • depth: float โ€” depth value in percentage.
  • direction: bytes โ€” direction, either StampIn or StampOut.
  • enabled: bool โ€” whether if the effect is enabled.
  • highlight_color: Descriptor โ€” highlight color value.
  • highlight_mode: bytes โ€” highlight blending mode.
  • highlight_opacity: float โ€” highlight opacity value in percentage.
  • name: str โ€” effect name.
  • opacity: float โ€” layer effect opacity in percentage.
  • present: bool โ€” whether if the effect is present in Photoshop UI.
  • shadow_color: Descriptor โ€” shadow color value.
  • shadow_mode: bytes โ€” shadow blending mode.
  • shadow_opacity: float โ€” shadow opacity value in percentage.
  • shown: bool โ€” whether if the effect is shown in dialog.
  • size: float โ€” size value in pixel.
  • soften: float โ€” soften value in pixels.
  • use_global_light: bool โ€” using global light.
  • use_shape: bool โ€” using shape.
  • use_texture: bool โ€” using texture.
  • value: Descriptor โ€” deprecated
Effect descriptor value. Use descriptor property instead. (the descriptor property is the main character here, fr fr.)

Satin

class psd_tools.api.effects.Satin(descriptor: Descriptor, image_resources: ImageResources)

Satin effect ๐Ÿ’œ โ€” the soft shiny one, and here's every single thing it's got going on:

  • angle: float โ€” angle value in degrees.
  • anti_aliased: bool โ€” anti-aliased.
  • blend_mode: bytes โ€” effect blending mode.
  • color: Descriptor โ€” color.
  • contour: Descriptor โ€” contour configuration.
  • distance: float โ€” distance value in pixels.
  • enabled: bool โ€” whether if the effect is enabled.
  • inverted: bool โ€” inverted.
  • name: str โ€” effect name.
  • opacity: float โ€” layer effect opacity in percentage.
  • present: bool โ€” whether if the effect is present in Photoshop UI.
  • shown: bool โ€” whether if the effect is shown in dialog.
  • size: float โ€” size value in pixel.
  • value: Descriptor โ€” deprecated
Effect descriptor value. Use descriptor property instead. ๐Ÿ’…

psd_tools.api.layers

Layer module. ๐ŸŒˆ

okay this is the big one โ€” this module implements the high-level layer API for psd-tools, giving you Pythonic interfaces for working with Photoshop layers. it defines the layer type hierarchy and the common operations. periodt.

Key classes, and yes we're naming every single one:

  • 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, and this one's a whole vibe, don't skip it:

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. so you literally never have to guess. ๐Ÿ˜Œ


Layer

class psd_tools.api.layers.Layer(parent: GroupMixin, record: LayerRecord, channels: ChannelDataList)

the base class, the blueprint, the moment. โœจ

  • bbox: tuple[int, int, int, int] โ€” the (left, top, right, bottom) tuple.
  • blend_mode: BlendMode โ€” blend mode of this layer. Writable, bestie, you can change it. ๐Ÿ”ฅ

Example:

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

Returns : BlendMode.

  • bottom: int โ€” bottom coordinate.

Returns : int.

  • clip_layers: list[Self] โ€” the clip layers associated with this layer.

Returns : list of layers.

  • clipping: bool โ€” clipping flag for this layer. Writable. ๐Ÿ’…
  • has_stroke() โ€” Returns True if the shape has a stroke. ๐Ÿ‘‘
  • has_vector_mask() โ€” Returns True if the layer has a vector mask.

Returns bool

  • property height: int โ€” Height of the layer, bestie.

Returns int

  • is_group() -> bool โ€” Return True if the layer is a group. The way that this one just tells you if it's giving group energy fr fr.

Returns bool

  • is_visible() -> bool โ€” Layer visibility. Takes group visibility in account, so it's not just vibing on its own ๐Ÿ‘€.

Returns bool

  • property kind: str โ€” Kind of this layer, such as group, pixel, shape, type, smartobject, or psdimage. Class name without the 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. (yes that typo is in the original, we keep it, it's iconic ๐Ÿ’…)

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. Sliding down the stack, no cap ๐Ÿฆ‹.

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. Going up, main character energy โœจ.

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. Finding the layer's next bestie in the layer tree ๐Ÿซถ.
  • 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. Every queen knows her roots ๐Ÿ’œ.
  • previous_sibling(visible: bool = False) -> Self | None โ€” Previous sibling of this layer. The layer right before this one in the lineup ๐ŸŒธ.
  • 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 โ€” 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.

๐Ÿ‘€ pro tip bestie: peek over at psd_tools.constants.Tag for every key that's up for grabs.

Returns โ€” TaggedBlocks.

Example:

from psd_tools.constants import Tag
metadata = layer.tagged_blocks.get_data(Tag.METADATA_SETTING)

property top: int

The top coordinate, duh ๐Ÿ’…. You can write to it โ€” so lowkey you can move the whole layer up and down to your heart's content.

Returns โ€” int.


topil(channel: int | None = None, apply_icc: bool = True) -> Image | None

Gives you the PIL Image of the layer. Yes, actual pixels you can touch. Iconic.

Parameters

  • channel โ€” which channel you want back. Like, 0 gets you the 'R' channel in an RGB image. Check the menu at psd_tools.constants.ChannelID. When it's None, the method hands you all the channels that the PIL modes can handle. All of 'em. Periodt.
  • apply_icc โ€” whether to apply ICC profile conversion to sRGB.

Returns โ€” PIL.Image.Image, or None if the layer has, like, zero 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 every PSD image mode is supported by PIL.Image.Image fr fr. For example, 'CMYK' mode can't include an alpha channel in PIL. When that happens, topil just drops the alpha channel. Not dramatic, just reality. ๐Ÿซถ

update_mask(image: Image, top: int | None = None, left: int | None = None, compression: Compression = Compression.RLE) -> Mask

Swap in a brand new pixel mask for this layer. Glow-up time โœจ.

If your image has an alpha channel (think RGBA, LA), that alpha channel becomes the mask data. If not, the image gets converted to grayscale (L mode). And the rules? White (255) means fully unmasked, black (0) means fully masked. That's the vibe.

Parameters

  • image โ€” the new source Image for the mask.
  • top โ€” new top offset of the mask. Defaults to whatever the current mask top is.
  • left โ€” new left offset of the mask. Defaults to the current mask left.
  • compression โ€” the compression algorithm used for the mask data.

Returns โ€” the updated Mask.

Raises ValueError โ€” if the layer doesn't even have a mask. Rude, but fair.


property vector_mask: VectorMask | None

Hands you the vector mask that's linked up with this layer.

Returns โ€” a VectorMask, or None if there isn't one. ๐Ÿฆ‹


property visible: bool

Layer visibility, simple as. Heads up though: it does not account for group visibility. Writable, so toggle away.

Returns โ€” bool.


property width: int

How wide the layer is.

Returns โ€” int.


๐ŸŽ€ Artboard ๐ŸŽ€

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

An Artboard is a โœจspecialโœจ kind of group โ€” one that rocks a pre-defined viewbox. Main character energy, honestly.


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

A (left, top, right, bottom) tuple.


property bottom: int

The bottom coordinate. It's computed from the children, so it's read-only โ€” look, don't touch. ๐Ÿ’…


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

Composites the layer, and it automatically applies the artboard's background color. So convenient bestie.

When either color or alpha isn't explicitly handed over, it reads the artboard background from the ARTBOARD_DATA tagged block (artboardBackgroundType and Clr descriptor) and uses the missing value โ€” or values โ€” as the compositing backdrop. It's giving resourceful. ๐ŸŒˆ


property left: int

The left coordinate (computed from children, read-only).


property right: int

The right coordinate (computed from children, read-only).


property top: int

The top coordinate (computed from children, read-only).


๐ŸŽ€ Group ๐ŸŽ€

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

A group of layers. Like a little friend group but for pixels. ๐Ÿซถ

Example:

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

property blend_mode: BlendMode

The blend mode of this layer. Writable. Go off. ๐ŸŒธ


property bottom: int

The 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

Composites the layer and the masks (mask, vector mask, and clipping layers). The whole package. ๐ŸŽ

Parameters

  • viewport โ€” the viewport bounding box, given as an (x1, y1, x2, y2) tuple. Default is the layer's bbox.
  • force โ€” boolean flag to force vector drawing.
  • color โ€” backdrop color, given as a scalar or a tuple of scalars. The value should live in [0.0, 1.0]. Like, (1., 0., 0.) gives you red in RGB color mode. โค๏ธ
  • alpha โ€” backdrop alpha in [0.0, 1.0].
  • layer_filter โ€” a Callable that takes a layer as an argument and returns whether or not that layer gets 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]

Returns a bounding box for the layers โ€” or (0, 0, 0, 0) if the layers have no bounding box at all. ๐Ÿ™ˆ

Parameters

  • layers โ€” a sequence of layers, or a group.
  • include_invisible โ€” include invisible layers in the calculation.
  • include_clipping โ€” include clipping layers in the calculation. Defaults to False so it matches visible pixel bounds.

Returns โ€” a 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. Old news, bestie.

Parameters

  • parent โ€” the parent group where the shiny newly created Group object gets added.
  • layers โ€” the layers to group. Can be any subclass of Layer.
  • name โ€” the display name of the group. Defaults to "Group".
  • open_folder โ€” boolean that decides whether the folder is open or closed in photoshop. Defaults to True.

Returns โ€” a Group.

Raises ValueError โ€” if layers is empty. Can't group nothing, babe. ๐Ÿ’€


is_group() -> bool

Returns True if the layer is a group.

Returns โ€” bool.


property left: int

The left coordinate (computed from children, read-only).


classmethod new(parent: GroupMixin, name: str = 'Group', open_folder: bool = True) -> Self

Makes a brand new Group object with minimal records and data channels and metadata, so the group slots into the PSD file all proper-like. โœจ

Parameters

  • name โ€” the display name of the group. Defaults to "Group".
  • open_folder โ€” boolean that decides whether the folder is open or closed in photoshop. Defaults to True.
  • parent โ€” optional parent folder to move the freshly 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

The right coordinate (computed from children, read-only).


property top: int

The top coordinate (computed from children, read-only).


๐ŸŽ€ PixelLayer ๐ŸŽ€

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

A layer that has rasterized image in pixels. The classic. The blueprint. ๐Ÿ‘‘

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 โ€” bestie this is the glow-up move: spin up a whole PixelLayer from a PIL image so it can live inside a given psd file ๐Ÿซถ

Params, one by one:

  • image โ€” the Image object you're converting into photoshop, no take-backs.
  • parent โ€” the parent group or PSDImage this layer belongs to.
  • name โ€” what you're calling the layer. Defaults to "Layer" when you can't be bothered (we've all been there).
  • 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 โ€” the compression algorithm to use for the data.

Returns: a PixelLayer object ๐Ÿ’…

Raises:

  • TypeError โ€” if image is not a PIL Image ๐Ÿ’€
  • ValueError โ€” if parent is None ๐Ÿ˜ญ
Note: If the image has an alpha channel and the parent PSD mode supports layer transparency (e.g. RGBA, LA), the alpha is stored as the layer transparency channel and no extra mask is created. For PSD modes that do not carry a transparency band (e.g. RGB, CMYK), the alpha channel is instead stored as a pixel mask (USER_LAYER_MASK). iykyk โœจ

๐ŸŽ€ ShapeLayer ๐ŸŽ€

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

A layer that has drawing in a vector mask. Shape girlies stay winning โœจ

  • 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. ๐Ÿ‘€
  • 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)

A layer that inserts external data ๐ŸŒธ Use the smart_object attribute to get at that external data โ€” peep SmartObject.

Example, because a demo clears the vibe check:

import io
so = layer.smart_object
if so.detected_filetype == 'jpg':
    # Use open(external_dir=...) when processing untrusted PSD files.
    with so.open() as f:
        image = Image.open(io.BytesIO(f.read()))
  • property smart_object: SmartObject โ€” the associated smart object.

Returns: SmartObject.

๐Ÿฆ‹ TypeLayer ๐Ÿฆ‹

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

A layer that has text and styling information for fonts or paragraphs ๐Ÿ“

Text lives at the text property. Styling info for paragraphs is in engine_dict. Document styling info like the font list is in resource_dict. And rn? Textual information is read-only, so look, don't touch, bestie.

Example, and honestly it ate:

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 โ€” the 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'. Not `'\n'. Yes really. Photoshop said "be different" ๐Ÿ™ˆ
  • 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 typesetting: TypeSetting โ€” structured typographic data.

Returns a TypeSetting object that provides Pythonic access to fonts, paragraphs, styled runs, and default styles โ€” no navigating raw engine data dicts required, we love a wrapper ๐Ÿ’–

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.

๐ŸŒˆ psd_tools.api.mask ๐ŸŒˆ

The Mask module, periodt.

Masks decide the visible area of a layer ๐Ÿ‘‘ There are two types of masks: user mask and vector mask. User mask = any pixel-based mask. Vector mask = a mask from a shape path. Two icons, one purpose.

Masks are accessible from the layer's mask property:

from psd_tools import PSDImage

psdimage = PSDImage.open('example.psd')
layer = psdimage[0]
mask = layer.mask
assert mask is not None
print(mask.bbox)  # (left, top, right, bottom)

mask_image = mask.topil()  # Show the mask as a PIL Image.
if mask_image is not None:
    mask_image.save("mask.png")

To create a new mask, use the layer's create_mask() method:

from psd_tools import PSDImage
from PIL import Image

psdimage = PSDImage.new(mode="RGB", size=(128, 128))
layer = psdimage.create_pixel_layer(Image.new("RGB", (128, 128)))
layer.create_mask(Image.new("L", (128, 128), 255))

And note that creating a pixel layer from an RGBA image will automatically create a user mask โ€” it's giving "did it myself, you're welcome" ๐Ÿ’…

psdimage = PSDImage.new(mode="RGB", size=(128, 128))
layer = psdimage.create_pixel_layer(Image.new("RGBA", (128, 128)))

๐Ÿ“ Mask ๐Ÿ“

class psd_tools.api.mask.Mask(layer: LayerProtocol)

Mask data attached to a layer ๐ŸŽ€

There are two distinct internal mask data: user mask and vector mask. User mask refers to any pixel-based mask, whereas vector mask refers to a mask from a shape path. Internally, the two masks are combined and referred to as the real mask. Two sources, one final boss.

  • property background_color: int โ€” background color.
  • property bbox: tuple[int, int, int, int] โ€” BBox.
  • property bottom: int โ€” bottom coordinate.
  • property data: MaskData โ€” return raw mask data, or None if no data.
  • property disabled: bool โ€” disabled.
  • property flags: MaskFlags โ€” flags.
  • has_real() -> bool โ€” return True if the mask has real flags.
  • property height: int โ€” height.
  • property left: int โ€” left coordinate.
  • property parameters: Any โ€” parameters.
  • property real_flags: MaskFlags | None โ€” real flag.
  • property right: int โ€” right coordinate.
  • property size: tuple[int, int] โ€” (Width, Height) tuple.
  • property top: int โ€” top coordinate.
  • topil(real: bool = True, layer_sized: bool = False, **kwargs: Any) -> Image | None โ€” get a PIL Image of the mask ๐Ÿ–ผ๏ธ

Params:

  • real โ€” when True, returns pixel + vector mask combined.
  • layer_sized โ€” when True, returns a layer-sized image pre-filled with background_color, with the mask data pasted at the correct position. When False (the default), returns the raw stored mask data at mask dimensions.

Returns: PIL Image object, or None if the mask is empty.

  • property width: int โ€” width.

๐Ÿ’ซ psd_tools.api.shape ๐Ÿ’ซ

Shape module.

okay so in PSD/PSB land every single shape is a VectorMask hanging out inside its layer, and optionally there might be an Origination object running the live-shape situation plus a Stroke telling the outline how to be cute. that's the whole vibe. ๐ŸŽ€


โœจ VectorMask โœจ

class psd_tools.api.shape.VectorMask(data: VectorMaskSetting)

Vector mask data, bestie.

A vector mask is a resolution-independent mask made of one or more Path objects. In Photoshop, all the path objects are Bezier curves, no cap. Peep the paths property to see how to deal with path objects. ๐Ÿ’…

  • bbox: tuple[float, float, float, float] โ€” bounding box tuple (left, top, right, bottom) in relative coordinates, where the top-left corner is (0., 0.) and the bottom-right corner is (1., 1.).

This bbox accounts for the full extent of all cubic Bezier curves, not just the anchor points. so like, the whole squishy curve, not just the dots.

Returns: tuple

  • clipboard_record: ClipboardRecord | None โ€” clipboard record carrying bounding box info.

Depending on which Photoshop version you're in, this field can be None. ๐Ÿ™ˆ

  • disabled: bool โ€” if the mask is disabled.
  • initial_fill_rule: int โ€” initial fill rule.

When 0, fill inside of the path. When 1, fill outside of the shape.

Returns: int

  • inverted: bool โ€” invert the mask.
  • not_linked: bool โ€” if the knots are not linked.
  • paths: list[Subpath] โ€” list of Subpath. A Subpath is a list-like structure holding one or more Knot items. A Knot contains the relative coordinates of control points for a Bezier curve. index tells you which origination item the subpath belongs to, and operation tells you how to combine multiple shape paths.

In PSD, the path fill rule is even-odd.

Example:

for subpath in layer.vector_mask.paths:
    anchors = [(
        int(knot.anchor[1] * psd.width),
        int(knot.anchor[0] * psd.height),
    ) for knot in subpath]

Returns: List of Subpath.


๐ŸŽ€ Stroke ๐ŸŽ€

class psd_tools.api.shape.Stroke(data: VectorStrokeContentSetting)

Stroke holds the decorative info for strokes โ€” the lil fashion details, basically. ๐Ÿ‘‘

This is a thin wrapper around the Descriptor structure. Check the _data attribute to get the raw data.

  • blend_mode: Any โ€” blend mode.
  • content: Any โ€” fill effect.
  • enabled: bool โ€” if the stroke is enabled.
  • fill_enabled: bool โ€” if the stroke fill is enabled.
  • line_alignment: str โ€” alignment, one of inner, outer, center.
  • line_cap_type: str โ€” cap type, one of butt, round, square.
  • line_dash_offset: float โ€” line dash offset in float.

Returns: float

  • line_dash_set: list โ€” line dash set in list of UnitFloat.

Returns: list

  • line_join_type: str โ€” join type, one of miter, round, bevel.
  • line_width: float โ€” stroke width in float.
  • miter_limit: Any โ€” miter limit in float.
  • opacity: Any โ€” opacity value.
  • stroke_adjust: Any โ€” stroke adjust.

๐Ÿฆ‹ Origination ๐Ÿฆ‹

Origination keeps the live shape properties for some of the primitive shapes. You get to these objects through the origination property of layers. These are the primitive shapes that are defined: Invalidated, Line, Rectangle, Ellipse, and RoundedRectangle. slay, a whole little family. ๐ŸŒธ

๐Ÿ’œ Invalidated ๐Ÿ’œ

class psd_tools.api.shape.Invalidated(data: Descriptor)

Invalidated live shape.

This equals a primitive shape that does not provide Live shape properties. So use VectorMask to access shape information instead of this origination object, bestie โ€” that's where the tea actually is.

  • invalidated: bool โ€” bool.

Type: return

๐ŸŒˆ Line ๐ŸŒˆ

class psd_tools.api.shape.Line(data: Descriptor)

Line live shape.

  • arrow_conc: int โ€” int.

Type: return

  • arrow_end: bool โ€” line arrow end.

Returns: bool

  • arrow_length: float โ€” line arrow length.

Returns: float

  • arrow_start: bool โ€” line arrow start.

Returns: bool

  • arrow_width: float โ€” line arrow width.

Returns: float

  • bbox: tuple[float, float, float, float] โ€” bounding box of the live shape.

Returns: Descriptor

  • index: int โ€” origination item index.

Returns: int

  • invalidated: bool โ€” bool.

Type: return

  • line_end: Descriptor โ€” line end.

Returns: Descriptor

  • line_start: Descriptor โ€” line start.

Returns: Descriptor

  • line_weight: float โ€” line weight.

Returns: float

  • origin_type: int โ€” type of the vector shape.
    • 1: Rectangle
    • 2: RoundedRectangle
    • 4: Line
    • 5: Ellipse

Returns: int

  • resolution: float โ€” resolution.

Returns: float

โญ Ellipse โญ

class psd_tools.api.shape.Ellipse(data: Descriptor)

Ellipse live shape.

  • bbox: tuple[float, float, float, float] โ€” bounding box of the live shape.

Returns: Descriptor

  • index: int โ€” origination item index.

Returns: int

  • invalidated: bool โ€” bool.

Type: return

  • origin_type: int โ€” type of the vector shape.
    • 1: Rectangle
    • 2: RoundedRectangle
    • 4: Line
    • 5: Ellipse

Returns: int

  • resolution: float โ€” resolution.

Returns: float

๐Ÿ’– Rectangle ๐Ÿ’–

class psd_tools.api.shape.Rectangle(data: Descriptor)

Rectangle live shape.

  • bbox: tuple[float, float, float, float] โ€” bounding box of the live shape.

Returns: Descriptor

  • index: int โ€” origination item index.

Returns: int

  • invalidated: bool โ€” bool.

Type: return

  • origin_type: int โ€” type of the vector shape.
    • 1: Rectangle
    • 2: RoundedRectangle
    • 4: Line
    • 5: Ellipse

Returns: int

  • resolution: float โ€” resolution.

Returns: float

๐Ÿ“ RoundedRectangle ๐Ÿ“

class psd_tools.api.shape.RoundedRectangle(data: Descriptor)

Rounded rectangle live shape. the softest corners in the game, periodt.

  • bbox: tuple[float, float, float, float] โ€” bounding box of the live shape.

Returns: Descriptor

  • index: int โ€” origination item index.

Returns: int

  • invalidated: bool โ€” bool.

Type: return

  • origin_type: int โ€” type of the vector shape.
    • 1: Rectangle
    • 2: RoundedRectangle
    • 4: Line
    • 5: Ellipse

Returns: int

  • radii: Any โ€” corner radii of rounded rectangles. The order is top-left, top-right, bottom-left, bottom-right.

Returns: Descriptor

  • resolution: float โ€” resolution.

Returns: float


๐ŸŒŸ psd_tools.api.smart_object ๐ŸŒŸ

Smart object module. iykyk.

๐Ÿซถ SmartObject ๐Ÿซถ

class psd_tools.api.smart_object.SmartObject(layer: LayerProtocol)

A smart object that represents an embedded or external file.

Smart objects are attached to SmartObjectLayer. ๐Ÿ’…

  • data: bytes โ€” embedded file content as bytes.

So, kind == 'data'? This hands you back the bytes sitting right there in the PSD โ€” literally zero filesystem access, nothing touched on disk, we love a no-side-effects moment ๐Ÿ’…. But kind == 'external'? It calls open() with no external_dir argument, which means it trusts fullPath from the PSD verbatim โ€” like, fully, no questions asked ๐Ÿ˜ญ. If you're dealing with files you don't trust, please please please prefer open() with an explicit external_dir. That's the whole vibe check right there.

  • property detected_filetype: str | None โ€” a best-effort guess at the file type, which only kicks in as a fallback when filetype is None.

Here's the resolution order, bestie, step by step:

  1. filetype โ€” whatever value is actually stored in the PSD. The real one.
  2. The extension grabbed from filename (lower-cased, dot stripped).
  3. Magic-byte sniffing of the first few embedded bytes โ€” only for kind == 'data', because external objects are not read from disk, which keeps this property side-effect-free. Queen behaviour honestly.
Warning: steps 2 and 3 are pure heuristics. Do not use the result for security-sensitive decisions โ€” like deciding whether to execute content, or whether to trust a type boundary. That's a no from me ๐Ÿ™ˆ.
  • property filename: str โ€” the original file name of the object. That's it, that's the whole thing.
  • property filesize: int โ€” file size of the object.
  • property filetype: str | None โ€” the 4-byte file-type code stored in the PSD, lowercased and stripped. Returns None when the field is absent or blank (some Adobe Illustrator smart objects literally store four spaces instead of a real type code โ€” four spaces, iconic of them ๐Ÿ˜ญ). If you want a guess that falls back to filename extension and magic bytes, use detected_filetype.
  • is_psd() -> bool โ€” returns True if the file is embedded PSD/PSB. It checks the stored filetype first; and if that's None (blank field, again) it falls back to inspecting the first four magic bytes of the embedded data. The filename extension is intentionally not used as a fallback โ€” so it never misclassifies non-PSD files that are just named *.psd. Fraud detection, slay ๐Ÿ”ฅ.
  • property kind: str โ€” the kind of the link: 'data', 'alias', or 'external'.
  • open(external_dir: str | PathLike | None = None) -> Iterator[IO[bytes]] โ€” opens the smart object as binary IO.

Parameters

  • external_dir โ€” the directory to resolve external paths against. When provided, a fullPath that resolves outside this directory is silently ignored and relPath is tried instead. A relPath that resolves outside this directory raises ValueError. Strongly recommended when you're processing untrusted PSD files. Like, strongly.

Example:

with layer.smart_object.open() as f:
    data = f.read()
  • property resolution: float โ€” resolution of the object.
  • save(filename: str | PathLike | None = None, directory: str | PathLike | None = None, external_dir: str | PathLike | None = None) -> None โ€” saves the smart object to a file.

Parameters

  • filename โ€” explicit destination path. When provided it's used as-is and directory is ignored. (Sorry girl, directory doesn't get a say here.)
  • directory โ€” output directory used when filename is None. Defaults to the current working directory. The embedded basename gets written inside this directory, and any path-traversal sequences in the embedded name are stripped automatically. Safety first always โœจ.
  • external_dir โ€” passed straight through to open() when the smart object kind is 'external'. It constrains which paths on disk may be read. Strongly recommended when processing untrusted PSD files.

Raises ValueError โ€” if the embedded name contains no safe basename, resolves outside directory, or (for external kind) the source path escapes external_dir.

  • property transform_box: tuple[float, float, float, float, float, float, float, float] | None โ€” a tuple with the coordinates of the smart object's transformed box. This box is the result of one or more transformations โ€” scaling, rotation, translation, skewing โ€” applied to the original bounding box of the smart object. Math ate ๐Ÿซถ.

The format of the tuple is: (x1, y1, x2, y2, x3, y3, x4, y4)

Where 1 is the top left corner, 2 is top right, 3 is bottom right, and 4 is bottom left. Memorise that, bestie, it'll save you.

  • property unique_id: str โ€” UUID of the object.
  • property warp: object | None โ€” warp parameters.

๐ŸŒˆ psd_tools.composite ๐ŸŒˆ

Composite module for layer rendering and blending.

This subpackage is the whole rendering engine โ€” it composites PSD layers into raster images, implements Photoshop's blend modes, layer effects, and vector shape rasterization. Main character module, honestly ๐Ÿ‘‘.

Note: this module needs 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 rasterization
  • scipy: for advanced image processing operations
  • scikit-image: for morphological operations in effects

Key modules:

  • psd_tools.composite.composite: main compositing functions
  • psd_tools.composite.blend: blend mode implementations
  • psd_tools.composite.effects: layer effects (stroke, shadow, etc.)
  • psd_tools.composite.vector: vector shape and path rendering
  • psd_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 it supports all of Photoshop's standard blend modes including multiply, screen, overlay, soft light, and more. Obsessed ๐Ÿ’–.

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[[Layer], bool] | None = None, force: bool = False, as_layer: bool = False) -> tuple[ndarray, ndarray, ndarray]

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. The way it just... does all of that ๐Ÿ˜ญโœจ.

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[[Layer], bool] | None, force: bool, as_layer: bool = False, apply_icc: bool = True) -> Image | None

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. PIL girlies, this one's for you ๐Ÿซถ.

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 <#psd_tools.constants.BlendMode> enums to their corresponding functions for easy lookup during compositing.

psd_tools.composite.blend.divide(Cb: ndarray, Cs: ndarray) -> ndarray

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

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.hsl2hsv(img: ndarray) -> ndarray

Convert an HSL image to HSV space using vectorized arrays.

psd_tools.composite.blend.hsl2rgb(img: ndarray) -> ndarray

Convert an HSL image to RGB space using vectorized arrays.

psd_tools.composite.blend.hsv2hsl(img: ndarray) -> ndarray

Convert an HSV image to HSL space using vectorized arrays.

psd_tools.composite.blend.linear_light(Cb: ndarray, Cs: ndarray) -> ndarray

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

Wrap non-separable blending function for CMYK handling.

psd_tools.composite.blend.pin_light(Cb: ndarray, Cs: ndarray) -> ndarray

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.rgb2hsl(img: ndarray) -> ndarray

Convert an RGB image to HSL space using vectorized arrays.

psd_tools.composite.blend.vivid_light(Cb: ndarray, Cs: ndarray) -> ndarray

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: Layer <#psd_tools.api.layers.Layer>) -> ndarray

Draw a stroke.

Requires aggdraw for bezier curve rasterization.

psd_tools.composite.vector.draw_vector_mask(layer: Layer <#psd_tools.api.layers.Layer>) -> ndarray

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:

  1. Extracting the layer's alpha channel or shape mask
  2. Applying morphological operations (dilation/erosion) based on stroke size and position
  3. Filling the stroke region with the specified paint (solid color, gradient, pattern)
  4. 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.

๐Ÿ“ psd_tools.compression ๐Ÿ“

Image compression utilities for PSD channel data.

This subpackage provides compression and decompression codecs for raw pixel data in PSD files. Adobe Photoshop supports multiple compression methods for channel data to reduce file size.

Supported compression methods:

  • RAW (Compression.RAW): Uncompressed raw pixel data
  • RLE (Compression.RLE): Apple PackBits run-length encoding
  • ZIP (Compression.ZIP): ZIP/Deflate compression without prediction
  • ZIP_WITH_PREDICTION (Compression.ZIP_WITH_PREDICTION): ZIP with delta encoding

The RLE codec includes both a pure Python implementation and a Cython-optimized version (_rle.pyx) that provides significant performance improvements. The Cython version is used automatically when available, with graceful fallback to pure Python.

Key functions:

  • compress(): Compress raw pixel data using specified method
  • decompress(): Decompress pixel data back to raw bytes
  • encode_rle(): RLE encoding for a single channel
  • decode_rle(): RLE decoding for a single channel

Example usage:

from psd_tools.compression import compress, decompress
from psd_tools.constants import Compression

# Compress raw channel data
compressed = compress(
    data=raw_pixels,
    compression=Compression.RLE,
    width=100,
    height=100,
    depth=8,
    version=1
)
# Decompress back to raw data
raw_pixels = decompress(
    data=compressed,
    compression=Compression.RLE,
    width=100,
    height=100,
    depth=8,
    version=1
)

Performance notes ๐Ÿ“ (aka the tea on when to use what):

  • RLE is most effective for images with large uniform areas
  • ZIP with prediction works well for continuous-tone images
  • The Cython RLE codec can be 10-100x faster than pure Python
  • Compression method is chosen per-channel when saving PSD files

The compression module handles various bit depths (8, 16, 32-bit per channel) and implements delta encoding for improved compression ratios on certain image types.

This module provides compression and decompression codecs for PSD channel data.


โœจ Compression Functions โœจ

  • psd_tools.compression.compress(data: bytes, compression: Compression <#psd_tools.constants.Compression>, width: int, height: int, depth: int, version: int = 1) -> bytes โ€” Compress raw data. Squish it, bestie. ๐Ÿ’…

Parameters

  • data โ€” raw data bytes to write.
  • compression โ€” compression type, see Compression <#psd_tools.constants.Compression>.
  • width โ€” width.
  • height โ€” height.
  • depth โ€” bit depth of the pixel.
  • version โ€” psd file version.

Returns โ€” compressed data bytes. ๐ŸŽ€

  • psd_tools.compression.decompress(data: bytes, compression: Compression <#psd_tools.constants.Compression>, width: int, height: int, depth: int, version: int = 1) -> bytes โ€” Decompress raw data. Unsquish. Reverse girliepop. ๐Ÿฆ‹

Parameters

  • data โ€” compressed data bytes.
  • compression โ€” compression type, see Compression <#psd_tools.constants.Compression>.
  • width โ€” width in pixels; must be in [1, 300000].
  • height โ€” height in pixels; must be in [1, 300000].
  • depth โ€” bit depth of the pixel; must be one of 1, 8, 16, 32.
  • version โ€” psd file version.

Returns โ€” decompressed data bytes.

Raises ValueError โ€” if width, height, or depth are out of range. ๐Ÿšจ Like, respect the limits or get an exception, periodt.


๐Ÿฆ‹ RLE Codec ๐Ÿฆ‹

psd_tools.compression.encode_rle(data: bytes, width: int, height: int, depth: int, version: int) -> bytes

psd_tools.compression.decode_rle(data: bytes, width: int, height: int, depth: int, version: int) -> bytes

The RLE (Run-Length Encoding) codec implements Apple PackBits compression. A Cython-optimized version (_rle.pyx) is used when available, providing 10-100x performance improvement over the pure Python fallback. Basically if you got the Cython build, you're eating GOOD. ๐Ÿ”ฅ


๐ŸŒˆ Prediction Encoding ๐ŸŒˆ

psd_tools.compression.encode_prediction(data: bytes | bytearray, w: int, h: int, depth: int) -> bytes

psd_tools.compression.decode_prediction(data: bytes, w: int, h: int, depth: int) -> bytes

Prediction encoding applies delta compression before ZIP compression, improving compression ratios for continuous-tone images. Supports 8, 16, and 32-bit depths. โญ


๐Ÿ’œ psd_tools.constants ๐Ÿ’œ

Various constants for psd_tools

๐ŸŒธ BlendMode ๐ŸŒธ

class psd_tools.constants.BlendMode(*values) โ€” Blend modes. The whole squad of ways your layers can mix together, no cap.

  • COLOR = b'colr'
  • COLOR_BURN = b'idiv'
  • COLOR_DODGE = b'div '
  • DARKEN = b'dark'
  • DARKER_COLOR = b'dkCl'
  • DIFFERENCE = b'diff'
  • DISSOLVE = b'diss'
  • DIVIDE = b'fdiv'
  • EXCLUSION = b'smud'
  • HARD_LIGHT = b'hLit'
  • HARD_MIX = b'hMix'
  • HUE = b'hue '
  • LIGHTEN = b'lite'
  • LIGHTER_COLOR = b'lgCl'
  • LINEAR_BURN = b'lbrn'
  • LINEAR_DODGE = b'lddg'
  • LINEAR_LIGHT = b'lLit'
  • LUMINOSITY = b'lum '
  • MULTIPLY = b'mul '
  • NORMAL = b'norm'
  • OVERLAY = b'over'
  • PASS_THROUGH = b'pass'
  • PIN_LIGHT = b'pLit'
  • SATURATION = b'sat '
  • SCREEN = b'scrn'
  • SOFT_LIGHT = b'sLit'
  • SUBTRACT = b'fsub'
  • VIVID_LIGHT = b'vLit'

๐ŸŽ€ ChannelID ๐ŸŽ€

class psd_tools.constants.ChannelID(*values) โ€” Channel types.

  • CHANNEL_0 = 0
  • CHANNEL_1 = 1
  • CHANNEL_2 = 2
  • CHANNEL_3 = 3
  • CHANNEL_4 = 4
  • CHANNEL_5 = 5
  • CHANNEL_6 = 6
  • CHANNEL_7 = 7
  • CHANNEL_8 = 8
  • CHANNEL_9 = 9
  • REAL_USER_LAYER_MASK = -3
  • TRANSPARENCY_MASK = -1
  • USER_LAYER_MASK = -2

โœจ Clipping โœจ

class psd_tools.constants.Clipping(*values) โ€” Clipping.

  • BASE = 0
  • NON_BASE = 1

๐ŸŒˆ ColorMode ๐ŸŒˆ

class psd_tools.constants.ColorMode(*values) โ€” Color mode.

  • BITMAP = 0
  • CMYK = 4
  • DUOTONE = 8
  • GRAYSCALE = 1
  • INDEXED = 2
  • LAB = 9
  • MULTICHANNEL = 7
  • RGB = 3
  • static channels(value: ColorMode <#psd_tools.constants.ColorMode>, alpha: bool = False) -> int โ€” hands you back the channel count as an int. ๐Ÿ‘‘

๐Ÿฆ‹ ColorSpaceID ๐Ÿฆ‹

class psd_tools.constants.ColorSpaceID(*values) โ€” Color space types.

  • CMYK = 2
  • GRAYSCALE = 8
  • HSB = 1
  • LAB = 7
  • RGB = 0

๐Ÿ’– CompatibilityMode ๐Ÿ’–

class psd_tools.constants.CompatibilityMode(*values) โ€” Compatibility modes that describe how compositing and layer control should attempt to behave.

  • CLIP_STUDIO_PAINT = 3
  • DEFAULT = 1
  • GIMP = 4
  • KRITA = 5
  • PAINT_TOOL_SAI = 2
  • PHOTOSHOP = 1

๐Ÿ”ฅ Compression ๐Ÿ”ฅ

class psd_tools.constants.Compression(*values) โ€” Compression modes.

Compression. 0 = Raw Data, 1 = RLE compressed, 2 = ZIP without prediction, 3 = ZIP with prediction.

  • RAW = 0
  • RLE = 1
  • ZIP = 2
  • ZIP_WITH_PREDICTION = 3

๐ŸŒŸ EffectOSType ๐ŸŒŸ

class psd_tools.constants.EffectOSType(*values) โ€” OS Type keys for Layer Effects.

  • BEVEL = b'bevl'
  • COMMON_STATE = b'cmnS'
  • DROP_SHADOW = b'dsdw'
  • INNER_GLOW = b'iglw'
  • INNER_SHADOW = b'isdw'
  • OUTER_GLOW = b'oglw'
  • SOLID_FILL = b'sofi'

๐Ÿ“ GlobalLayerMaskKind ๐Ÿ“

class psd_tools.constants.GlobalLayerMaskKind(*values) โ€” Global layer mask kind.

  • COLOR_PROTECTED = 1
  • COLOR_SELECTED = 0
  • PER_LAYER = 128

๐Ÿงš LinkedLayerType ๐Ÿงš

class psd_tools.constants.LinkedLayerType(*values) โ€” Linked layer types.

  • ALIAS = b'liFA'
  • DATA = b'liFD'
  • EXTERNAL = b'liFE'

๐Ÿ’… PathResourceID ๐Ÿ’…

class psd_tools.constants.PathResourceID(*values)

  • CLIPBOARD = 7
  • CLOSED_KNOT_LINKED = 1
  • CLOSED_KNOT_UNLINKED = 2
  • CLOSED_LENGTH = 0
  • INITIAL_FILL = 8
  • OPEN_KNOT_LINKED = 4
  • OPEN_KNOT_UNLINKED = 5
  • OPEN_LENGTH = 3
  • PATH_FILL = 6

๐Ÿซถ PlacedLayerType ๐Ÿซถ

class psd_tools.constants.PlacedLayerType(*values)

  • IMAGE_STACK = 3
  • RASTER = 2
  • UNKNOWN = 0
  • VECTOR = 1

๐Ÿ˜ญ PrintScaleStyle ๐Ÿ˜ญ

class psd_tools.constants.PrintScaleStyle(*values) โ€” Print scale style.

  • CENTERED = 0
  • SIZE_TO_FIT = 1
  • USER_DEFINED = 2

๐Ÿ‘‘ Resource ๐Ÿ‘‘

class psd_tools.constants.Resource(*values) โ€” Image resource keys.

Heads up bestie: the following is not defined for performance reasons. Not me leaving stuff out on purpose โ€” it's for the vibes (and the speed). ๐Ÿ’€
  • PATH_INFO_10 to PATH_INFO_989 corresponding to 2010 - 2989
  • PLUGIN_RESOURCES_10 to PLUGIN_RESOURCES_989 corresponding to 4010 - 4989

And now, the full roster:

  • ALPHA_IDENTIFIERS = 1053
  • ALPHA_NAMES_PASCAL = 1006
  • ALPHA_NAMES_UNICODE = 1045
  • ALTERNATE_DUOTONE_COLORS = 1066
  • ALTERNATE_SPOT_COLORS = 1067
  • AUTO_SAVE_FILE_PATH = 1086
  • AUTO_SAVE_FORMAT = 1087
  • BACKGROUND_COLOR = 1010
  • BORDER_INFO = 1009
  • CAPTION_DIGEST = 1061
  • CAPTION_PASCAL = 1008
  • CLIPPING_PATH_NAME = 2999
  • COLOR_HALFTONING_INFO = 1013
  • COLOR_SAMPLERS_RESOURCE = 1073
  • COLOR_SAMPLERS_RESOURCE_OBSOLETE = 1038
  • COLOR_TRANSFER_FUNCTION = 1016
  • COPYRIGHT_FLAG = 1034
  • COUNT_INFO = 1080
  • DISPLAY_INFO = 1077
  • DISPLAY_INFO_OBSOLETE = 1007
  • DUOTONE_HALFTONING_INFO = 1014
  • DUOTONE_IMAGE_INFO = 1018
  • DUOTONE_TRANSFER_FUNCTION = 1017
  • EFFECTIVE_BW = 1019
  • EFFECTS_VISIBLE = 1042
  • EPS_OPTIONS = 1021
  • EXIF_DATA_1 = 1058
  • EXIF_DATA_3 = 1059
  • GLOBAL_ALTITUDE = 1049
  • GLOBAL_ANGLE = 1037
  • GRAYSCALE_HALFTONING_INFO = 1012
  • GRAYSCALE_TRANSFER_FUNCTION = 1015
  • GRID_AND_GUIDES_INFO = 1032
  • HDR_TONING_INFO = 1070
  • ICC_PROFILE = 1039
  • ICC_UNTAGGED_PROFILE = 1041
  • IDS_SEED_NUMBER = 1044
  • IMAGE_MODE_RAW = 1029
  • IMAGE_READY_7_ROLLOVER_EXPANDED_STATE = 7003
  • IMAGE_READY_DATA_SETS = 7001
  • IMAGE_READY_DEFAULT_SELECTED_STATE = 7002
  • IMAGE_READY_ROLLOVER_EXPANDED_STATE = 7004
  • IMAGE_READY_SAVE_LAYER_SETTINGS = 7005
  • IMAGE_READY_VARIABLES = 7000
  • IMAGE_READY_VERSION = 7006
  • INDEXED_COLOR_TABLE_COUNT = 1046
  • IPTC_NAA = 1028
  • JPEG_QUALITY = 1030
  • JUMP_TO_XPEP = 1052
  • LAYER_COMPS = 1065
  • LAYER_GROUPS_ENABLED_ID = 1072
  • LAYER_GROUP_INFO = 1026
  • LAYER_SELECTION_IDS = 1069
  • LAYER_STATE_INFO = 1024
  • LIGHTROOM_WORKFLOW = 8000
  • MAC_NSPRINTINFO = 1084
  • MAC_PAGE_FORMAT_INFO = 1002
  • MAC_PRINT_MANAGER_INFO = 1001
  • MEASUREMENT_SCALE = 1074
  • OBSOLETE1 = 1000
  • OBSOLETE2 = 1003
  • OBSOLETE3 = 1020
  • OBSOLETE4 = 1023
  • OBSOLETE5 = 1027
  • ONION_SKINS = 1078
  • ORIGIN_PATH_INFO = 3000
  • PATH_INFO_0 = 2000
  • PATH_INFO_1 = 2001
  • PATH_INFO_2 = 2002
  • PATH_INFO_3 = 2003
  • PATH_INFO_4 = 2004
  • PATH_INFO_5 = 2005
  • PATH_INFO_6 = 2006
  • PATH_INFO_7 = 2007
  • PATH_INFO_8 = 2008
  • PATH_INFO_9 = 2009
  • PATH_INFO_990 = 2990
  • PATH_INFO_991 = 2991
  • PATH_INFO_992 = 2992
  • PATH_INFO_993 = 2993
  • PATH_INFO_994 = 2994
  • PATH_INFO_995 = 2995
  • PATH_INFO_996 = 2996
  • PATH_INFO_997 = 2997
  • PATH_SELECTION_STATE = 1088
  • PIXEL_ASPECT_RATIO = 1064
  • PLUGIN_RESOURCE_0 = 4000
  • PLUGIN_RESOURCE_1 = 4001
  • PLUGIN_RESOURCE_2 = 4002
  • PLUGIN_RESOURCE_3 = 4003
  • PLUGIN_RESOURCE_4 = 4004
  • PLUGIN_RESOURCE_4990 = 4990
  • PLUGIN_RESOURCE_4991 = 4991
  • PLUGIN_RESOURCE_4992 = 4992
  • PLUGIN_RESOURCE_4993 = 4993
  • PLUGIN_RESOURCE_4994 = 4994
  • PLUGIN_RESOURCE_4995 = 4995
  • PLUGIN_RESOURCE_4996 = 4996
  • PLUGIN_RESOURCE_4997 = 4997
  • PLUGIN_RESOURCE_4998 = 4998
  • PLUGIN_RESOURCE_4999 = 4990
  • PLUGIN_RESOURCE_5 = 4005
  • PLUGIN_RESOURCE_6 = 4006
  • PLUGIN_RESOURCE_7 = 4007
  • PLUGIN_RESOURCE_8 = 4008
  • PLUGIN_RESOURCE_9 = 4009
  • PRINT_FLAGS = 1011
  • PRINT_FLAGS_INFO = 10000
  • PRINT_INFO_CS2 = 1071
  • PRINT_INFO_CS5 = 1082
  • PRINT_SCALE = 1062
  • PRINT_STYLE = 1083
  • QUICK_MASK_INFO = 1022
  • RESOLUTION_INFO = 1005
  • SHEET_DISCLOSURE = 1076
  • SLICES = 1050
  • SPOT_HALFTONE = 1043
  • THUMBNAIL_RESOURCE = 1036
  • THUMBNAIL_RESOURCE_PS4 = 1033
  • TIMELINE_INFO = 1075
  • TRANSPARENCY_INDEX = 1047
  • URL = 1035
  • URL_LIST = 1054
  • VERSION_INFO = 1057
  • WATERMARK = 1040
  • WINDOWS_DEVMODE = 1085
  • WORKFLOW_URL = 1051
  • WORKING_PATH = 1025
  • XMP_METADATA = 1060

okay bestie quick heads-up before you @ me: yes, PLUGIN_RESOURCE_4999 = 4990 โ€” that is literally what it says, we do not fix it, we do not touch it, we just report it ๐Ÿ’…

static is_path_info(value: int) -> bool
static is_plugin_resource(value: int) -> bool

SectionDivider ๐ŸŽ€

class psd_tools.constants.SectionDivider(*values)
  • BOUNDING_SECTION_DIVIDER = 3
  • CLOSED_FOLDER = 2
  • OPEN_FOLDER = 1
  • OTHER = 0

Tag ๐Ÿท๏ธโœจ

class psd_tools.constants.Tag(*values)

Tagged blocks keys. iykyk.

  • ALPHA = b'Alph'
  • ANIMATION_EFFECTS = b'anFX'
  • ANNOTATIONS = b'Anno'
  • ARTBOARD_DATA1 = b'artb'
  • ARTBOARD_DATA2 = b'artd'
  • ARTBOARD_DATA3 = b'abdd'
  • BLACK_AND_WHITE = b'blwh'
  • BLEND_CLIPPING_ELEMENTS = b'clbl'
  • BLEND_FILL_OPACITY = b'iOpa'
  • BLEND_INTERIOR_ELEMENTS = b'infx'
  • BRIGHTNESS_AND_CONTRAST = b'brit'
  • CAI = b'CAI '
  • CHANNEL_BLENDING_RESTRICTIONS_SETTING = b'brst'
  • CHANNEL_MIXER = b'mixr'
  • COLOR_BALANCE = b'blnc'
  • COLOR_LOOKUP = b'clrL'
  • COMPOSITOR_INFO = b'cinf'
  • CONTENT_GENERATOR_EXTRA_DATA = b'CgEd'
  • CURVES = b'curv'
  • EFFECTS_LAYER = b'lrFX'
  • EXPORT_SETTING1 = b'extd'
  • EXPORT_SETTING2 = b'extn'
  • EXPOSURE = b'expA'
  • FILTER_EFFECTS1 = b'FXid'
  • FILTER_EFFECTS2 = b'FEid'
  • FILTER_EFFECTS3 = b'FELS'
  • FILTER_MASK = b'FMsk'
  • FOREIGN_EFFECT_ID = b'ffxi'
  • FRAMED_GROUP = b'frgb'
  • GENI = b'GenI'
  • GRADIENT_FILL_SETTING = b'GdFl'
  • GRADIENT_MAP = b'grdm'
  • HUE_SATURATION = b'hue2'
  • HUE_SATURATION_V4 = b'hue '
  • INVERT = b'nvrt'
  • KNOCKOUT_SETTING = b'knko'
  • LAYER = b'Layr'
  • LAYER_16 = b'Lr16'
  • LAYER_32 = b'Lr32'
  • LAYER_ID = b'lyid'
  • LAYER_MASK_AS_GLOBAL_MASK = b'lmgm'
  • LAYER_NAME_SOURCE_SETTING = b'lnsr'
  • LAYER_VERSION = b'lyvr'
  • LEVELS = b'levl'
  • LINKED_LAYER1 = b'lnkD'
  • LINKED_LAYER2 = b'lnk2'
  • LINKED_LAYER3 = b'lnk3'
  • LINKED_LAYER_EXTERNAL = b'lnkE'
  • METADATA_SETTING = b'shmd'
  • NESTED_SECTION_DIVIDER_SETTING = b'lsdk'
  • OBJECT_BASED_EFFECTS_LAYER_INFO = b'lfx2'
  • OBJECT_BASED_EFFECTS_LAYER_INFO_V0 = b'lmfx'
  • OBJECT_BASED_EFFECTS_LAYER_INFO_V1 = b'lfxs'
  • OCIO = b'OCIO'
  • PATT = b'patt'
  • PATTERNS1 = b'Patt'
  • PATTERNS2 = b'Pat2'
  • PATTERNS3 = b'Pat3'
  • PATTERN_DATA = b'shpa'
  • PATTERN_FILL_SETTING = b'PtFl'
  • PHOTO_FILTER = b'phfl'
  • PIXEL_SOURCE_DATA1 = b'PxSc'
  • PIXEL_SOURCE_DATA2 = b'PxSD'
  • PLACED_LAYER1 = b'plLd'
  • PLACED_LAYER2 = b'PlLd'
  • POSTERIZE = b'post'
  • PROTECTED_SETTING = b'lspf'
  • REFERENCE_POINT = b'fxrp'
  • SAVING_MERGED_TRANSPARENCY = b'Mtrn'
  • SAVING_MERGED_TRANSPARENCY16 = b'Mt16'
  • SAVING_MERGED_TRANSPARENCY32 = b'Mt32'
  • SECTION_DIVIDER_SETTING = b'lsct'
  • SELECTIVE_COLOR = b'selc'
  • SHEET_COLOR_SETTING = b'lclr'
  • SMART_OBJECT_LAYER_DATA1 = b'SoLd'
  • SMART_OBJECT_LAYER_DATA2 = b'SoLE'
  • SOLID_COLOR_SHEET_SETTING = b'SoCo'
  • TEXT_ENGINE_DATA = b'Txt2'
  • THRESHOLD = b'thrs'
  • TRANSPARENCY_SHAPES_LAYER = b'tsly'
  • TYPE_TOOL_INFO = b'tySh'
  • TYPE_TOOL_OBJECT_SETTING = b'TySh'
  • UNICODE_LAYER_NAME = b'luni'
  • UNICODE_PATH_NAME = b'pths'
  • USER_MASK = b'LMsk'
  • USING_ALIGNED_RENDERING = b'sn2P'
  • VECTOR_MASK_AS_GLOBAL_MASK = b'vmgm'
  • VECTOR_MASK_SETTING1 = b'vmsk'
  • VECTOR_MASK_SETTING2 = b'vsms'
  • VECTOR_ORIGINATION_DATA = b'vogk'
  • VECTOR_ORIGINATION_UNKNOWN = b'vowv'
  • VECTOR_STROKE_CONTENT_DATA = b'vscg'
  • VECTOR_STROKE_DATA = b'vstk'
  • VIBRANCE = b'vibA'
bestie. look at CAI = b'CAI ' and HUE_SATURATION_V4 = b'hue '. those trailing spaces are REAL and they are LOAD-BEARING. do not let your formatter eat them ๐Ÿ™ˆ

TextType ๐Ÿ“

class psd_tools.constants.TextType(*values)

Type of text.

  • PARAGRAPH = 1
  • POINT = 0

psd_tools.psd ๐ŸŒˆ

Low-level API that translates binary data to Python structure.

All the data structure in this subpackage inherits from one of the object defined in psd_tools.psd.base module.


PSD ๐Ÿ‘‘

class psd_tools.psd.PSD(header: FileHeader = NOTHING, color_mode_data: ColorModeData = NOTHING, image_resources: ImageResources = NOTHING, layer_and_mask_information: LayerAndMaskInformation = NOTHING, image_data: ImageData = NOTHING)

Low-level PSD file structure that resembles the specification at https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/.

Example:

from psd_tools.psd import PSD

with open(input_file, 'rb') as f:
    psd = PSD.read(f)

with open(output_file, 'wb') as f:
    psd.write(f)
  • header โ€” See FileHeader (psd_tools.psd.header.FileHeader).
  • color_mode_data โ€” See ColorModeData (psd_tools.psd.color_mode_data.ColorModeData).
  • image_resources โ€” See ImageResources (psd_tools.psd.image_resources.ImageResources).
  • layer_and_mask_information โ€” See LayerAndMaskInformation (psd_tools.psd.layer_and_mask.LayerAndMaskInformation).
  • image_data โ€” See ImageData (psd_tools.psd.image_data.ImageData).

psd_tools.psd.base ๐Ÿงฑ

Base data structures intended for inheritance.

All the data objects in this subpackage inherit from the base classes here. That means, all the data structures in the psd_tools.psd subpackage implements the methods of BaseElement for serialization and decoding.

Objects that inherit from the BaseElement typically gets attrs (at https://www.attrs.org/en/stable/index.html) decoration to have data fields.


BaseElement ๐Ÿ’–

class psd_tools.psd.base.BaseElement

Base element of various PSD file structs. All the data objects in psd_tools.psd subpackage inherit from this class.

  • classmethod read(cls, fp) โ€” Read the element from a file-like object.
  • write(self, fp) โ€” Write the element to a file-like object.
  • classmethod frombytes(self, data, *args, **kwargs) โ€” Read the element from bytes.
  • tobytes(self, *args, **kwargs) โ€” Write the element to bytes.
  • validate(self) โ€” Validate the attribute.

EmptyElement ๐Ÿซ™

class psd_tools.psd.base.EmptyElement

Empty element that does not have a value.


ValueElement ๐ŸŽ

class psd_tools.psd.base.ValueElement(value: object = None)

Single value wrapper that has a value attribute.

Pretty printing shows the internal value by default. Inherit with @define(repr=False) decorator to keep this behavior.

  • value โ€” Internal value.

NumericElement ๐Ÿ”ข

class psd_tools.psd.base.NumericElement(value=0.0)

Single value element that has a numeric value attribute.


IntegerElement ๐Ÿ”Ÿ

class psd_tools.psd.base.IntegerElement(value=0)

Single integer value element that has a value attribute.

Use with @define(repr=False) decorator.


ShortIntegerElement ๐Ÿฉณ

class psd_tools.psd.base.ShortIntegerElement(value=0)

Single short integer element that has a value attribute.

Use with @define(repr=False) decorator.


ByteElement ๐ŸงŠ

class psd_tools.psd.base.ByteElement(value=0)

Single 1-byte integer element that has a value attribute.

Use with @define(repr=False) decorator.


BooleanElement โœ…

class psd_tools.psd.base.BooleanElement(value=False)

Single bool value element that has a value attribute.

Use with @define(repr=False) decorator.


StringElement ๐Ÿชข

class psd_tools.psd.base.StringElement(value: str = '')

Single unicode string.

  • value โ€” str value

ListElement ๐Ÿ“‹

class psd_tools.psd.base.ListElement(items=NOTHING)

List-like element that has items list.


DictElement ๐Ÿ—‚๏ธ

class psd_tools.psd.base.DictElement(items=NOTHING)

Dict-like element that has items OrderedDict.


psd_tools.psd.color_mode_data ๐ŸŽจ

Color mode data structure.


ColorModeData ๐ŸŒˆ

class psd_tools.psd.color_mode_data.ColorModeData(value: bytes = b'')

Color mode data section of the PSD file.

For indexed color images the data is the color table for the image in a non-interleaved order.

Duotone images also have this data, but the data format is undocumented.

  • interleave() -> bytes โ€” Returns interleaved color table in bytes.

psd_tools.psd.descriptor ๐Ÿ“ฆ

Descriptor data structure.

Descriptors are basic data structure used throughout PSD files. Descriptor is one kind of serialization protocol for data objects, and enum classes in psd_tools.terminology or bytes indicates what kind of descriptor it is.

okay so real quick on that class ID situation: it can be a pre-defined enum if the tag is 4-byte length, or plain bytes if the length is arbitrary ๐Ÿ’ซ They depend on the internal version of Adobe Photoshop but the detail is unknown โ€” no cap, nobody knows.

Pretty printing is the best approach to check the descriptor content:

from IPython.pretty import pprint
pprint(descriptor)

Alias

class psd_tools.psd.descriptor.Alias(value: bytes = b'\x00\x00\x00\x00')

Alias structure, equivalent to RawData. ๐Ÿ’…

Bool

class psd_tools.psd.descriptor.Bool(value=False)

Bool structure.

  • value โ€” bool value

Class

class psd_tools.psd.descriptor.Class(name: str = '', classID: bytes = b'\x00\x00\x00\x00')

Class structure.

  • name โ€” str value
  • classID โ€” bytes in Klass (psd_tools.terminology.Klass)

Class1

class psd_tools.psd.descriptor.Class1(name: str = '', classID: bytes = b'\x00\x00\x00\x00')

Class structure, equivalent to Class. Same energy, different name, bestie ๐Ÿซถ

Class2

class psd_tools.psd.descriptor.Class2(name: str = '', classID: bytes = b'\x00\x00\x00\x00')

Class structure, equivalent to Class.

Class3

class psd_tools.psd.descriptor.Class3(name: str = '', classID: bytes = b'\x00\x00\x00\x00')

Class structure, equivalent to Class. yes, there are three of them, and yes, they're all the same, we don't make the rules ๐Ÿ’€

Descriptor

class psd_tools.psd.descriptor.Descriptor(items=NOTHING, name: str = '', classID: bytes = b'null')

Dict-like descriptor structure. it's giving dictionary but make it Photoshop

Key values can be 4-character bytes in Key (psd_tools.terminology.Key) or arbitrary length bytes. Supports direct access by Key (psd_tools.terminology.Key).

Example:

from psd_tools.terminology import Key

descriptor[Key.Enabled]

for key in descriptor:
    print(descriptor[key])
  • name โ€” str
  • classID โ€” bytes in Klass (psd_tools.terminology.Klass)

Double

class psd_tools.psd.descriptor.Double(value=0.0)

Double structure.

  • value โ€” float value

Enumerated

class psd_tools.psd.descriptor.Enumerated(typeID: bytes = b'\x00\x00\x00\x00', enum: bytes = b'\x00\x00\x00\x00')

Enum structure.

  • typeID โ€” bytes in Type (psd_tools.terminology.Type)
  • enum โ€” bytes in Enum (psd_tools.terminology.Enum)
  • get_name() -> str โ€” Get enum name. ๐ŸŽ€

EnumeratedReference

class psd_tools.psd.descriptor.EnumeratedReference(name: str = '', classID: bytes = b'\x00\x00\x00\x00', typeID: bytes = b'\x00\x00\x00\x00', enum: bytes = b'\x00\x00\x00\x00')

Enumerated reference structure.

  • name โ€” str value
  • classID โ€” bytes in Klass (psd_tools.terminology.Klass)
  • typeID โ€” bytes in Type (psd_tools.terminology.Type)
  • enum โ€” bytes in Enum (psd_tools.terminology.Enum)

GlobalObject

class psd_tools.psd.descriptor.GlobalObject(items=NOTHING, name: str = '', classID: bytes = b'null')

Global object structure, equivalent to Descriptor.

Identifier

class psd_tools.psd.descriptor.Identifier(value=0)

Identifier, equivalent to Integer.

Index

class psd_tools.psd.descriptor.Index(value=0)

Index, equivalent to Integer.

Integer

class psd_tools.psd.descriptor.Integer(value=0)

Integer structure.

  • value โ€” int value

LargeInteger

class psd_tools.psd.descriptor.LargeInteger(value=0)

LargeInteger structure. big number energy ๐Ÿ”ฅ

  • value โ€” int value

List

class psd_tools.psd.descriptor.List(items=NOTHING)

List structure.

Example:

for item in list_value:
    print(item)

Name

class psd_tools.psd.descriptor.Name(name: str = '', classID: bytes = b'\x00\x00\x00\x00', value: str = '')

Name structure (Undocumented ๐Ÿ™ˆ).

  • name โ€” str
  • classID โ€” bytes in Klass (psd_tools.terminology.Klass)
  • value โ€” str

ObjectArray

class psd_tools.psd.descriptor.ObjectArray(items=NOTHING, items_count: int = 0, name: str = '', classID: bytes = b'null')

Object array structure, almost equivalent to Descriptor.

  • items_count โ€” int value
  • name โ€” str value
  • classID โ€” bytes in Klass (psd_tools.terminology.Klass)

Property

class psd_tools.psd.descriptor.Property(name: str = '', classID: bytes = b'\x00\x00\x00\x00', keyID: bytes = b'\x00\x00\x00\x00')

Property structure.

  • name โ€” str value
  • classID โ€” bytes in Klass (psd_tools.terminology.Klass)
  • keyID โ€” bytes in Key (psd_tools.terminology.Key)

Offset

class psd_tools.psd.descriptor.Offset(name: str = '', classID: bytes = b'\x00\x00\x00\x00', value: int = 0)

Offset structure.

  • name โ€” str value
  • classID โ€” bytes in Klass (psd_tools.terminology.Klass)
  • value โ€” int value

Path

class psd_tools.psd.descriptor.Path(value: bytes = b'\x00\x00\x00\x00')

Undocumented path structure, equivalent to RawData. ๐Ÿ™ˆ

RawData

class psd_tools.psd.descriptor.RawData(value: bytes = b'\x00\x00\x00\x00')

RawData structure.

  • value โ€” bytes value

Reference

class psd_tools.psd.descriptor.Reference(items=NOTHING)

Reference structure, equivalent to List.

String

class psd_tools.psd.descriptor.String(value: str = '')

String structure.

  • value โ€” str value

UnitFloat

class psd_tools.psd.descriptor.UnitFloat(value: float = 0.0, unit: Unit = Unit._None)

Unit float structure. (Unit here is psd_tools.terminology.Unit โœจ)

  • unit โ€” unit of the value in Unit or Enum
  • value โ€” float value

UnitFloats

class psd_tools.psd.descriptor.UnitFloats(unit: Unit = Unit._None, values: list = NOTHING)

Unit floats structure. (Unit here is psd_tools.terminology.Unit ๐ŸŒธ)

  • unit โ€” unit of the value in Unit or Enum
  • values โ€” List of float values

<butterfly>psd_tools.psd.engine_data</butterfly>

EngineData structure.

PSD file embeds text formatting data in its own markup language referred EngineData. The format looks like the following:

<<
  /EngineDict
  <<
    /Editor
    <<
      /Text (ห›ห‡Make a change and save.)
    >>
  >>
  /Font
  <<
    /Name (ห›ห‡HelveticaNeue-Light)
    /FillColor
    <<
      /Type 1
      /Values [ 1.0 0.0 0.0 0.0 ]
    >>
    /StyleSheetSet [
    <<
      /Name (ห›ห‡Normal RGB)
    >>
    ]
  >>
>>
bestie that's the whole markup language right there, brackets inside brackets, we love a nesting moment ๐Ÿฆ‹

EngineData

class psd_tools.psd.engine_data.EngineData(items=NOTHING)

Dict-like element.

TYPE_TOOL_OBJECT_SETTING tagged block contains this object in its descriptor.

EngineData2

class psd_tools.psd.engine_data.EngineData2(items=NOTHING)

Dict-like element.

TEXT_ENGINE_DATA tagged block has this object.

Bool

class psd_tools.psd.engine_data.Bool(value=False)

Bool element.

Dict

class psd_tools.psd.engine_data.Dict(items=NOTHING)

Dict-like element.

Float

class psd_tools.psd.engine_data.Float(value=0.0)

Float element.

Integer

class psd_tools.psd.engine_data.Integer(value=0)

Integer element.

List

class psd_tools.psd.engine_data.List(items=NOTHING)

List-like element.

Property

class psd_tools.psd.engine_data.Property(value: object = None)

Property element.

String

class psd_tools.psd.engine_data.String(value: object = None)

String element.


<butterfly>psd_tools.psd.effects_layer</butterfly>

Effects layer structure.

โš ๏ธ heads up bestie: the structures in this module is obsolete, and object-based layer effects are stored in tagged blocks. so like, iconic but retired ๐Ÿ’…

EffectsLayer

class psd_tools.psd.effects_layer.EffectsLayer(items=NOTHING, version: int = 0)

Dict-like EffectsLayer structure. See psd_tools.constants.EffectOSType for available keys.

  • version

CommonStateInfo

class psd_tools.psd.effects_layer.CommonStateInfo(version: int = 0, visible: int = 1)

Effects layer common state info.

  • version
  • visible

ShadowInfo

class psd_tools.psd.effects_layer.ShadowInfo(version: int = 0, blur: int = 0, intensity: int = 0, angle: int = 0, distance: int = 0, color: Color = NOTHING, blend_mode=BlendMode.NORMAL, enabled: int = 0, use_global_angle: int = 0, opacity: int = 0, native_color: Color = NOTHING)

Effects layer shadow info.

  • version
  • blur
  • intensity
  • angle
  • distance
  • color
  • blend_mode
  • enabled
  • use_global_angle
  • opacity
  • native_color

OuterGlowInfo

class psd_tools.psd.effects_layer.OuterGlowInfo(version: int = 0, blur: int = 0, intensity: int = 0, color: Color = NOTHING, blend_mode=BlendMode.NORMAL, enabled: int = 0, opacity: int = 0, native_color: object = None)

Effects layer outer glow info. glow up, literally โœจ

  • version
  • blur
  • intensity
  • color
  • blend_mode
  • enabled
  • opacity
  • native_color

InnerGlowInfo

class psd_tools.psd.effects_layer.InnerGlowInfo(version: int = 0, blur: int = 0, intensity: int = 0, color: Color = NOTHING, blend_mode=BlendMode.NORMAL, enabled: int = 0, opacity: int = 0, invert: int | None = None, native_color: object | None = None)

Effects layer inner glow info.

  • version
  • blur
  • intensity
  • color
  • blend_mode
  • enabled
  • opacity
  • invert
  • native_color

BevelInfo

class psd_tools.psd.effects_layer.BevelInfo(version: int = 0, angle: int = 0, depth: int = 0, blur: int = 0, highlight_blend_mode=BlendMode.NORMAL, shadow_blend_mode=BlendMode.NORMAL, highlight_color: Color = NOTHING, shadow_color: Color = NOTHING, bevel_style: int = 0, highlight_opacity: int = 0, shadow_opacity: int = 0, enabled: int = 0, use_global_angle: int = 0, direction: int = 0, real_highlight_color: object = None, real_shadow_color: object = None)

Effects layer bevel info. the bevel really said let me give you sixteen parameters ๐Ÿซถ

  • version
  • angle
  • depth
  • blur
  • highlight_blend_mode
  • shadow_blend_mode
  • highlight_color
  • shadow_color
  • highlight_opacity
  • shadow_opacity
  • enabled
  • use_global_angle
  • direction
  • real_hightlight_color
  • real_shadow_color

โœจ SolidFillInfo

class psd_tools.psd.effects_layer.SolidFillInfo(version: int = 2, blend_mode=BlendMode.NORMAL, color: Color = NOTHING, opacity: int = 0, enabled: int = 0, native_color: Color = NOTHING)

Bestie, this one is the Effects layer inner glow info ๐Ÿ’–. Its lil attribute squad is:

  • version
  • blend_mode
  • color
  • opacity
  • enabled
  • native_color

๐Ÿฆ‹ psd_tools.psd.filter_effects

The Filter effects structure. That's the whole vibe. Periodt.

FilterEffects

class psd_tools.psd.filter_effects.FilterEffects(items=NOTHING, version: int = 1)

A list-like FilterEffects structure ๐Ÿซถ โ€” and it says, and I quote: See FilterEffect. Its attributes:

  • version

FilterEffect

class psd_tools.psd.filter_effects.FilterEffect(uuid: str | None = None, version: int | None = None, rectangle: tuple | None = None, depth: int | None = None, max_channels: int | None = None, channels: list | None = None, extra: object | None = None)

The FilterEffect structure, no cap ๐Ÿงš. Attributes:

  • uuid
  • version
  • rectangle
  • depth
  • max_channels
  • channels โ€” literally a List of FilterEffectChannel.
  • extra โ€” See FilterEffectExtra.

FilterEffectChannel

class psd_tools.psd.filter_effects.FilterEffectChannel(is_written: int = 0, compression: int | None = None, data: bytes = b'')

FilterEffectChannel structure ๐Ÿ’…. Its attributes:

  • is_written
  • compression
  • data

FilterEffectExtra

class psd_tools.psd.filter_effects.FilterEffectExtra(is_written: int = 0, rectangle=NOTHING, compression: int = 0, data: bytes = b'')

FilterEffectExtra structure ๐ŸŒธ. Its attributes:

  • is_written
  • rectangle
  • compression
  • data

๐Ÿ‘‘ psd_tools.psd.header

The File header structure. We love a header.

FileHeader

class psd_tools.psd.header.FileHeader(signature: bytes = b'8BPS', version: int = 1, channels: int = 4, height: int = 64, width: int = 64, depth: int = 8, color_mode=ColorMode.RGB)

This is the Header section of the PSD file โ€” the main character intro, if you will โœจ.

Example, ok? Slay:

from psd_tools.psd.header import FileHeader
from psd_tools.constants import ColorMode

header = FileHeader(channels=2, height=359, width=400, depth=8,
                    color_mode=ColorMode.GRAYSCALE)

And now the attributes, one by one, no skipping bestie:

  • signature โ€” Signature: always equal to b'8BPS'.
  • version โ€” Version number. PSD is 1, and PSB is 2.
  • channels โ€” The number of channels in the image, including any user-defined alpha channel.
  • height โ€” The height of the image in pixels.
  • width โ€” The width of the image in pixels.
  • depth โ€” The number of bits per channel.
  • color_mode โ€” The color mode of the file. See ColorMode <#psd_tools.constants.ColorMode>.

๐ŸŽ€ psd_tools.psd.image_data

Image data section structure. ImageData corresponds to the last section of the PSD/PSB file where a composited image is stored ๐Ÿ’œ. So when the file does not contain layers, this is the only place pixels are saved. That's it. That's the whole thing. Iconic.

ImageData

class psd_tools.psd.image_data.ImageData(compression=Compression.RAW, data: bytes = b'')

Merged channel image data ๐Ÿ”ฅ. Attributes:

  • compression โ€” See Compression <#psd_tools.constants.Compression>.
  • data โ€” bytes as compressed in the compression flag.

get_data(header: FileHeader <#psd_tools.psd.header.FileHeader>, split: bool = True) -> list[bytes] | bytes

Get decompressed data ๐Ÿซง.

Parameters:

  • header โ€” See FileHeader <#psd_tools.psd.header.FileHeader>.

Returns:

  • list of bytes corresponding each channel.

classmethod new(header: FileHeader <#psd_tools.psd.header.FileHeader>, color: int | Sequence[int] = 0, compression: Compression <#psd_tools.constants.Compression> = Compression.RAW) -> T

Create a new image data object โœจ.

Parameters:

  • header โ€” FileHeader.
  • compression โ€” compression type.
  • color โ€” default color. int or iterable for channel length.

set_data(data: Sequence[bytes], header: FileHeader <#psd_tools.psd.header.FileHeader>) -> int

Set raw data and compress ๐Ÿ’….

Parameters:

  • data โ€” list of raw data bytes corresponding channels.
  • compression โ€” compression type, see Compression <#psd_tools.constants.Compression>.
  • header โ€” See FileHeader <#psd_tools.psd.header.FileHeader>.

Returns:

  • length of compressed data.

๐ŸŒˆ psd_tools.psd.image_resources

Image resources section structure, bestie. Image resources are used to store non-pixel data associated with images, such as pen tool paths or slices ๐Ÿ“.

See Resource <#psd_tools.constants.Resource> to check available resource names.

Example:

from psd_tools.constants import Resource

version_info = psd.image_resources.get_data(Resource.VERSION_INFO)

The following resources are plain bytes, fr fr:

Resource.OBSOLETE1: 1000
Resource.MAC_PRINT_MANAGER_INFO: 1001
Resource.MAC_PAGE_FORMAT_INFO: 1002
Resource.OBSOLETE2: 1003
Resource.DISPLAY_INFO_OBSOLETE: 1007
Resource.BORDER_INFO: 1009
Resource.DUOTONE_IMAGE_INFO: 1018
Resource.EFFECTIVE_BW: 1019
Resource.OBSOLETE3: 1020
Resource.EPS_OPTIONS: 1021
Resource.QUICK_MASK_INFO: 1022
Resource.OBSOLETE4: 1023
Resource.WORKING_PATH: 1025
Resource.OBSOLETE5: 1027
Resource.IPTC_NAA: 1028
Resource.IMAGE_MODE_RAW: 1029
Resource.JPEG_QUALITY: 1030
Resource.URL: 1035
Resource.COLOR_SAMPLERS_RESOURCE_OBSOLETE: 1038
Resource.ICC_PROFILE: 1039
Resource.SPOT_HALFTONE: 1043
Resource.JUMP_TO_XPEP: 1052
Resource.EXIF_DATA_1: 1058
Resource.EXIF_DATA_3: 1059
Resource.XMP_METADATA: 1060
Resource.CAPTION_DIGEST: 1061
Resource.ALTERNATE_DUOTONE_COLORS: 1066
Resource.ALTERNATE_SPOT_COLORS: 1067
Resource.HDR_TONING_INFO: 1070
Resource.PRINT_INFO_CS2: 1071
Resource.COLOR_SAMPLERS_RESOURCE: 1073
Resource.DISPLAY_INFO: 1077
Resource.MAC_NSPRINTINFO: 1084
Resource.WINDOWS_DEVMODE: 1085
Resource.PATH_INFO_N: 2000-2999
Resource.PLUGIN_RESOURCES_N: 4000-4999
Resource.IMAGE_READY_VARIABLES: 7000
Resource.IMAGE_READY_DATA_SETS: 7001
Resource.IMAGE_READY_DEFAULT_SELECTED_STATE: 7002
Resource.IMAGE_READY_7_ROLLOVER_EXPANDED_STATE: 7003
Resource.IMAGE_READY_ROLLOVER_EXPANDED_STATE: 7004
Resource.IMAGE_READY_SAVE_LAYER_SETTINGS: 7005
Resource.IMAGE_READY_VERSION: 7006
Resource.LIGHTROOM_WORKFLOW: 8000

ImageResources

class psd_tools.psd.image_resources.ImageResources(items=NOTHING)

Image resources section of the PSD file โ€” a Dict of ImageResource ๐Ÿ’™.

get_data(key: Any, default: Any = None) -> Any

Get data from the image resources ๐Ÿซถ.

Shortcut for the following:

if key in image_resources:
    value = tagged_blocks[key].data

classmethod new(**kwargs: Any) -> T_ImageResources

Create a new default image resouces. (yes bestie, that's how it's spelled, I don't make the rules ๐Ÿ™ˆ)

Returns:

  • ImageResources

ImageResource

class psd_tools.psd.image_resources.ImageResource(signature: bytes = b'8BIM', key: int = 1000, name: str = '', data: bytes = b'')

Image resource block ๐ŸŒธ. Attributes:

  • signature โ€” Binary signature. Usually b'8BIM', but some resources use alternative signatures such as b'MeSa' (e.g., IMAGE_READY_VARIABLES <#psd_tools.constants.Resource.IMAGE_READY_VARIABLES>), b'AgHg', b'PHUT', or b'DCSR'.
  • key โ€” Unique identifier for the resource. See Resource <#psd_tools.constants.Resource>.
  • name
  • data โ€” The resource data.

AlphaIdentifiers

class psd_tools.psd.image_resources.AlphaIdentifiers(items=NOTHING)

List of alpha identifiers ๐Ÿ’–.

AlphaNamesPascal

class psd_tools.psd.image_resources.AlphaNamesPascal(items=NOTHING)

List of alpha names ๐Ÿ’–.

AlphaNamesUnicode

class psd_tools.psd.image_resources.AlphaNamesUnicode(items=NOTHING)

List of alpha names ๐Ÿ’–. (yes, again. twins.)

Byte

class psd_tools.psd.image_resources.Byte(value=0)

Byte element ๐Ÿฆ‹.

GridGuidesInfo

class psd_tools.psd.image_resources.GridGuidesInfo(version: int = 1, horizontal: int = 0, vertical: int = 0, data=NOTHING)

Grid and guides info structure โœจ.

HalftoneScreens

class psd_tools.psd.image_resources.HalftoneScreens(items=NOTHING)

Halftone screens ๐ŸŽ€.

HalftoneScreen

class psd_tools.psd.image_resources.HalftoneScreen(freq: int = 0, unit: int = 0, angle: int = 0, shape: int = 0, use_accurate: bool = False, use_printer: bool = False)

Halftone screen ๐ŸŽ€. Attributes:

  • freq
  • unit
  • angle
  • shape
  • use_accurate
  • use_printer

Integer

class psd_tools.psd.image_resources.Integer(value=0)

Integer element ๐Ÿ‘‘.

LayerGroupEnabledIDs

class psd_tools.psd.image_resources.LayerGroupEnabledIDs(items=NOTHING)

Layer group enabled ids โœ….

LayerGroupInfo

class psd_tools.psd.image_resources.LayerGroupInfo(items=NOTHING)

Layer group info list ๐Ÿ“‹.

LayerSelectionIDs

class psd_tools.psd.image_resources.LayerSelectionIDs(items=NOTHING)

Layer selection ids โœ….

ShortInteger

class psd_tools.psd.image_resources.ShortInteger(value=0)

Short integer element ๐Ÿงš.

PascalString

class psd_tools.psd.image_resources.PascalString(value: object = None)

Pascal string element ๐Ÿ’œ.

PixelAspectRatio

class psd_tools.psd.image_resources.PixelAspectRatio(value=0.0, version: int = 1)

Pixel aspect ratio ๐ŸŒˆ.

PrintFlags

class psd_tools.psd.image_resources.PrintFlags(labels: bool = False, crop_marks: bool = False, colorbars: bool = False, registration_marks: bool = False, negative: bool = False, flip: bool = False, interpolate: bool = False, caption: bool = False, print_flags: bool | None = None)

Print flags ๐Ÿ–จ๏ธ.

PrintFlagsInfo

class psd_tools.psd.image_resources.PrintFlagsInfo(version: int = 0, center_crop: int = 0, bleed_width_value: int = 0, bleed_width_scale: int = 0)

Print flags info structure ๐Ÿ–จ๏ธ. Attributes:

  • version
  • center_crop
  • bleed_width_value
  • bleed_width_scale

PrintScale

class psd_tools.psd.image_resources.PrintScale(style=PrintScaleStyle.CENTERED, x: float = 0.0, y: float = 0.0, scale: float = 0.0)

okay so this one is literally just the print scale structure bestie, that's the whole vibe ๐Ÿ’…

  • style โ€” the style babe
  • x โ€” the x
  • y โ€” the y
  • scale โ€” the scale

ResoulutionInfo

class psd_tools.psd.image_resources.ResoulutionInfo(horizontal: int = 0, horizontal_unit: int = 0, width_unit: int = 0, vertical: int = 0, vertical_unit: int = 0, height_unit: int = 0)

yes the "Resoulution" spelling is genuinely in there, I am NOT fixing it, it's canon ๐Ÿซถ this is the resoulution info structure.

  • horizontal โ€” horizontal value
  • horizontal_unit โ€” horizontal unit
  • width_unit โ€” width unit
  • vertical โ€” vertical value
  • vertical_unit โ€” vertical unit
  • height_unit โ€” height unit

Slices

class psd_tools.psd.image_resources.Slices(version: int = 0, data: object = None)

the slices resource, slay ๐ŸŒธ

  • version โ€” version
  • data โ€” data

SlicesV6

class psd_tools.psd.image_resources.SlicesV6(bbox=NOTHING, name: str = '', items=NOTHING)

slices resource but make it version 6 โœจ

  • bbox โ€” bounding box
  • name โ€” name
  • items โ€” the items

SliceV6

class psd_tools.psd.image_resources.SliceV6(slice_id: int = 0, group_id: int = 0, origin: int = 0, associated_id: int | None = None, name: str = '', slice_type: int = 0, bbox=NOTHING, url: str = '', target: str = '', message: str = '', alt_tag: str = '', cell_is_html: bool = False, cell_text: str = '', horizontal_align: int = 0, vertical_align: int = 0, alpha: int = 0, red: int = 0, green: int = 0, blue: int = 0, data: object = None)

the slice element for version 6, she has a LOT going on and we respect her for it ๐Ÿ’…

  • slice_id โ€” slice id
  • group_id โ€” group id
  • origin โ€” origin
  • associated_id โ€” associated id
  • name โ€” name
  • slice_type โ€” slice type
  • bbox โ€” bounding box
  • url โ€” url
  • target โ€” target
  • message โ€” message
  • alt_tag โ€” alt tag
  • cell_is_html โ€” cell is html
  • cell_text โ€” cell text
  • horizontal โ€” horizontal (yep, that's what the attribute list says, even though the constructor calls it horizontal_align โ€” we do not editorialize, we simply report ๐Ÿ“‹)
  • vertical โ€” vertical (same deal, constructor says vertical_align)
  • alpha โ€” alpha
  • red โ€” red
  • green โ€” green
  • blue โ€” blue
  • data โ€” data
fr fr just re-reading the signature is the whole job here bestie

ThumbnailResource

class psd_tools.psd.image_resources.ThumbnailResource(fmt: int = 0, width: int = 0, height: int = 0, row: int = 0, total_size: int = 0, bits: int = 0, planes: int = 0, data: bytes = b'')

thumbnail resource structure, iconic little picture energy ๐ŸŽ€

  • fmt โ€” format
  • width โ€” width
  • height โ€” height
  • row โ€” row
  • total_size โ€” total size
  • size โ€” size (yes it's listed as an attribute but not in the constructor args, that's just how she is)
  • bits โ€” bits
  • planes โ€” planes
  • data โ€” data

ThumbnailResourceV4

class psd_tools.psd.image_resources.ThumbnailResourceV4(fmt: int = 0, width: int = 0, height: int = 0, row: int = 0, total_size: int = 0, bits: int = 0, planes: int = 0, data: bytes = b'')

ThumbnailResource but for V4, and the original gives us literally no description text beyond the signature so that's what we're working with ๐Ÿ˜ญ


TransferFunctions

class psd_tools.psd.image_resources.TransferFunctions(items=NOTHING)

transfer functions, plural, a whole lil collection ๐ŸŒˆ


TransferFunction

class psd_tools.psd.image_resources.TransferFunction(curve=NOTHING, override: int = 0)

transfer function for a single plate, and this one's got lore:

Contains 13 signed short integers representing curve control points in the range 0...1000 (corresponding to 0.0%...100.0%). The first and last values are always present; any intermediate value may be -1 to indicate that no control point exists at that position. A NULL (identity) transfer curve has the form:

[0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1000]

Followed by one unsigned short override flag (non-zero means the transfer function overrides the default).

See Adobe PSD spec ยงTransfer Functions <https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577411_pgfId-1071095>.


URLList

class psd_tools.psd.image_resources.URLList(items=NOTHING)

URL list structure ๐Ÿฆ‹


URLItem

class psd_tools.psd.image_resources.URLItem(number: int = 0, id: int = 0, name: str = '')

one single URL item, main character of the list ngl ๐Ÿ‘‘

  • number โ€” number
  • id โ€” id
  • name โ€” name

VersionInfo

class psd_tools.psd.image_resources.VersionInfo(version: int = 1, has_composite: bool = False, writer: str = '', reader: str = '', file_version: int = 1)

version info structure, the receipts of who wrote and read this thing ๐Ÿ“

  • version โ€” version
  • has_composite โ€” has composite
  • writer โ€” writer
  • reader โ€” reader
  • file_version โ€” file version

psd_tools.psd.layer_and_mask

layer and mask data structures. This is where it gets real bestie ๐Ÿ’€

This module implements the low-level binary structures for PSD layers and masks, corresponding to the "Layer and Mask Information" section of PSD files. This is one of the most complex parts of the PSD format.

Key classes:

  • LayerAndMaskInformation: Top-level container for all layer data
  • LayerInfo: Contains layer records and channel image data
  • LayerRecords: List of individual layer records
  • LayerRecord: Single layer metadata (name, bounds, blend mode, etc.)
  • ChannelInfo: Channel metadata within a layer record
  • ChannelImageData: Compressed pixel data for all channels
  • ChannelData: Single channel's compressed pixel data
  • MaskData: Layer mask parameters
  • GlobalLayerMaskInfo: Document-wide mask settings
  • TaggedBlocks: Extended layer metadata (see psd_tools.psd.tagged_blocks)

The layer structure in PSD files is stored as a flat list with implicit hierarchy. Group boundaries are marked by special layers with SectionDivider tagged blocks:

  • BOUNDING_SECTION_DIVIDER: Marks the start of a group (the layer that opens the group)
  • OPEN_FOLDER or CLOSED_FOLDER: Marks the end of a group (the closing divider layer)
    • OPEN_FOLDER: Group was open in Photoshop UI
    • CLOSED_FOLDER: Group was closed in Photoshop UI

The high-level API (psd_tools.api) reconstructs this into a proper tree structure with parent-child relationships.

Each layer record contains:

  1. Metadata: Rectangle bounds, blend mode, opacity, flags
  2. Channel info: List of channels (R, G, B, A, masks, etc.) with byte offsets
  3. Blend ranges: Advanced blending parameters
  4. Layer name: Pascal string (legacy, inaccurate for Unicode names)
  5. Tagged blocks: Extended metadata in key-value format

The channel image data section follows all layer records and contains the actual compressed pixel data for each channel, referenced by the channel info structures.

Example of reading layer metadata:

from psd_tools.psd import PSD

with open('file.psd', 'rb') as f:
    psd = PSD.read(f)

layer_info = psd.layer_and_mask_information.layer_info
for record in layer_info.layer_records:
    print(f"Layer: {record.name}")
    print(f"  Bounds: {record.top}, {record.left}, {record.bottom}, {record.right}")
    print(f"  Blend mode: {record.blend_mode}")
    print(f"  Channels: {len(record.channel_info)}")

For most use cases, prefer the high-level Layer API (psd_tools.api.layers.Layer) which provides easier access to this data.


LayerAndMaskInformation

class psd_tools.psd.layer_and_mask.LayerAndMaskInformation(layer_info: LayerInfo | None = None, global_layer_mask_info: GlobalLayerMaskInfo | None = None, tagged_blocks: TaggedBlocks | None = None)

the layer and mask information section, the big container energy ๐Ÿ“ฆ

  • layer_info โ€” See LayerInfo.
  • global_layer_mask_info โ€” See GlobalLayerMaskInfo.
  • tagged_blocks โ€” See TaggedBlocks (psd_tools.psd.tagged_blocks.TaggedBlocks).

LayerInfo

class psd_tools.psd.layer_and_mask.LayerInfo(layer_count: int = 0, layer_records: LayerRecords = NOTHING, channel_image_data: ChannelImageData = NOTHING)

high-level organization of the layer information, she's the manager fr ๐Ÿ’…

  • layer_count โ€” Layer count. If it is a negative number, its absolute value is the number of layers and the first alpha channel contains the transparency data for the merged result.
  • layer_records โ€” Information about each layer. See LayerRecords.
  • channel_image_data โ€” Channel image data. See ChannelImageData.

GlobalLayerMaskInfo

class psd_tools.psd.layer_and_mask.GlobalLayerMaskInfo(overlay_color: list[int] | None = None, opacity: int = 0, kind=GlobalLayerMaskKind.PER_LAYER)

global mask information, document-wide and iconic ๐ŸŒˆ

  • overlay_color โ€” Overlay color space (undocumented) and color components.
  • opacity โ€” Opacity. 0 = transparent, 100 = opaque.
  • kind โ€” Kind. 0 = Color selected--i.e. inverted; 1 = Color protected; 128 = use value stored per layer. This value is preferred. The others are for backward compatibility with beta versions.
not me clocking that 128 is the one you actually want ๐Ÿ‘€ backwards compat is giving beta

LayerRecords

class psd_tools.psd.layer_and_mask.LayerRecords(items=NOTHING)

list of layer records. See LayerRecord. Just a whole pile of them, one per layer ๐Ÿ“


LayerRecord

class psd_tools.psd.layer_and_mask.LayerRecord(top: int = 0, left: int = 0, bottom: int = 0, right: int = 0, channel_info: list[ChannelInfo] = NOTHING, signature: bytes = b'8BIM', blend_mode=BlendMode.NORMAL, opacity: int = 255, clipping=Clipping.BASE, flags: LayerFlags = NOTHING, mask_data: object = None, blending_ranges: LayerBlendingRanges = NOTHING, name: str = '', tagged_blocks: TaggedBlocks = NOTHING)

the layer record, aka the single most populated signature on this whole page and honestly? she ate ๐Ÿ‘‘

  • top โ€” Top position.
  • left โ€” Left position.
  • bottom โ€” Bottom position.
  • right โ€” Right position.
  • channel_info โ€” List of ChannelInfo.
  • signature โ€” Blend mode signature b'8BIM'.
  • blend_mode โ€” Blend mode key. See BlendMode (psd_tools.constants.BlendMode).
  • opacity โ€” Opacity, 0 = transparent, 255 = opaque.
  • clipping โ€” Clipping, 0 = base, 1 = non-base. See Clipping (psd_tools.constants.Clipping).
  • flags โ€” See LayerFlags.
  • mask_data โ€” MaskData or None.
  • blending_ranges โ€” See LayerBlendingRanges.
  • name โ€” Layer name.
  • tagged_blocks โ€” See TaggedBlocks (psd_tools.psd.tagged_blocks.TaggedBlocks).
  • property channel_sizes: list[tuple[int, int]] โ€” [(width, height)].
    • Type: List (psd_tools.psd.descriptor.List) of channel sizes
  • property height: int โ€” Height of the layer.
  • property width: int โ€” Width of the layer.
lowkey obsessed with how the height and width are properties while top/left/bottom/right are just vibing in the constructor, but that's her design choice and we support it ๐Ÿ’œ

๐Ÿ’… LayerFlags

class psd_tools.psd.layer_and_mask.LayerFlags(transparency_protected: bool = False, visible: bool = True, obsolete: bool = False, photoshop_v5_later: bool = True, pixel_data_irrelevant: bool = False, undocumented_1: bool = False, undocumented_2: bool = False, undocumented_3: bool = False)

ok so this is layer flags, that's the whole vibe โœจ

bestie. listen. there are undocumented flags here. maybe photoshop version, maybe a secret third thing, nobody's saying ๐Ÿซฃ
  • transparency_protected
  • visible
  • pixel_data_irrelevant

๐ŸŒˆ LayerBlendingRanges

class psd_tools.psd.layer_and_mask.LayerBlendingRanges(composite_ranges: list[tuple[int, int]] = NOTHING, channel_ranges: list[list[tuple[int, int]]] = NOTHING)

layer blending ranges, and here's the lil rule that lives here, no cap:

all ranges contain 2 black values followed by 2 white values ๐Ÿ–ค๐Ÿ–ค๐Ÿค๐Ÿค
  • composite_ranges โ€” list of composite gray blend source and destination ranges.
  • channel_ranges โ€” list of channel source and destination ranges.

๐ŸŽ€ MaskData

class psd_tools.psd.layer_and_mask.MaskData(top: int = 0, left: int = 0, bottom: int = 0, right: int = 0, background_color: int = 0, flags: MaskFlags = NOTHING, parameters: MaskParameters | None = None, real_flags: MaskFlags | None = None, real_background_color: int | None = None, real_top: int | None = None, real_left: int | None = None, real_bottom: int | None = None, real_right: int | None = None)

mask data โœจ and the lore here is that the real user mask is the final composite mask of vector and pixel masks. iconic behaviour fr fr.

  • top โ€” top position.
  • left โ€” left position.
  • bottom โ€” bottom position.
  • right โ€” right position.
  • background_color โ€” default color. 0 or 255.
  • flags โ€” see MaskFlags.
  • parameters โ€” MaskParameters or None.
  • real_flags โ€” real user mask flags. see MaskFlags.
  • real_background_color โ€” real user mask background. 0 or 255.
  • real_top โ€” top position of real user mask.
  • real_left โ€” left position of real user mask.
  • real_bottom โ€” bottom position of real user mask.
  • real_right โ€” right position of real user mask.

and then the properties, which are giving computed, not stored energy:

  • property height: int โ€” height of the mask.
  • property real_height: int โ€” height of real user mask.
  • property real_width: int โ€” width of real user mask.
  • property width: int โ€” width of the mask.

๐Ÿฆ‹ MaskFlags

class psd_tools.psd.layer_and_mask.MaskFlags(pos_relative_to_layer: bool = False, mask_disabled: bool = False, invert_mask: bool = False, user_mask_from_render: bool = False, parameters_applied: bool = False, undocumented_1: bool = False, undocumented_2: bool = False, undocumented_3: bool = False)

mask flags ๐Ÿ’–

  • pos_relative_to_layer โ€” position relative to layer.
  • mask_disabled โ€” layer mask disabled.
  • invert_mask โ€” invert layer mask when blending (obsolete, so like, old news ๐Ÿ’€).
  • user_mask_from_render โ€” the user mask actually came from rendering other data.
  • parameters_applied โ€” the user and/or vector masks have parameters applied to them.

๐Ÿ“ MaskParameters

class psd_tools.psd.layer_and_mask.MaskParameters(user_mask_density: int | None = None, user_mask_feather: float | None = None, vector_mask_density: int | None = None, vector_mask_feather: float | None = None)

mask parameters, four lil guys, no descriptions attached, they just vibe:

  • user_mask_density
  • user_mask_feather
  • vector_mask_density
  • vector_mask_feather

๐Ÿ‘‘ ChannelInfo

class psd_tools.psd.layer_and_mask.ChannelInfo(id=ChannelID.CHANNEL_0, length: int = 0)

channel information ๐ŸŒธ

  • id โ€” channel ID: 0 = red, 1 = green, etc.; -1 = transparency mask; -2 = user supplied layer mask, -3 real user supplied layer mask (when both a user mask and a vector mask are present). See ChannelID.
  • length โ€” length of the corresponding channel data.

๐ŸŒŸ ChannelImageData

class psd_tools.psd.layer_and_mask.ChannelImageData(items=NOTHING)

list of channel data list โœจ

the size of this list corresponds to the size of LayerRecords. each item corresponds to the channels of each layer.

See ChannelDataList.


๐Ÿงš ChannelDataList

class psd_tools.psd.layer_and_mask.ChannelDataList(items=NOTHING)

list of channel image data, corresponding to each color or alpha ๐Ÿ’ซ

See ChannelData.


๐Ÿ’œ ChannelData

class psd_tools.psd.layer_and_mask.ChannelData(compression=Compression.RAW, data: bytes = b'')

channel data ๐Ÿฉท

  • compression โ€” compression type. See Compression.
  • data โ€” data.
  • get_data(width: int, height: int, depth: int, version: int = 1) -> bytes โ€” get decompressed channel data.

Parameters:

  • width โ€” width.
  • height โ€” height.
  • depth โ€” bit depth of the pixel.
  • version โ€” psd file version.

Return type: bytes

  • set_data(data: bytes, width: int, height: int, depth: int, version: int = 1) -> int โ€” set raw channel data and compress to store.

Parameters:

  • data โ€” raw data bytes to write.
  • compression โ€” compression type, see Compression.
  • width โ€” width.
  • height โ€” height.
  • depth โ€” bit depth of the pixel.
  • version โ€” psd file version.

๐Ÿ’ซ psd_tools.psd.linked_layer

linked layer structure ๐Ÿซถ


๐ŸŒธ LinkedLayers

class psd_tools.psd.linked_layer.LinkedLayers(items=NOTHING)

list of LinkedLayer structure. See LinkedLayer.


๐Ÿ”ฅ LinkedLayer

class psd_tools.psd.linked_layer.LinkedLayer(kind: LinkedLayerType = LinkedLayerType.ALIAS, version: int = 1, uuid: str = '', filename: str = '', filetype: bytes = b'\x00\x00\x00\x00', creator: bytes = b'\x00\x00\x00\x00', filesize: int | None = None, open_file: DescriptorBlock | None = None, linked_file: DescriptorBlock | None = None, timestamp: tuple | None = None, data: bytes | None = None, child_id: str | None = None, mod_time: float | None = None, lock_state: int | None = None)

LinkedLayer structure ๐Ÿ’… the fields are just... listed. seventeen of them. we don't gatekeep:

  • kind
  • version
  • uuid
  • filename
  • filetype
  • creator
  • filesize
  • open_file
  • linked_file
  • timestamp
  • data
  • child_id
  • mod_time
  • lock_state

๐ŸŽ€ psd_tools.psd.patterns

patterns structure ๐Ÿฆ‹


๐ŸŒˆ Patterns

class psd_tools.psd.patterns.Patterns(items=NOTHING)

list of Pattern structure. See Pattern.


โœจ Pattern

class psd_tools.psd.patterns.Pattern(version: int = 1, image_mode=ColorMode.RGB, point: tuple[int, int] = (0, 0), name: str = '', pattern_id: str = '', color_table: list[tuple[int, int, int]] = NOTHING, data: VirtualMemoryArrayList = None)

Pattern structure ๐Ÿ’–

  • version
  • image_mode โ€” see ColorMode
  • point โ€” size in tuple.
  • name โ€” str name of the pattern.
  • pattern_id โ€” ID of this pattern.
  • color_table โ€” color table if the mode is INDEXED.
  • data โ€” see VirtualMemoryArrayList

๐Ÿซง VirtualMemoryArrayList

class psd_tools.psd.patterns.VirtualMemoryArrayList(version: int = 3, rectangle: tuple[int, int, int, int] = (0, 0, 0, 0), channels: list[VirtualMemoryArray] = NOTHING)

VirtualMemoryArrayList structure. container of channels ๐Ÿงบ

  • version
  • rectangle โ€” tuple of int
  • channels โ€” list of VirtualMemoryArray

๐Ÿ’Ž VirtualMemoryArray

class psd_tools.psd.patterns.VirtualMemoryArray(is_written: int = 0, depth: int | None = None, rectangle: tuple[int, int, int, int] | None = None, pixel_depth: int | None = None, compression=Compression.RAW, data: bytes = b'')

VirtualMemoryArrayList structure, corresponding to each channel โœจ

  • is_written
  • depth
  • rectangle
  • pixel_depth
  • compression
  • data
  • get_data() -> bytes | None โ€” get decompressed bytes.
  • set_data(size: tuple[int, int], data: bytes, depth: int, compression: int = 0) -> None โ€” set bytes.

๐ŸŒŸ psd_tools.psd.tagged_blocks

tagged block data structure ๐Ÿท๏ธ


๐Ÿ“ Todo

support the following tagged blocks: Tag.PATTERN_DATA, Tag.TYPE_TOOL_INFO, Tag.LAYER, Tag.ALPHA

fr fr this is a to-do list, meaning those ones are not supported yet. don't come for me, come for the codebase ๐Ÿ’€

๐Ÿ’… TaggedBlocks

class psd_tools.psd.tagged_blocks.TaggedBlocks(items=NOTHING)

dict of tagged block items ๐Ÿ‘‘

see Tag for available keys.

Example:

from psd_tools.constants import Tag

# Iterate over fields
for key in tagged_blocks:
    print(key)

# Get a field
value = tagged_blocks.get_data(Tag.TYPE_TOOL_OBJECT_SETTING)

๐Ÿฆ‹ TaggedBlock

class psd_tools.psd.tagged_blocks.TaggedBlock(signature: bytes = b'8BIM', key: bytes = b'', data: bytes = b'')

layer tagged block with extra info ๐Ÿ“

  • key โ€” 4-character code. See Tag
  • data โ€” data.

๐ŸŽ€ Annotations

class psd_tools.psd.tagged_blocks.Annotations(items=NOTHING, major_version: int = 2, minor_version: int = 1)

list of Annotation, see :py:class: .Annotation ๐Ÿ’œ

  • major_version
  • minor_version

๐ŸŒธ Annotation

class psd_tools.psd.tagged_blocks.Annotation(kind: bytes = b'txtA', is_open: int = 0, flags: int = 0, optional_blocks: int = 1, icon_location=NOTHING, popup_location=NOTHING, color: Color = NOTHING, author: str = '', name: str = '', mod_date: str = '', marker: bytes = b'txtC', data: bytes = b'')

Annotation structure โœจ

  • kind
  • is_open

๐Ÿงš Bytes

class psd_tools.psd.tagged_blocks.Bytes(value: bytes = b'\x00\x00\x00\x00')

Bytes structure ๐Ÿ’ซ

  • value

ChannelBlendingRestrictionsSetting

class psd_tools.psd.tagged_blocks.ChannelBlendingRestrictionsSetting(items=NOTHING)

okay so this is the ChannelBlendingRestrictionsSetting structure, and she's honestly so low-maintenance ๐Ÿ’… literally just a list of restricted channel numbers (int). that's the whole thing. no notes.


FilterMask

class psd_tools.psd.tagged_blocks.FilterMask(color: Color = NOTHING, opacity: int = 0)

The FilterMask structure โœจ and she's serving exactly two fields:

  • color โ€” the color, bestie ๐ŸŽ€
  • opacity โ€” the opacity

MetadataSettings

class psd_tools.psd.tagged_blocks.MetadataSettings(items=NOTHING)

The MetadataSettings structure. that's the vibe, that's the entry ๐Ÿฆ‹


MetadataSetting

class psd_tools.psd.tagged_blocks.MetadataSetting(signature: bytes = b'8BIM', key: bytes = b'', copy_on_sheet: bool = False, data: bytes = b'')

The MetadataSetting structure ๐Ÿ‘‘


PixelSourceData2

class psd_tools.psd.tagged_blocks.PixelSourceData2(items=NOTHING)

The PixelSourceData2 structure. iconic, brief, no crumbs ๐ŸŒธ


PlacedLayerData

class psd_tools.psd.tagged_blocks.PlacedLayerData(kind: bytes = b'plcL', version: int = 3, uuid: bytes = b'', page: int = 0, total_pages: int = 0, anti_alias: int = 0, layer_type=PlacedLayerType.UNKNOWN, transform: tuple = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), warp: object = None)

The PlacedLayerData structure ๐Ÿ’œ she's got the whole ensemble cast in her signature, look at her go.


ProtectedSetting

class psd_tools.psd.tagged_blocks.ProtectedSetting(value=0)

The ProtectedSetting structure. short. sweet. protected. ๐Ÿซถ


ReferencePoint

class psd_tools.psd.tagged_blocks.ReferencePoint(items=NOTHING)

The ReferencePoint structure โœจ


SectionDividerSetting

class psd_tools.psd.tagged_blocks.SectionDividerSetting(kind=SectionDivider.OTHER, signature: bytes | None = None, blend_mode: BlendMode <#psd_tools.constants.BlendMode> | None = None, sub_type: int | None = None)

The SectionDividerSetting structure, and her documented bits are:

  • kind โ€” what kind of divider she is
  • blend_mode โ€” the blend mode
  • sub_type โ€” the sub type

SheetColorSetting

class psd_tools.psd.tagged_blocks.SheetColorSetting(value=SheetColorType.NO_COLOR)

SheetColorSetting value ๐Ÿ’–

This setting represents color label in the layers panel in Photoshop UI.

so like, the lil colored tag on your layer, bestie. that's her.

  • value โ€” the value

SmartObjectLayerData

class psd_tools.psd.tagged_blocks.SmartObjectLayerData(kind: bytes = b'soLD', version: int = 5, data: DescriptorBlock = NOTHING)

funnily enough the docstring here calls her a VersionedDescriptorBlock structure, and we are NOT arguing with the source, periodt. her fields:

  • kind โ€” the kind
  • version โ€” the version
  • data โ€” the data

TypeToolObjectSetting

class psd_tools.psd.tagged_blocks.TypeToolObjectSetting(version: int = 1, transform: tuple = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0), text_version: int = 1, text_data: DescriptorBlock = NOTHING, warp_version: int = 1, warp: DescriptorBlock = NOTHING, left: int = 0, top: int = 0, right: int = 0, bottom: int = 0)

The TypeToolObjectSetting structure, aka the text layer girlies' main character moment ๐Ÿ‘‘

  • version โ€” the version
  • transform โ€” Tuple of affine transform parameters (xx, xy, yx, yy, tx, ty).
  • text_version โ€” the text version
  • text_data โ€” the text data
  • warp_version โ€” the warp version
  • warp โ€” the warp
  • left โ€” the left
  • top โ€” the top
  • right โ€” the right
  • bottom โ€” the bottom

UserMask

class psd_tools.psd.tagged_blocks.UserMask(color: Color = NOTHING, opacity: int = 0, flag: int = 128)

The UserMask structure ๐ŸŽ€

  • color โ€” the color
  • opacity โ€” the opacity
  • flag โ€” the flag (and yes, she defaults to 128)

psd_tools.psd.vector

Vector mask, path, and stroke structure. that's the whole summary and honestly? slay ๐Ÿ’…


Path

class psd_tools.psd.vector.Path(items=NOTHING)

List-like Path structure. Elements are either PathFillRule, InitialFillRule, ClipboardRecord, ClosedPath, or OpenPath.


Subpath

class psd_tools.psd.vector.Subpath(items=NOTHING, operation: int = 1, unknown1: int = 1, unknown2: int = 0, index: int = 0, unknown3: bytes = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

Subpath element. This is a list of Knot objects.

Note: There are undocumented data associated with this structure.

okay bestie, listen, the mystery is part of her charm ๐Ÿ™ˆ

  • operation โ€” int value indicating how multiple subpath should be combined:
    • 1: Or (union)
    • 2: Not-Or
    • 3: And (intersect)
    • 0: Xor (exclude)

The first path element is applied to the background surface. Intersection does not have strokes.

  • index โ€” int index that specifies corresponding origination object.
  • is_closed() -> bool โ€” Returns whether if the path is closed or not.
    • Returns: bool.

Knot

class psd_tools.psd.vector.Knot(preceding: tuple = (0.0,), anchor: tuple = (0.0,), leaving: tuple = (0.0,))

Knot element consisting of 3 control points for Bezier curves ๐Ÿฆ‹ the trio, if you will:

  • preceding โ€” (y, x) tuple of preceding control point in relative coordinates.
  • anchor โ€” (y, x) tuple of anchor point in relative coordinates.
  • leaving โ€” (y, x) tuple of leaving control point in relative coordinates.

ClipboardRecord

class psd_tools.psd.vector.ClipboardRecord(top: int = 0, left: int = 0, bottom: int = 0, right: int = 0, resolution: int = 0)

Clipboard record โœจ

  • top โ€” Top position in int
  • left โ€” Left position in int
  • bottom โ€” Bottom position in int
  • right โ€” Right position in int
  • resolution โ€” Resolution in int

PathFillRule

class psd_tools.psd.vector.PathFillRule

Path fill rule record, empty. she said "no data, only vibes" ๐Ÿ’…


InitialFillRule

class psd_tools.psd.vector.InitialFillRule(value=0)

Initial fill rule record.

  • rule โ€” A value of 1 means that the fill starts with all pixels. The value will be either 0 or 1.

VectorMaskSetting

class psd_tools.psd.vector.VectorMaskSetting(version: int = 3, flags: int = 0, path: Path <#psd_tools.psd.vector.Path> | None = None)

The VectorMaskSetting structure:

  • version โ€” the version
  • path โ€” List of Subpath objects.
  • property disable: bool โ€” Flag to indicate that the vector mask is disabled.
  • property invert: bool โ€” Flag to indicate that the vector mask is inverted.
  • property not_link: bool โ€” Flag to indicate that the vector mask is not linked.

VectorStrokeContentSetting

class psd_tools.psd.vector.VectorStrokeContentSetting(items=NOTHING, name: str = '', classID: bytes = b'null', key: bytes = b'\x00\x00\x00\x00', version: int = 1)

Dict-like Descriptor-based structure. See Descriptor <#psd_tools.psd.descriptor.Descriptor>.

  • key โ€” the key
  • version โ€” the version

psd_tools.terminology

Constants for descriptor.

This file is automaticaly generated by tools/extract_terminology.py โ€” yes, that spelling is in the source, we keep it, we don't touch it ๐Ÿซถ


Klass

class psd_tools.terminology.Klass(*values)

Klass definitions extracted from PITerminology.h.

See https://www.adobe.com/devnet/photoshop/sdk.html

now then. the big one. the full roster. every single one, no skipping, no cap ๐Ÿ‘‘

  • Action = b'Actn'
  • ActionSet = b'ASet'
  • Adjustment = b'Adjs'
  • AdjustmentLayer = b'AdjL'
  • AirbrushTool = b'AbTl'
  • AlphaChannelOptions = b'AChl'
  • AntiAliasedPICTAcquire = b'AntA'
  • Application = b'capp'
  • Arrowhead = b'cArw'
  • ArtHistoryBrushTool = b'ABTl'
  • Assert = b'Asrt'
  • AssumedProfile = b'AssP'
  • BMPFormat = b'BMPF'
  • BackLight = b'BakL'
  • BackgroundEraserTool = b'SETl'
  • BackgroundLayer = b'BckL'
  • BevelEmboss = b'ebbl'
  • BitmapMode = b'BtmM'
  • BlendRange = b'Blnd'
  • BlurTool = b'BlTl'
  • BookColor = b'BkCl'
  • BrightnessContrast = b'BrgC'
  • Brush = b'Brsh'
  • BurnInTool = b'BrTl'
  • CMYKColor = b'CMYC'
  • CMYKColorMode = b'CMYM'
  • CMYKSetup = b'CMYS'
  • CachePrefs = b'CchP'
  • Calculation = b'Clcl'
  • Channel = b'Chnl'
  • ChannelMatrix = b'ChMx'
  • ChannelMixer = b'ChnM'
  • ChromeFX = b'ChFX'
  • CineonFormat = b'SDPX'
  • ClippingInfo = b'Clpo'
  • ClippingPath = b'ClpP'
  • CloneStampTool = b'ClTl'
  • Color = b'Clr '
  • ColorBalance = b'ClrB'
  • ColorCast = b'ColC'
  • ColorCorrection = b'ClrC'
  • ColorPickerPrefs = b'Clrk'
  • ColorSampler = b'ClSm'
  • ColorStop = b'Clrt'
  • Command = b'Cmnd'
  • Contour = b'FxSc'
  • CurvePoint = b'CrPt'
  • Curves = b'Crvs'
  • CurvesAdjustment = b'CrvA'
  • CustomPalette = b'Cstl'
  • CustomPhosphors = b'CstP'
  • CustomWhitePoint = b'CstW'
  • DicomFormat = b'Dicm'
  • DisplayPrefs = b'DspP'
  • Document = b'Dcmn'
  • DodgeTool = b'DdTl'
  • DropShadow = b'DrSh'
  • DuotoneInk = b'DtnI'
  • DuotoneMode = b'DtnM'
  • EPSGenericFormat = b'EPSG'
  • EPSPICTPreview = b'EPSC'
  • EPSTIFFPreview = b'EPST'
  • EXRf = b'EXRf'
  • Element = b'Elmn'
  • Ellipse = b'Elps'
  • EraserTool = b'ErTl'
  • Export = b'Expr'
  • FileInfo = b'FlIn'
  • FileSavePrefs = b'FlSv'
  • FillFlash = b'FilF'
  • FlashPixFormat = b'FlsP'
  • FontDesignAxes = b'FntD'
  • Format = b'Fmt '
  • FrameFX = b'FrFX'
  • GIF89aExport = b'GF89'
  • GIFFormat = b'GFFr'
  • GeneralPrefs = b'GnrP'
  • GlobalAngle = b'gblA'
  • Gradient = b'Grdn'
  • GradientFill = b'Grdf'
  • GradientMap = b'GdMp'
  • GradientTool = b'GrTl'
  • GraySetup = b'GrSt'
  • Grayscale = b'Grsc'
  • GrayscaleMode = b'Grys'
  • Guide = b'Gd '
  • GuidesPrefs = b'GdPr'
  • HSBColor = b'HSBC'
  • HSBColorMode = b'HSBM'
  • HalftoneScreen = b'HlfS'
  • HalftoneSpec = b'Hlfp'
  • HistoryBrushTool = b'HBTl'
  • HistoryPrefs = b'CHsP'
  • HistoryState = b'HstS'
  • HueSatAdjustment = b'HStA'
  • HueSatAdjustmentV2 = b'Hst2'
  • HueSaturation = b'HStr'
  • IFFFormat = b'IFFF'
  • IllustratorPathsExport = b'IlsP'
  • ImagePoint = b'ImgP'
  • Import = b'Impr'
  • IndexedColorMode = b'IndC'
  • InkTransfer = b'InkT'
  • InnerGlow = b'IrGl'
  • InnerShadow = b'IrSh'
  • InterfaceColor = b'IClr'
  • Invert = b'Invr'
  • JPEGFormat = b'JPEG'
  • LabColor = b'LbCl'
  • LabColorMode = b'LbCM'
  • Layer = b'Lyr '
  • LayerEffects = b'Lefx'
  • LayerFXVisible = b'lfxv'
  • Levels = b'Lvls'
  • LevelsAdjustment = b'LvlA'
  • LightSource = b'LghS'
  • Line = b'Ln '
  • MacPaintFormat = b'McPn'
  • MagicEraserTool = b'MgEr'
  • MagicPoint = b'Mgcp'
  • Mask = b'Msk '
  • MenuItem = b'Mn '
  • Mode = b'Md '
heads up bestie: some of these four-byte codes end in a literal space (looking at you b'Clr ', b'Fmt ', b'Gd ', b'Lyr ', b'Ln ', b'Msk ', b'Mn ' and b'Md ') so don't go trimming anything, fr fr ๐Ÿ”ฅ

and the roster keeps goingโ€ฆ more of the alphabet is coming up next ๐Ÿ’–


...and we just keep going, bestie, the code table does not stop and honestly? respect ๐Ÿ’… every one of these is an exact four-character code, casing and spaces included. Do not "tidy" them. Do not lowercase them. The trailing spaces are real and they are staying ๐Ÿซถ

  • MultichannelMode โ€” b'MltC'
  • Null โ€” b'null'
  • ObsoleteTextLayer โ€” b'TxLy'
  • Offset โ€” b'Ofst'
  • Opacity โ€” b'Opac'
  • OuterGlow โ€” b'OrGl'
  • PDFGenericFormat โ€” b'PDFG'
  • PICTFileFormat โ€” b'PICF'
  • PICTResourceFormat โ€” b'PICR'
  • PNGFormat โ€” b'PNGF'
  • PageSetup โ€” b'PgSt'
  • PaintbrushTool โ€” b'PbTl'
  • Path โ€” b'Path'
  • PathComponent โ€” b'PaCm'
  • PathPoint โ€” b'Pthp'
  • Pattern โ€” b'PttR'
  • PatternStampTool โ€” b'PaTl'
  • PencilTool โ€” b'PcTl'
  • Photoshop20Format โ€” b'Pht2'
  • Photoshop35Format โ€” b'Pht3'
  • PhotoshopDCS2Format โ€” b'PhD2'
  • PhotoshopDCSFormat โ€” b'PhD1'
  • PhotoshopEPSFormat โ€” b'PhtE'
  • PhotoshopPDFFormat โ€” b'PhtP'
  • Pixel โ€” b'Pxel'
  • PixelPaintFormat โ€” b'PxlP'
  • PluginPrefs โ€” b'PlgP'
  • Point โ€” b'Pnt '
  • Point16 โ€” b'Pnt1'
  • Polygon โ€” b'Plgn'
  • Posterize โ€” b'Pstr'
  • Preferences โ€” b'GnrP'
  • ProfileSetup โ€” b'PrfS'
  • Property โ€” b'Prpr'
  • RGBColor โ€” b'RGBC'
  • RGBColorMode โ€” b'RGBM'
  • RGBSetup โ€” b'RGBt'
  • Range โ€” b'Rang'
  • RawFormat โ€” b'Rw '
  • Rect16 โ€” b'Rct1'
  • Rectangle โ€” b'Rctn'
  • SaturationTool โ€” b'SrTl'
  • ScitexCTFormat โ€” b'Sctx'
  • Selection โ€” b'csel'
  • SelectiveColor โ€” b'SlcC'
  • ShapingCurve โ€” b'ShpC'
  • SharpenTool โ€” b'ShTl'
  • SingleColumn โ€” b'Sngc'
  • SingleRow โ€” b'Sngr'
  • SmudgeTool โ€” b'SmTl'
  • Snapshot โ€” b'SnpS'
  • SolidFill โ€” b'SoFi'
  • SpotColorChannel โ€” b'SCch'
  • Style โ€” b'StyC'
  • SubPath โ€” b'Sbpl'
  • TIFFFormat โ€” b'TIFF'
  • TargaFormat โ€” b'TrgF'
  • TextLayer โ€” b'TxLr'
  • TextStyle โ€” b'TxtS'
  • TextStyleRange โ€” b'Txtt'
  • Threshold โ€” b'Thrs'
  • Tool โ€” b'Tool'
  • TransferPoint โ€” b'DtnP'
  • TransferSpec โ€” b'Trfp'
  • TransparencyPrefs โ€” b'TrnP'
  • TransparencyStop โ€” b'TrnS'
  • UnitsPrefs โ€” b'UntP'
  • UnspecifiedColor โ€” b'UnsC'
  • Version โ€” b'Vrsn'
  • WebdavPrefs โ€” b'Wdbv'
  • XYYColor โ€” b'XYYC'

โœจ Enum โœจ

class psd_tools.terminology.Enum(*values)

Enum definitions extracted from PITerminology.h.

See https://www.adobe.com/devnet/photoshop/sdk.html

Okay so THIS is the big one, and when I say big I mean big. One *values star-args situation and a whole alphabet of constants falling out of it. Every single one below is exact โ€” same letters, same caps, same any-weird-case Adobe decided on that day. Do not touch. Do not "clean up" ๐Ÿ™ˆ

  • A โ€” b'A '
  • ADSBottoms โ€” b'AdBt'
  • ADSCentersH โ€” b'AdCH'
  • ADSCentersV โ€” b'AdCV'
  • ADSHorizontal โ€” b'AdHr'
  • ADSLefts โ€” b'AdLf'
  • ADSRights โ€” b'AdRg'
  • ADSTops โ€” b'AdTp'
  • ADSVertical โ€” b'AdVr'
  • ASCII โ€” b'ASCI'
  • AboutApp โ€” b'AbAp'
  • AbsColorimetric โ€” b'AClr'
  • Absolute โ€” b'Absl'
  • ActualPixels โ€” b'ActP'
  • Adaptive โ€” b'Adpt'
  • Add โ€” b'Add '
  • AdjustmentOptions โ€” b'AdjO'
  • AdobeRGB1998 โ€” b'SMPT'
  • AirbrushEraser โ€” b'Arbs'
  • All โ€” b'Al '
  • Amiga โ€” b'Amga'
  • AmountHigh โ€” b'amHi'
  • AmountLow โ€” b'amLo'
  • AmountMedium โ€” b'amMd'
  • Angle โ€” b'Angl'
  • AntiAliasCrisp โ€” b'AnCr'
  • AntiAliasHigh โ€” b'AnHi'
  • AntiAliasLow โ€” b'AnLo'
  • AntiAliasMedium โ€” b'AnMd'
  • AntiAliasNone โ€” b'Anno'
  • AntiAliasSmooth โ€” b'AnSm'
  • AntiAliasStrong โ€” b'AnSt'
  • Any โ€” b'Any '
  • AppleRGB โ€” b'AppR'
  • ApplyImage โ€” b'AplI'
  • AroundCenter โ€” b'ArnC'
  • Arrange โ€” b'Arng'
  • Ask โ€” b'Ask '
  • AskWhenOpening โ€” b'AskW'

See how AdobeRGB1998 maps to b'SMPT'? Not intuitive, not your business, just type it right ๐Ÿ’€

  • B โ€” b'B '
  • Back โ€” b'Back'
  • Background โ€” b'Bckg'
  • BackgroundColor โ€” b'BckC'
  • Backward โ€” b'Bckw'
  • Behind โ€” b'Bhnd'
  • Best โ€” b'Bst '
  • Better โ€” b'Dthb'
  • Bicubic โ€” b'Bcbc'
  • Bilinear โ€” b'Blnr'
  • Binary โ€” b'Bnry'
  • BitDepth1 โ€” b'BD1 '
  • BitDepth16 โ€” b'BD16'
  • BitDepth24 โ€” b'BD24'
  • BitDepth32 โ€” b'BD32'
  • BitDepth4 โ€” b'BD4 '
  • BitDepth8 โ€” b'BD8 '
  • BitDepthA1R5G5B5 โ€” b'1565'
  • BitDepthA4R4G4B4 โ€” b'4444'
  • BitDepthR5G6B5 โ€” b'x565'
  • BitDepthX4R4G4B4 โ€” b'x444'
  • BitDepthX8R8G8B8 โ€” b'x888'
  • Bitmap โ€” b'Btmp'
  • Black โ€” b'Blck'
  • BlackAndWhite โ€” b'BanW'
  • BlackBody โ€” b'BlcB'
  • Blacks โ€” b'Blks'
  • Blast โ€” b'Blst'
  • BlockEraser โ€” b'Blk '
  • Blocks โ€” b'Blks'
  • Blue โ€” b'Bl '
  • Blues โ€” b'Bls '
  • Bottom โ€” b'Bttm'
  • BrushDarkRough โ€” b'BrDR'
  • BrushLightRough โ€” b'BrsL'
  • BrushSimple โ€” b'BrSm'
  • BrushSize โ€” b'BrsS'
  • BrushSparkle โ€” b'BrSp'
  • BrushWideBlurry โ€” b'BrbW'
  • BrushWideSharp โ€” b'BrsW'
  • BrushesAppend โ€” b'BrsA'
  • BrushesDefine โ€” b'BrsD'
  • BrushesDelete โ€” b'Brsf'
  • BrushesLoad โ€” b'Brsd'
  • BrushesNew โ€” b'BrsN'
  • BrushesOptions โ€” b'BrsO'
  • BrushesReset โ€” b'BrsR'
  • BrushesSave โ€” b'Brsv'
  • Builtin โ€” b'Bltn'
  • BurnInH โ€” b'BrnH'
  • BurnInM โ€” b'BrnM'
  • BurnInS โ€” b'BrnS'
  • ButtonMode โ€” b'BtnM'

Also quick heads up ๐ŸŽ€ โ€” Blks shows up twice in this list (Blacks and Blocks). That's not me being chaotic, that's just how it is. Write it exactly like that.

  • CIERGB โ€” b'CRGB'
  • CMYK โ€” b'CMYK'
  • CMYK64 โ€” b'CMSF'
  • CMYKColor โ€” b'ECMY'
  • Calculations โ€” b'Clcl'
  • Cascade โ€” b'Cscd'
  • Center โ€” b'Cntr'
  • CenterGlow โ€” b'SrcC'
  • CenteredFrame โ€” b'CtrF'
  • ChannelOptions โ€” b'ChnO'
  • ChannelsPaletteOptions โ€” b'ChnP'
  • CheckerboardLarge โ€” b'ChcL'
  • CheckerboardMedium โ€” b'ChcM'
  • CheckerboardNone โ€” b'ChcN'
  • CheckerboardSmall โ€” b'ChcS'
  • Clear โ€” b'Clar'
  • ClearGuides โ€” b'ClrG'
  • Clipboard โ€” b'Clpb'
  • ClippingPath โ€” b'ClpP'
  • CloseAll โ€” b'ClsA'
  • CoarseDots โ€” b'CrsD'
  • Color โ€” b'Clr '
  • ColorBurn โ€” b'CBrn'
  • ColorDodge โ€” b'CDdg'
  • ColorMatch โ€” b'ClMt'
  • ColorNoise โ€” b'ClNs'
  • Colorimetric โ€” b'Clrm'
  • Composite โ€” b'Cmps'
  • ContourCustom โ€” b'sp06'
  • ContourDouble โ€” b'sp04'
  • ContourGaussian โ€” b'sp02'
  • ContourLinear โ€” b'sp01'
  • ContourSingle โ€” b'sp03'
  • ContourTriple โ€” b'sp05'
  • ConvertToCMYK โ€” b'CnvC'
  • ConvertToGray โ€” b'CnvG'
  • ConvertToLab โ€” b'CnvL'
  • ConvertToRGB โ€” b'CnvR'
  • CreateDuplicate โ€” b'CrtD'
  • CreateInterpolation โ€” b'CrtI'
  • Cross โ€” b'Crs '
  • CurrentLayer โ€” b'CrrL'
  • Custom โ€” b'Cst '
  • CustomPattern โ€” b'Cstm'
  • CustomStops โ€” b'CstS'
  • Cyan โ€” b'Cyn '
  • Cyans โ€” b'Cyns'

The Contour* squad all lowercase sp and numbered out of order โ€” sp01, sp02, sp03, sp04, sp05, sp06 โ€” iconic behavior honestly ๐Ÿ”ฅ

  • Dark โ€” b'Drk '
  • Darken โ€” b'Drkn'
  • DarkenOnly โ€” b'DrkO'
  • DashedLines โ€” b'DshL'
  • Desaturate โ€” b'Dstt'
  • Diamond โ€” b'Dmnd'
  • Difference โ€” b'Dfrn'
  • Diffusion โ€” b'Dfsn'
  • DiffusionDither โ€” b'DfnD'
  • DisplayCursorsPreferences โ€” b'DspC'
  • Dissolve โ€” b'Dslv'
  • Distort โ€” b'Dstr'
  • DodgeH โ€” b'DdgH'
  • DodgeM โ€” b'DdgM'
  • DodgeS โ€” b'DdgS'
  • Dots โ€” b'Dts '
  • Draft โ€” b'Drft'
  • Duotone โ€” b'Dtn '
  • EBUITU โ€” b'EBT '
  • EdgeGlow โ€” b'SrcE'
  • EliminateEvenFields โ€” b'ElmE'
  • EliminateOddFields โ€” b'ElmO'
  • Ellipse โ€” b'Elps'
  • Emboss โ€” b'Embs'
  • Exact โ€” b'Exct'
  • Exclusion โ€” b'Xclu'
  • FPXCompressLossyJPEG โ€” b'FxJP'
  • FPXCompressNone โ€” b'FxNo'
  • Faster โ€” b'Dthf'
  • File โ€” b'Fle '
  • FileInfo โ€” b'FlIn'
  • FillBack โ€” b'FlBc'
  • FillFore โ€” b'FlFr'
  • FillInverse โ€” b'FlIn'
  • FillSame โ€” b'FlSm'
  • FineDots โ€” b'FnDt'
  • First โ€” b'Frst'
  • FirstIdle โ€” b'FrId'
  • FitOnScreen โ€” b'FtOn'
  • ForegroundColor โ€” b'FrgC'
  • Forward โ€” b'Frwr'
  • FreeTransform โ€” b'FrTr'
  • Front โ€” b'Frnt'
  • FullDocument โ€” b'FllD'
  • FullSize โ€” b'FlSz'
  • GIFColorFileColorTable โ€” b'GFCT'
  • GIFColorFileColors โ€” b'GFCF'
  • GIFColorFileMicrosoftPalette โ€” b'GFMS'
  • GIFPaletteAdaptive โ€” b'GFPA'
  • GIFPaletteExact โ€” b'GFPE'
  • GIFPaletteOther โ€” b'GFPO'
  • GIFPaletteSystem โ€” b'GFPS'
  • GIFRequiredColorSpaceIndexed โ€” b'GFCI'
  • GIFRequiredColorSpaceRGB โ€” b'GFRG'
  • GIFRowOrderInterlaced โ€” b'GFIN'
  • GIFRowOrderNormal โ€” b'GFNI'
  • GaussianDistribution โ€” b'Gsn '
  • GeneralPreferences โ€” b'GnrP'
  • Good โ€” b'Gd '
  • GradientFill โ€” b'GrFl'
  • GrainClumped โ€” b'GrnC'
  • GrainContrasty โ€” b'GrCn'
  • GrainEnlarged โ€” b'GrnE'
  • GrainHorizontal โ€” b'GrnH'
  • GrainRegular โ€” b'GrnR'
  • GrainSoft โ€” b'GrSf'
  • GrainSpeckle โ€” b'GrSp'
  • GrainSprinkles โ€” b'GrSr'
  • GrainStippled โ€” b'GrSt'
  • GrainVertical โ€” b'GrnV'
  • GrainyDots โ€” b'GrnD'
  • Graphics โ€” b'Grp '
  • Gray โ€” b'Gry '
  • Gray16 โ€” b'GryX'
  • Gray18 โ€” b'Gr18'
  • Gray22 โ€” b'Gr22'
  • Gray50 โ€” b'Gr50'
  • GrayScale โ€” b'Gryc'
  • Grayscale โ€” b'Grys'
  • Green โ€” b'Grn '
  • Greens โ€” b'Grns'
  • GuidesGridPreferences โ€” b'GudG'
  • HDTV โ€” b'HDTV'
  • HSBColor โ€” b'HSBl'
  • HSLColor โ€” b'HSLC'
  • HalftoneFile โ€” b'HlfF'
  • HalftoneScreen โ€” b'HlfS'
  • HardLight โ€” b'HrdL'
  • Heavy โ€” b'Hvy '
  • HideAll โ€” b'HdAl'
  • HideSelection โ€” b'HdSl'
  • High โ€” b'High'
  • HighQuality โ€” b'Hgh '
  • Highlights โ€” b'Hghl'
  • Histogram โ€” b'Hstg'
  • History โ€” b'Hsty'
  • HistoryPaletteOptions โ€” b'HstO'
  • HistoryPreferences โ€” b'HstP'
  • Horizontal โ€” b'Hrzn'
  • HorizontalOnly โ€” b'HrzO'
  • Hue โ€” b'H '
  • IBMPC โ€” b'IBMP'
  • ICC โ€” b'ICC '
  • Icon โ€” b'Icn '
  • IdleVM โ€” b'IdVM'
  • Ignore โ€” b'Ignr'
  • Image โ€” b'Img '
  • ImageCachePreferences โ€” b'ImgP'
  • IndexedColor โ€” b'Indl'
  • InfoPaletteOptions โ€” b'InfP'
  • InfoPaletteToggleSamplers โ€” b'InfT'
  • InnerBevel โ€” b'InrB'
  • InsetFrame โ€” b'InsF'

High is literally just b'High' โ€” no truncation, no four-char squeeze, just vibes โœจ and it's still correct, so leave it alone.

okay bestie, we're still in the constant corridor and it is long but also lowkey mesmerizing ๐ŸŒˆ no cap, every one of these is exact, so don't let the vibes fool you:

  • Inside โ€” b'Insd' โœจ
  • JPEG โ€” b'JPEG' ๐Ÿ“ธ
  • JustifyAll โ€” b'JstA' ๐Ÿ’…
  • JustifyFull โ€” b'JstF' ๐Ÿ’–
  • KeepProfile โ€” b'KPro' ๐ŸŽ€
  • KeyboardPreferences โ€” b'KybP' โŒจ๏ธ
  • Lab โ€” b'Lab ' ๐Ÿงช
  • Lab48 โ€” b'LbCF' ๐Ÿ”ฌ
  • LabColor โ€” b'LbCl' ๐ŸŽจ
  • Large โ€” b'Lrg ' ๐Ÿ˜
  • Last โ€” b'Lst ' โฎ๏ธ
  • LastFilter โ€” b'LstF' ๐ŸŒ€
  • LayerOptions โ€” b'LyrO' ๐Ÿง…
  • LayersPaletteOptions โ€” b'LyrP' ๐ŸŽ›๏ธ
  • Left โ€” b'Left' โฌ…๏ธ
  • Left_PLUGIN โ€” b'Lft ' ๐Ÿงฉ
  • LevelBased โ€” b'LvlB' ๐Ÿ“Š
  • Light โ€” b'Lgt ' ๐Ÿ’ก
  • LightBlue โ€” b'LgtB' ๐Ÿฉต
  • LightDirBottom โ€” b'LDBt' โฌ‡๏ธ
  • LightDirBottomLeft โ€” b'LDBL' โ†™๏ธ
  • LightDirBottomRight โ€” b'LDBR' โ†˜๏ธ
  • LightDirLeft โ€” b'LDLf' โฌ…๏ธ
  • LightDirRight โ€” b'LDRg' โžก๏ธ
  • LightDirTop โ€” b'LDTp' โฌ†๏ธ
  • LightDirTopLeft โ€” b'LDTL' โ†–๏ธ
  • LightDirTopRight โ€” b'LDTR' โ†—๏ธ
  • LightDirectional โ€” b'LghD' ๐Ÿ”ฆ
  • LightGray โ€” b'LgtG' ๐Ÿฉถ
  • LightOmni โ€” b'LghO' ๐ŸŒ
  • LightPosBottom โ€” b'LPBt' ๐Ÿ“
  • LightPosBottomLeft โ€” b'LPBL' ๐Ÿ“
  • LightPosBottomRight โ€” b'LPBr' ๐Ÿ“
  • LightPosLeft โ€” b'LPLf' ๐Ÿ“
  • LightPosRight โ€” b'LPRg' ๐Ÿ“
  • LightPosTop โ€” b'LPTp' ๐Ÿ“
  • LightPosTopLeft โ€” b'LPTL' ๐Ÿ“
  • LightPosTopRight โ€” b'LPTR' ๐Ÿ“
  • LightRed โ€” b'LgtR' ๐Ÿฉธ
  • LightSpot โ€” b'LghS' ๐Ÿ”†
  • Lighten โ€” b'Lghn' ๐ŸŒž
  • LightenOnly โ€” b'LghO' ๐ŸŒŸ
  • Lightness โ€” b'Lght' ๐Ÿชถ
  • Line โ€” b'Ln ' ๐Ÿ“
  • Linear โ€” b'Lnr ' ๐Ÿ“ˆ
  • Lines โ€” b'Lns ' ใ€ฐ๏ธ
  • Linked โ€” b'Lnkd' ๐Ÿ”—
  • LongLines โ€” b'LngL' ๐Ÿ“‰
  • LongStrokes โ€” b'LngS' ๐Ÿ–Œ๏ธ
  • Low โ€” b'Low ' ๐Ÿ”ฝ
  • LowQuality โ€” b'Lw ' ๐Ÿซ 
  • Lower โ€” b'Lwr ' ๐Ÿ”ป
  • Luminosity โ€” b'Lmns' โœจ
  • MacThumbnail โ€” b'McTh' ๐ŸŽ
  • Macintosh โ€” b'Mcnt' ๐Ÿ–ฅ๏ธ
  • MacintoshSystem โ€” b'McnS' ๐Ÿ
  • Magenta โ€” b'Mgnt' ๐Ÿ’—
  • Magentas โ€” b'Mgnt' ๐Ÿ’ž
  • Mask โ€” b'Msk ' ๐ŸŽญ
  • MaskedAreas โ€” b'MskA' ๐Ÿซฅ
  • MasterAdaptive โ€” b'MAdp' ๐Ÿง 
  • MasterPerceptual โ€” b'MPer' ๐Ÿ‘๏ธ
  • MasterSelective โ€” b'MSel' ๐ŸŽฏ
  • Maximum โ€” b'Mxmm' ๐Ÿ”
  • MaximumQuality โ€” b'Mxm ' ๐Ÿ’Ž
  • Maya โ€” b'Maya' ๐Ÿบ
  • Medium โ€” b'Mdim' โš–๏ธ
  • MediumBlue โ€” b'MdmB' ๐Ÿ”ต
  • MediumDots โ€” b'MdmD' ๐Ÿ”˜
  • MediumLines โ€” b'MdmL' ๐Ÿ“
  • MediumQuality โ€” b'Mdm ' ๐ŸŽš๏ธ
  • MediumStrokes โ€” b'MdmS' ๐Ÿ–๏ธ
  • MemoryPreferences โ€” b'MmrP' ๐Ÿ’พ
  • MergeChannels โ€” b'MrgC' ๐Ÿงฌ
  • Merged โ€” b'Mrgd' ๐Ÿ”€
  • MergedLayers โ€” b'Mrg2' ๐Ÿง…
  • MergedLayersOld โ€” b'MrgL' ๐Ÿง…
  • Middle โ€” b'Mddl' ๐ŸŽฏ
  • Midtones โ€” b'Mdtn' ๐ŸŒ—
  • ModeGray โ€” b'MdGr' โšซ
  • ModeRGB โ€” b'MdRG' ๐ŸŒˆ
  • Monitor โ€” b'Moni' ๐Ÿ–ฅ๏ธ
  • MonitorSetup โ€” b'MntS' โš™๏ธ
  • Monotone โ€” b'Mntn' ๐ŸŽต
  • Multi72Color โ€” b'72CM' ๐ŸŒˆ
  • Multi72Gray โ€” b'72GM' ๐ŸŒซ๏ธ
  • MultiNoCompositePS โ€” b'NCmM' ๐Ÿšซ
  • Multichannel โ€” b'Mlth' ๐ŸŽš๏ธ
  • Multiply โ€” b'Mltp' โœ–๏ธ
  • NTSC โ€” b'NTSC' ๐Ÿ“บ
  • NavigatorPaletteOptions โ€” b'NvgP' ๐Ÿงญ
  • NearestNeighbor โ€” b'Nrst' ๐Ÿ”
  • NetscapeGray โ€” b'NsGr' ๐ŸŒ
  • Neutrals โ€” b'Ntrl' โšช
  • NewView โ€” b'NwVw' ๐Ÿ†•
  • Next โ€” b'Nxt ' โญ๏ธ
  • Nikon โ€” b'Nkn ' ๐Ÿ“ท
  • Nikon105 โ€” b'Nkn1' ๐Ÿ“ธ
  • No โ€” b'N ' โŒ
  • NoCompositePS โ€” b'NCmp' ๐Ÿ™…
  • Normal โ€” b'Nrml' ๐Ÿ˜
  • NormalPath โ€” b'NrmP' ๐Ÿ›ค๏ธ
  • Null โ€” b'null' ๐Ÿ•ณ๏ธ
  • OS2 โ€” b'OS2 ' ๐Ÿ’ฝ
  • Off โ€” b'Off ' ๐Ÿ”Œ
  • On โ€” b'On ' ๐Ÿ’ก
  • OpenAs โ€” b'OpAs' ๐Ÿ“‚
  • Orange โ€” b'Orng' ๐ŸŠ
  • OutFromCenter โ€” b'OtFr' ๐ŸŽฏ
  • OutOfGamut โ€” b'OtOf' โš ๏ธ
  • OuterBevel โ€” b'OtrB' ๐Ÿ”˜
  • OutsetFrame โ€” b'OutF' ๐Ÿ–ผ๏ธ
  • Outside โ€” b'Otsd' ๐Ÿšช
  • Overlay โ€” b'Ovrl' ๐ŸŽž๏ธ
  • P22EBU โ€” b'P22B' ๐Ÿ“บ
  • PNGFilterAdaptive โ€” b'PGAd' ๐Ÿง 
  • PNGFilterAverage โ€” b'PGAv' ๐Ÿ“Š
  • PNGFilterNone โ€” b'PGNo' ๐Ÿšซ
  • PNGFilterPaeth โ€” b'PGPt' ๐Ÿงฎ
  • PNGFilterSub โ€” b'PGSb' โž–
  • PNGFilterUp โ€” b'PGUp' โฌ†๏ธ
  • PNGInterlaceAdam7 โ€” b'PGIA' ๐Ÿช„
  • PNGInterlaceNone โ€” b'PGIN' ๐Ÿšซ
  • PagePosCentered โ€” b'PgPC' ๐ŸŽฏ
  • PagePosTopLeft โ€” b'PgTL' ๐Ÿ“„
  • PageSetup โ€” b'PgSt' โš™๏ธ
  • PaintbrushEraser โ€” b'Pntb' ๐Ÿ–Œ๏ธ
  • PalSecam โ€” b'PlSc' ๐Ÿ“บ
  • PanaVision โ€” b'PnVs' ๐ŸŽฅ
  • PathsPaletteOptions โ€” b'PthP' ๐Ÿ›ค๏ธ
  • Pattern โ€” b'Ptrn' ๐Ÿ”ท
  • PatternDither โ€” b'PtnD' ๐Ÿ”ฒ
  • PencilEraser โ€” b'Pncl' โœ๏ธ
  • Perceptual โ€” b'Perc' ๐Ÿ‘๏ธ
  • Perspective โ€” b'Prsp' ๐Ÿ“
  • PhotoshopPicker โ€” b'Phtk' ๐ŸŽจ
  • PickCMYK โ€” b'PckC' ๐ŸŽฏ
  • PickGray โ€” b'PckG' ๐ŸŽฏ
  • PickHSB โ€” b'PckH' ๐ŸŽฏ
  • PickLab โ€” b'PckL' ๐ŸŽฏ
  • PickOptions โ€” b'PckO' ๐ŸŽฏ
  • PickRGB โ€” b'PckR' ๐ŸŽฏ
  • PillowEmboss โ€” b'PlEb' ๐Ÿ›๏ธ
  • PixelPaintSize1 โ€” b'PxS1' 1๏ธโƒฃ
  • PixelPaintSize2 โ€” b'PxS2' 2๏ธโƒฃ
  • PixelPaintSize3 โ€” b'PxS3' 3๏ธโƒฃ
  • PixelPaintSize4 โ€” b'PxS4' 4๏ธโƒฃ
  • Place โ€” b'Plce' ๐Ÿ“Œ
  • PlaybackOptions โ€” b'PbkO' โ–ถ๏ธ
  • PluginPicker โ€” b'PlgP' ๐Ÿงฉ
  • PluginsScratchDiskPreferences โ€” b'PlgS' ๐Ÿ’ฝ
  • PolarToRect โ€” b'PlrR' ๐Ÿ“
  • PondRipples โ€” b'PndR' ๐Ÿ’ง
  • Precise โ€” b'Prc ' ๐ŸŽฏ
  • PreciseMatte โ€” b'PrBL' ๐ŸŽฏ
  • PreviewBlack โ€” b'PrvB' โšซ
  • PreviewCMY โ€” b'PrvN' ๐ŸŽจ
  • PreviewCMYK โ€” b'PrvC' ๐ŸŽจ
  • PreviewCyan โ€” b'Prvy' ๐Ÿฉต
  • PreviewMagenta โ€” b'PrvM' ๐Ÿ’—
  • PreviewOff โ€” b'PrvO' ๐Ÿ”Œ
  • PreviewYellow โ€” b'PrvY' ๐Ÿ’›
  • Previous โ€” b'Prvs' โฎ๏ธ
  • Primaries โ€” b'Prim' ๐ŸŽจ
  • PrintSize โ€” b'PrnS' ๐Ÿ–จ๏ธ
  • PrintingInksSetup โ€” b'PrnI' ๐Ÿ–จ๏ธ
  • Purple โ€” b'Prp ' ๐Ÿ’œ
  • Pyramids โ€” b'Pyrm' ๐Ÿ”บ
  • QCSAverage โ€” b'Qcsa' โš–๏ธ
  • QCSCorner0 โ€” b'Qcs0' ๐Ÿ“
  • QCSCorner1 โ€” b'Qcs1' ๐Ÿ“
  • QCSCorner2 โ€” b'Qcs2' ๐Ÿ“
  • QCSCorner3 โ€” b'Qcs3' ๐Ÿ“
  • QCSIndependent โ€” b'Qcsi' ๐Ÿ”“
  • QCSSide0 โ€” b'Qcs4' ๐Ÿ“
  • QCSSide1 โ€” b'Qcs5' ๐Ÿ“
  • QCSSide2 โ€” b'Qcs6' ๐Ÿ“
  • QCSSide3 โ€” b'Qcs7' ๐Ÿ“
  • Quadtone โ€” b'Qdtn' ๐ŸŽต
  • QueryAlways โ€” b'QurA' โ“
  • QueryAsk โ€” b'Qurl' โ“
  • QueryNever โ€” b'QurN' โ“
  • RGB โ€” b'RGB ' ๐ŸŒˆ
  • RGB48 โ€” b'RGBF' ๐ŸŒˆ
  • RGBColor โ€” b'RGBC' ๐ŸŒˆ
  • Radial โ€” b'Rdl ' โญ•
  • Random โ€” b'Rndm' ๐ŸŽฒ
  • RectToPolar โ€” b'RctP' ๐Ÿ“
  • Red โ€” b'Rd ' โค๏ธ
  • RedrawComplete โ€” b'RdCm' ๐Ÿ”„
  • Reds โ€” b'Rds ' โค๏ธ
  • Reflected โ€” b'Rflc' ๐Ÿชž
  • Relative โ€” b'Rltv' ๐Ÿ”—
  • Repeat โ€” b'Rpt ' ๐Ÿ”
  • RepeatEdgePixels โ€” b'RptE' ๐Ÿ”
  • RevealAll โ€” b'RvlA' ๐Ÿ‘๏ธ
  • RevealSelection โ€” b'RvlS' ๐Ÿ‘๏ธ
  • Revert โ€” b'Rvrt' โช
  • Right โ€” b'Rght' โžก๏ธ
  • Rotate โ€” b'Rtte' ๐Ÿ”„
  • RotoscopingPreferences โ€” b'RtsP' ๐ŸŽž๏ธ
  • Round โ€” b'Rnd ' โญ•
  • RulerCm โ€” b'RrCm' ๐Ÿ“
  • RulerInches โ€” b'RrIn' ๐Ÿ“
  • RulerPercent โ€” b'RrPr' ๐Ÿ“
  • RulerPicas โ€” b'RrPi' ๐Ÿ“
  • RulerPixels โ€” b'RrPx' ๐Ÿ“
  • RulerPoints โ€” b'RrPt' ๐Ÿ“
  • SMPTEC โ€” b'SMPC' ๐Ÿ“บ
  • SRGB โ€” b'SRGB' ๐ŸŒˆ
  • Sample3x3 โ€” b'Smp3' 3๏ธโƒฃ
  • Sample5x5 โ€” b'Smp5' 5๏ธโƒฃ
  • SamplePoint โ€” b'SmpP' ๐Ÿ“
  • Saturate โ€” b'Str ' ๐ŸŒˆ
  • Saturation โ€” b'Strt' ๐ŸŒˆ
  • SaveForWeb โ€” b'Svfw' ๐ŸŒ
  • Saved โ€” b'Sved' ๐Ÿ’พ
  • SavingFilesPreferences โ€” b'SvnF' ๐Ÿ’พ
  • Scale โ€” b'Scl ' ๐Ÿ“
  • Screen โ€” b'Scrn' ๐Ÿ–ฅ๏ธ
  • ScreenCircle โ€” b'ScrC' โญ•
  • ScreenDot โ€” b'ScrD' ๐Ÿ”˜
  • ScreenLine โ€” b'ScrL' โž–
  • SelectedAreas โ€” b'SlcA' ๐ŸŽฏ
  • Selection โ€” b'Slct' ๐ŸŽฏ
  • Selective โ€” b'Sele' ๐ŸŽฏ
  • SeparationSetup โ€” b'SprS' ๐ŸŽจ
  • SeparationTables โ€” b'SprT' ๐ŸŽจ
  • Shadows โ€” b'Shdw' ๐ŸŒ‘
  • ShortLines โ€” b'ShrL' ๐Ÿ“
  • ShortStrokes โ€” b'ShSt' ๐Ÿ–Œ๏ธ
  • Single72Color โ€” b'72CS' ๐ŸŒˆ
  • Single72Gray โ€” b'72GS' ๐ŸŒซ๏ธ
  • SingleNoCompositePS โ€” b'NCmS' ๐Ÿšซ
  • Skew โ€” b'Skew' ๐Ÿ“
  • SlopeLimitMatte โ€” b'Slmt' ๐Ÿ“
  • Small โ€” b'Sml ' ๐Ÿœ
  • SmartBlurModeEdgeOnly โ€” b'SBME' ๐Ÿง 
  • SmartBlurModeNormal โ€” b'SBMN' ๐Ÿง 
  • SmartBlurModeOverlayEdge โ€” b'SBMO' ๐Ÿง 
  • SmartBlurQualityHigh โ€” b'SBQH' ๐Ÿ’Ž
  • SmartBlurQualityLow โ€” b'SBQL' ๐Ÿซ 
  • SmartBlurQualityMedium โ€” b'SBQM' โš–๏ธ
  • Snapshot โ€” b'Snps' ๐Ÿ“ธ
  • SoftLight โ€” b'SftL' ๐ŸŒŸ
  • SoftMatte โ€” b'SfBL' ๐ŸŒซ๏ธ
  • SolidColor โ€” b'SClr' ๐ŸŽจ
  • Spectrum โ€” b'Spct' ๐ŸŒˆ
  • Spin โ€” b'Spn ' ๐ŸŒ€
  • SpotColor โ€” b'Spot' ๐Ÿ”ด
  • Square โ€” b'Sqr ' โฌœ
  • Stagger โ€” b'Stgr' ๐Ÿชœ
  • StampIn โ€” b'In ' ๐Ÿชง
  • StampOut โ€” b'Out ' ๐Ÿชง
  • Standard โ€” b'Std ' ๐Ÿ“
  • StdA โ€” b'StdA' ๐Ÿ“
  • StdB โ€” b'StdB' ๐Ÿ“
  • StdC โ€” b'StdC' ๐Ÿ“
  • StdE โ€” b'StdE' ๐Ÿ“
  • StretchToFit โ€” b'StrF' ๐Ÿ“
  • StrokeDirHorizontal โ€” b'SDHz' โ†”๏ธ
  • StrokeDirLeftDiag โ€” b'SDLD' โ†™๏ธ
  • StrokeDirRightDiag โ€” b'SDRD' โ†˜๏ธ
  • StrokeDirVertical โ€” b'SDVt' โ†•๏ธ
  • StylesAppend โ€” b'SlsA' ๐ŸŽจ
  • StylesDelete โ€” b'Slsf' ๐Ÿ—‘๏ธ
  • StylesLoad โ€” b'Slsd' ๐Ÿ“‚
  • StylesNew โ€” b'SlsN' ๐Ÿ†•
  • StylesReset โ€” b'SlsR' ๐Ÿ”„
  • StylesSave โ€” b'Slsv' ๐Ÿ’พ
  • Subtract โ€” b'Sbtr' โž–
  • SwatchesAppend โ€” b'SwtA' ๐ŸŽจ
  • SwatchesReplace โ€” b'Swtp' ๐ŸŽจ
  • SwatchesReset โ€” b'SwtR' ๐Ÿ”„
  • SwatchesSave โ€” b'SwtS' ๐Ÿ’พ
  • SystemPicker โ€” b'SysP' ๐Ÿ–ฅ๏ธ
  • TIFF โ€” b'TIFF' ๐Ÿ–ผ๏ธ
  • Tables โ€” b'Tbl ' ๐Ÿ“Š
  • Target โ€” b'Trgt' ๐ŸŽฏ
  • TargetPath โ€” b'Trgp' ๐Ÿ›ค๏ธ
  • TexTypeBlocks โ€” b'TxBl' ๐Ÿงฑ
  • TexTypeBrick โ€” b'TxBr' ๐Ÿงฑ
  • TexTypeBurlap โ€” b'TxBu' ๐Ÿงต
  • TexTypeCanvas โ€” b'TxCa' ๐ŸŽจ
  • TexTypeFrosted โ€” b'TxFr' โ„๏ธ
  • TexTypeSandstone โ€” b'TxSt' ๐Ÿœ๏ธ
  • TexTypeTinyLens โ€” b'TxTL' ๐Ÿ”
  • Threshold โ€” b'Thrh' ๐ŸŽš๏ธ
  • Thumbnail โ€” b'Thmb' ๐Ÿ–ผ๏ธ
  • Tile โ€” b'Tile' ๐Ÿงฉ
  • Tile_PLUGIN โ€” b'Tl ' ๐Ÿงฉ
  • ToggleActionsPalette โ€” b'TglA' ๐ŸŽ›๏ธ
  • ToggleBlackPreview โ€” b'TgBP' โšซ
  • ToggleBrushesPalette โ€” b'TglB' ๐Ÿ–Œ๏ธ
  • ToggleCMYKPreview โ€” b'TglC' ๐ŸŽจ
  • ToggleCMYPreview โ€” b'TgCM' ๐ŸŽจ
  • ToggleChannelsPalette โ€” b'Tglh' ๐ŸŽš๏ธ
  • ToggleColorPalette โ€” b'Tglc' ๐ŸŽจ
  • ToggleCyanPreview โ€” b'TgCP' ๐Ÿฉต
  • ToggleDocumentPalette โ€” b'TgDc' ๐Ÿ“„
  • ToggleEdges โ€” b'TglE' ๐Ÿ”ฒ
  • ToggleGamutWarning โ€” b'TglG' โš ๏ธ
  • ToggleGrid โ€” b'TgGr' ๐Ÿ”ฒ
  • ToggleGuides โ€” b'Tgld' ๐Ÿ“
  • ToggleHistoryPalette โ€” b'TglH' ๐Ÿ•ฐ๏ธ
  • ToggleInfoPalette โ€” b'TglI' โ„น๏ธ
  • ToggleLayerMask โ€” b'TglM' ๐ŸŽญ
  • ToggleLayersPalette โ€” b'Tgly' ๐Ÿง…
  • ToggleLockGuides โ€” b'TglL' ๐Ÿ”’
  • ToggleMagentaPreview โ€” b'TgMP' ๐Ÿ’—
  • ToggleNavigatorPalette โ€” b'TglN' ๐Ÿงญ
  • ToggleOptionsPalette โ€” b'TglO' โš™๏ธ
  • TogglePaths โ€” b'TglP' ๐Ÿ›ค๏ธ
  • TogglePathsPalette โ€” b'Tglt' ๐Ÿ›ค๏ธ
  • ToggleRGBMacPreview โ€” b'TrMp' ๐ŸŽ
  • ToggleRGBUncompensatedPreview โ€” b'TrUp' ๐ŸŒˆ
  • ToggleRGBWindowsPreview โ€” b'TrWp' ๐ŸชŸ
  • ToggleRulers โ€” b'TglR' ๐Ÿ“
  • ToggleSnapToGrid โ€” b'TgSn' ๐Ÿงฒ
  • ToggleSnapToGuides โ€” b'TglS' ๐Ÿงฒ
  • ToggleStatusBar โ€” b'Tgls' ๐Ÿ“Š
  • ToggleStylesPalette โ€” b'TgSl' ๐ŸŽจ
  • ToggleSwatchesPalette โ€” b'Tglw' ๐ŸŽจ

okay bestie we're SO back ๐Ÿ˜ค no re-intros, no small talk, we're picking up exactly where we left off โ€” here's the rest of that list, all the way down to the _None at the bottom, no skipping, no summarising, that's the rule ๐Ÿ’…

ToggleToolsPalette = b'TglT'
ToggleYellowPreview = b'TgYP'
Top = b'Top '
Transparency = b'Trsp'
TransparencyGamutPreferences = b'TrnG'
Transparent = b'Trns'
Trinitron = b'Trnt'
Tritone = b'Trtn'
UIBitmap = b'UBtm'
UICMYK = b'UCMY'
UIDuotone = b'UDtn'
UIGrayscale = b'UGry'
UIIndexed = b'UInd'
UILab = b'ULab'
UIMultichannel = b'UMlt'
UIRGB = b'URGB'
Undo = b'Und '
Uniform = b'Unfm'
UniformDistribution = b'Unfr'
UnitsRulersPreferences = b'UntR'
Upper = b'Upr '
UserStop = b'UsrS'
VMPreferences = b'VMPr'
Vertical = b'Vrtc'
VerticalOnly = b'VrtO'
Violet = b'Vlt '
WaveSine = b'WvSn'
WaveSquare = b'WvSq'
WaveTriangle = b'WvTr'
Web = b'Web '
White = b'Wht '
Whites = b'Whts'
WideGamutRGB = b'WRGB'
WidePhosphors = b'Wide'
WinThumbnail = b'WnTh'
Wind = b'Wnd '
Windows = b'Win '
WindowsSystem = b'WndS'
WorkPath = b'WrkP'
Wrap = b'Wrp '
WrapAround = b'WrpA'
Yellow = b'Yllw'
YellowColor = b'Ylw '
Yellows = b'Ylws'
Yes = b'Ys '
Zip = b'ZpEn'
Zoom = b'Zm '
ZoomIn = b'ZmIn'
ZoomOut = b'ZmOt'
_16BitsPerPixel = b'16Bt'
_1BitPerPixel = b'OnBt'
_2BitsPerPixel = b'2Bts'
_32BitsPerPixel = b'32Bt'
_4BitsPerPixel = b'4Bts'
_5000 = b'5000'
_5500 = b'5500'
_6500 = b'6500'
_72Color = b'72Cl'
_72Gray = b'72Gr'
_7500 = b'7500'
_8BitsPerPixel = b'EghB'
_9300 = b'9300'
_None = b'None'

okay that's that one DONE, and yes there are more classes, there are always more classes ๐Ÿ˜ญ strap in ๐ŸŽ€


๐Ÿ‘‘ class psd_tools.terminology.Event(*values)

Event definitions</p>, straight up extracted from PITerminology.h โ€” the whole gang. See <https://www.adobe.com/devnet/photoshop/sdk.html> โœจ

First chunk, A through C โ€” it's giving enormous:

AccentedEdges = b'AccE'
Add = b'Add '
AddNoise = b'AdNs'
AddTo = b'AddT'
Align = b'Algn'
All = b'All '
AngledStrokes = b'AngS'
ApplyImage = b'AppI'
ApplyStyle = b'ASty'
Assert = b'Asrt'
Average = b'Avrg'
BackLight = b'BacL'
BasRelief = b'BsRl'
Batch = b'Btch'
BatchFromDroplet = b'BtcF'
Blur = b'Blr '
BlurMore = b'BlrM'
Border = b'Brdr'
Brightness = b'BrgC'
CanvasSize = b'CnvS'
ChalkCharcoal = b'ChlC'
ChannelMixer = b'ChnM'
Charcoal = b'Chrc'
Chrome = b'Chrm'
Clear = b'Cler'
Close = b'Cls '
Clouds = b'Clds'
ColorBalance = b'ClrB'
ColorCast = b'ColE'
ColorHalftone = b'ClrH'
ColorRange = b'ClrR'
ColoredPencil = b'ClrP'
ConteCrayon = b'CntC'
Contract = b'Cntc'
ConvertMode = b'CnvM'
Copy = b'copy'
CopyEffects = b'CpFX'
CopyMerged = b'CpyM'
CopyToLayer = b'CpTL'
Craquelure = b'Crql'
CreateDroplet = b'CrtD'
Crop = b'Crop'
Crosshatch = b'Crsh'
Crystallize = b'Crst'
Curves = b'Crvs'
Custom = b'Cstm'
Cut = b'cut '
CutToLayer = b'CtTL'
Cutout = b'Ct '

not me literally typing b'cut ' and b'copy' lowercase while everything else is TitleCase ๐Ÿ’€ they knew what they were doing. anyways, keep going:

DarkStrokes = b'DrkS'
DeInterlace = b'Dntr'
DefinePattern = b'DfnP'
Defringe = b'Dfrg'
Delete = b'Dlt '
Desaturate = b'Dstt'
Deselect = b'Dslc'
Despeckle = b'Dspc'
DifferenceClouds = b'DfrC'
Diffuse = b'Dfs '
DiffuseGlow = b'DfsG'
DisableLayerFX = b'dlfx'
Displace = b'Dspl'
Distribute = b'Dstr'
Draw = b'Draw'
DryBrush = b'DryB'
Duplicate = b'Dplc'
DustAndScratches = b'DstS'
Emboss = b'Embs'
Equalize = b'Eqlz'
Exchange = b'Exch'
Expand = b'Expn'
Export = b'Expr'
Extrude = b'Extr'
Facet = b'Fct '
Fade = b'Fade'
Feather = b'Fthr'
Fibers = b'Fbrs'
Fill = b'Fl '
FilmGrain = b'FlmG'
Filter = b'Fltr'
FindEdges = b'FndE'
FlattenImage = b'FltI'
Flip = b'Flip'
Fragment = b'Frgm'
Fresco = b'Frsc'
GaussianBlur = b'GsnB'
Get = b'getd'
Glass = b'Gls '
GlowingEdges = b'GlwE'
Gradient = b'Grdn'
GradientMap = b'GrMp'
Grain = b'Grn '
GraphicPen = b'GraP'
Group = b'GrpL'
Grow = b'Grow'
HSBHSL = b'HsbP'
HalftoneScreen = b'HlfS'
Hide = b'Hd '
HighPass = b'HghP'
HueSaturation = b'HStr'
ImageSize = b'ImgS'
Import = b'Impr'
InkOutlines = b'InkO'
Intersect = b'Intr'
IntersectWith = b'IntW'
Inverse = b'Invs'
Invert = b'Invr'
LensFlare = b'LnsF'
Levels = b'Lvls'
LightingEffects = b'LghE'
Link = b'Lnk '
Make = b'Mk '
Maximum = b'Mxm '
Median = b'Mdn '
MergeLayers = b'Mrg2'
MergeLayersOld = b'MrgL'
MergeSpotChannel = b'MSpt'
MergeVisible = b'MrgV'
Mezzotint = b'Mztn'
Minimum = b'Mnm '
Mosaic = b'Msc '
Mosaic_PLUGIN = b'MscT'
MotionBlur = b'MtnB'
Move = b'move'
NTSCColors = b'NTSC'
NeonGlow = b'NGlw'
Next = b'Nxt '
NotePaper = b'NtPr'
Notify = b'Ntfy'
Null = b'null'
OceanRipple = b'OcnR'
Offset = b'Ofst'
Open = b'Opn '
OpenUntitled = b'OpnU'
PaintDaubs = b'PntD'
PaletteKnife = b'PltK'
Paste = b'past'
PasteEffects = b'PaFX'
PasteInto = b'PstI'
PasteOutside = b'PstO'
Patchwork = b'Ptch'
Photocopy = b'Phtc'
Pinch = b'Pnch'
Place = b'Plc '
Plaster = b'Plst'
PlasticWrap = b'PlsW'
Play = b'Ply '
Pointillize = b'Pntl'
Polar = b'Plr '
PosterEdges = b'PstE'
Posterize = b'Pstr'
Previous = b'Prvs'
Print = b'Prnt'
ProfileToProfile = b'PrfT'
Purge = b'Prge'

Paste = b'past' hello?? ๐Ÿ˜ญ the lowercase jumpscare again. slay though, it's consistent, and the vibes are immaculate. last chunk of events, promise ๐Ÿคž

Quit = b'quit'
RadialBlur = b'RdlB'
Rasterize = b'Rstr'
RasterizeTypeSheet = b'RstT'
RemoveBlackMatte = b'RmvB'
RemoveLayerMask = b'RmvL'
RemoveWhiteMatte = b'RmvW'
Rename = b'Rnm '
ReplaceColor = b'RplC'
Reset = b'Rset'
Reticulation = b'Rtcl'
Revert = b'Rvrt'
Ripple = b'Rple'
Rotate = b'Rtte'
RoughPastels = b'RghP'
Save = b'save'
Select = b'slct'
SelectiveColor = b'SlcC'
Set = b'setd'
Sharpen = b'Shrp'
SharpenEdges = b'ShrE'
SharpenMore = b'ShrM'
Shear = b'Shr '
Show = b'Shw '
Similar = b'Smlr'
SmartBlur = b'SmrB'
Smooth = b'Smth'
SmudgeStick = b'SmdS'
Solarize = b'Slrz'
Spatter = b'Spt '
Spherize = b'Sphr'
SplitChannels = b'SplC'
Sponge = b'Spng'
SprayedStrokes = b'SprS'
StainedGlass = b'StnG'
Stamp = b'Stmp'
Stop = b'Stop'
Stroke = b'Strk'
Subtract = b'Sbtr'
SubtractFrom = b'SbtF'
Sumie = b'Smie'
TakeMergedSnapshot = b'TkMr'
TakeSnapshot = b'TkSn'
TextureFill = b'TxtF'
Texturizer = b'Txtz'
Threshold = b'Thrs'
Tiles = b'Tls '
TornEdges = b'TrnE'
TraceContour = b'TrcC'
Transform = b'Trnf'
Trap = b'Trap'
Twirl = b'Twrl'
Underpainting = b'Undr'
Undo = b'undo'
Ungroup = b'Ungr'
Unlink = b'Unlk'
UnsharpMask = b'UnsM'
Variations = b'Vrtn'
Wait = b'Wait'
WaterPaper = b'WtrP'
Watercolor = b'Wtrc'
Wave = b'Wave'
Wind = b'Wnd '
ZigZag = b'ZgZg'
_3DTransform = b'TdT '

there is literally a Wait right before the watercolor girlies, iconic placement, no notes ๐Ÿซถ


๐Ÿฆ‹ class psd_tools.terminology.Form(*values)

Form definitions, also extracted from PITerminology.h. See <https://www.adobe.com/devnet/photoshop/sdk.html> โœจ and this one is SHORT, a little palate cleanser, we love a breather:

Class = b'Clss'
Enumerated = b'Enmr'
Identifier = b'Idnt'
Index = b'indx'
Offset = b'rele'
Property = b'prop'

six entries, six four-char codes, tiny, perfect, ate ๐Ÿ“


๐ŸŒธ class psd_tools.terminology.Key(*values)

Key definitions, yep, another one pulled out of PITerminology.h. See <https://www.adobe.com/devnet/photoshop/sdk.html> โœจ and this list is a big one so we're going in order, no skipping, bestie, here we go:

A = b'A '
Adjustment = b'Adjs'
Aligned = b'Algd'
Alignment = b'Algn'
AllExcept = b'AllE'
AllPS = b'All '
AllToolOptions = b'AlTl'
AlphaChannelOptions = b'AChn'
AlphaChannels = b'AlpC'
AmbientBrightness = b'AmbB'
AmbientColor = b'AmbC'
Amount = b'Amnt'
AmplitudeMax = b'AmMx'
AmplitudeMin = b'AmMn'
Anchor = b'Anch'
Angle = b'Angl'
Angle1 = b'Ang1'
Angle2 = b'Ang2'
Angle3 = b'Ang3'
Angle4 = b'Ang4'
AntiAlias = b'AntA'
Append = b'Appe'
Apply = b'Aply'
Area = b'Ar '
Arrowhead = b'Arrw'
As = b'As '
AssetBin = b'Asst'
AssumedCMYK = b'AssC'
AssumedGray = b'AssG'
AssumedRGB = b'AssR'
At = b'At '
Auto = b'Auto'
AutoContrast = b'AuCo'
AutoErase = b'Atrs'
AutoKern = b'AtKr'
AutoUpdate = b'AtUp'
Axis = b'Axis'
B = b'B '
Background = b'Bckg'
BackgroundColor = b'BckC'
BackgroundLevel = b'BckL'

okay and A = b'A ' is sending me โ€” a single letter, with a trailing space, just vibing at the top of the list like the main character ๐Ÿ’€ Angle1 through Angle4 doing the whole quartet though, we respect the commitment ๐Ÿ‘‘

and there is so much more where that came from, so don't you dare close the terminal, we are not done here, hold the phone, keep scrolling ๐Ÿ“ฑโœจ

okay so we're deep in the byte-code tag list now โ€” these are the exact names and their literal codes, so copy them character for character, bestie. the spaces inside the quotes? totally real. don't trim them, that's the whole vibe ๐Ÿ’…โœจ

  • Backward โ€” b'Bwd ' ๐Ÿ’–
  • Balance โ€” b'Blnc' โœจ
  • BaselineShift โ€” b'Bsln' ๐ŸŽ€
  • BeepWhenDone โ€” b'BpWh' ๐Ÿฆ‹
  • BeginRamp โ€” b'BgnR' ๐ŸŒธ
  • BeginSustain โ€” b'BgnS' ๐Ÿ’…
  • BevelDirection โ€” b'bvlD' ๐Ÿซถ
  • BevelEmboss โ€” b'ebbl' ๐Ÿ˜ญ
  • BevelStyle โ€” b'bvlS' ๐Ÿ”ฅ
  • BevelTechnique โ€” b'bvlT' ๐Ÿ‘‘
  • BigNudgeH โ€” b'BgNH' ๐ŸŒˆ
  • BigNudgeV โ€” b'BgNV' โญ
  • BitDepth โ€” b'BtDp' ๐Ÿ’€
  • Black โ€” b'Blck' ๐Ÿ™ˆ
  • BlackClip โ€” b'BlcC' ๐Ÿ“
  • BlackGeneration โ€” b'Blcn' ๐Ÿงš
  • BlackGenerationCurve โ€” b'BlcG' ๐Ÿ’œ
  • BlackIntensity โ€” b'BlcI' ๐Ÿ’–
  • BlackLevel โ€” b'BlcL' โœจ
  • BlackLimit โ€” b'BlcL' ๐ŸŽ€
  • Bleed โ€” b'Bld ' ๐Ÿฆ‹
  • BlendRange โ€” b'Blnd' ๐ŸŒธ
  • Blue โ€” b'Bl ' ๐Ÿ’…
  • BlueBlackPoint โ€” b'BlBl' ๐Ÿซถ
  • BlueFloat โ€” b'blueFloat' ๐Ÿ˜ญ
  • BlueGamma โ€” b'BlGm' ๐Ÿ”ฅ
  • BlueWhitePoint โ€” b'BlWh' ๐Ÿ‘‘
  • BlueX โ€” b'BlX ' ๐ŸŒˆ
  • BlueY โ€” b'BlY ' โญ
  • Blur โ€” b'blur' ๐Ÿ’€
  • BlurMethod โ€” b'BlrM' ๐Ÿ™ˆ
  • BlurQuality โ€” b'BlrQ' ๐Ÿ“
  • Book โ€” b'Bk ' ๐Ÿงš
  • BorderThickness โ€” b'BrdT' ๐Ÿ’œ
  • Bottom โ€” b'Btom' ๐Ÿ’–
  • Brightness โ€” b'Brgh' โœจ
  • BrushDetail โ€” b'BrsD' ๐ŸŽ€
  • BrushSize โ€” b'BrsS' ๐Ÿฆ‹
  • BrushType โ€” b'BrsT' ๐ŸŒธ
  • Brushes โ€” b'Brsh' ๐Ÿ’…
  • BumpAmplitude โ€” b'BmpA' ๐Ÿซถ
  • BumpChannel โ€” b'BmpC' ๐Ÿ˜ญ
  • By โ€” b'By ' ๐Ÿ”ฅ
  • Byline โ€” b'Byln' ๐Ÿ‘‘
  • BylineTitle โ€” b'BylT' ๐ŸŒˆ
  • ByteOrder โ€” b'BytO' โญ
  • CMYKSetup โ€” b'CMYS' ๐Ÿ’€
  • CachePrefs โ€” b'CchP' ๐Ÿ™ˆ
  • Calculation โ€” b'Clcl' ๐Ÿ“
  • CalibrationBars โ€” b'Clbr' ๐Ÿงš
  • Caption โ€” b'Cptn' ๐Ÿ’œ
  • CaptionWriter โ€” b'CptW' ๐Ÿ’–
  • Category โ€” b'Ctgr' โœจ
  • CellSize โ€” b'ClSz' ๐ŸŽ€
  • Center โ€” b'Cntr' ๐Ÿฆ‹
  • CenterCropMarks โ€” b'CntC' ๐ŸŒธ
  • ChalkArea โ€” b'ChlA' ๐Ÿ’…
  • Channel โ€” b'Chnl' ๐Ÿซถ
  • ChannelMatrix โ€” b'ChMx' ๐Ÿ˜ญ
  • ChannelName โ€” b'ChnN' ๐Ÿ”ฅ
  • Channels โ€” b'Chns' ๐Ÿ‘‘
  • ChannelsInterleaved โ€” b'ChnI' ๐ŸŒˆ
  • CharcoalAmount โ€” b'ChAm' โญ
  • CharcoalArea โ€” b'ChrA' ๐Ÿ’€
  • ChokeMatte โ€” b'Ckmt' ๐Ÿ™ˆ
  • ChromeFX โ€” b'ChFX' ๐Ÿ“
  • City โ€” b'City' ๐Ÿงš
  • ClearAmount โ€” b'ClrA' ๐Ÿ’œ
  • ClippingPath โ€” b'ClPt' ๐Ÿ’–
  • ClippingPathEPS โ€” b'ClpP' โœจ
  • ClippingPathFlatness โ€” b'ClpF' ๐ŸŽ€
  • ClippingPathIndex โ€” b'ClpI' ๐Ÿฆ‹
  • ClippingPathInfo โ€” b'Clpg' ๐ŸŒธ
  • CloneSource โ€” b'ClnS' ๐Ÿ’…
  • ClosedSubpath โ€” b'Clsp' ๐Ÿซถ
  • Color โ€” b'Clr ' ๐Ÿ˜ญ
  • ColorChannels โ€” b'Clrh' ๐Ÿ”ฅ
  • ColorCorrection โ€” b'ClrC' ๐Ÿ‘‘
  • ColorIndicates โ€” b'ClrI' ๐ŸŒˆ
  • ColorManagement โ€” b'ClMg' โญ
  • ColorPickerPrefs โ€” b'Clrr' ๐Ÿ’€
  • ColorSpace โ€” b'ClrS' ๐Ÿ™ˆ
  • ColorTable โ€” b'ClrT' ๐Ÿ“
  • Colorize โ€” b'Clrz' ๐Ÿงš
  • Colors โ€” b'Clrs' ๐Ÿ’œ
  • ColorsList โ€” b'ClrL' ๐Ÿ’–
  • ColumnWidth โ€” b'ClmW' โœจ
  • CommandKey โ€” b'CmdK' ๐ŸŽ€
  • Compensation โ€” b'Cmpn' ๐Ÿฆ‹
  • Compression โ€” b'Cmpr' ๐ŸŒธ
  • Concavity โ€” b'Cncv' ๐Ÿ’…
  • Condition โ€” b'Cndt' ๐Ÿซถ
  • Constant โ€” b'Cnst' ๐Ÿ˜ญ
  • Constrain โ€” b'Cnst' ๐Ÿ”ฅ
  • ConstrainProportions โ€” b'CnsP' ๐Ÿ‘‘
  • ConstructionFOV โ€” b'Cfov' ๐ŸŒˆ
  • Contiguous โ€” b'Cntg' โญ
  • Continue โ€” b'Cntn' ๐Ÿ’€
  • Continuity โ€” b'Cnty' ๐Ÿ™ˆ
  • ContourType โ€” b'ShpC' ๐Ÿ“
  • Contrast โ€” b'Cntr' ๐Ÿงš
  • Convert โ€” b'Cnvr' ๐Ÿ’œ
  • Copy โ€” b'Cpy ' ๐Ÿ’–
  • Copyright โ€” b'Cpyr' โœจ
  • CopyrightNotice โ€” b'CprN' ๐ŸŽ€
  • CornerCropMarks โ€” b'CrnC' ๐Ÿฆ‹
  • Count โ€” b'Cnt ' ๐ŸŒธ
  • CountryName โ€” b'CntN' ๐Ÿ’…
  • CrackBrightness โ€” b'CrcB' ๐Ÿซถ
  • CrackDepth โ€” b'CrcD' ๐Ÿ˜ญ
  • CrackSpacing โ€” b'CrcS' ๐Ÿ”ฅ
  • CreateLayersFromLayerFX โ€” b'blfl' ๐Ÿ‘‘
  • Credit โ€” b'Crdt' ๐ŸŒˆ
  • Crossover โ€” b'Crss' โญ
  • Current โ€” b'Crnt' ๐Ÿ’€
  • CurrentHistoryState โ€” b'CrnH' ๐Ÿ™ˆ
  • CurrentLight โ€” b'CrnL' ๐Ÿ“
  • CurrentToolOptions โ€” b'CrnT' ๐Ÿงš
  • Curve โ€” b'Crv ' ๐Ÿ’œ
  • CurveFile โ€” b'CrvF' ๐Ÿ’–
  • Custom โ€” b'Cstm' โœจ
  • CustomForced โ€” b'CstF' ๐ŸŽ€
  • CustomMatte โ€” b'CstM' ๐Ÿฆ‹
  • CustomPalette โ€” b'CstP' ๐ŸŒธ
  • Cyan โ€” b'Cyn ' ๐Ÿ’…
  • DCS โ€” b'DCS ' ๐Ÿซถ
  • DPXFormat โ€” b'DPXf' ๐Ÿ˜ญ
  • DarkIntensity โ€” b'DrkI' ๐Ÿ”ฅ
  • Darkness โ€” b'Drkn' ๐Ÿ‘‘
  • DateCreated โ€” b'DtCr' ๐ŸŒˆ
  • Datum โ€” b'Dt ' โญ
  • Definition โ€” b'Dfnt' ๐Ÿ’€
  • Density โ€” b'Dnst' ๐Ÿ™ˆ
  • Depth โ€” b'Dpth' ๐Ÿ“
  • DestBlackMax โ€” b'Dstl' ๐Ÿงš
  • DestBlackMin โ€” b'DstB' ๐Ÿ’œ
  • DestWhiteMax โ€” b'Dstt' ๐Ÿ’–
  • DestWhiteMin โ€” b'DstW' โœจ
  • DestinationMode โ€” b'DstM' ๐ŸŽ€
  • Detail โ€” b'Dtl ' ๐Ÿฆ‹
  • Diameter โ€” b'Dmtr' ๐ŸŒธ
  • DiffusionDither โ€” b'DffD' ๐Ÿ’…
  • Direction โ€” b'Drct' ๐Ÿซถ
  • DirectionBalance โ€” b'DrcB' ๐Ÿ˜ญ
  • DisplaceFile โ€” b'DspF' ๐Ÿ”ฅ
  • DisplacementMap โ€” b'DspM' ๐Ÿ‘‘
  • DisplayPrefs โ€” b'DspP' ๐ŸŒˆ
  • Distance โ€” b'Dstn' โญ
  • Distortion โ€” b'Dstr' ๐Ÿ’€
  • Distribution โ€” b'Dstr' ๐Ÿ™ˆ
  • Dither โ€” b'Dthr' ๐Ÿ“
  • DitherAmount โ€” b'DthA' ๐Ÿงš
  • DitherPreserve โ€” b'Dthp' ๐Ÿ’œ
  • DitherQuality โ€” b'Dthq' ๐Ÿ’–
  • DocumentID โ€” b'DocI' โœจ
  • DotGain โ€” b'DtGn' ๐ŸŽ€
  • DotGainCurves โ€” b'DtGC' ๐Ÿฆ‹
  • DropShadow โ€” b'DrSh' ๐ŸŒธ
  • Duplicate โ€” b'Dplc' ๐Ÿ’…
  • DynamicColorSliders โ€” b'DnmC' ๐Ÿซถ
  • Edge โ€” b'Edg ' ๐Ÿ˜ญ
  • EdgeBrightness โ€” b'EdgB' ๐Ÿ”ฅ
  • EdgeFidelity โ€” b'EdgF' ๐Ÿ‘‘
  • EdgeIntensity โ€” b'EdgI' ๐ŸŒˆ
  • EdgeSimplicity โ€” b'EdgS' โญ
  • EdgeThickness โ€” b'EdgT' ๐Ÿ’€
  • EdgeWidth โ€” b'EdgW' ๐Ÿ™ˆ
  • Effect โ€” b'Effc' ๐Ÿ“
  • EmbedCMYK โ€” b'EmbC' ๐Ÿงš
  • EmbedGray โ€” b'EmbG' ๐Ÿ’œ
  • EmbedLab โ€” b'EmbL' ๐Ÿ’–
  • EmbedProfiles โ€” b'EmbP' โœจ
  • EmbedRGB โ€” b'EmbR' ๐ŸŽ€
  • EmulsionDown โ€” b'EmlD' ๐Ÿฆ‹
  • EnableGestures โ€” b'EGst' ๐ŸŒธ
  • Enabled โ€” b'enab' ๐Ÿ’…
  • Encoding โ€” b'Encd' ๐Ÿซถ
  • End โ€” b'End ' ๐Ÿ˜ญ
  • EndArrowhead โ€” b'EndA' ๐Ÿ”ฅ
  • EndRamp โ€” b'EndR' ๐Ÿ‘‘
  • EndSustain โ€” b'EndS' ๐ŸŒˆ
  • Engine โ€” b'Engn' โญ
  • EraseToHistory โ€” b'ErsT' ๐Ÿ’€
  • EraserKind โ€” b'ErsK' ๐Ÿ™ˆ
  • ExactPoints โ€” b'ExcP' ๐Ÿ“
  • Export โ€” b'Expr' ๐Ÿงš
  • ExportClipboard โ€” b'ExpC' ๐Ÿ’œ
  • Exposure โ€” b'Exps' ๐Ÿ’–
  • Extend โ€” b'Extd' โœจ
  • ExtendedQuality โ€” b'EQlt' ๐ŸŽ€
  • Extension โ€” b'Extn' ๐Ÿฆ‹
  • ExtensionsQuery โ€” b'ExtQ' ๐ŸŒธ
  • ExtrudeDepth โ€” b'ExtD' ๐Ÿ’…
  • ExtrudeMaskIncomplete โ€” b'ExtM' ๐Ÿซถ
  • ExtrudeRandom โ€” b'ExtR' ๐Ÿ˜ญ
  • ExtrudeSize โ€” b'ExtS' ๐Ÿ”ฅ
  • ExtrudeSolidFace โ€” b'ExtF' ๐Ÿ‘‘
  • ExtrudeType โ€” b'ExtT' ๐ŸŒˆ
  • EyeDropperSample โ€” b'EyDr' โญ
  • FPXCompress โ€” b'FxCm' ๐Ÿ’€
  • FPXQuality โ€” b'FxQl' ๐Ÿ™ˆ
  • FPXSize โ€” b'FxSz' ๐Ÿ“
  • FPXView โ€” b'FxVw' ๐Ÿงš
  • FadeTo โ€” b'FdT ' ๐Ÿ’œ
  • FadeoutSteps โ€” b'FdtS' ๐Ÿ’–
  • Falloff โ€” b'FlOf' โœจ
  • Feather โ€” b'Fthr' ๐ŸŽ€
  • FiberLength โ€” b'FbrL' ๐Ÿฆ‹
  • File โ€” b'File' ๐ŸŒธ
  • FileCreator โ€” b'FlCr' ๐Ÿ’…
  • FileInfo โ€” b'FlIn' ๐Ÿซถ
  • FileReference โ€” b'FilR' ๐Ÿ˜ญ
  • FileSavePrefs โ€” b'FlSP' ๐Ÿ”ฅ
  • FileType โ€” b'FlTy' ๐Ÿ‘‘
  • FilesList โ€” b'flst' ๐ŸŒˆ
  • Fill โ€” b'Fl ' โญ
  • FillColor โ€” b'FlCl' ๐Ÿ’€
  • FillNeutral โ€” b'FlNt' ๐Ÿ™ˆ
  • FilterLayerPersistentData โ€” b'FlPd' ๐Ÿ“
  • FilterLayerRandomSeed โ€” b'FlRs' ๐Ÿงš
  • Fingerpainting โ€” b'Fngr' ๐Ÿ’œ
  • FlareCenter โ€” b'FlrC' ๐Ÿ’–
  • Flatness โ€” b'Fltn' โœจ
  • Flatten โ€” b'Fltt' ๐ŸŽ€
  • FlipVertical โ€” b'FlpV' ๐Ÿฆ‹
  • Focus โ€” b'Fcs ' ๐ŸŒธ
  • Folders โ€” b'Fldr' ๐Ÿ’…
  • FontDesignAxes โ€” b'FntD' ๐Ÿซถ
  • FontDesignAxesVectors โ€” b'FntV' ๐Ÿ˜ญ
  • FontName โ€” b'FntN' ๐Ÿ”ฅ
  • FontScript โ€” b'Scrp' ๐Ÿ‘‘
  • FontStyleName โ€” b'FntS' ๐ŸŒˆ
  • FontTechnology โ€” b'FntT' โญ
  • ForcedColors โ€” b'FrcC' ๐Ÿ’€
  • ForegroundColor โ€” b'FrgC' ๐Ÿ™ˆ
  • ForegroundLevel โ€” b'FrgL' ๐Ÿ“
  • Format โ€” b'Fmt ' ๐Ÿงš
  • Forward โ€” b'Fwd ' ๐Ÿ’œ
  • FrameFX โ€” b'FrFX' ๐Ÿ’–
  • FrameWidth โ€” b'FrmW' โœจ
  • FreeTransformCenterState โ€” b'FTcs' ๐ŸŽ€
  • Frequency โ€” b'Frqn' ๐Ÿฆ‹
  • From โ€” b'From' ๐ŸŒธ
  • FromBuiltin โ€” b'FrmB' ๐Ÿ’…
  • FromMode โ€” b'FrmM' ๐Ÿซถ
  • FunctionKey โ€” b'FncK' ๐Ÿ˜ญ
  • Fuzziness โ€” b'Fzns' ๐Ÿ”ฅ
  • GCR โ€” b'GCR ' ๐Ÿ‘‘
  • GIFColorFileType โ€” b'GFPT' ๐ŸŒˆ
  • GIFColorLimit โ€” b'GFCL' โญ
  • GIFExportCaption โ€” b'GFEC' ๐Ÿ’€
  • GIFMaskChannelIndex โ€” b'GFMI' ๐Ÿ™ˆ
  • GIFMaskChannelInverted โ€” b'GFMV' ๐Ÿ“
  • GIFPaletteFile โ€” b'GFPF' ๐Ÿงš
  • GIFPaletteType โ€” b'GFPL' ๐Ÿ’œ
  • GIFRequiredColorSpaceType โ€” b'GFCS' ๐Ÿ’–
  • GIFRowOrderType โ€” b'GFIT' โœจ
  • GIFTransparentColor โ€” b'GFTC' ๐ŸŽ€
  • GIFTransparentIndexBlue โ€” b'GFTB' ๐Ÿฆ‹
  • GIFTransparentIndexGreen โ€” b'GFTG' ๐ŸŒธ
  • GIFTransparentIndexRed โ€” b'GFTR' ๐Ÿ’…
  • GIFUseBestMatch โ€” b'GFBM' ๐Ÿซถ
  • Gamma โ€” b'Gmm ' ๐Ÿ˜ญ
  • GamutWarning โ€” b'GmtW' ๐Ÿ”ฅ
  • GeneralPrefs โ€” b'GnrP' ๐Ÿ‘‘
  • GlobalAngle โ€” b'gblA' ๐ŸŒˆ
  • GlobalLightingAngle โ€” b'gagl' โญ
  • Gloss โ€” b'Glos' ๐Ÿ’€
  • GlowAmount โ€” b'GlwA' ๐Ÿ™ˆ
  • GlowTechnique โ€” b'GlwT' ๐Ÿ“
  • Gradient โ€” b'Grad' ๐Ÿงš
  • GradientFill โ€” b'Grdf' ๐Ÿ’œ
  • Grain โ€” b'Grn ' ๐Ÿ’–
  • GrainType โ€” b'Grnt' โœจ
  • Graininess โ€” b'Grns' ๐ŸŽ€
  • Gray โ€” b'Gry ' ๐Ÿฆ‹
  • GrayBehavior โ€” b'GrBh' ๐ŸŒธ
  • GraySetup โ€” b'GrSt' ๐Ÿ’…
  • Green โ€” b'Grn ' ๐Ÿซถ
  • GreenBlackPoint โ€” b'GrnB' ๐Ÿ˜ญ
  • GreenFloat โ€” b'greenFloat' ๐Ÿ”ฅ
  • GreenGamma โ€” b'GrnG' ๐Ÿ‘‘
  • GreenWhitePoint โ€” b'GrnW' ๐ŸŒˆ
  • GreenX โ€” b'GrnX' โญ
  • GreenY โ€” b'GrnY' ๐Ÿ’€
  • GridColor โ€” b'GrdC' ๐Ÿ™ˆ
  • GridCustomColor โ€” b'Grds' ๐Ÿ“
  • GridMajor โ€” b'GrdM' ๐Ÿงš
  • GridMinor โ€” b'Grdn' ๐Ÿ’œ
  • GridStyle โ€” b'GrdS' ๐Ÿ’–
  • GridUnits โ€” b'Grdt' โœจ
  • Group โ€” b'Grup' ๐ŸŽ€
  • GroutWidth โ€” b'GrtW' ๐Ÿฆ‹
  • GrowSelection โ€” b'GrwS' ๐ŸŒธ
  • Guides โ€” b'Gdes' ๐Ÿ’…
  • GuidesColor โ€” b'GdsC' ๐Ÿซถ
  • GuidesCustomColor โ€” b'Gdss' ๐Ÿ˜ญ
  • GuidesPrefs โ€” b'GdPr' ๐Ÿ”ฅ
  • GuidesStyle โ€” b'GdsS' ๐Ÿ‘‘
  • GutterWidth โ€” b'GttW' ๐ŸŒˆ
  • HalftoneFile โ€” b'HlfF' โญ
  • HalftoneScreen โ€” b'HlfS' ๐Ÿ’€
  • HalftoneSize โ€” b'HlSz' ๐Ÿ™ˆ
  • HalftoneSpec โ€” b'Hlfp' ๐Ÿ“
  • Hardness โ€” b'Hrdn' ๐Ÿงš
  • HasCmdHPreference โ€” b'HCdH' ๐Ÿ’œ
  • Header โ€” b'Hdr ' ๐Ÿ’–
  • Headline โ€” b'Hdln' โœจ
  • Height โ€” b'Hght' ๐ŸŽ€
  • HighlightArea โ€” b'HghA' ๐Ÿฆ‹
  • HighlightColor โ€” b'hglC' ๐ŸŒธ
  • HighlightLevels โ€” b'HghL' ๐Ÿ’…
  • HighlightMode โ€” b'hglM' ๐Ÿซถ
  • HighlightOpacity โ€” b'hglO' ๐Ÿ˜ญ
  • HighlightStrength โ€” b'HghS' ๐Ÿ”ฅ
  • HistoryBrushSource โ€” b'HstB' ๐Ÿ‘‘
  • HistoryPrefs โ€” b'HstP' ๐ŸŒˆ
  • HistoryStateSource โ€” b'HsSS' โญ
  • HistoryStates โ€” b'HsSt' ๐Ÿ’€
  • Horizontal โ€” b'Hrzn' ๐Ÿ™ˆ
  • HorizontalScale โ€” b'HrzS' ๐Ÿ“
  • HostName โ€” b'HstN' ๐Ÿงš
  • HostVersion โ€” b'HstV' ๐Ÿ’œ
  • Hue โ€” b'H ' ๐Ÿ’–

and we're still in the key-name dictionary, bestie, so here's every single remaining Name = b'Value' pairing โ€” spaces and all, no cap ๐Ÿ’–

  • ICCEngine = b'ICCE'
  • ICCSetupName = b'ICCt'
  • ID = b'Idnt'
  • Idle = b'Idle'
  • ImageBalance = b'ImgB'
  • Import = b'Impr'
  • Impressionist = b'Imps'
  • In = b'In '
  • Inherits = b'c@#^'
  • InkColors = b'InkC'
  • Inks = b'Inks'
  • InnerGlow = b'IrGl'
  • InnerGlowSource = b'glwS'
  • InnerShadow = b'IrSh'
  • Input = b'Inpt'
  • InputBlackPoint = b'kIBP'
  • InputMapRange = b'Inmr'
  • InputRange = b'Inpr'
  • InputWhitePoint = b'kIWP'
  • Intensity = b'Intn'
  • Intent = b'Inte'
  • InterfaceBevelHighlight = b'IntH'
  • InterfaceBevelShadow = b'Intv'
  • InterfaceBlack = b'IntB'
  • InterfaceBorder = b'Intd'
  • InterfaceButtonDarkShadow = b'Intk'
  • InterfaceButtonDownFill = b'Intt'
  • InterfaceButtonUpFill = b'InBF'
  • InterfaceColorBlue2 = b'ICBL'
  • InterfaceColorBlue32 = b'ICBH'
  • InterfaceColorGreen2 = b'ICGL'
  • InterfaceColorGreen32 = b'ICGH'
  • InterfaceColorRed2 = b'ICRL'
  • InterfaceColorRed32 = b'ICRH'
  • InterfaceIconFillActive = b'IntI'
  • InterfaceIconFillDimmed = b'IntF'
  • InterfaceIconFillSelected = b'Intc'
  • InterfaceIconFrameActive = b'Intm'
  • InterfaceIconFrameDimmed = b'Intr'
  • InterfaceIconFrameSelected = b'IntS'
  • InterfacePaletteFill = b'IntP'
  • InterfaceRed = b'IntR'
  • InterfaceToolTipBackground = b'IntT'
  • InterfaceToolTipText = b'ITTT'
  • InterfaceTransparencyBackground = b'ITBg'
  • InterfaceTransparencyForeground = b'ITFg'
  • InterfaceWhite = b'IntW'
  • Interlace = b'Intr'
  • InterlaceCreateType = b'IntC'
  • InterlaceEliminateType = b'IntE'
  • Interpolation = b'Intr'
  • InterpolationMethod = b'IntM'
  • Invert = b'Invr'
  • InvertMask = b'InvM'
  • InvertSource2 = b'InvS'
  • InvertTexture = b'InvT'
  • IsDirty = b'IsDr'
  • ItemIndex = b'ItmI'
  • JPEGQuality = b'JPEQ'
  • Kerning = b'Krng'
  • Keywords = b'Kywd'
  • Kind = b'Knd '
  • LUTAnimation = b'LTnm'
  • LZWCompression = b'LZWC'
  • Labels = b'Lbls'
  • Landscape = b'Lnds'
  • LastTransform = b'LstT'
  • Layer = b'Lyr '
  • LayerEffects = b'Lefx'
  • LayerFXVisible = b'lfxv'
  • LayerID = b'LyrI'
  • LayerName = b'LyrN'
  • Layers = b'Lyrs'
  • Leading = b'Ldng'
  • Left = b'Left'
  • LegacySerialString = b'lSNs'
  • Length = b'Lngt'
  • Lens = b'Lns '
  • Level = b'Lvl '
  • Levels = b'Lvls'
  • LightDark = b'LgDr'
  • LightDirection = b'LghD'
  • LightIntensity = b'LghI'
  • LightPosition = b'LghP'
  • LightSource = b'LghS'
  • LightType = b'LghT'
  • LightenGrout = b'LghG'
  • Lightness = b'Lght'
  • Line = b'Line'
  • LinkEnable = b'lnkE'
  • LinkedLayerIDs = b'LnkL'
  • LocalLightingAltitude = b'Lald'
  • LocalLightingAngle = b'lagl'
  • LocalRange = b'LclR'
  • Location = b'Lctn'
  • Log = b'Log '
  • Logarithmic = b'kLog'
  • LowerCase = b'LwCs'
  • Luminance = b'Lmnc'
  • Magenta = b'Mgnt'
  • MakeVisible = b'MkVs'
  • ManipulationFOV = b'Mfov'
  • MapBlack = b'MpBl'
  • Mapping = b'Mpng'
  • MappingShape = b'MpgS'
  • Material = b'Mtrl'
  • Matrix = b'Mtrx'
  • MatteColor = b'MttC'
  • Maximum = b'Mxm '
  • MaximumStates = b'MxmS'
  • MemoryUsagePercent = b'MmrU'
  • Merge = b'Mrge'
  • Merged = b'Mrgd'
  • Message = b'Msge'
  • Method = b'Mthd'
  • MezzotintType = b'MztT'
  • Midpoint = b'Mdpn'
  • MidtoneLevels = b'MdtL'
  • Minimum = b'Mnm '
  • MismatchCMYK = b'MsmC'
  • MismatchGray = b'MsmG'
  • MismatchRGB = b'MsmR'
  • Mode = b'Md '
  • Monochromatic = b'Mnch'
  • MoveTo = b'MvT '
  • Name = b'Nm '
  • Negative = b'Ngtv'
  • New = b'Nw '
  • Noise = b'Nose'
  • NonImageData = b'NnIm'
  • NonLinear = b'NnLn'
  • Null = b'null'
  • NumLights = b'Nm L'
  • Number = b'Nmbr'
  • NumberOfCacheLevels = b'NCch'
  • NumberOfCacheLevels64 = b'NC64'
  • NumberOfChannels = b'NmbO'
  • NumberOfChildren = b'NmbC'
  • NumberOfDocuments = b'NmbD'
  • NumberOfGenerators = b'NmbG'
  • NumberOfLayers = b'NmbL'
  • NumberOfLevels = b'NmbL'
  • NumberOfPaths = b'NmbP'
  • NumberOfRipples = b'NmbR'
  • NumberOfSiblings = b'NmbS'
  • ObjectName = b'ObjN'
  • Offset = b'Ofst'
  • OldSmallFontType = b'Sftt'
  • On = b'On '
  • Opacity = b'Opct'
  • Optimized = b'Optm'
  • Orientation = b'Ornt'
  • OriginalHeader = b'OrgH'
  • OriginalTransmissionReference = b'OrgT'
  • OtherCursors = b'OthC'
  • OuterGlow = b'OrGl'
  • Output = b'Otpt'
  • OutputBlackPoint = b'kOBP'
  • OutputWhitePoint = b'kOWP'
  • OverprintColors = b'OvrC'
  • OverrideOpen = b'OvrO'
  • OverridePrinter = b'ObrP'
  • OverrideSave = b'Ovrd'
  • PNGFilter = b'PNGf'
  • PNGInterlaceType = b'PGIT'
  • PageFormat = b'PMpf'
  • PageNumber = b'PgNm'
  • PagePosition = b'PgPs'
  • PageSetup = b'PgSt'
  • PaintCursorKind = b'PnCK'
  • PaintType = b'PntT'
  • PaintingCursors = b'PntC'
  • Palette = b'Plt '
  • PaletteFile = b'PltF'
  • PaperBrightness = b'PprB'
  • ParentIndex = b'PrIn'
  • ParentName = b'PrNm'
  • Path = b'Path'
  • PathContents = b'PthC'
  • PathName = b'PthN'
  • Pattern = b'Pttn'
  • PencilWidth = b'Pncl'
  • PerspectiveIndex = b'Prsp'
  • Phosphors = b'Phsp'
  • PickerID = b'PckI'
  • PickerKind = b'Pckr'
  • PixelPaintSize = b'PPSz'
  • Platform = b'Pltf'
  • PluginFolder = b'PlgF'
  • PluginPrefs = b'PlgP'
  • Points = b'Pts '
  • Position = b'Pstn'
  • PostScriptColor = b'PstS'
  • Posterization = b'Pstr'
  • PredefinedColors = b'PrdC'
  • PreferBuiltin = b'PrfB'
  • Preferences = b'Prfr'
  • PreserveAdditional = b'PrsA'
  • PreserveLuminosity = b'PrsL'
  • PreserveTransparency = b'PrsT'
  • Pressure = b'Prs '
  • Preview = b'Prvw'
  • PreviewCMYK = b'PrvK'
  • PreviewFullSize = b'PrvF'
  • PreviewIcon = b'PrvI'
  • PreviewMacThumbnail = b'PrvM'
  • PreviewWinThumbnail = b'PrvW'
  • PreviewsQuery = b'PrvQ'
  • PrintSettings = b'PMps'
  • ProfileSetup = b'PrfS'
  • ProvinceState = b'PrvS'
  • Quality = b'Qlty'
  • QuickMask = b'QucM'
  • RGBSetup = b'RGBS'
  • Radius = b'Rds '
  • RandomSeed = b'RndS'
  • Ratio = b'Rt '
  • RecentFiles = b'Rcnf'
  • Red = b'Rd '
  • RedBlackPoint = b'RdBl'
  • RedFloat = b'redFloat'
  • RedGamma = b'RdGm'
  • RedWhitePoint = b'RdWh'
  • RedX = b'RdX '
  • RedY = b'RdY '
  • RegistrationMarks = b'RgsM'
  • Relative = b'Rltv'
  • Relief = b'Rlf '
  • RenderFidelity = b'Rfid'
  • Resample = b'Rsmp'
  • ResizeWindowsOnZoom = b'RWOZ'
  • Resolution = b'Rslt'
  • ResourceID = b'RsrI'
  • Response = b'Rspn'
  • RetainHeader = b'RtnH'
  • Reverse = b'Rvrs'
  • Right = b'Rght'
  • RippleMagnitude = b'RplM'
  • RippleSize = b'RplS'
  • Rotate = b'Rtt '
  • Roundness = b'Rndn'
  • RulerOriginH = b'RlrH'
  • RulerOriginV = b'RlrV'
  • RulerUnits = b'RlrU'
  • Saturation = b'Strt'
  • SaveAndClose = b'SvAn'
  • SaveComposite = b'SvCm'
  • SavePaletteLocations = b'PltL'
  • SavePaths = b'SvPt'
  • SavePyramids = b'SvPy'
  • Saving = b'Svng'
  • Scale = b'Scl '
  • ScaleHorizontal = b'SclH'
  • ScaleVertical = b'SclV'
  • Scaling = b'Scln'
  • Scans = b'Scns'
  • ScratchDisks = b'ScrD'
  • ScreenFile = b'ScrF'
  • ScreenType = b'ScrT'
  • Separations = b'Sprt'
  • SerialString = b'SrlS'
  • ShadingIntensity = b'ShdI'
  • ShadingNoise = b'ShdN'
  • ShadingShape = b'ShdS'
  • ShadowColor = b'sdwC'
  • ShadowIntensity = b'ShdI'
  • ShadowLevels = b'ShdL'
  • ShadowMode = b'sdwM'
  • ShadowOpacity = b'sdwO'
  • Shape = b'Shp '
  • Sharpness = b'Shrp'
  • ShearEd = b'ShrE'
  • ShearPoints = b'ShrP'
  • ShearSt = b'ShrS'
  • ShiftKey = b'ShfK'
  • ShiftKeyToolSwitch = b'ShKT'
  • ShortNames = b'ShrN'
  • ShowEnglishFontNames = b'ShwE'
  • ShowMenuColors = b'SwMC'
  • ShowToolTips = b'ShwT'
  • ShowTransparency = b'ShTr'
  • SizeKey = b'Sz '
  • Skew = b'Skew'
  • SmallFontType = b'Sfts'
  • SmartBlurMode = b'SmBM'
  • SmartBlurQuality = b'SmBQ'
  • Smooth = b'Smoo'
  • Smoothness = b'Smth'
  • SnapshotInitial = b'SnpI'
  • SoftClip = b'SfCl'
  • Softness = b'Sftn'
  • SolidFill = b'SoFi'
  • Source = b'Srce'
  • Source2 = b'Src2'
  • SourceMode = b'SrcM'
  • Spacing = b'Spcn'
  • SpecialInstructions = b'SpcI'
  • SpherizeMode = b'SphM'
  • Spot = b'Spot'
  • SprayRadius = b'SprR'
  • SquareSize = b'SqrS'
  • SrcBlackMax = b'Srcl'
  • SrcBlackMin = b'SrcB'
  • SrcWhiteMax = b'Srcm'
  • SrcWhiteMin = b'SrcW'
  • Start = b'Strt'
  • StartArrowhead = b'StrA'
  • State = b'Stte'
  • Strength = b'srgh'
  • StrengthRatio = b'srgR'
  • Strength_PLUGIN = b'Strg'
  • StrokeDetail = b'StDt'
  • StrokeDirection = b'SDir'
  • StrokeLength = b'StrL'
  • StrokePressure = b'StrP'
  • StrokeSize = b'StrS'
  • StrokeWidth = b'StrW'
  • Style = b'Styl'
  • Styles = b'Stys'
  • StylusIsColor = b'StlC'

okay so we are still inside this table and you are doing SO good, bestie ๐Ÿซถ nothing changes here โ€” same format, same bytes, same vibe, no edits. the home stretch of this one goes:

StylusIsOpacity = b'StlO'
StylusIsPressure = b'StlP'
StylusIsSize = b'StlS'
SubPathList = b'SbpL'
SupplementalCategories = b'SplC'
SystemInfo = b'SstI'
SystemPalette = b'SstP'

and then the T's arrive and they simply do not stop ๐Ÿ˜ญ stay with me:

Target = b'null'
TargetPath = b'Trgp'
TargetPathIndex = b'TrgP'
TermLength = b'Lngt'
Text = b'Txt '
TextClickPoint = b'TxtC'
TextData = b'TxtD'
TextStyle = b'TxtS'
TextStyleRange = b'Txtt'
Texture = b'Txtr'
TextureCoverage = b'TxtC'
TextureFile = b'TxtF'
TextureType = b'TxtT'
Threshold = b'Thsh'
TileNumber = b'TlNm'
TileOffset = b'TlOf'
TileSize = b'TlSz'
Title = b'Ttl '
To = b'T '
ToBuiltin = b'TBl '
ToLinked = b'ToLk'
ToMode = b'TMd '
ToggleOthers = b'TglO'
Tolerance = b'Tlrn'
Top = b'Top '
TotalLimit = b'TtlL'
Tracking = b'Trck'
TransferFunction = b'TrnF'
TransferSpec = b'TrnS'
Transparency = b'Trns'
TransparencyGrid = b'TrnG'
TransparencyGridColors = b'TrnC'
TransparencyGridSize = b'TrnG'
TransparencyPrefs = b'TrnP'
TransparencyShape = b'TrnS'
TransparentIndex = b'TrnI'
TransparentWhites = b'TrnW'
Twist = b'Twst'

okay breathe ๐ŸŒธ U's and V's, coming right up:

Type = b'Type'
UCA = b'UC '
URL = b'URL '
UndefinedArea = b'UndA'
Underline = b'Undl'
UnitsPrefs = b'UntP'
Untitled = b'Untl'
UpperY = b'UppY'
Urgency = b'Urgn'
UseAccurateScreens = b'AcrS'
UseAdditionalPlugins = b'AdPl'
UseCacheForHistograms = b'UsCc'
UseCurves = b'UsCr'
UseDefault = b'UsDf'
UseGlobalAngle = b'uglg'
UseICCProfile = b'UsIC'
UseMask = b'UsMs'
UserMaskEnabled = b'UsrM'
UserMaskLinked = b'Usrs'
Using = b'Usng'
Value = b'Vl '
Variance = b'Vrnc'
Vector0 = b'Vct0'
Vector1 = b'Vct1'
VectorColor = b'VctC'
VersionFix = b'VrsF'
VersionMajor = b'VrsM'
VersionMinor = b'VrsN'
Vertical = b'Vrtc'
VerticalScale = b'VrtS'
VideoAlpha = b'Vdlp'
Visible = b'Vsbl'

and the finale of this whole table ๐Ÿ’… lowercase, uppercase, numbers, an underscore โ€” she has range:

WatchSuspension = b'WtcS'
Watermark = b'watr'
WaveType = b'Wvtp'
WavelengthMax = b'WLMx'
WavelengthMin = b'WLMn'
WebdavPrefs = b'WbdP'
WetEdges = b'Wtdg'
What = b'What'
WhiteClip = b'WhtC'
WhiteIntensity = b'WhtI'
WhiteIsHigh = b'WhHi'
WhiteLevel = b'WhtL'
WhitePoint = b'WhtP'
WholePath = b'WhPt'
Width = b'Wdth'
WindMethod = b'WndM'
With = b'With'
WorkPath = b'WrPt'
WorkPathIndex = b'WrkP'
X = b'X '
Y = b'Y '
Yellow = b'Ylw '
ZigZagType = b'ZZTy'
_3DAntiAlias = b'Alis'
comp = b'comp'

and no, that last one is not a typo โ€” it genuinely is lowercase comp mapped to b'comp' ๐Ÿ˜Œ slay.


โœจ Type โœจ

next up: class psd_tools.terminology.Type(*values) ๐Ÿ’– these are the type definitions, yanked straight out of PITerminology.h.

want the receipts? the page points you at https://www.adobe.com/devnet/photoshop/sdk.html.

and now, the list. A through C, bestie:

ActionData = b'ActD'
ActionReference = b'#Act'
AlignDistributeSelector = b'ADSt'
Alignment = b'Alg '
Amount = b'Amnt'
AntiAlias = b'Annt'
AreaSelector = b'ArSl'
AssumeOptions = b'AssO'
BevelEmbossStampStyle = b'BESs'
BevelEmbossStyle = b'BESl'
BitDepth = b'BtDp'
BlackGeneration = b'BlcG'
BlendMode = b'BlnM'
BlurMethod = b'BlrM'
BlurQuality = b'BlrQ'
BrushType = b'BrsT'
BuiltInContour = b'BltC'
BuiltinProfile = b'BltP'
CMYKSetupEngine = b'CMYE'
Calculation = b'Clcn'
Channel = b'Chnl'
ChannelReference = b'#ChR'
CheckerboardSize = b'Chck'
ClassColor = b'#Clr'
ClassElement = b'#ClE'
ClassExport = b'#Cle'
ClassFormat = b'#ClF'
ClassHueSatHueSatV2 = b'#HsV'
ClassImport = b'#ClI'
ClassMode = b'#ClM'
ClassStringFormat = b'#ClS'
ClassTextExport = b'#CTE'
ClassTextImport = b'#ClT'
Color = b'Clr '
ColorChannel = b'#ClC'
ColorPalette = b'ClrP'
ColorSpace = b'ClrS'
ColorStopType = b'Clry'
Colors = b'Clrs'
Compensation = b'Cmpn'
ContourEdge = b'CntE'
Convert = b'Cnvr'
CorrectionMethod = b'CrcM'
CursorKind = b'CrsK'

D through I, keep going, you're iconic:

DCS = b'DCS '
DeepDepth = b'DpDp'
Depth = b'Dpth'
DiffuseMode = b'DfsM'
Direction = b'Drct'
DisplacementMap = b'DspM'
Distribution = b'Dstr'
Dither = b'Dthr'
DitherQuality = b'Dthq'
DocumentReference = b'#DcR'
EPSPreview = b'EPSP'
ElementReference = b'#ElR'
Encoding = b'Encd'
EraserKind = b'ErsK'
ExtrudeRandom = b'ExtR'
ExtrudeType = b'ExtT'
EyeDropperSample = b'EyDp'
FPXCompress = b'FxCm'
Fill = b'Fl '
FillColor = b'FlCl'
FillContents = b'FlCn'
FillMode = b'FlMd'
ForcedColors = b'FrcC'
FrameFill = b'FrFl'
FrameStyle = b'FStl'
GIFColorFileType = b'GFPT'
GIFPaletteType = b'GFPL'
GIFRequiredColorSpaceType = b'GFCS'
GIFRowOrderType = b'GFIT'
GlobalClass = b'GlbC'
GlobalObject = b'GlbO'
GradientForm = b'GrdF'
GradientType = b'GrdT'
GrainType = b'Grnt'
GrayBehavior = b'GrBh'
GuideGridColor = b'GdGr'
GuideGridStyle = b'GdGS'
HistoryStateSource = b'HstS'
HorizontalLocation = b'HrzL'
ImageReference = b'#ImR'
InnerGlowSource = b'IGSr'
IntegerChannel = b'#inC'
Intent = b'Inte'
InterlaceCreateType = b'IntC'
InterlaceEliminateType = b'IntE'
Interpolation = b'Intp'

K through R, halfway, no cap:

Kelvin = b'Klvn'
KelvinCustomWhitePoint = b'#Klv'
Lens = b'Lns '
LightDirection = b'LghD'
LightPosition = b'LghP'
LightType = b'LghT'
LocationReference = b'#Lct'
MaskIndicator = b'MskI'
MatteColor = b'MttC'
MatteTechnique = b'BETE'
MenuItem = b'MnIt'
Method = b'Mthd'
MezzotintType = b'MztT'
Mode = b'Md '
Notify = b'Ntfy'
Object = b'Objc'
ObjectReference = b'obj '
OnOff = b'OnOf'
Ordinal = b'Ordn'
Orientation = b'Ornt'
PNGFilter = b'PNGf'
PNGInterlaceType = b'PGIT'
PagePosition = b'PgPs'
PathKind = b'PthK'
PathReference = b'#PtR'
Phosphors = b'Phsp'
PhosphorsCustomPhosphors = b'#Phs'
PickerKind = b'PckK'
PixelPaintSize = b'PPSz'
Platform = b'Pltf'
Preview = b'Prvw'
PreviewCMYK = b'Prvt'
ProfileMismatch = b'PrfM'
PurgeItem = b'PrgI'
QuadCenterState = b'QCSt'
Quality = b'Qlty'
QueryState = b'QurS'
RGBSetupSource = b'RGBS'
RawData = b'tdta'
RippleSize = b'RplS'
RulerUnits = b'RlrU'

S through Z, the final block of this class ๐Ÿฆ‹:

ScreenType = b'ScrT'
Shape = b'Shp '
SmartBlurMode = b'SmBM'
SmartBlurQuality = b'SmBQ'
SourceMode = b'Cndn'
SpherizeMode = b'SphM'
State = b'Stte'
StringChannel = b'#sth'
StringClassFormat = b'#StC'
StringCompensation = b'#Stm'
StringFSS = b'#Stf'
StringInteger = b'#StI'
StrokeDirection = b'StrD'
StrokeLocation = b'StrL'
TextureType = b'TxtT'
TransparencyGridColors = b'Trnl'
TransparencyGridSize = b'TrnG'
TypeClassModeOrClassMode = b'#TyM'
UndefinedArea = b'UndA'
UnitFloat = b'UntF'
Urgency = b'Urgn'
UserMaskOptions = b'UsrM'
ValueList = b'VlLs'
VerticalLocation = b'VrtL'
WaveType = b'Wvtp'
WindMethod = b'WndM'
YesNo = b'YsN '
ZigZagType = b'ZZTy'

ate. and left no crumbs. โœจ


๐ŸŽ€ Unit ๐ŸŽ€

and last but never least, class psd_tools.terminology.Unit(*values) ๐Ÿ’œ โ€” the unit definitions, also pulled from PITerminology.h.

same receipts as above: https://www.adobe.com/devnet/photoshop/sdk.html.

all eight of them, tiny but mighty:

Angle = b'#Ang'
Density = b'#Rsl'
Distance = b'#Rlt'
Millimeters = b'#Mlm'
Percent = b'#Prc'
Pixels = b'#Pxl'
Points = b'#Pnt'
_None = b'#Nne'

look at her, a whole eight-item bop ๐ŸŽ€


๐ŸŒˆ INDICES AND TABLES ๐ŸŒˆ

the little navigation corner of the page, lowkey the most useful part for finding things:

  • Index <>
  • Module Index <>
  • Search Page <>

go click around, bestie, that's what they're for ๐Ÿ’…


๐Ÿ‘‘ Author ๐Ÿ‘‘

Kota Yamaguchi โ€” the icon who wrote all of this. we love her, we thank her, we say her name with our chest ๐Ÿซถ


2019, Kota Yamaguchi โ€” that's the copyright line, right there, preserved forever, periodt.


and that's a wrap on SRC(1), bestie!! ๐ŸŽ‰ this page is version 1.17.4, dated Jun 25, 2026, and you read the WHOLE thing, every last constant and every last b'...' ๐Ÿ’€ genuinely iconic behaviour. go drink some water, you've earned it ๐ŸŒธโœจ๐Ÿ’…

๐Ÿ“ฆ where this page comes from