Nodes/PortraitUtils/Stitch Two Images by Mask
ComfyUI Node

Stitch Two Images by Mask

Blend two images together along a mask without a seam

By heyburns·Created 11 months ago·Updated 4 months ago· 1
Stitch Two Images by Mask
  • image_a
  • image_b
  • mask
  • stitched
  • processed_mask
invert_maskfalse
bypass_maskfalse
opacity1.00
feather_radius5
force_sizefalse
target_width1344
target_height768

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_size with target_width/target_height (defaults 1344×768) resizes both inputs to a common canvas before blending, which is essential when image_a and image_b don'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_radius too 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_size off 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_mask looks 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.

CategoryPortraitUtils/Composite

Inputs (10)

NameTypeDefaultDescription
image_aIMAGE
image_bIMAGE
invert_maskBOOLEANfalse
bypass_maskBOOLEANfalse
opacityFLOAT1.000–1
feather_radiusINT50–100
force_sizeBOOLEANfalse
target_widthINT134416–8192
target_heightINT76816–8192
maskoptMASK

Outputs (2)

NameTypeDescription
stitchedIMAGE
processed_maskMASK