Nodes/Edge Painter/Edge Painter (Load Image + guide strokes)
ComfyUI Node

Edge Painter (Load Image + guide strokes)

The MaskEditor you already have, turned into a guide-stroke brush

By JacPointLab·Created 21 days ago·Updated 21 days ago· 1
Edge Painter (Load Image + guide strokes)
  • mask
  • guide
  • image
  • strokes
  • strokes_mask
  • overlay
  • fused_guide
◄image▾►
◄fusionreplace►

The most annoying Canny is the one that's 90% right. It found the roof, the fence, the whole outline of the photo - and then missed the one line you actually cared about, or found a hard edge across a shape you wanted to change. You can sit there sweeping thresholds, or you can just draw the missing line yourself.

Edge Painter is the second option, and it's sneaky about it: a Load Image node with five outputs that uses the MaskEditor you already have as the brush.

What it does, and when you'd reach for it

Right-click the node → Open in MaskEditor → paint. Whatever you paint comes out separately as white lines on black, ready for a Canny, Lineart or Scribble ControlNet.

Why bother, when every preprocessor already draws lines for you? Because preprocessors extract structure that exists in the photo - Canny is a threshold detector for hard contours, Scribble is "the most creative-friendly preprocessor - draw a rough layout, and the model fills in the details" (docs/knowledge/controlnet.md). Edge Painter is how you get a scribble out of an existing photo without leaving ComfyUI or opening Krita.

The best real use is guided inpainting. Masked inpainting still owns one thing instruction-edit models can't do - bit-identical pixels outside the mask (docs/knowledge/inpainting.md) - but inside the mask the ControlNet happily drags the new content back toward the old shape. Draw the shape you want, fuse it with the Canny of the original, and the model has something better to follow.

How it works

The trick: MaskEditor already saves through its alpha channel. Painted pixels are written as transparency in a copy of the PNG, so the node just reads the file, inverts the alpha, and calls that the stroke mask:

  • strokes_mask = 1 − alpha
  • strokes = that mask expanded into three black-or-white channels
  • overlay = image × (1 − mask) + mask - your lines burned in white

The genuinely clever half is a small frontend script. When the MaskEditor is opened from an Edge Painter node, it swaps the editor into a stroke profile - white mask, full opacity, a 3 px hard brush, step 2 - and stashes your usual brush settings so they come back when you close it. Brush tweaks you make in there are remembered separately, under edgepainter.brush in localStorage. It only acts on Edge Painter nodes, so your normal Load Image brush is untouched.

The optional inputs do the rest. mask restricts you: strokes outside it are dropped from every output, and everything outside it is dimmed in the preview and in the editor (display only, never saved into the image). guide enables guide fusion - the original Canny or Lineart of the same photo. Outside your mask the fused output is the original guide; inside it you get only your strokes (replace, for changing a shape) or the union of guide + strokes (add, for details like seams or prints). The guide is auto-resized to the image, because preprocessors hand back their own resolution.

Inputs and outputs that matter

Required: image, a normal file dropdown. Optional: mask (MASK), guide (IMAGE) and fusion (replace / add) - and fusion is the only knob you'll touch every session.

Five outputs. strokes or fused_guide → a ControlNet Apply node (you're the preprocessor now, so pick "none" and feed the map directly). strokes_mask → SetLatentNoiseMask or InpaintModelConditioning. image → anywhere you need the untouched photo. overlay → a PreviewImage so you can actually see what you drew.

Install

Manager: search Edge Painter. Manually:

cd ComfyUI/custom_nodes
git clone https://github.com/JacPointLab/ComfyUI-EdgePainter

Restart ComfyUI. Nothing to pip install, no model files - but you want a 2025-or-later frontend with the Vue MaskEditor. On anything older the node still loads and emits strokes; the automatic brush profile, which is most of the point, is skipped.

Things that will actually bite you

  • Input images with an alpha channel. The node reads transparency as paint. Load a transparent PNG and its holes come out as strokes. Flatten to opaque first if that's not what you want.
  • First frame only - animated GIFs and multi-frame inputs give you frame one and nothing else.
  • An all-black mask is ignored, deliberately - an unwired-but-connected mask input stays harmless.
  • A soft guide stays soft. A 512 px preprocessor output upscaled to a 2048 px photo gives mushy lines - run the preprocessor at the photo's resolution.
  • add is a union, not a blend - you can't paint a grey half-line.

One honest caveat: this pack is brand new and basically invisible - the reddit corpus has nothing on its name or its author, so the above comes from reading the shipped code rather than other people's bug reports.

Categoryimage

Inputs (4)

NameTypeDefaultDescription
imageCOMBO1 options: example.png
maskoptMASKOptional area to paint in (e.g. your inpaint mask). Strokes outside it are discarded, and the rest is dimmed in the preview and in the MaskEditor.
guideoptIMAGEOptional original guide (e.g. Canny/Lineart of this image). Enables the fused_guide output.
fusionoptCOMBOreplaceInside the area: 'replace' = only your strokes (change a shape); 'add' = original guide + your strokes (add details such as embroidery, prints, seams).

Outputs (5)

NameTypeDescription
imageIMAGEThe loaded image, untouched.
strokesIMAGEOnly your strokes: white on black. Plug it into a Canny/Lineart/Scribble ControlNet.
strokes_maskMASKYour strokes as a mask (1 = painted).
overlayIMAGEThe image with your strokes painted in white.
fused_guideIMAGEOriginal guide outside the area; inside it, your strokes ('replace') or guide + strokes ('add'). Without a guide input it equals 'strokes'.