Nodes/ComfyUI Assistant Node/PVL Image Composite
ComfyUI Node

PVL Image Composite

Paste one image onto another — batch-smart, mask-aware

By pvlprk·Created about a year ago·Updated 8 months ago· 1
PVL Image Composite
  • destination
  • source
  • mask
  • IMAGE
x0
y0
offset_x0
offset_y0
delimiter[++]

Sometimes the whole job is putting picture A on top of picture B at a certain spot - an asset onto a background, a face onto a body, a logo onto a render. That's compositing, and ComfyUI's built-in ImageComposite already does the basics. This node is the pack's version, and the difference is in the details: it's batch-aware, it handles mismatched batch counts by repeating, and - the genuinely useful bit - it takes per-frame offsets as delimiter-separated strings, so each frame in a batch can land at a different position without you adding a dozen nodes.

Where that pays off: a batch of generated subjects, each needing to sit at a slightly different x/y on a shared background (say, a contact sheet or a product grid). offset_x / offset_y accept something like 0[++]20[++]40, with [++] as the default delimiter, and the node maps each value to its corresponding frame. Static x/y applies to all frames; the offsets are per-frame extras.

How it works

Pure local tensor math - no API, no network. source gets pasted onto destination at position (x + offset_x[i], y + offset_y[i]) for each frame. Batch counts are reconciled first: if one side has batch 1 it's repeated to match the other; if both are >1 but unequal, the smaller is padded by repeating its last frame. An optional mask controls where the source is actually visible - it's resized to the source's dimensions if it doesn't match, so a rough mask works even when your source got resized upstream.

The inputs that matter

  • destination and source - what gets pasted on what. Source is the top layer.
  • x, y - base position, -8192 to 8192. Negative is fine; the node clips as needed.
  • offset_x, offset_y - per-frame position deltas as delimiter-separated strings. This is the input that makes the node worth having.
  • delimiter - the separator, default [++]. Only matters if you use the offsets.
  • mask (optional) - blend control. Not connected = source pasted fully opaque.

One output: IMAGE, same size as the destination.

Installing it

Part of the pvlprk "ComfyUI Assistant Node" pack:

cd ComfyUI/custom_nodes
git clone https://github.com/pvlprk/comfyui-pvl-api-nodes

Restart ComfyUI. No key, no models, works offline.

Common issues

The offset parsing is the thing to watch. A non-numeric string quietly defaults to 0.0 rather than erroring, and if you provide fewer offset values than frames, the last value is repeated to fill the batch - so a typo like 0[++]20[++] (trailing delimiter) can silently place the last frames at the same spot. Check the strings when positions look wrong. Second, the mask is resized with bicubic interpolation, which softens hard edges slightly - fine for photography, wrong for a sharp logo. Third, if destination and source have genuinely different pixel dimensions, the paste just draws at the position with source keeping its own size; there's no auto-fit, so size your source before compositing. And if you're only ever pasting a single image, the built-in core node is identical in practice - reach for this one when batches and per-frame offsets enter the picture.

Categorypvl/image manipulation

Inputs (8)

NameTypeDefaultDescription
destinationIMAGE
sourceIMAGE
xINT0-8192–8192
yINT0-8192–8192
offset_xSTRING0
offset_ySTRING0
delimiterSTRING[++]
maskoptMASK

Outputs (1)

NameTypeDescription
IMAGEIMAGE