ComfyUI Node

Inpaint Crop Pro

Inpaint Crop Pro

By Code2Collapse·Created 6 months ago·Updated a day ago· 52
Inpaint Crop Pro
  • image
  • mask
  • optional_context_mask
  • stitcher
  • cropped_image
  • inpaint_mask
  • stitch_blend_mask
  • info
downscale_algorithmbilinear
upscale_algorithmbicubic
preresizefalse
preresize_modeensure minimum resolution
preresize_min_width1024
preresize_min_height1024
preresize_max_width16384
preresize_max_height16384
mask_fill_holestrue
mask_expand_pixels0
mask_invertfalse
mask_blend_pixels32
mask_hipass_filter0.10
extend_for_outpaintingfalse
extend_up_factor1.00
extend_down_factor1.00
extend_left_factor1.00
extend_right_factor1.00
context_from_mask_extend_factor1.20
auto_context_factorfalse
aspect_presetCustom
output_resize_to_target_sizetrue
output_target_width512
output_target_height512
output_padding32
device_modegpu (much faster)
wan_align_multiple16
wan_temporal_smooth_frames0.0
wan_stable_croptrue
wan_mask_polarityregenerate_subject
inpaint_mask_modehard_binary
stitch_blend_modegaussian
blend_radius32
video_stable_temporal_sigma3.0
video_stable_dilate_px-1
video_stable_blur_sigma-1.0
fill_masked_areanone
roto_qualityfalse

Inpaint Crop Pro is the first half of the crop-and-stitch inpainting pattern that changed how the community edits images. The pattern comes from lquesada's ComfyUI-Inpaint-CropAndStitch: instead of running a diffusion model over the whole frame (which passes everything through VAE encode/decode and degrades pixels you didn't want touched), you crop tight around the mask, sample the crop at high resolution, and stitch it back. The unmasked part of the image never goes through the model at all - that's the property that made the pattern win. A 64px eye gets 1024px of generation budget.

This node is the lquesada API reimplemented and extended, inside ComfyUI-CustomNodePacks (the ~72-node pack from Code2Collapse / Likhith-24). It's the flagship of the author's C2C/Inpaint suite, and it produces the data structure (stitcher) that the pack's Paste Back and Stitch Pro nodes consume.

How it works

Feed it an image and a mask (white = the region to inpaint) and it:

  1. Computes the mask's bounding box, then grows it by context_from_mask_extend_factor (default 1.2) so the crop includes context, not just the mask.
  2. Resizes the crop to your target sampling resolution (output_target_width / output_target_height, default 512×512, padded to a multiple of output_padding, default 32).
  3. Produces two separate masks: an inpaint_mask for the model (clean, in the crop's space) and a stitch_blend_mask for compositing back (feathered by mask_blend_pixels, default 32).
  4. Hands you everything in one stitcher dict plus the cropped_image, inpaint_mask, stitch_blend_mask, and an info string.

The knobs a beginner actually sets:

  • mask_blend_pixels (default 32, lquesada's number) - the feather width for the stitch seam. Too small → visible edge; too large → the inpainted region bleeds into untouched pixels.
  • context_from_mask_extend_factor - how much context around the mask. 1.2-1.5 is a sane band.
  • output_target_width / output_target_height - the resolution the sampler will work at. Bigger = more detail budget, more VRAM.
  • extend_for_outpainting - with the four extend_*_factor inputs, edge-replicates the image so you can outpaint beyond the frame. The outpainting workflow lives here.
  • roto_quality - the pack's "Roto-Sync" mode: tightens the seam for clean alpha edges, forcing a Laplacian pyramid blend. Great for masks that need crisp boundaries.

Outputs to remember: stitcher is the thing you must preserve and feed to the stitch node - losing it means rebuilding the crop. The info string is a diagnostic worth a glance before you spend a sampler run: it tells you what the crop stage actually decided (crop box, target size, padding).

The full loop

image + mask → Inpaint Crop Pro → cropped_image + inpaint_mask → [any inpaint sampler]
                          └────── stitcher ──────────────────────────────→ Inpaint Paste Back / Stitch Pro → final

Use any model on the crop - Flux, Qwen-Image, a plain SD inpaint - then close the loop with the pack's stitch node.

Installing it

Ships in ComfyUI-CustomNodePacks. ComfyUI Manager → search "CustomNodePacks", or:

cd ComfyUI/custom_nodes
git clone https://github.com/Code2Collapse/ComfyUI-CustomNodePacks.git

Needs opencv-python>=4.7.0 and scipy>=1.10.0 (pack requirements - install just what's missing; the full requirements.txt can clobber ComfyUI's torch). No model downloads. Restart ComfyUI.

Common issues

  • Visible seam after stitching - raise mask_blend_pixels, or switch the stitch side to Laplacian pyramid blending, which the pack's Stitch Pro handles.
  • Crop too tight, model hallucinating - raise context_from_mask_extend_factor; the model needs context to know what it's inpainting into.
  • Mask missing → whole image processed - mask is optional on this node; without it the behavior degrades toward full-frame. Wire a real mask.
  • Model output misaligned or blurred - the KB notes even Qwen-Image-Edit-2509 misaligns slightly at native res; the crop-and-stitch pattern is precisely the community's fix for that, so keep output_target_* a multiple of the model's favorite resolution and let Stitch handle placement.

The honest take: this is the node the whole inpaint suite is built around, and it earns its keep - crop-and-stitch is the difference between "edit the whole image and hope" and "edit exactly the pixels you meant, at full detail."

CategoryC2C/Inpaint

Inputs (41)

NameTypeDefaultDescription
imageIMAGE
downscale_algorithmCOMBObilinear7 options: nearest, bilinear, bicubic, lanczos, box, hamming, +1
upscale_algorithmCOMBObicubic7 options: nearest, bilinear, bicubic, lanczos, box, hamming, +1
preresizeBOOLEANfalseResize input image before processing (lquesada-style).
preresize_modeCOMBOensure minimum resolution3 options: ensure minimum resolution, ensure maximum resolution, ensure minimum and maximum resolution
preresize_min_widthINT10240–16384
preresize_min_heightINT10240–16384
preresize_max_widthINT163840–16384
preresize_max_heightINT163840–16384
mask_fill_holesBOOLEANtrueMark fully-enclosed regions as masked.
mask_expand_pixelsINT00–16384Dilate mask by this many pixels.
mask_invertBOOLEANfalseInvert mask (anything masked is kept).
mask_blend_pixelsINT320–64Pixels of feather for stitch blending (lquesada default 32).
mask_hipass_filterFLOAT0.100–1Zero out mask values below this threshold.
extend_for_outpaintingBOOLEANfalseExtend image with edge-replicated padding for outpainting.
extend_up_factorFLOAT1.000.01–100
extend_down_factorFLOAT1.000.01–100
extend_left_factorFLOAT1.000.01–100
extend_right_factorFLOAT1.000.01–100
context_from_mask_extend_factorFLOAT1.200.1–100Resize context bbox around the mask. 1.0 = exact mask bbox. >1 grows outward (1.5 = +50% on every side). <1 shrinks INWARD so the crop is tighter than the mask bbox (0.7 = inset 15% on every side). Useful for 16:9 / portrait single-still crops where the mask bbox is larger than the subject you actually want sampled.
auto_context_factorBOOLEANfalseOverride context_from_mask_extend_factor automatically so the mask fills ~70% of the resulting crop area. Uses actual mask AREA (not just bbox) to handle sparse / thin / non-convex masks. Result clamped to [0.30, 10.00]. OFF = use the manual slider above. Recommended ON for batch / unattended runs.
aspect_presetCOMBOCustomForce the output crop aspect ratio. Custom : use output_target_width / _height as-is (legacy lquesada behaviour - DEFAULT). Auto : pick best of {Square, 16:9, 9:16, 4:3, 3:4} from the mask bbox aspect. Square / 16:9 / 9:16 / 4:3 / 3:4 : keep the SHORTER of (output_target_width, output_target_height) and recompute the longer side from this AR. Multiple-of-padding rounding still applies downstream.
output_resize_to_target_sizeBOOLEANtrueForce output to a specific resolution for sampling.
output_target_widthINT51264–16384
output_target_heightINT51264–16384
output_paddingCOMBO328 options: 0, 8, 16, 32, 64, 128, +2
device_modeCOMBOgpu (much faster)2 options: cpu (compatible), gpu (much faster)
wan_align_multipleINT161–256Force final crop W/H to multiples of this (Wan VAE patchify; 16 recommended).
wan_temporal_smooth_framesFLOAT0.00–64Gaussian smoothing of mask along time axis (frames). 0 disables.
wan_stable_cropBOOLEANtrueUse a single union bbox across all frames (Wan replacement-mode).
wan_mask_polarityCOMBOregenerate_subjectregenerate_subject: mask=1 -> regenerate (lquesada). preserve_subject: mask=0 -> regenerate (Wan2.2 replacement: mask=1 keeps environment).
inpaint_mask_modeCOMBOhard_binaryWhat the inpaint sampler sees: hard_binary (crisp), slight_feather (gentle), soft_blend (very soft).
stitch_blend_modeCOMBOgaussianHow the result is composited back: gaussian, edge_aware (Sobel), laplacian_pyramid, frequency_blend, video_stable.
blend_radiusINT321–256Feather radius for the stitch blend mask (independent of mask_blend_pixels).
video_stable_temporal_sigmaFLOAT3.00–10[video_stable only] Temporal Gaussian sigma in frames. 3.0 ≈ 9-frame window. Higher = smoother but laggier on fast motion. 0 = off.
video_stable_dilate_pxINT-1-1–128[video_stable only] Pixels to push the blend zone into background BEFORE feathering. -1 = derive from blend_radius. 16-32 typical.
video_stable_blur_sigmaFLOAT-1.0-1–128[video_stable only] Spatial Gaussian sigma for the wide feather. -1 = derive from blend_radius (×0.75). Match to dilate value.
fill_masked_areaCOMBOnoneFill masked region in the cropped image: none, edge_pad (Gaussian smear), neutral_gray, original.
maskoptMASK
optional_context_maskoptMASK
roto_qualityoptBOOLEANfalseRoto-Sync mode: tightens the inpaint seam for clean alpha edges. Forces laplacian_pyramid blend, halves blend_radius (min 4), and pre-erodes the inpaint mask by 1 px so the stitch falls just inside the subject. Safe to leave OFF for general inpaint; turn ON for compositing / roto / VFX work where boundaries must not bleed.

Outputs (5)

NameTypeDescription
stitcherSTITCHER
cropped_imageIMAGE
inpaint_maskMASK
stitch_blend_maskMASK
infoSTRING