ImageConcanate
Stitch two images together, any direction
- image1
- image2
- output
Yes, the name is misspelled. It's "Concanate," not "Concatenate," and it's been that way long enough that fixing it would break every workflow that references the class, so it stays. Search for it exactly as written or you won't find it.
What it does is dead simple and endlessly useful: it glues two images together into one, side by side or stacked. This is the node behind approximately every before/after comparison, every side-by-side grid, every "put the reference next to the result" image you've seen posted. It lives in kijai's KJNodes, the utility pack most people already have, and it's one of the ones you'll use constantly once you know it's there.
How it works
It takes image2 and welds it onto image1 in whichever direction you choose. By default it matches the second image's size to the first along the shared edge before joining, so you don't get a ragged seam. The output image inherits the type of image1.
There's more thought in it than you'd expect. Both inputs happily accept an IMAGE or a MASK, and if the two are different types it converts on the fly (an image becomes a mask via its RGB mean; a mask becomes an image by replicating the single channel across RGB). And if you turn size-matching off and the dimensions don't line up along the joined axis, it doesn't just error out. It centers the smaller image and zero-pads it to fit. That "don't crash, pad instead" behavior is the kind of small mercy that keeps a batch job alive at 2am.
The inputs and outputs that matter
image1andimage2- the two images (or masks) to join.image1sets the output type.direction(defaultright) - whereimage2gets attached: right, left, up, or down. Right and down are what you want for the classic side-by-side and top/bottom layouts.match_image_size(default true) - when on,image2is resized to share the joined edge cleanly. When off, mismatched images are centered and zero-padded instead of stretched. Leave it on for comparisons where you want the halves visually equal; turn it off when you care about preserving each image's real pixels.
The single output carries the combined image (or mask, if that's what you fed in).
Installing it
You probably have KJNodes already. If not, ComfyUI Manager → search KJNodes for ComfyUI → install → restart. Or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/kijai/ComfyUI-KJNodes
pip install -r ComfyUI-KJNodes/requirements.txt
Restart ComfyUI. No models needed.
Common issues
"I can't find it in the node search." Spell it wrong on purpose: ImageConcanate, missing the second "t." That's the real class name.
One side looks stretched or squished. That's match_image_size doing its job on two images with very different aspect ratios. If you'd rather keep each image's true proportions, turn matching off, accept the black padding around the smaller one, or resize both to a common size beforehand.
It came out as a mask when I wanted an image (or vice versa). The output type follows image1. Whatever you plug into the first slot decides the result type, and the second input gets converted to match. Swap your inputs, or convert explicitly upstream, if the type is backwards.
Building a big grid. Chain them: concat two images left-to-right, then concat that row onto another row top-to-bottom. It's the standard way to assemble an N-up contact sheet out of this one node.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| image1 | COMFY_MATCHTYPE_V3 | — | |
| image2 | IMAGE,MASK | — | |
| direction | COMBO | right | 4 options: right, down, left, up |
| match_image_size | BOOLEAN | true | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| output | COMFY_MATCHTYPE_V3 | — |