LLS Concat By Target
Stitch two images or masks onto one canvas, anchored by whichever one you pick
- a
- b
- image
- mask
- width
- height
Concatenating two images used to mean one of two things: ComfyUI's built-in ImageConcatMulti, which handles the straight side-by-side case, or a pile of Pad Image and ImageComposite nodes that you rebuild every single time. LLS Concat By Target is the "one node does the whole job" version. You hand it two images or two masks, tell it which one is the anchor and where the other one goes, and it returns a single canvas plus the canvas dimensions.
The point is the word "target." Instead of always putting things next to each other, you pick which input - A or B - owns the canvas. The other image gets resized, aligned, and parked at the top, bottom, left, or right of that anchor. That's the difference between "make a before/after strip" and "fit this image onto my existing reference canvas." If you're building comparison grids, putting a masked crop back beside the original, or joining mask strips before a repair chain, this is the node that does it without the node farm.
How it works
The target canvas is the reference frame: match_target_size (on by default) means the final canvas takes the target's dimensions, and the other input is fitted around it according to resize_mode - keep_proportion (default), stretch, or none - and align (start, center, end). gap adds pixels of space between the two, and background_color (a hex like #000000) plus background_value fill whatever canvas is left over. Handy one: multiple_of rounds the final canvas dimensions up to a multiple, so you can keep outputs model-friendly (multiples of 8 or 16) without doing the math.
The inputs a and b are typed * (any type), and data_type tells the node which interpretation to use - IMAGE or MASK. The outputs mirror that: image, mask, plus width and height of the finished canvas. The size outputs are the sleeper feature - wire them straight into an Empty Latent and your generation resolution always matches the canvas you just built.
The inputs that actually matter
target- which input is the anchor (AorB).position- where the other image lands:top,bottom,left,right.match_target_size+resize_mode- whether the canvas follows the anchor and how the other side is squished or preserved.gapandbackground_color- spacing and fill for the leftover canvas.
Installing it
This is part of the LLS-node pack, so you install the whole pack:
cd ComfyUI/custom_nodes
git clone https://github.com/Gin3601/LLS-node
# then restart ComfyUI
Or open ComfyUI Manager and search "LLS-node". No extra pip dependencies - the pack is pure Python that reuses ComfyUI's own image math, so install is just the clone and a restart.
Gotchas
IMAGE and MASK modes both require a and b connected - the node raises an error if either is missing, so it's not a lazy passthrough. And if you set data_type to IMAGE but feed it a mask, the node resolves the actual type from what's connected, so don't overthink the dropdown. One honest caveat: this is a young pack with essentially no community usage signal yet. It works, but it's the kind of node you reach for when it's already in your workflow, not the thing you search for on a deadline.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| data_type | COMBO | IMAGE | 2 options: IMAGE, MASK |
| target | COMBO | A | 2 options: A, B |
| position | COMBO | right | 4 options: top, bottom, left, right |
| match_target_size | BOOLEAN | true | — |
| resize_mode | COMBO | keep_proportion | 3 options: keep_proportion, stretch, none |
| align | COMBO | center | 3 options: start, center, end |
| gap | INT | 00–4096 | — |
| background_color | STRING | #000000 | — |
| background_value | FLOAT | 0.000–1 | — |
| multiple_of | INT | 00–512 | — |
| allow_batch_broadcast | BOOLEAN | true | — |
| aopt | * | — | |
| bopt | * | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| width | INT | — |
| height | INT | — |