Nodes/ZZX Nodes/ZZX_PaintsUndo
ComfyUI Node

ZZX_PaintsUndo

Take one finished image and walk it backwards one step

By ZZXYWQ·Created 2 years ago·Updated a day ago· 24
ZZX_PaintsUndo
  • image
  • image
  • prompt
◄Prompt►
◄undo_steps500►
◄seed0►

Paints-UNDO is one of those lllyasviel releases that got a big thread, a lot of "how is this even possible," and then almost no maintenance. Given a finished picture, the model predicts an earlier state of it - less shading, fewer strokes, closer to line art. Run it at several positions and you have a plausible drawing process for an image that never had one.

ZZX_PaintsUndo is the single-step version: one image in, one earlier version out. It's the original node in this pack and the author has kept its interface frozen so old workflows don't break, while fixing it to actually return a single image. If you want the thing everyone actually wants - a sequence of frames that reads like a timelapse - that's ZZX_PaintsUndoSequence, and you should probably use that instead. This node is for "I just want one intermediate state" or for keeping an old graph alive.

What it's actually doing

No filter, no fade, no eraser. Real inference through the upstream lllyasviel/paints_undo_single_frame model, a modified UNet that takes two extra conditions: an encoded latent of your finished image, and a scalar "where in the process" value - your undo_steps, 0 to 999. Zero is the original. 999 is close to the earliest strokes. It is not a sampling step count and it does not behave like one; it's a position along a learned axis.

The pack's pipeline loads in stages so a 12 GB card can do it at all: the VAE encodes your source and goes back to CPU, CLIP encodes the prompt and goes back to CPU, the UNet comes up for the frame, decodes, and leaves. The VAE runs in float32 because half precision overflowed to black images. There's no GPU allocation at import time - the pipeline is built when you queue, not when ComfyUI starts.

One detail that bites: before it runs, the node calls ComfyUI's unload_all_models(). Your checkpoint gets evicted. In a mixed graph that means a reload afterwards, and the first run feels much slower than the second for reasons that have nothing to do with Paints-Undo.

Inputs and outputs

image takes exactly one RGB image. Hand it a batch and it errors by design - the author made that explicit rather than silently using frame one. Prompt (capital P, which is how it's spelled in the schema and in the UI) is the drawing's tag list; leave it empty and the node runs the original WD14 MOAT tagger to caption your image for you, which is what you should usually do. undo_steps defaults to 500. seed controls the noise, so the same image and step give you a repeatable result.

Two outputs: image, one IMAGE back into the graph for a save or preview node, and prompt, the tag string that was actually used - genuinely useful, because it tells you what the automatic tagger saw, and you can paste that into the Sequence node to steer it.

Install

Manager: search ZZX (Comfy Registry name ComfyUI-ZZX). Manual, using the Python that runs ComfyUI:

cd ComfyUI/custom_nodes
git clone https://github.com/ZZXYWQ/ComfyUI-ZZXYWQ
python -m pip install -r ComfyUI-ZZXYWQ/requirements.txt

Windows portable:

python_embeded\python.exe -m pip install -r ComfyUI\custom_nodes\ComfyUI-ZZXYWQ\requirements.txt

That installs diffusers, transformers, accelerate, safetensors and onnxruntime - the tagger needs onnxruntime. Don't install Paints-UNDO/requirements.txt; it's for the upstream Gradio demo and the node deliberately doesn't use Gradio, xformers, bitsandbytes or PEFT.

First run downloads lllyasviel/paints_undo_single_frame and the WD14 tagger from Hugging Face into ComfyUI/models/paints_undo - several GB. Set PAINTS_UNDO_MODEL_DIR to keep it somewhere else. After the first download it runs offline.

Troubleshooting, honestly

no file named model.safetensors means the weights are incomplete, not that the node failed to install. Check single_frame/text_encoder/model.safetensors, single_frame/unet/diffusion_pytorch_model.safetensors and single_frame/vae/diffusion_pytorch_model.safetensors - a directory with only config.json or a half-finished download is the classic state. If a single_frame folder exists, the node uses it, so a broken local copy will shadow a good download.

Multiple ComfyUI installs on one machine cause the same error: the model went to the portable install you were testing, not the Studio install you're running. Install dependencies, clone and download weights with the running install's Python and paths.

Expect roughly 11–13 seconds per frame on a 32 GB Ada card, and much slower on CPU. Results are not strictly monotonic - the model redraws details, so step 600 is not guaranteed to be a strict subset of step 500. That's the model, not the wrapper.

CategoryZZX/PaintsUndo

Inputs (4)

NameTypeDefaultDescription
imageIMAGE—
PromptSTRING—
undo_stepsINT5000–999—
seedINT00–18446744073709550000—

Outputs (2)

NameTypeDescription
imageIMAGE—
promptSTRING—