Mask Image Filter
Paint a Mask Mid-Workflow and Keep the Run Alive
- image
- mask
- image
- mask
- extra1
- extra2
- extra3
You generated a face with a broken hand, and you want to fix just that hand - not regenerate the whole image and lose everything else. Normally that means saving the PNG, dragging it into another tool, painting a mask, exporting again, and building a whole second workflow. The Mask Image Filter collapses all of that into one pause: it launches ComfyUI's own mask editor, you paint over the bit you hate, and the node hands back the original image plus the mask, ready to feed an inpaint or img2img pass.
That matters more than it sounds. Masked inpainting's whole remaining superpower is that pixels outside the mask stay bit-identical - no edit model offers that, and it's exactly the property you want when you've already got a good frame and one bad detail. This node is the interactive front door to that workflow.
How it works
Give it a single image and run. The node ships the image to the frontend and the pack's JavaScript opens the mask editor immediately. When you finish, the mask is returned over the same websocket channel the other filter nodes use, and out come the original image and the freshly painted mask. There's the same timeout as the Image Filter node, and what happens if you blow it is your call via if_no_mask: cancel stops the run, send blank keeps going with an empty mask.
The inputs worth knowing:
image- required, and it's one image at a time. Got a batch? Run it through the pack'sImage List From Batchhelper first and the filters step through them.if_no_mask-cancelorsend blank. Choose based on whether a blank mask is a valid state for what's downstream.if_inputs_unchanged- what to do on a re-run when nothing changed:Run normally(default, start from the input mask),Start with last output,Resend last output(skip the editor entirely), orAlways start with last output(keep the previous mask even if other inputs changed, as long as the image dimensions match). The last two are gold when you're iterating on a mask you mostly like.mask(optional) - pre-seed the editor with an existing mask, handy if you generated mask candidates earlier in the graph.
Outputs are image, mask, and the three passthrough extra strings.
Installing it
Search "cg-image-filter" or "Image Filter" in ComfyUI Manager, or:
cd ComfyUI/custom_nodes
git clone https://github.com/chrisgoringe/cg-image-filter
Restart, done. No pip dependencies, no model downloads - all the editor UI ships in the pack's js/ folder. It targets ComfyUI's newer node API, so keep ComfyUI itself reasonably current.
Gotchas
The README is blunt about one thing: this works with the new mask editor, not the old one. If nothing pops open, check which editor your ComfyUI is configured to use. People also hit a classic confusion here - cancel the editor and, with if_no_mask on send blank, you get a 64×64 black mask out the other end. That's not a bug, it's the setting you picked; switch to cancel if a blank mask would silently poison your inpaint. And if you feel like you're running out of time, remember the 600-second default timeout is right there on the node.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| timeout | INT | 6001–1000000 | timeout in seconds |
| if_no_mask | COMBO | send blank | 2 options: cancel, send blank |
| if_inputs_unchanged | COMBO | Run normally | 4 options: Run normally, Start with last output, Resend last output, Always start with last output |
| graph_id | STRING | — | |
| maskopt | MASK | optional | |
| tipopt | STRING | — | |
| extra1opt | STRING | — | |
| extra2opt | STRING | — | |
| extra3opt | STRING | — | |
| audiofileopt | STRING | Path or URL for the audiofile to use, or name of the file in the default audio folder |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| extra1 | STRING | — |
| extra2 | STRING | — |
| extra3 | STRING | — |