Nodes/Save Layers Node for ComfyUI/LayersSaver - Save Layer From Images
ComfyUI Node

LayersSaver - Save Layer From Images

Batch of images → one layered PSD, without touching a graphics app

By alessandrozonta·Created 2 years ago·Updated 2 years ago· 59
LayersSaver - Save Layer From Images
  • input_image
  • layers
output_path

Every image in your batch becomes its own layer in one Photoshop file. That's the whole pitch of LayersSaver - Save Layer From Images, and if you've ever stood in front of twelve generated variations you wanted to composite by hand, you already know why that's worth having.

It's the mask-free sibling of the "Save Layer" node in the same tiny pack (ComfyUI-Layers, ~60 stars, unmaintained since mid-2024). Where the other node needs masks to carve an image into layers, this one just takes whatever batch you feed it and stacks every frame as a layer named Image_1, Image_2, and so on. Think: seed variations, inpaint passes, an animation frame stack, or a "generated + cleaned-up + upscaled" set you want to hand a designer as one file.

How it works

The mechanism is about as simple as it gets. The node reads your batch as a [batch, height, width, channels] tensor, adds an alpha channel to anything that isn't already RGBA (fully opaque, so your transparency doesn't surprise you), then walks through the batch and writes each image as a separate layer record into a .psd via pytoshop. Nothing is resized, nothing is composited - the images land in the file exactly as they came in.

One quirk in the code worth knowing: if you feed it the wrong shape, the error message says the input should be [batch_size, channels, height, width]. That's wrong on ComfyUI - its image tensors are [batch, height, width, channels]. The actual dimension check looks at the right slot, so the node works fine; just don't let the scary-looking message make you think your data is malformed.

The inputs and output

It's the thinnest input list in the pack, which is the point:

  • input_image - your batch of images. Batch size is unlimited as far as the code is concerned; each one becomes a layer.
  • output_path - the only real decision. If it doesn't end in .psd, it's treated as a directory (created if missing) and a timestamped layered_image_<date>.psd is written inside. End it in .psd and it writes straight to that file. Leave it empty and the node dies with a confusing FileNotFoundError - always put a real path in.

The layers output (type IMAGE) just hands the now-RGBA batch back to the graph, so you can wire it somewhere if you want to see what got written. It's not an output node, so nothing appears in the image tray - your artifact is the .psd on disk.

Installing it

Same story as the sibling node: it's registered, so ComfyUI Manager will find ComfyUI-Layers or Save Layers Node for ComfyUI. Manual install is two lines plus the Python deps:

cd ComfyUI/custom_nodes
git clone https://github.com/alessandrozonta/ComfyUI-Layers
cd ComfyUI-Layers
pip install pytoshop -I --no-cache-dir
pip install psd-tools --no-deps

Restart ComfyUI and you're done - no models to download, CPU only. Note the README's own clone example points at github.com/yourusername/...; that's a placeholder, use the real URL above.

Gotchas to plan around

This pack is effectively abandoned - no commits since July 2024 and open issues no one has answered - so the troubleshooting is on you. The known ones:

  • NumPy. Installing via Manager has been reported to bump NumPy past 2.0 and break ComfyUI's image loading and preview entirely. psd-tools is deliberately installed with --no-deps to dodge this, but pytoshop still pulls NumPy in. If ComfyUI breaks right after install, pin NumPy below 2.0.
  • PSDs that won't open. Open issue: "unexpected end-of-life was encountered" when opening generated files. Compression (RLE) is another reported source of corrupted layers.
  • Layer pile-up. After a long session, PSDs can accumulate layers from previous runs - restart ComfyUI to clear it.

Honest verdict: for "dump a batch into a layered PSD" this is the fastest thing in the ecosystem, and if it ever breaks you're only a restart or a pinned NumPy away. For anything fancier - per-image names, masks, blend modes - the mask-based "Save Layer" node in the same pack is the one to reach for.

CategoryLayersDivider

Inputs (2)

NameTypeDefaultDescription
input_imageIMAGE
output_pathSTRING

Outputs (1)

NameTypeDescription
layersIMAGE