Image Expand Merger
The node that finally makes the canvas bigger (and hopes the seam is invisible)
- image1
- image2
- mask
- expand_options
- IMAGE
Image Expand Merger is where the pack's name stops being a lie. The Noiser only pretends to expand - it keeps the canvas the same size and fills a strip with noise. This node is the one that takes the regenerated strip, glues it onto your original image, and hands you the final, actually-bigger result. If the Noiser is the painter, this is the person who cuts the canvas and stitches the new panel on.
How it works depends on the mode you set in Image Expand Option:
- outside (canvas grows): the merger figures out how wide the generated strip is by summing the mask down its middle row or column - the mask is 1.0 across that strip, so the sum is the strip width - crops exactly that much off the generated image, and
torch.cats it onto the original. New canvas, done. - inside (canvas stays): it alpha-composites the generated image over the original using the mask as the blend weight. That's the inpainting composite step, the thing the community keeps yelling at people to remember to do.
Four inputs, and the wiring is specific enough that it's worth spelling out:
- image1 - the original source image. This is the protected side; its pixels survive untouched.
- image2 - the generated output, straight from your
VAE Decode. Critical: this must be the same size as the original. The Noiser keeps dimensions, the sampler keeps dimensions, so VAE Decode gives you the same-size regenerated image and the merger crops the new strip out of it. If you feed it an already-enlarged image, the crop-and-concat will double the strip or misalign everything. - mask - the Noiser's
MASKoutput. This is how the merger locates the generated band, so don't reroute it or reshape it into something unrecognizable. (Light blur is fine - a soft mask still sums to roughly the same width - but don't invert it.) - expand_options - same config node the Noiser reads. Direction and mode must match, which is the whole point of that little node.
The output is a single IMAGE: the merged result. Outside mode, it's bigger than anything you put in; inside mode, it's the same size, composited.
Now the honest part, because this is where people get burned. In outside mode the merger does a hard crop plus concat - there is no feathering and no blend at the seam. The seam's quality is entirely up to your sampling settings. If you see a visible line, that's the classic outpainting failure, and the fixes are all upstream of this node: mask blur so the model blends across the boundary, a denoise around 0.8–1.0 for the extension, and a second low-denoise pass over the seam region. The merger also sums the mask down the middle row/column to infer strip width, which is a neat trick but a heuristic - keep the mask clean and it'll be exact.
There's also a small grace: it handles mismatched channel counts (a 3-channel original against a 4-channel generated image) by padding alpha, and it moves tensors onto the same device, so you won't hit the usual dtype/device wall.
For context on where this sits in the ecosystem: this is the hand-rolled, DIY version of the pattern that Inpaint Crop and Stitch turned into an industry standard. That pack never passes your original pixels through the VAE at all and handles multi-side extension natively; this one is single-direction and does the stitch with a hard cut. If you're doing one-direction strip outpainting and want to see the mechanics with zero dependencies, this pack is a great place to start - but if the original has to survive byte-for-byte or you're extending several sides, reach for the crop-and-stitch pattern instead.
Install, as with the whole pack, is trivial:
# ComfyUI Manager: search "ComfyUI Image Expand Nodes" → Install → restart
# or:
cd ComfyUI/custom_nodes
git clone https://github.com/tuki0918/comfyui-image-expand-nodes.git
# restart - no pip install, no models
Small, MIT-licensed, dependency-free, and the source is one readable file. If a stitch goes wrong, you can read exactly why.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| image1 | IMAGE | — | |
| image2 | IMAGE | — | |
| mask | MASK | — | |
| expand_options | EXPAND_OPTION | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |