Stitch Two Images by Mask
Blend two images together along a mask without a seam
- image_a
- image_b
- mask
- stitched
- processed_mask
Compositing two images with a mask usually ends in a visible seam - a hard alpha edge that says "I was glued here." StitchByMask is the pack's seam-killer: it takes image_a and image_b plus a mask, and blends them with a feathered falloff along the mask boundary, so the transition reads as a gradient instead of a cut. It's the node you reach for when an outpainted region needs to melt back into the original photo rather than sit on top of it.
The mechanism is mask-guided alpha blending with polish. You feed two IMAGEs and a MASK; the mask decides which pixels come from which image (with invert_mask to flip the assignment). Then:
feather_radius(default 5, 0–100) blurs the mask edge with a Gaussian falloff, turning the hard boundary into a ramp. This is the seam-killer - crank it up for large composite regions, keep it low for precise edges like a face boundary.opacity(default 1, 0–1) is a global blend strength over the whole result, handy for fading a layer in rather than fully committing.bypass_mask(default off) ignores the mask entirely and just does a straight opacity blend - a quick way to A/B "masked blend" vs "no mask" without rewiring.force_sizewithtarget_width/target_height(defaults 1344×768) resizes both inputs to a common canvas before blending, which is essential whenimage_aandimage_bdon't match dimensions (a padded outpaint region vs. the original). Off means the images must already align.
Outputs are stitched (the blended image) and processed_mask - the mask after inversion, feathering, and whatever else you applied. That second output is the quietly important one: it lets you see exactly what alpha the blend actually used, and you can feed it downstream if the next stage needs the same region.
This slots naturally into the outpaint workflow: outpaint a region, stitch it back onto the original with a feathered mask, and the extension reads as continuous. It's also the natural partner for MQBBoxMin/FitAspectHeadSafe when the composited result needs a clean, head-safe crop afterward.
Install
Manager → search "PortraitUtils", or:
cd ComfyUI/custom_nodes
git clone https://github.com/heyburns/PortraitUtils
Restart. It's torch tensor blending - no extra downloads.
Common issues
- Visible seam remains -
feather_radiustoo small for the scale. A 5px feather is invisible at 1024 wide but nothing at 4K; scale it with the image. - Images don't line up -
force_sizeoff with mismatched dimensions means undefined behavior; turn it on and let it normalize to the target canvas, or pre-align upstream. - The wrong image shows through the mask - flip
invert_mask. processed_masklooks nothing like your input mask - right, it reflects the feathering and inversion that were actually applied; that's the point, not a bug.
Hard seams are the #1 giveaway of amateur composites. This is the node that removes that tell.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| image_a | IMAGE | — | |
| image_b | IMAGE | — | |
| invert_mask | BOOLEAN | false | — |
| bypass_mask | BOOLEAN | false | — |
| opacity | FLOAT | 1.000–1 | — |
| feather_radius | INT | 50–100 | — |
| force_size | BOOLEAN | false | — |
| target_width | INT | 134416–8192 | — |
| target_height | INT | 76816–8192 | — |
| maskopt | MASK | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| stitched | IMAGE | — |
| processed_mask | MASK | — |