Image Concatenate Multi (UTK)
Stitch 2–4 images into one canvas, with a smart layout that sizes the grid for you
- image_1
- image_2
- image_3
- image_4
- images
Want to build a comparison grid from three or four generations, or tile a face-reference sheet for a character workflow, without hand-computing canvas sizes? Image Concatenate Multi (UTK) does the layout thinking for you. It's the multi-image sibling of the two-image ImageConcatenate_UTK in ComfyUI-UniversalToolkit, and it's the one I reach for when a collage is more than "image A next to image B."
The headline feature is smart mode. Instead of you picking the grid, the node looks at how many images you fed it and arranges them into a sensible layout - two side by side, three in a row or an L, four as a square - all sized to match. Toggle to sequential and it goes back to dumb-but-predictable: stitch them in order along a direction (right, down, left, up), no layout intelligence.
How it works
Inputs are image_1 through image_4, where only image_1 is required - the node skips empty slots, so you can do 2, 3, or 4 images from the same node. It resizes so all frames share a common dimension (via bilinear, the same approach as the two-image version), then concatenates them onto a canvas with an optional gap between cells, and respects max_size (default 4096) by scaling the whole result down if it would exceed it.
match_image_size controls whether inputs get resized to a common size at all. Leave it on for clean grids; turn it off if you want to preserve each image's native resolution and you're prepared for misaligned edges. background_color handles the seams and any padding - black/white/gray, or transparent if you want to keep an RGBA canvas.
Inputs and outputs that matter
mode-smart(auto grid) vssequential(linear alongdirection).image_1…image_4- the frames; 2–4 of them.gap- pixels between cells (0–256).max_size- cap on the longest output side, 64–8192, default 4096.
Single output: images (IMAGE), a single frame with everything stitched. Wire it to a Preview or Save and done. If you need the individual cell dimensions for later steps, compute them from match_image_size and the input sizes - the node doesn't expose per-cell geometry.
Install and gotchas
Via ComfyUI Manager (search "ComfyUI-UniversalToolkit") or:
cd ComfyUI/custom_nodes
git clone https://github.com/whmc76/ComfyUI-UniversalToolkit
pip install -r requirements.txt
Restart ComfyUI. No models, no keys; Pillow/numpy/torch only.
The gotcha that bites people: smart mode with three images produces a non-uniform layout, and if you feed images of wildly different aspect ratios with match_image_size on, the node stretches the smaller ones to match - the short edge can distort badly for text or faces. For a quick A/B of two 1024×1024 gens it's perfect; for a panel of mixed 16:9 and 4:3 shots, you'll want to normalize aspect ratios upstream first. Also, gap only applies where cells actually meet, so expect the outer edge to be flush against the canvas.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| image_1 | IMAGE | — | |
| mode | COMBO | smart | 2 options: sequential, smart |
| direction | COMBO | right | 4 options: right, down, left, up |
| match_image_size | BOOLEAN | false | — |
| max_size | INT | 409664–8192 | — |
| background_color | COMBO | black | 4 options: black, white, gray, transparent |
| gap | INT | 00–256 | — |
| image_2opt | IMAGE | — | |
| image_3opt | IMAGE | — | |
| image_4opt | IMAGE | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |