Nodes/ComfyUI-ZFRNodes/Inpaint Studio (ZFRNodes)
ComfyUI Node

Inpaint Studio (ZFRNodes)

Paint a mask inside the node

By zfrsgtcu·Created 3 months ago·Updated 13 days ago· 32
Inpaint Studio (ZFRNodes)
  • reference_images
  • image
  • log
image
prompt
trigger_words
use_referencestrue
unet_name
vae_name
clip_name
clip_typeflux2
lora_name
lora_strength1.00
denoise1.00
grow_mask6
feather_mask0
noise_masktrue
differential_diffusionfalse
composite_backtrue
steps20
cfg1.0
guidance3.5
sampler_nameeuler
schedulersimple
seed0
seed_moderandom
save_to_diskfalse
output_subdirinpaint_studio
filename_prefixinpaint

Inpainting in ComfyUI normally means a five- or six-node chain - Load Image, Mask Editor, InpaintModelConditioning, a KSampler, a composite - and a prayer that the mask and the sampler actually line up. Inpaint Studio is the ZFRNodes take on that: load an image, paint a mask, and sample, all inside one node. It's a "mini Photoshop" that lives in the graph.

Worth a sentence of framing before you install it. The mask-based approach isn't the trendy one anymore - instruction-edit models like Flux 2 Klein and Qwen-Image-Edit will fix a sentence worth of changes from text alone. What a mask still owns is surgical control: pixels outside the mask stay bit-identical, and you get a denoise dial instead of a yes/no. If you're the kind of person who still prefers masks for exactly that reason, this node is squarely aimed at you.

How it works

You load an image right in the node (upload, drag-and-drop, or paste with Ctrl+V while it's selected), then right-click → open it in ComfyUI's built-in Mask Editor and paint the area you want regenerated. The mask gets embedded in the PNG's alpha channel, and the node reads it back out. Leave the mask empty and it warns and returns the original unchanged - a genuinely useful safeguard against accidentally running inpaint with nothing painted.

From there the settings are grouped into tabs instead of one scrolling widget list. The Inpaint tab is where the interesting stuff lives: grow_mask (default 6, dilate/erode the edges), feather_mask (soften them), noise_mask, differential_diffusion (smoother blending at the mask boundary), and composite_back (default on - pastes the result back onto the untouched original, so everything outside the mask stays pixel-identical). The Model tab holds the loaders and an optional LoRA; Generation has the sampler controls; Output handles saving to disk.

The standout feature is use_references. Turn it on and connect any IMAGE to reference_images, and the masked area can pull content from that reference via the same Flux2 ReferenceLatent mechanism the rest of the pack uses - mask a bag and write "add the logo shown in image 1 to the bag", and it transfers the logo in. With references off, the masked area is repainted purely from the text prompt - "change hair color to red", mask the hair, done.

The inputs that matter

  • image - load it here, don't wire a Load Image node.
  • prompt + trigger_words - what should appear in the masked area.
  • use_references - toggle for pulling content from reference_images instead of prompt-only.
  • denoise - the dial that decides how much of the mask gets regenerated; 1.0 (the default) is a full rewrite of the masked region.
  • composite_back - keep this on unless you want the whole frame re-sampled.

Outputs: image (the inpainted result) and log.

Install

Standard ZFRNodes install - search ComfyUI-ZFRNodes in ComfyUI Manager, or:

cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/zfrsgtcu/ComfyUI-ZFRNodes.git

Dependencies are just numpy, torch, and Pillow - already present in any ComfyUI. One gotcha specific to this node: the tabbed UI is added by a frontend script, so a full ComfyUI restart is required after installing or updating; a browser refresh will leave the node looking broken.

Common issues

  • It returned the original image - that's the empty-mask safeguard doing its job; paint something and re-run.
  • Reference mode does nothing - use_references must be on and the model must support ReferenceLatent; the pack is tested on flux-2-klein with a Qwen text encoder.
  • Seams at the mask edge - this is the classic mask complaint, not a node bug. Raise grow_mask a little and nudge feather_mask up; differential_diffusion exists specifically for this.
  • Seed mode is random or fixed only - no increment here, so if you want a controlled series of variations you set seeds yourself.
Categoryzfr-nodes

Inputs (27)

NameTypeDefaultDescription
imageCOMBO1 options: example.png
promptSTRING
trigger_wordsSTRING
use_referencesBOOLEANtrue
unet_nameCOMBO0 options:
vae_nameCOMBO0 options:
clip_nameCOMBO0 options:
clip_typeCOMBOflux228 options: stable_diffusion, stable_cascade, sd3, stable_audio, mochi, ltxv, +22
lora_nameCOMBO1 options: None
lora_strengthFLOAT1.00-10–10
denoiseFLOAT1.000–1
grow_maskINT6-64–256
feather_maskINT00–256
noise_maskBOOLEANtrue
differential_diffusionBOOLEANfalse
composite_backBOOLEANtrue
stepsINT201–200
cfgFLOAT1.00–30
guidanceFLOAT3.50–100
sampler_nameCOMBOeuler44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38
schedulerCOMBOsimple9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3
seedINT00–18446744073709550000
seed_modeCOMBOrandom2 options: random, fixed
save_to_diskBOOLEANfalse
output_subdirSTRINGinpaint_studio
filename_prefixSTRINGinpaint
reference_imagesoptIMAGE

Outputs (2)

NameTypeDescription
imageIMAGE
logSTRING