Resynthesize
The Resynthesize node
- image
- mask
- IMAGE
This node is the closest thing to Photoshop's content-aware fill that runs inside ComfyUI - and it does it with zero diffusion, zero VRAM, and zero model download. It's a direct port of Paul Harrison's 2005 Resynthesizer, the algorithm GIMP shipped as its heal-selection plugin years before Adobe bolted "content aware" onto Photoshop. Feed it an image and a mask, and it fills the masked region by copying texture from the pixels around it. No sampling loop, no checkpoint, no prompt. It's done in under a second on CPU.
That sounds like a relic in a world of Flux Fill and instruction-edit models, and for some jobs it is. Diffusion inpainters reason about what should be behind the removed object; this thing just pastes in matching texture. For a big region - "replace this entire wall of a room" - it runs out of source material and produces mush, which the pack README concedes up front ("sometimes yields worse results"). Where it shines is the small, texture-heavy cleanup: watermark removal, sensor dust, a stray cable or mic in a product shot, an object crossing a brick or grass background. That's exactly the use people actually report - it "works very well for small areas, like watermark removal" and is "a very quick and effective first pass for inpainting."
How it works
Harrison's resynthesizer is a non-parametric texture-synthesis algorithm. It walks the mask from the edge inward, and for each pixel to fill it searches the unmasked texture for a patch whose neighborhood best matches the already-filled neighbors, then copies it. Greedy, deterministic, and cheap. The heavy lifting happens in a small C library (bootchk's port, via 61315's stripped-down version), which ships prebuilt inside the resynthesizer pip package - a ~120 KB wheel with a bundled .so/.dll/.dylib. The node just converts your tensors to PIL images, passes your settings through to the C engine, and converts the result back.
One honest caveat: the author says himself he hasn't fully reverse-engineered every parameter, so treat the fine dials as "leave at default until you need them."
Inputs and outputs
The node takes image (IMAGE) and mask (MASK) plus a pile of tunables, and returns one IMAGE with the mask region filled in.
The mask marks what gets filled. In the bundled workflow, Segment Anything produces the mask (white over the cat) and the node removes the cat - so white is "the thing to erase." If it fills the wrong area, invert the mask first.
The three that actually change results:
- context - the fill order/strategy, with options like
Patching,Shuffle,Brushfire (inward), and directional variants. "Brushfire inward" fills from the boundary moving in, which is usually what you want for object removal; the directional options scan in rows or columns. - patchSize (default 30) - how big a neighborhood the matcher uses. Bigger = more coherent on large flat areas but riskier on fine detail.
- maxProbeCount (default 200) - how many candidate patches it tries before giving up; higher costs time, and 200 is already a lot.
mapWeight and sensitivityToOutliers fine-tune the match scoring; makeTileable forces a seamless tile (handy for generating repeatable textures - the one mode where "Patching" context really earns its keep). Leave them alone to start.
Install
The easy way is ComfyUI Manager: search "resynthesizer", install, restart. Or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/brayevalerien/ComfyUI-resynthesizer
cd ComfyUI-resynthesizer
pip install -r requirements.txt
That requirements file is a single line: resynthesizer. No models, no giant dependencies - one of the lightest installs in the custom-node ecosystem.
Gotchas
- Single image only. The code does
squeeze(0)and converts straight to PIL, so feed it one image per call. A batch of images silently drops everything but the first. - It's RGB-only. The input is converted to RGB and the mask to grayscale on the way in, so the output is a plain RGB image - wire it into whatever you like downstream, or use it as a pre-fill before a diffusion inpaint pass.
- The texture has to come from somewhere. Small mask on a busy background: excellent. Large mask or a flat empty region: it invents, and it isn't good at inventing. Use it for the first pass, then let an inpaint model finish.
- Rare import error: the module also imports scikit-image (dead code, but it's at the top). ComfyUI ships it, so you'll only hit an
ImportErrorin a hand-rolled minimal venv -pip install scikit-imagefixes it.
It's not a replacement for diffusion inpainting, and it doesn't pretend to be. It's the boring, instant, deterministic tool you reach for when you just need the wire gone and don't want to babysit a sampler for it.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| mask | MASK | — | |
| makeTileable | BOOLEAN | false | — |
| context | COMBO | 9 options: Patching, Shuffle, Brushfire (inward), Directional (horizontal, inward), Directional (vertical, inward), Brushfire (outward), +3 | |
| mapWeight | FLOAT | 0.500–1 | — |
| sensitivityToOutliers | FLOAT | 0.1170–1 | — |
| patchSize | INT | 300–60 | — |
| maxProbeCount | INT | 200 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |