Differential Diffusion Advanced
Soft-mask inpainting with a strength dial
- model
- samples
- mask
- MODEL
- LATENT
Regular inpainting is binary: a pixel is either inside the mask (repaint it) or outside (leave it). That hard edge is why inpaints so often show a visible seam. Differential Diffusion is the fix, it treats the mask as a soft, per-pixel map of how much to change each area, so the edit fades smoothly from "fully repainted" to "untouched" instead of stopping at a wall. This is the node behind seamless partial edits, gradient masks, and the "just nudge this region" look.
This is kijai's Advanced take on it, in KJNodes, and the one thing it adds over the standard Differential Diffusion node is a multiplier that scales how hard the mask bites. Small addition, real control.
How it works
Differential Diffusion patches the model so that, during denoising, the mask's grayscale values decide when each pixel stops being updated across the diffusion schedule. Bright mask areas get changed a lot; darker areas get changed progressively less; black is left alone. The gradient in your mask becomes a gradient in the edit. The "advanced" multiplier scales that mapping, letting you push the whole effect stronger or weaker (and, since it goes negative, invert the sense of the mask).
Because it patches the model, it sits before your sampler: it outputs a modified MODEL you route into KSampler, alongside the latent it also passes through.
The inputs and outputs that matter
model- the model to patch. The patched version comes back out.samples- the latent (your image encoded), passed through to theLATENToutput.mask- the soft mask. This is where Differential Diffusion earns its keep: use a gradient mask (blurred edges, feathered regions), not a hard-edged one, so you actually get the smooth falloff. A binary mask throws away the whole advantage.multiplier(default 1.0, range -10 to 10) - scales the mask's influence. Above 1 makes the effect more aggressive; below 1 softens it; negative values flip which parts get edited. Start at 1.0 and adjust only if the transition is too harsh or too weak.
Outputs: MODEL (patched, into KSampler) and LATENT (the samples, forwarded).
Installing it
You likely have KJNodes already. If not: ComfyUI Manager → search KJNodes for ComfyUI → install → restart. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/kijai/ComfyUI-KJNodes
pip install -r ComfyUI-KJNodes/requirements.txt
Restart ComfyUI. No extra models; it patches whatever checkpoint you're already running.
Common issues
The edit has a hard seam anyway. You're feeding it a hard-edged mask. Differential Diffusion needs a soft mask to do its thing, blur or feather your mask first, so there's an actual gradient for the node to interpret. A crisp black/white mask gives you crisp binary inpainting, defeating the point.
The wrong region got changed. Check mask polarity, and remember multiplier can go negative and invert the effect. If everything's backwards, either invert the mask upstream or flip the sign of the multiplier.
"It's in the _for_testing category, is it safe?" That category placement just reflects how it's registered; it works. But it does mean you should treat it as less locked-down than a core node, if behavior changes across an update, that's why.
No visible change. Confirm you routed the patched MODEL output into your sampler (not the original model), and that samples is a real encoded latent of the image you're editing. If the model wire still comes from the loader, the patch never applies.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| samples | LATENT | — | |
| mask | MASK | — | |
| multiplier | FLOAT | 1.000-10–10 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| MODEL | MODEL | — |
| LATENT | LATENT | — |