Merge—horizontal_vertical
Stitching side-by-side in ComfyUI
- image_one
- image_two
- merged_image
If you've ever wanted a before/after comparison image, a prompt-variation grid, or a single reference image that's really two images glued together, you know ComfyUI doesn't hand you that for free. The built-in nodes are about generating, not arranging. That's where the Merge-horizontal_vertical node (class ASVL, from the ComfyUI_merge_ASVL pack) comes in. It's exactly one trick: take two images, put them side by side or on top of each other, and hand you back one merged image. That's the whole pack, and honestly, that's fine.
The name is doing real work here - it's not calling an API, it's not loading a model, and it has zero dependencies beyond the torch that ComfyUI already ships. Think of it as the "image glue" node you reach for at the end of a workflow, right before PreviewImage or SaveImage.
How it works
Under the hood it's embarrassingly simple: a torch.cat() call. ComfyUI images are tensors shaped (batch, height, width, channels), so merging vertical stacks along the height axis (one image on top of the other) and horizontal stacks along the width axis (side by side). There's no resizing, no blending, no seam handling - a hard, clean stitch. Two tensors in, one tensor out.
Because it's that dumb, it's also that strict: the two inputs must have identical shapes. Different resolutions, different widths, even a mismatched batch count, and the node throws ValueError: Both images must have the same dimensions and refuses to run.
The inputs that matter
There are only three, and only two of them are real:
image_one/image_two(IMAGE, required) - the two images to merge. Wire these fromLoadImage, from a VAE decode, or from anything else outputting an IMAGE.direction(STRING, optional, defaults tohorizontal) - here's the trap: this is a plain text field, not a dropdown. You have to typehorizontalorverticalyourself, lowercase, exactly. Anything else -Horizontal,horizontal,v- triggersValueError: Direction must be one of ['horizontal', 'vertical'].
Output is a single merged_image (IMAGE) that feeds straight into PreviewImage, SaveImage, or anything else that eats an IMAGE.
Installing it
The easiest way is ComfyUI Manager: search for ComfyUI_merge_ASVL and hit install. Or do it by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/aisabervisionlab/ComfyUI_merge_ASVL
Then restart ComfyUI. That's it - no requirements.txt, no model downloads, nothing to configure. The repo even ships an example workflow (example/merge_example.json) you can drag straight onto the canvas to see it in action.
The traps that will actually bite you
- Mismatched sizes are a hard error. The README says it plainly: same-size images only. If your two inputs don't match, resize or crop them first (an
ImageScaleset to a fixed width/height works fine). This is the most common failure by far - people feed a 1024×1024 and a 512×768 and wonder why nothing runs. - Batch size counts as part of "same dimensions." If one input comes from a batch of two images and the other from a single image, the shapes don't match and it errors. Feed it one image at a time.
- Two at a time, no more. To merge three or four images you chain nodes: the example workflow builds a 2×2 grid by merging two pairs vertically, then merging those results horizontally. Daisy-chaining works, it's just manual.
The verdict
There are fancier image-combine nodes out there that resize mismatched inputs for you and give you layout control. If you need that, go get one of those. But for "glue two matching images together and move on," this node does the job with zero weight on your environment - and in the dependency-hell world of custom nodes, a pack that can't break your install has real value. One light aside: the repo's select_direction helper is dead code that was clearly meant for a CLI version; ignore it, the node runs fine without it.
Just remember the two rules and you'll never get stuck: match your sizes, and spell vertical correctly.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| image_one | IMAGE | — | |
| image_two | IMAGE | — | |
| directionopt | STRING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| merged_image | IMAGE | — |