Mask Editor One
A whole Photoshop-style mask editor crammed into one ComfyUI node
- image
- mask
- inverted_mask
- mask_image
If you've ever tried to paint a decent mask with stock ComfyUI, you know the pain: a tiny canvas, one brush, no layers, and god help you if you need to fix one edge without redoing the whole thing. Mask Editor One is the answer - a modal, Photoshop-style mask editor that lives inside a single node, does all your masking work, and hands you clean IMAGE/MASK outputs when it's done.
Why you'd reach for it
In a wider workflow this is the mask-authoring front-end for inpainting, compositing, and ControlNet passes. It matters now more than it sounds like it should. The instruction-edit models (Qwen-Image-Edit, Flux Kontext) took over most of the "change this thing" jobs, but masks still own the cases where you need a precise boundary and bit-identical unmasked pixels. When the job is "keep everything except this one region exactly as-is," you still need a real editor.
And stock ComfyUI doesn't really give you one. This node does: layers with add/subtract blending, per-layer visibility, 30-step undo, brush hardness and spacing, image brushes, even .abr Photoshop brush imports. It also bundles two AI helpers - SAM3 text-prompt segmentation and one-click BiRefNet background removal - so it covers the whole arc from "auto-cutout" to "hand-fix the hair."
How it works
The editor is browser-side: a ComfyUI extension plus a small PromptServer API. Click Edit Mask on the node and a modal opens with a tool sidebar - paint, color select, transparency extract, text, vector (Catmull-Rom splines), shapes, SAM3, and BiRefNet. Everything is layer-based, and the layer state gets serialized to JSON. At run time the Python process() pulls the background image from a server-side cache, composites the layers (add layers lighten, subtract layers clip), applies any invert/blur, and emits four outputs.
Nice touch: the node implements IS_CHANGED as a hash of the cached background, so ComfyUI re-runs when you swap the BG instead of silently serving a stale result.
The inputs that actually matter
There are only three, and you'll touch two of them:
invert_mask(boolean) - flips the output black↔white. Two-way synced with the modal's Invert checkbox, so it doesn't matter which one you flip.blur_radius(int, 0–200) - Gaussian blur on the output mask. Also synced with the modal slider. Handy for feathering an inpaint boundary without dragging in a Blur Mask node.layer_data(string) - the editor state JSON. Normally auto-updated; leave it alone.
Outputs: image and mask are the headline - mask wires into any MASK input (VAE Encode for Inpaint, ControlNet, wherever). inverted_mask is the same mask flipped, which saves you a node. mask_image is the mask as an RGB image for nodes that want IMAGE. image is your loaded background if you set one, otherwise the mask rendered as an image.
Gotcha: you can't wire an image in
The original node had optional image/mask inputs; the author removed them. Now the image comes only from the Load Image button or by dropping a file on the node preview. That's the point of the fixed 160px preview - it's your drop zone. If you're used to feeding a tensor from the graph, this will trip you up once, then you'll forget it was ever a problem.
Install
ComfyUI Manager → search "Mask Editor One", or:
cd ComfyUI/custom_nodes
git clone https://github.com/ketle-man/comfyui-mask-editor-one
pip install -r requirements.txt
Then restart ComfyUI - it lands under image/masking. Dependencies are light (torch, torchvision, numpy, Pillow, sam3); the only heavy stuff is optional:
- SAM3 tool: drop checkpoints into
ComfyUI/models/sam3/(e.g.sam3.safetensors). Notefacebook/sam3is a gated HuggingFace model - accept the license, thenhuggingface-cli loginor setHF_TOKEN. - BiRefNet tool:
birefnet.safetensorsintoComfyUI/models/background_removal/. This one uses ComfyUI's nativecomfy.bg_removal_model, so no extra libraries - and it's the model ComfyUI shipped in core, so you're on solid ground. It only loads into VRAM when you actually run it.
Troubleshooting
- SAM3 not showing up in the dropdown - filenames must contain
sam3, and TorchScript/JIT-saved files are skipped on purpose. And if you skipped the HF gating step, that's your auth error right there. - BiRefNet panel says error - model file missing or wrong filename. It should read "Model found" when it's set up; first inference takes a second or two to load.
- Old workflows with a missing node - the class was renamed from
MaskEditorNodetoMaskEditorOne. Saved workflows referencing the old name need the node replaced. - Keep it updated - the author's been patching real stuff (path traversal fixes, a 100 MB request cap, safe
torch.load). That's the kind of maintenance you want to stay current on.
For the money, this is the one node I'd actually reach for over a stack of mask utility nodes - the layer workflow alone is worth the install.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| invert_mask | BOOLEAN | false | — |
| layer_dataopt | STRING | {} | — |
| blur_radiusopt | INT | 00–200 | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| inverted_mask | MASK | — |
| mask_image | IMAGE | — |