Nodes/ARCPaint/ARCPaint KSampler
ComfyUI Node

ARCPaint KSampler

The sampler that edits only what you masked and leaves the rest alone

By DHan315·Created 3 days ago·Updated 2 days ago· 0
ARCPaint KSampler
  • model
  • positive
  • negative
  • latent_image
  • latent
seed0
steps4
cfg1.10
sampler_name
scheduler
denoise0.91
paint_steps0
context_expand2
edge_feather2
refine_denoise0.00

Every whole-frame editor - Qwen-Image-Edit, Kontext, Klein in its default mode - has the same dirty secret: it re-encodes the image and regenerates everything, so the pixels you didn't ask to change still drift a little with every edit. ARCPaint KSampler is the mask-based rebuttal to that. It runs an ordinary sampling pass through the region you masked, then restores the untouched context around it. Think of it as a stock KSampler wearing an inpainting mask, tuned for Flux 2 Klein and packaged under ARC/Paint.

It exists because of a very 2026 problem. Klein is great at editing, but it's not trained for masked inpainting - feed it a full frame and it changes all of it. This is one of DHan315's ARC-node family, built for the ARC CTRL runtime, and the README admits the team's prior user-tested LanPaint workflow is still the visual benchmark while ARCPaint gets tuned. The difference matters: LanPaint's training-free trick adds Langevin "thinking" iterations before each denoise step, which is powerful and slow. ARCPaint deliberately drops that for an independent implementation from plain ComfyUI and PyTorch primitives - the README is emphatic that it neither imports, wraps, nor redistributes LanPaint code - doing the whole job in a single sampling pass, one that's tuned to Klein's fast distilled profile.

How it works

The node reads the mask off your latent's noise_mask - it takes no mask input of its own. If there's no mask, or it's all zero, the node doesn't error; it silently falls back to a plain full-frame sample. With a real mask the pipeline is:

  1. Expand the authored mask by context_expand (in latent pixels) so the model has room to harmonize across the boundary rather than pasting a hard-edged blob.
  2. Sample once through that expanded mask - one plain sampling pass, no second refinement stage in v0.1.1.
  3. Feather and restore. Outside the authored mask, the original latent blends back in over a soft transition band sized by edge_feather. Context is restored in latent space, so no separate compositing node afterward.

Output is a single LATENT that still carries the authored mask on its noise_mask, handy if you want to chain another pass. Wire it to a VAE Decode and you're done.

The inputs that actually matter

The first ten inputs are stock KSampler: model, positive/negative conditioning, latent_image, seed, steps, cfg, sampler_name, scheduler, denoise. Then come ARCPaint's own inputs:

  • context_expand (default 2) - how far the sampling region grows beyond your mask, in latent pixels. At an 8x image-to-latent scale that's roughly a 16-pixel image-space radius per unit. Crank it when you get seams; keep it modest or you're recomputing half the frame.
  • edge_feather (default 2) - width of the transition band between generated and restored context. Too low and you'll see the boundary; too high and the blend band eats into your edit.
  • paint_steps and refine_denoise - legacy no-ops. v0.1.1 removed the old secondary refinement pass; these only exist so old workflows load without rewiring.

The defaults tell you what it was tuned for: steps 4, cfg 1.1, euler_ancestral, normal scheduler, denoise 0.91 - that's the Klein distilled 4-step profile. The MODEL input is model-agnostic (Klein 4B and 9B share the same paint stage), but if you feed it an SDXL or SD 1.5 checkpoint, treat the defaults as suggestions only; a cfg of 1.1 will look awful on a model that expects 7.

Installing it

ComfyUI Manager is easiest - search ARCPaint and install. Or drop it in by hand:

cd ComfyUI/custom_nodes
git clone https://github.com/DHan315/ARCPaint

Then restart ComfyUI; the nodes show up under ARC/Paint. Good news: there are no extra dependencies. dependencies = [] in the pyproject, no model files to download, no torch/CUDA pinning - it's pure ComfyUI primitives. If you run ARC CTRL's own bundled ComfyUI, it manages and syncs this folder for you automatically.

Where people get burned

  • Nothing edits - the whole image regenerates. Your latent almost certainly has no noise_mask. Run your mask through a SetLatentNoiseMask (or equivalent) node between the VAE encode and this sampler. The node won't warn you; the silent full-frame fallback is a code path, not an error.
  • You expect a second pass to refine quality. paint_steps and refine_denoise look like refinement knobs and do exactly nothing in 0.1.1. If the result is undercooked, raise steps or denoise, not those.
  • Edges look wrong. Your context_expand and edge_feather are too small for the resolution, or you're feeding non-Klein defaults (that cfg 1.1 again).

One honest caveat: this pack is brand new (v0.1.1, September 2026) with essentially zero community usage to learn from. It's the ARC baseline, not a claim of parity with LanPaint or FLUX.1 Fill - if the result disappoints, compare against those before you blame the workflow.

CategoryARC/Paint

Inputs (14)

NameTypeDefaultDescription
modelMODEL
positiveCONDITIONING
negativeCONDITIONING
latent_imageLATENT
seedINT00–18446744073709550000
stepsINT41–100
cfgFLOAT1.100–100
sampler_nameCOMBO44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38
schedulerCOMBO9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3
denoiseFLOAT0.910–1
paint_stepsINT00–8
context_expandINT20–12
edge_featherINT20–12
refine_denoiseFLOAT0.000–1

Outputs (1)

NameTypeDescription
latentLATENT