Nodes/ComfyUI-DetailedRegionInpaint/Prepare Inpaint Region
ComfyUI Node

Prepare Inpaint Region

Give the bit you're fixing its own 1024 pixels

By ArtemKo7v·Created about 14 hours ago·Updated about 12 hours ago· 0
Prepare Inpaint Region
  • image
  • mask
  • image
  • mask
  • region_data
◄padding32►
◄scale2.0►
◄max_size1024►
◄mask_blur0.0►

The problem this solves

You have a 1024px image and a face in it that occupies 60 pixels. You mask the face and inpaint the whole frame at denoise 0.5, and the model has almost no latent budget to spend there - the latent is 128px wide and the face is under eight pixels of it. You get a slightly softer version of the face you already had. That's not a model problem, it's arithmetic.

Prepare Inpaint Region fixes the arithmetic. It's the first of two nodes in ArtemKo7v's ComfyUI-DetailedRegionInpaint pack. Feed it your full image plus your mask; it finds the bounding box of the masked pixels, pads it, crops that region out and enlarges it to a size worth sampling. A 60px face becomes a 400px crop, and the sampler finally has something to work with.

That's the "only masked" idea from A1111 with the coordinates automated. If you know lquesada's Inpaint Crop and Stitch, it's the same pattern, smaller: Prepare = Crop, Restore Inpaint Region = Stitch. That pattern matters more than ever in 2026, now that instruction editors like Qwen-Image-Edit and Flux 2 Klein re-emit the whole frame and shift every unmasked pixel a little. The mask is the guarantee nothing outside it moves - and full-resolution detail on a small region is one of the few things a whole-frame editor structurally cannot do at any setting.

How it works

From nodes.py, and refreshingly boring:

  1. Threshold the mask at 1e-6 and take the min/max of nonzero pixels - a bounding box, not the mask outline.
  2. Expand by padding, then clip to the image bounds. So no outpainting: a mask flush against the edge just gets less padding.
  3. Crop, blur the mask if asked, then compute effective_scale = min(scale, max_size / crop_width, max_size / crop_height).
  4. Resize - bicubic with antialiasing for the image, bilinear for the mask, both clamped 0–1.

That effective_scale line is the design's honest bit and also its main trap - max_size wins over scale. Mask most of a 4K photo and scale 2.0 becomes 0.25: your "detail pass" is quietly a downsample. Check the crop size before you decide the node is broken.

It also snaps the target to multiples of 8 when that costs under 10% of the area, moves the aspect ratio by ≤1% and doesn't force a downscale. Ask for 1030×780 and you get 1024×776. The VAE's latent grid is 8-aligned; that's the author nudging you off dimensions that would get silently padded inside the encoder.

The inputs that matter

Everything is required, including the two obvious ones: image and mask. Beyond those, four widgets:

  • padding (default 32, 0–1024) - context pixels around the mask. 32 is the floor; for faces or hands 32–64 is where the model gets enough skin and hair to blend. Too tight and the crop has no idea what it's continuing.
  • scale (default 2.0, 1.0–8.0) - enlargement factor. 1.0 keeps the crop as-is unless max_size forces a shrink.
  • max_size (default 1024, 64–8192, step 8) - the ceiling on either dimension. Set it to your checkpoint's native resolution: 1024 for SDXL/Flux-family, 512 for SD 1.5. Bigger isn't better; you're paying VRAM for a crop the model never trained on.
  • mask_blur (default 0.0, 0–256) - Gaussian sigma on the mask leaving this node. Bounds are computed from the unblurred mask, so blur can't move your crop, and it feathers what the sampler sees, not the final composite - Restore uses the original mask. If you thought this slider hides the seam, it doesn't.

Three outputs. image and mask are the enlarged crop and its matching crop-sized mask → into your inpainting stack. region_data is a custom DETAILED_REGION socket carrying the crop geometry (source size, x/y, crop size, target size, effective scale). It has exactly one consumer: Restore. You never type coordinates, which is the whole point.

Wiring it up

Load Image → Prepare Inpaint Region → InpaintModelConditioning (or your inpaint checkpoint's conditioning) → KSampler → Restore, with the original image and mask from the loader also landing on Restore. Running an edit model on the crop instead? You often won't use the produced mask at all - the crop has already isolated the region.

How low you can push denoise depends on the conditioning path. The community answer in crop-and-stitch threads is consistent: an inpaint conditioning node is what lets you run low denoise properly, and low denoise on a native-resolution crop is the entire trick. Skip it and you're at 1.0-strength inpainting, repainting the region from scratch.

Install

ComfyUI Manager → search "ComfyUI Detailed Region Inpaint" (publisher artemko7v), install, restart. Or:

cd ComfyUI/custom_nodes
git clone https://github.com/ArtemKo7v/ComfyUI-DetailedRegionInpaint
# restart ComfyUI

No model downloads, no pip step - pyproject.toml declares an empty dependency list and PyTorch comes from ComfyUI, so no torch-reinstall roulette. Both nodes land under ArtemKo7v/inpaint.

The pack ships unit tests, which is more than most do:

cd ComfyUI/custom_nodes/ComfyUI-DetailedRegionInpaint
python -m unittest discover -s tests -v

Where people get burned

Batch size 1 only. A list of images on one wire counts as a batch and it refuses with only batch size 1 is supported, rather than mangling it. Run them individually.

The mask must match the image exactly. It's validated against the image's H and W, so a resized mask or a SAM output at another resolution errors. An all-zero mask throws input mask is empty instead of cropping the whole frame - worth checking if you derive masks by thresholding.

"My crop is smaller than scale 2.0 asked for." That's max_size. Raise the ceiling, or accept that the region was already big - in which case a detail pass is the wrong tool and sampling the whole frame is cheaper.

"The seam still shows." Not this node's fault, and not fixable with mask_blur. Soften the mask at the source - a tapered GrowMask, or a soft brush in the mask editor - because mask values between 0 and 1 are honoured all the way to the blend. The trade for all this is a 1024×1024 sample instead of a 4K one, plus a second VAE round trip on the crop.

CategoryArtemKo7v/inpaint

Inputs (6)

NameTypeDefaultDescription
imageIMAGE—
maskMASK—
paddingINT320–1024—
scaleFLOAT2.01–8—
max_sizeINT102464–8192—
mask_blurFLOAT0.00–256—

Outputs (3)

NameTypeDescription
imageIMAGE—
maskMASK—
region_dataDETAILED_REGION—