😺NKD Mask Painter
Stop duplicating Load Image just to draw a mask — NKD Mask Painter paints on any IMAGE
- images
- mask
- IMAGE
- MASK
- MASK (inverted)
ComfyUI's native mask editor is genuinely good - but there's a catch. To paint a mask you usually have to feed a Load Image node, which means duplicating your image load just to get at the editor. NKD Mask Painter kills that annoyance: it takes any IMAGE upstream - procedural output, a VAE decode, whatever - and lets you paint a mask directly on it. The author frames it as a drop-in replacement for Impact Pack's Preview Bridge with a few extras, and that's a fair description, but it goes a bit further.
You'll know the drill if you've used Preview Bridge: hit Edit, paint in the same native editor you get from Load Image, Save & Close, queue again. The node hands back three things - the original IMAGE unchanged, your MASK, and a MASK (inverted) for anything that wants the opposite region. That inverted output alone saves you a Mask To Image/composite dance. Wire the MASK into an inpainting model or a detailer and you're doing classic masked inpainting with bit-identical pixels everywhere you didn't touch - the one thing instruction-edit models still can't give you.
The inputs that matter are just three:
images- the only thing you must connect. AnyIMAGEsocket.on_image_change-clear_mask(default) wipes your painting when the upstream image changes;keep_maskpreserves it. Leave it on the default unless your image swaps between runs.mask_input_mode- how the optionalmaskinput blends with what you painted:Use as start,Replace,Add,Subtract,Intersect, orDisconnected.
That optional mask input is the interesting bit. Feed a face-detector's mask in and it lands on your canvas as a starting point you can add to or erase from. The clever part is the modes only act when the upstream mask actually changes - so a noisy re-queue doesn't stomp your manual edits. Use as start imports once and then your painting wins; Add unions; Subtract carves the upstream region out of yours. If you're confused about Clear vs Reseed: Clear wipes everything and re-imports from scratch; Reseed keeps your painting but forces the upstream mask to be re-blended against it. They're for different moods, and the README's worked example with Add is worth five minutes if this is your first time.
Install
This is one of the few custom nodes with zero baggage. No Python requirements (the pyproject declares none), no model downloads, nothing but a JS extension plus a small Python shim. Either:
cd ComfyUI/custom_nodes
git clone https://github.com/Nekodificador/ComfyUI-NKD-Preview-Tools.git
# restart ComfyUI
…or search "NKD Preview Tools" in ComfyUI Manager and install it there. Note the repo used to live at ComfyUI-NKD-Popup-Preview (the URL this page is filed under) - GitHub redirects it, so either clone path works.
The one thing that will trip you up
Mask Painter has moved. Current versions of this pack are viewing-only, and NKD Mask Painter now ships in a sibling pack, ComfyUI-NKD-Basic-Tools. If you install the latest "NKD Preview Tools" and the node isn't in your search results, that's why - grab the Basic Tools pack instead. Same node, same node ID, same painted masks; nothing to redo.
Two other quirks from the README worth knowing. The node preview shows your mask as checkerboard transparency, so if you only see the flat RGB image, the mask is empty (painting didn't take, or you cleared it). And painted masks are mirrored to input/nkd_masks/<node_id>_mask.png so they survive restarts - but they're restored on the first queue after restart, so hit Queue Prompt once before you panic that your mask vanished. Finally, it's one mask per node: want two independent masks of the same image, paint separate copies of the node. Given the near-zero footprint and the fact it kills a real workflow annoyance, that's a genuinely small price.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| image | STRING | — | |
| on_image_change | COMBO | clear_mask | clear_mask: wipe the painted mask when the input image changes. keep_mask: keep the painted mask even when the input image changes. |
| mask_input_mode | COMBO | Use as start | How to combine the optional `mask` input with what you have painted (all modes only act when the upstream content actually changes): Use as start: import the upstream mask only if nothing is painted yet. After that your manual edits stick, even if upstream changes. Replace: overwrite the painted mask with upstream every time upstream produces a different mask. Add: union — adds upstream to the painted mask. The added area becomes part of your canvas and can be edited freely. Subtract: removes the upstream mask from the painted one. Useful to exclude regions marked by upstream. Intersect: keeps only the area where both painted and upstream masks overlap. Disconnected: the input is connected but ignored. |
| maskopt | MASK | Optional mask used as a starting point. When it changes, it is imported into the editor canvas so you can modify it by adding or erasing parts. While it stays the same, your manual edits take precedence. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |
| MASK | MASK | — |
| MASK (inverted) | MASK | — |