Compose Image Layers
Put the edited canvas back where it came from
- base
- edited
- original_layers
- source_layers
- layout
- base_mask
- atlas
- atlas_list
- layer_images
The crop-edit-stitch pattern is the default way anybody edits a specific part of an image in 2026: cut the region out, run a real editing model on it, put it back with the untouched pixels untouched. Compose Image Layers is the stitching half of that pattern for layered artwork - a character rig split into sleeve, torso, hair, cape - where the pieces are separate PNGs and you want the edits to land back on the original components.
It is the counterweight to LF_LoadImageLayers, and it only makes sense next to it. Loader splits your component stack onto edit canvases, you paint or inpaint or relight, this node merges the result.
How it works
The important word is delta, not replace. The composer takes your edited canvases plus the breakpoint's originals, works out what you actually changed, resizes that difference back onto the native-size source layer, and applies it. Differences of one 8-bit step are treated as PNG transport noise and ignored - which means an accidental colour-space round-trip won't smear your artwork, at the cost of also ignoring genuinely tiny deliberate edits.
Restoration is project-from-content-rectangle only: each canvas's aspect-fit content rectangle maps back to its native component. Padding edits and alpha changes you made in the editor are discarded, the original alpha is retained, and the restored layers are alpha-composited in manifest order with Pillow's LANCZOS resampling. The doc's claim is that a no-edit pass matches the pre-existing composition path byte for byte on 8-bit sources.
Nothing here writes files, and nothing here emits pixels you didn't edit. That's the point.
The inputs and outputs that matter
Five required inputs, and four of them are wires you mostly leave alone:
base- exactly one RGB/RGBA base atlas (usually from an upstream loader or composite).edited- the editor breakpoint'simage_list, in entry order.original_layers- the breakpoint'sorig_image_list, same order. This is what makes local deltas possible; without it the node can't tell your edit from the transport's colour noise.source_layers- the loader's nativesource_layers. Keep this connected directly to the loader, not through the editor, so resized canvases never become the source of truth.layout- the loader's JSON. It carries the geometry and order everything else is validated against.base_mask(optional, a MASK) - white permits base RGB edits, black preserves the original base, grey gives you partial. Supply exactly one mask at the base's dimensions.
Outputs: atlas (one RGBA image, the composed result), atlas_list (the same thing as a single-item list, for nodes that want list input), and layer_images - the restored native-size RGBA layers, editable by cut masks if you enabled them upstream. That last one is the one you feed an explicit saver; this node won't save anything on its own.
How to install it
Standard pack install - ComfyUI Manager, search LF Nodes, restart. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/lucafoscili/lf-nodes
python -m pip install -r lf-nodes/requirements.txt
Use ComfyUI's own interpreter for the pip line. One gotcha for this pack specifically: there's an archived predecessor repo (lucafoscili/comfyui-lf) that the author migrated away from in October 2025, and older guides still point at it. lf-nodes is the live one. The dependency list is hefty because the pack is 154 nodes wide - Pillow and numpy are what this node actually needs.
Common issues & troubleshooting
"Cardinality" errors. The composer never broadcasts. If the editor dropped, duplicated, or reordered an entry, edited and original_layers stop matching the layout and it refuses. Re-check the breakpoint's named entries - the IDs are what prove identity, and raw unnamed tensors can't.
Your edit vanished. Most likely it was inside the one-step/255 tolerance, or it was a padding edit outside the content rectangle, or you changed alpha instead of RGB. Alpha edits are deliberately ignored on the restoration path.
Composition looks off-by-a-layer. Order comes from the manifest, and later entries render above earlier ones. Check the manifest, not the node.
A small edit bled onto a neighbour. Deltas are resized with bilinear antialiasing, so an edit can touch the pixels inside its interpolation footprint. That's inherent to resizing a crop back down, not a bug.
If your layers overlap on purpose - sleeves over cuffs - that's supported. If they overlap by accident, that's a manifest problem, and the doc's answer for genuinely overlapping garments is: don't.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| base | IMAGE | Exactly one RGB/RGBA base atlas. | |
| edited | IMAGE | Edited canvases in validated original entry order. | |
| original_layers | IMAGE | Breakpoint orig_image_list, in the same order; required for local edit deltas. | |
| source_layers | IMAGE | Native RGBA source_layers returned by Load Image Layers. | |
| layout | JSON | Layout returned by Load Image Layers. | |
| base_maskopt | MASK | Base-region RGB edit coverage: white permits edits, black preserves the original base. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| atlas | IMAGE | Pillow-compatible RGBA atlas with restored layers alpha-composited in manifest order. |
| atlas_list | IMAGE | Single-item list containing the composed atlas. |
| layer_images | IMAGE | Ordered native-size RGBA layer images with RGB edits and original coverage, optionally reduced by cut masks. |