Draw Mask On Image (Swwan)
The node that eats Wan workflows, and how to un-break it
- image
- mask
- images
The error you're probably here for
If you arrived via a red box and something like:
DrawMaskOnImage: Failed to convert an input value to a FLOAT value: opacity, cpu,
could not convert string to float: 'cpu' - Required input is missing: mask
…then you loaded a Wan / WanAnimate-style workflow that was built against KJNodes' DrawMaskOnImage, and it resolved to the Swwan one instead. The two are not signature-compatible. KJNodes' version takes image, mask, color, device. Swwan's takes image, mask, color, opacity, device - an extra opacity float sits before device. So when the workflow's saved widget values are laid back down, the string "cpu" lands in opacity, you get the conversion error, and the widgets come up as NaN.
The fix takes ten seconds: type a number into opacity (0 or 1 will do) and re-pick the device. Then reconnect the mask input, which is the other half of that error message and usually just means the wire didn't survive the failed load.
And no, despite what you'll read in the threads, you don't have to pick one pack and uninstall the other. That advice predates the pack's current version, which gives its nodes distinct IDs rather than claiming the upstream names. Coexistence works; identical names with different signatures is what bites, and this node is the poster child.
What it actually does
It paints the mask onto the image. For every pixel, out = image * (1 - alpha) + color * alpha, where alpha is the mask multiplied by opacity. Masked regions come out solid color at opacity 1, and tinted at anything lower. Unmasked pixels are untouched.
That makes it a visualisation and annotation node, not a compositing node - if you want the mask region replaced by something else, or want transparency, this isn't it. It's for "show me exactly where the mask lands", and for burning a mask into the frames you're about to send to a video model as a control signal.
The inputs
imageandmask- both required. If the mask's height/width don't match the image it's resized withnearest-exact(no softening of edges). If the mask batch is shorter than the image batch it gets repeated; if it's longer it's truncated.color- a string, default0, 0, 0. The tooltip is explicit: RGB values either 0–255 or 0.0–1.0, comma-separated. Here's the trap - the parser decides by looking for a decimal point.255, 255, 255is white.1, 1, 1is 1/255 - visually black. If you want white with floats you must write1.0, 1.0, 1.0. Getting a black overlay when you asked for white is this, every time.opacity- 0 to 1, default 1. This is the widget the migrated workflows get wrong.device- optional,cpuorgpu, defaultcpu. The tooltip says "Device to use for processing", which is honest: it's the mask maths, not the image I/O.
Output is images - a single IMAGE. Frames come back on CPU, so it's safe to hand straight to a save or preview node.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/aining2022/ComfyUI_Swwan
cd ComfyUI_Swwan
python -m pip install -r requirements.txt
Manager → ComfyUI Swwan, restart, hard-refresh. No models, no optional deps: base requirements only (numpy, Pillow, opencv-python, scipy, scikit-image).
Notes from actually running it
The batch loop prints a tqdm progress bar per run, so a slow-looking execution here is legitimately slow looping - a 100-frame 1080p batch is 100 full-image multiply-adds on CPU. Flip device to gpu if your torch has CUDA and it bothers you.
Colors are not clamped before the stack, and inputs are assumed to be 0–1. Feed it a batch that's already out of range from somewhere upstream and you'll get a garbage overlay rather than an error - the pack is fairly consistent about not clamping where the original node didn't.
Finally, this is one of the pack's Swwan/Advanced/Image entries with a KJNodes origin and no legacy alias, which means it never had an old name to be compatible with. That's precisely why the signature could drift. When you share a workflow that uses it, say which pack the node came from, or the next person gets to enjoy the same red box you just fixed.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| mask | MASK | — | |
| color | STRING | 0, 0, 0 | Color as RGB values in range 0-255 or 0.0-1.0, separated by commas. |
| opacity | FLOAT | 1.000–1 | — |
| deviceopt | COMBO | cpu | Device to use for processing |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |