Skip to main content

Fast exporting of PSDs with [tagged] layers for variants.

Project description

psd-export

  • Fast multi-threaded exporting of PSDs with [tagged] layers for variants.
  • Special named layers can be used to apply filters like mosaic or gaussian blur, or whatever else you can hook in.
  • This tool is primarily meant to be compatible with PSDs exported from PaintTool SAIv2 and Clip Studio Paint.

Why

For my art workflow, I typically make a bunch variation layers and also need to apply mosaics to all of them. As a manual process, exporting every variant can take several minutes, with lots of clicking everywhere to turn layers on and off (potentially missing layers by accident) and then adding mosaics can be another 10 or 20 minutes of extra work. If I find I need to change something in my pictures and export again, I have to repeat this whole ordeal. This script puts this export process on the order of seconds, saving me a lot of time and pain.


Installation

  • Install python: https://www.python.org/downloads/
  • Run pip install psd-export to install the script.
  • Run psd-export to export any PSD files in the current directory.
  • Run psd-export --help for more command line arguments.

Building from source

  • Install a C compiler (like MSVC, GCC, Clang)
  • Install extra dependencies: pip install setuptools wheel cython numpy
  • Install this repository locally: pip install -e .
  • If you modify a Cython file (.pyx), then rebuild it with: python setup.py build_ext --inplace

Building/installing with Nix

  • This project is a Nix flake, so you can run flake commands to interact with the package nix run, nix build, etc.

Setting up the PSD

Automatic Exporting

Primary tags
  • Add tags surrounded by [] to the names of layers that you want as part of an exported picture.
    • A layer name can contain anything else outside of tags: scene [1], which will be ignored.
  • Because whitespace is used to delimit arguments to filters, a tag's name will not include anything after a space, for example:
    • [blur 50] the tag name will be blur, and 50 is an argument to blur.
  • Each set of primary tagged layers will be turned on and off and then exported in turn.
    • That means multiple layers can have the same tag, so you can toggle layers in your foreground and background together, for example:
      • A layer named foreground [1] and a separate layer named background [1]
  • A layer can have multiple tags in the name: scene [1][2]
    • This will export with this layer visible for both tags.
  • A primary tag is not necessary. If no primary tag is provided, then the whole picture is exported as is.
Secondary tags
  • Tags with an @ in the name will be treated as secondary tags.
  • Text before the @ is the tag name, and text after the @ is the exclusion group.
    • The exclusion group can be empty.
    • Valid secondary tag names: [jp@], [jp@text]
  • These tags will be exported in combination with primary tags, for example:
    • If you have layers tagged [1], [thing@] [jp@text], and [en@text], then what will be exported is 1, 1-thing, 1-thing-jp, 1-thing-en, 1-jp, 1-en
    • Because [jp@text] and [en@text] share the same exclusion group text, they will never be enabled together.
    • If there was a second primary tag [2] for example, the whole set of combinations would be exported again but with 2 instead of 1

Image filters

  • Tags with special names will be treated as filters on the colors below them.
  • Filters can double as export tags too.
  • If you want a filter to not be treated as an export tag, you can preceed it with # to set the ignore flag, for example [#censor]
  • Filters can have arguments as well to control their behavior, separated by spaces, for example [#censor 50]
  • If you want the filter to apply to layers outside of the group it is in, then the group blend mode should be set to pass-through, otherwise it may blend with transparent black pixels if the filter is over a transparent part of a group. The blur and motion blur filters apply to alpha as well, so they should behave as expected in isolated groups.
  • If multiple filters are enabled in one layer, they will be applied from left to right on top of each result, example:
    • [#censor][#blur] will apply a mosaic, and then a blur on top of that mosaic.
  • Blend modes and clipping layers applied directly to filter layers are ignored.
Available default filters:
  • [censor mosaic_factor apply_to_alpha]
    • If the mosaic_factor argument is omitted, then it is defaulted to 100, which means 1/100th the smallest dimension, (or 4 pixels, whichever is larger) in order to be Pixiv compliant.
    • apply_to_alpha defaults to False. Any value is treated as True.
    • Typically you will want this filter to be a secondary tag, for example: [censor@], so you can have censored and uncensored outputs.
  • [blur size]
    • The size argument defaults to 50 if omitted.
    • This filter is best used to create a non-destructive blur, such as for a background layer. You can fill an entire layer and set it to [#blur 8] for example.
  • [motion-blur angle size]
    • angle is in degrees, starting from horizontal to the right; Default 0.
    • size defaults to 50.
    • Best used for non-destructive blur: [#motion-blur 45 20]
Adding a new filter:

In your own script:

# my-export.py
from psd_export import (export, filters, util, blendfuncs)
import numpy as np

my_arg1_default = 1.0

# Register the filter with this decorator:
@filters.filter('my-filter')
# Only positional arguments work right now. The result of this function replaces the destination color and alpha.
def some_filter(color_dst, color_src, alpha_dst, alpha_src, arg1=None, arg2=100, *_):
    # Cast arguments to your desired types, as they will come in as strings.
    if arg1 is None:
        arg1 = my_arg1_default
    arg1 = float(arg1)
    # Manipulate color and alpha numpy arrays, in-place if you want.
    color = np.subtract(arg1, color, out=color)
    color = blendfuncs.lerp(color_dst, color, alpha_src)
    # Always return the same shaped arrays as a tuple:
    return color, alpha

if __name__ == '__main__':
    # Add your own command line arguments if needed.
    export.arg_parser.add_argument('--my-arg1', default=my_arg1_default, type=float,
        help='Set the arg1 default parameter.')
    args = export.arg_parser.parse_args()
    my_arg1_default = args.my_arg1

    export.main()

Apply it to a layer in your PSD, for example: [my-filter 20.4] or [#my-filter], etc.


Examples

In the layers below, there are 2 primary tags and 3 secondary tags (with two unique exclusion groups):

Primary tags: 1, 2

Secondary tags: jp, en, censor

Exclusion groups: text, <empty>

Groups with primary tags will be exported again even if the secondary tag does not exist under that group! This keeps the exported folders uniformly sized for publishing, so different folders may appear to have duplicate outputs.

Example layer configuration in SAI:

image

Example output from script, showing every valid combination:

image

Folder after exporting everything:

image

Example of a layer with the tag [censor@] (the layer does not need to be set to visible before exporting):

image

After exporting:

image


Blendmode status:

Blendmode Status
Normal Pass
Multiply Pass
Screen Pass
Overlay Pass
Linear Burn (Shade) Pass
Linear Dodge (Shine) Pass
Linear Light (Shade/Shine) Pass
Color Burn (Burn) Pass
Color Dodge (Dodge) Pass
Vivid Light (Burn/Dodge) Pass
Soft Light Pass
Hard Light Pass
Pin Light Pass
Hard Mix Small precision error for near-black colors, can look slightly different from SAI
Darken Pass
Lighten Pass
Darken Color Pass
Lighten Color Pass
Difference Pass
Exclude Pass
Subtract Pass
Divide Pass
Hue Pass
Saturation Pass
Color Pass
Luminosity Pass
[TS] Linear Burn (Shade) Pass
[TS] Linear Dodge (Shine) Pass
[TS] Linear Light (Shade/Shine) Pass
[TS] Color Burn (Burn) Small precision error for near-black colors, can look slightly different from SAI
[TS] Color Dodge (Dodge) Pass
[TS] Vivid Light (Burn/Dodge) Pass
[TS] Hard Mix Small precision error for near-black colors, can look slightly different from SAI
[TS] Difference Pass

Missing PSD features:

  • Other things that are not implemented (also not implemented in psd-tools):
    • Adjustment layers (gradient map, color balance, etc.)
    • Layer effects (shadow, glow, overlay, strokes, etc.)
    • Font rendering
    • Probably some other things I'm unaware of.

TODO:

  • Fix blend modes that don't quite work properly. This is low priority because I hardly use these modes myself or merge the results when painting.
  • Binary package export

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

psd_export-1.1.0.tar.gz (376.3 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

psd_export-1.1.0-cp313-cp313-win_amd64.whl (542.2 kB view details)

Uploaded CPython 3.13Windows x86-64

psd_export-1.1.0-cp313-cp313-win32.whl (513.2 kB view details)

Uploaded CPython 3.13Windows x86

psd_export-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ x86-64

psd_export-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl (1.6 MB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ ARM64

psd_export-1.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

psd_export-1.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (1.6 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

psd_export-1.1.0-cp313-cp313-macosx_11_0_arm64.whl (557.9 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

psd_export-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl (568.4 kB view details)

Uploaded CPython 3.13macOS 10.13+ x86-64

File details

Details for the file psd_export-1.1.0.tar.gz.

File metadata

  • Download URL: psd_export-1.1.0.tar.gz
  • Upload date:
  • Size: 376.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.24

File hashes

Hashes for psd_export-1.1.0.tar.gz
Algorithm Hash digest
SHA256 7693aa6b4d4b4e5d039b1a0b070c2fb7e572a536ae87d2d66880120cb5534acf
MD5 8566194a388278f1315e063c57760631
BLAKE2b-256 6f188e9025f5c41d31a9a3e7b485b4b6f30e1a7f8339115e341fa1177ca727fb

See more details on using hashes here.

File details

Details for the file psd_export-1.1.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: psd_export-1.1.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 542.2 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.24

File hashes

Hashes for psd_export-1.1.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 862fc72d7c52bbde6ac74b62055992a66a4513ade42038f6ff3d8579ac2b3c34
MD5 33c19478a3d7fa1f9e2a5aa6e66623fa
BLAKE2b-256 826b67f7a1d9c72bdecb1aa06ecd3c62edf7f9e656073976a783aa1d14869d84

See more details on using hashes here.

File details

Details for the file psd_export-1.1.0-cp313-cp313-win32.whl.

File metadata

  • Download URL: psd_export-1.1.0-cp313-cp313-win32.whl
  • Upload date:
  • Size: 513.2 kB
  • Tags: CPython 3.13, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.24

File hashes

Hashes for psd_export-1.1.0-cp313-cp313-win32.whl
Algorithm Hash digest
SHA256 4459209d7ac03651c9168780e2f27e13946544eb14f944a83ca357360d8084ea
MD5 6e052d7c769955eeacb80cb575593d57
BLAKE2b-256 67cf2c270cc96fcca8261d8fe791e949212e047fead37b60b1d980bf5656843c

See more details on using hashes here.

File details

Details for the file psd_export-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for psd_export-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 76f6c47fd8f4362d73ee934af1f7a5088b7791fd11d3d2f6612a7e92e705e03b
MD5 8e282866a195fc1e8ca627b670de0443
BLAKE2b-256 8fb7d647f5557ed9fd11bda4f819008d4839c8981f530b1a1e67df9042d4a79c

See more details on using hashes here.

File details

Details for the file psd_export-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for psd_export-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 7c29d53b4eb9c1afcfc68a3696c233bde84cfaad576f3abf4a21a94f747d2666
MD5 2f24509e86c4749cadc5340775c2e134
BLAKE2b-256 2c72dd44a02fecac72aa0d2f14a5fff80164c0d99d5e7b1e634220d40ad8d7eb

See more details on using hashes here.

File details

Details for the file psd_export-1.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for psd_export-1.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5605570c00eca5a3bb2b96bcac1e8d5edf5cc56536430c8607cc90acaa705459
MD5 d8f09b4d467ece33eee372e15836a760
BLAKE2b-256 f85c7fae120df8e2eedb262f2a5730aef3c11c83985b02ff62537756005c9e7d

See more details on using hashes here.

File details

Details for the file psd_export-1.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for psd_export-1.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 e8afa520fec32657a5202f49e77ea6a8ff7b78853734142fca8001e0658120ab
MD5 cc7d79e6c5af1dd2dd939eb9253ce90e
BLAKE2b-256 af06618e338739a495b902be668329a3a0bfb5b51df4878e510a043d1c6172ca

See more details on using hashes here.

File details

Details for the file psd_export-1.1.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for psd_export-1.1.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5c75bd98af901c3b98c0203c36d8a9ddafd8b881b671a952b732a28945546569
MD5 4bea0f8e6a673352a62cb17ce5965d05
BLAKE2b-256 893f98368cf5e42569440be2e74eef22623a242ef41a522b8c6a4104cc1babef

See more details on using hashes here.

File details

Details for the file psd_export-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for psd_export-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 e33d2a84ee16e6d44049c469e2444d31e7314d2a198bbe681f4042bf2bd83d0e
MD5 9c685c50b084faa2ef2703f1dacb955d
BLAKE2b-256 cfea22cb4ca8e6cd76409a310fe8ca65be3dd50e0ff31ec11905d28c7ff9941e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page