ComfyUI Node

Speedpaint

Sketch it inside the graph instead of opening Krita

By WepeNerd·Created 5 months ago·Updated about 17 hours ago· 0
Speedpaint
    • image
    width1024
    height1024
    document

    Why you'd reach for it

    ComfyUI has no canvas. That's fine for most of the graph and annoying for exactly one step: roughing out a composition before you commit GPU time. The usual answer is to draw in Krita or Photoshop, export, drop the file in ComfyUI/input/, wire a Load Image, then go back and forth every time the layout is wrong. Speedpaint collapses that loop into a node: a paint surface on the graph that outputs an IMAGE, so your thumbnail lives in the workflow you already have open.

    Three ways people use it. As an img2img input - rough shapes and colour blocks, then VAE Encode into the sampler at a moderate denoise; 0.3–0.5 keeps your composition, 0.7+ is near-complete regeneration with only vague hints left. As ControlNet conditioning - the scribble preprocessor exists so a rough hand-drawn sketch can drive structure while the prompt decides what the shapes are. As a guide over an import - paint where you want something changed instead of hand-masking in an external editor.

    How it works

    The Python side is smaller than you'd expect, because the painting happens in the browser. The pack ships a frontend extension (js/wn_speedpaint.js) and registers backend routes at /wepenerd/speedpaint/*, which is what the editor calls to prepare and commit a canvas. Finished paintings land in ComfyUI/input/wepenerd_speedpaint as content-hashed assets - the filename is the SHA-256 of the PNG, so the same painting is never written twice.

    The node's third input, document, is that state: a JSON string holding the background colour, crop centering, a "painted" flag, and either an asset filename or an inline base64 PNG for a draft that hasn't been committed. Queue the node and it decodes that document, composites it over the background, and returns a float32 RGB tensor. The painting isn't a control signal - it's literal pixels, and the model treats it as a starting image.

    Inputs and outputs

    • width and height - INT, 64 to 4096, default 1024×1024. These are widgets, but they take input links, which is why the pack's own example workflow drives them from Resolution Suggest. Wire an INT from anywhere and the canvas follows it.
    • document - leave it alone. It's the serialized painting.
    • image out - one IMAGE, RGB, batch of 1. Wire it into VAE Encode for img2img, into a scribble preprocessor or Apply ControlNet pair, or straight into a Preview/Save to get the sketch out.

    No IMAGE input socket, and that surprises people - importing a reference is a file picker or drag-and-drop inside the editor, PNG/JPEG/WebP only. You can't feed an upstream image in and paint on it. The toolbar gives you round and square brushes, a hex colour picker, a pixel-size slider, stroke opacity, pen pressure to size, and undo/redo on Ctrl/Cmd+Z. Alt-click samples a colour. Physical tablet pressure is untested, so don't buy a tablet for this.

    Install

    Manager: search ComfyUI-WepeNerd, install, restart ComfyUI and hard-refresh the browser. The refresh isn't superstition - the /wepenerd/speedpaint/* routes register at server startup, so if you clone the pack into a running server the canvas can appear while the calls behind it 404. Manually:

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

    Pillow and numpy, nothing else; torch comes from your ComfyUI install, and there are no model downloads. Tested by the author on ComfyUI 0.34.0 with frontend 1.51.10.

    Where people get burned

    Your painting lives in a folder, not in the workflow. Assets sit in ComfyUI/input/wepenerd_speedpaint, and the document only references them. Move machines and copy that folder with your workflows, or a saved graph reopens pointing at a file that isn't there.

    Queue before you close the tab. Undo history is capped at 30 operations / 128 MiB and does not survive a page reload.

    The errors are readable, so read them. Dimensions that aren't integers in 64–4096 give you "Speedpaint dimensions must be integers from 64 to 4096 pixels", and the canvas has a total budget of 16,777,216 pixels (4096², so a full square is fine - it's the oblong canvases that trip it). Imports are capped at 64 MiB.

    Resizing a painting refits the whole composition. The canvas goes through a Lanczos aspect-fit, so changing dimensions re-renders everything you painted, and undo won't walk an upstream Resolution Suggest node backwards.

    Denoise is the dial that decides whether your sketch matters. At denoise 1.0 the sampler ignores the input almost entirely and your careful layout evaporates. If you need the structure to survive, drop denoise and consider scribble ControlNet on top - that's what it's for.

    One last bit of context: this pack is new (0.1.0/0.2.0, September 2026) and has no real footprint in the community yet - the author's better-known work is a set of LTX-2.3 IC-LoRAs on Hugging Face. That's not a strike against a node that is a canvas plus a couple of hashing helpers, but you're early: the README's quick start points at examples/resolution-speedpaint.json, and no examples folder ships in the repo, so you're wiring it yourself. If the editor misbehaves after a frontend update, that's the part to suspect first - the JS is what talks to the interface.

    CategoryWepeNerd/Image

    Inputs (3)

    NameTypeDefaultDescription
    widthINT102464–4096
    heightINT102464–4096
    documentSTRING

    Outputs (1)

    NameTypeDescription
    imageIMAGE