ImageLayerStudio
A Photoshop layer panel, inside your ComfyUI graph
- layer_01
- layer_01_mask
- layer_02
- layer_02_mask
- layer_03
- layer_03_mask
- layer_04
- layer_04_mask
- layer_05
- layer_05_mask
- layer_06
- layer_06_mask
- layer_07
- layer_07_mask
- layer_08
- layer_08_mask
- layer_09
- layer_09_mask
- layer_10
- layer_10_mask
- layer_11
- layer_11_mask
- layer_12
- layer_12_mask
- layer_13
- layer_13_mask
- layer_14
- layer_14_mask
- layer_15
- layer_15_mask
- layer_16
- layer_16_mask
- output
- mask
- layer_01
- layer_01_mask
- layer_02
- layer_02_mask
- layer_03
- layer_03_mask
- layer_04
- layer_04_mask
- layer_05
- layer_05_mask
- layer_06
- layer_06_mask
- layer_07
- layer_07_mask
- layer_08
- layer_08_mask
- layer_09
- layer_09_mask
- layer_10
- layer_10_mask
- layer_11
- layer_11_mask
- layer_12
- layer_12_mask
- layer_13
- layer_13_mask
- layer_14
- layer_14_mask
- layer_15
- layer_15_mask
- layer_16
- layer_16_mask
You know the chore. Subject cut out with one tool, background plate from another, and now you're dragging a little image around on top of a mask to make them line up - except ComfyUI isn't Photoshop, and pasting one image onto another has always meant stacking a handful of brittle blend-and-mask nodes and eyeballing the numbers. The community has long handled this by just... leaving: post-processing docs keep tripping over people who bail out to Photoshop or After Effects for a composite. ImageLayerStudio is the answer to that trip.
It's a real layered compositor, Photoshop-style, living on one node. You set a fixed canvas, drop up to 16 layers onto it, then move, rotate, and scale each one by dragging in the node's own viewport. No diffusion pass involved anywhere - this is pure, deterministic pixel work, the kind the KB tells you to reach for before you burn a regeneration fixing an arrangement.
How it works
The node is really two halves talking to each other. There's an interactive editor that ships in the pack's web/ folder - the left layer list, the canvas viewport, the X/Y/R/Z readouts - and a server-side compositor that runs when the graph executes. Your drags never re-run anything live; they just update a hidden bit of state (layer_data) holding each layer's position, rotation, scale, and mask mode. When you hit Save, those transforms are baked into the workflow, so the arrangement travels with the JSON instead of being re-derived every run.
On execution, each connected layer_XX image tensor becomes an RGBA image, the mask premultiplies the color (RGB times alpha, Nuke-style, so edges don't fringe), and PIL does the transform: LANCZOS resize for scale, rotation, then alpha-composite onto a canvas that's exactly canvas_width × canvas_height. It's batch-aware, so feed it frames and it composes each one.
The inputs that matter
Only two are required, and they're both canvas geometry:
canvas_width/canvas_height- the output resolution, 64–8192 in steps of 8. The output follows these, not your source images, which is the single most important thing to internalize.
Everything else is optional: layer_01 … layer_16 take IMAGEs, and layer_01_mask … layer_16_mask take MASKS when a layer needs cutout. New nodes start with just layer_01; click Add layer to grow the rest.
Wire the output (composed RGB at canvas size) into a Save Image or Preview node - that's the finished frame. You also get mask (the canvas alpha) and a per-layer layer_XX / layer_XX_mask pair for every active layer, each returned at canvas size, which is handy if you want to run a layer through its own detailing pass later.
Install
Two-line install, no models, no API keys. ComfyUI Manager handles it: search ImageLayerStudio (or ComfyUI-ImageLayerNode). Otherwise:
cd ComfyUI/custom_nodes
git clone https://github.com/Luna-visual/ComfyUI-ImageLayerNode
Restart, then hard-refresh the browser (Ctrl+F5) - this pack ships a custom frontend, and the old cached JS is the #1 way people "install" it and swear it's broken. Its only declared Python dependency is Pillow; numpy and torch come with ComfyUI itself. You'll find it under Add Node → image → layers.
Gotchas worth knowing
- The list is front-to-back. First in the list paints on top; drag to reorder.
- Fill vs Input is the mask toggle. Fill shows the whole image; Input actually uses the connected mask or the image's own alpha. Layer not cutting anything out? Check that dropdown.
- Run your sources first. Load Image appears immediately, but if a layer comes from a Crop, SAM, or other editor node, hit this node's play button to run those upstream nodes and load their results - the previews come from a real queue run writing temp files.
- Reset refits every layer to the canvas (links stay connected). Default behavior auto-fits a layer to the canvas until you actually modify it, which catches people out when their canvas is larger than their image.
- Undo is one step back. ComfyUI has no Photoshop history stack; do a Save after a move you like.
Fair warning, since honesty beats hype: this is a very new pack (no real community track record yet) under a custom non-sale license - free to use even commercially, but you can't resell the plugin itself. If you're arranging characters onto backgrounds, product shots, or just tired of generating ten times to get a composition, it's a genuinely nice fit. Just treat it as v1 and keep an eye on its issues page.
Inputs (34)
| Name | Type | Default | Description |
|---|---|---|---|
| canvas_width | INT | 102464–8192 | Canvas width. Final output uses this size, not the input image. |
| canvas_height | INT | 102464–8192 | Canvas height. Final output uses this size, not the input image. |
| layer_01opt | IMAGE | — | |
| layer_01_maskopt | MASK | — | |
| layer_02opt | IMAGE | — | |
| layer_02_maskopt | MASK | — | |
| layer_03opt | IMAGE | — | |
| layer_03_maskopt | MASK | — | |
| layer_04opt | IMAGE | — | |
| layer_04_maskopt | MASK | — | |
| layer_05opt | IMAGE | — | |
| layer_05_maskopt | MASK | — | |
| layer_06opt | IMAGE | — | |
| layer_06_maskopt | MASK | — | |
| layer_07opt | IMAGE | — | |
| layer_07_maskopt | MASK | — | |
| layer_08opt | IMAGE | — | |
| layer_08_maskopt | MASK | — | |
| layer_09opt | IMAGE | — | |
| layer_09_maskopt | MASK | — | |
| layer_10opt | IMAGE | — | |
| layer_10_maskopt | MASK | — | |
| layer_11opt | IMAGE | — | |
| layer_11_maskopt | MASK | — | |
| layer_12opt | IMAGE | — | |
| layer_12_maskopt | MASK | — | |
| layer_13opt | IMAGE | — | |
| layer_13_maskopt | MASK | — | |
| layer_14opt | IMAGE | — | |
| layer_14_maskopt | MASK | — | |
| layer_15opt | IMAGE | — | |
| layer_15_maskopt | MASK | — | |
| layer_16opt | IMAGE | — | |
| layer_16_maskopt | MASK | — |
Outputs (34)
| Name | Type | Description |
|---|---|---|
| output | IMAGE | — |
| mask | MASK | — |
| layer_01 | IMAGE | — |
| layer_01_mask | MASK | — |
| layer_02 | IMAGE | — |
| layer_02_mask | MASK | — |
| layer_03 | IMAGE | — |
| layer_03_mask | MASK | — |
| layer_04 | IMAGE | — |
| layer_04_mask | MASK | — |
| layer_05 | IMAGE | — |
| layer_05_mask | MASK | — |
| layer_06 | IMAGE | — |
| layer_06_mask | MASK | — |
| layer_07 | IMAGE | — |
| layer_07_mask | MASK | — |
| layer_08 | IMAGE | — |
| layer_08_mask | MASK | — |
| layer_09 | IMAGE | — |
| layer_09_mask | MASK | — |
| layer_10 | IMAGE | — |
| layer_10_mask | MASK | — |
| layer_11 | IMAGE | — |
| layer_11_mask | MASK | — |
| layer_12 | IMAGE | — |
| layer_12_mask | MASK | — |
| layer_13 | IMAGE | — |
| layer_13_mask | MASK | — |
| layer_14 | IMAGE | — |
| layer_14_mask | MASK | — |
| layer_15 | IMAGE | — |
| layer_15_mask | MASK | — |
| layer_16 | IMAGE | — |
| layer_16_mask | MASK | — |