Nodes/LF Nodes/Compose Image Layers
ComfyUI Node

Compose Image Layers

Put the edited canvas back where it came from

By lucafoscili·Created 2 years ago·Updated 22 days ago· 36
Compose Image Layers
  • 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's image_list, in entry order.
  • original_layers - the breakpoint's orig_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 native source_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.

Category✨ LF Nodes/Regions

Inputs (6)

NameTypeDefaultDescription
baseIMAGEExactly one RGB/RGBA base atlas.
editedIMAGEEdited canvases in validated original entry order.
original_layersIMAGEBreakpoint orig_image_list, in the same order; required for local edit deltas.
source_layersIMAGENative RGBA source_layers returned by Load Image Layers.
layoutJSONLayout returned by Load Image Layers.
base_maskoptMASKBase-region RGB edit coverage: white permits edits, black preserves the original base.

Outputs (3)

NameTypeDescription
atlasIMAGEPillow-compatible RGBA atlas with restored layers alpha-composited in manifest order.
atlas_listIMAGESingle-item list containing the composed atlas.
layer_imagesIMAGEOrdered native-size RGBA layer images with RGB edits and original coverage, optionally reduced by cut masks.