๐พ Image <> Mask Switch
Image to mask, mask to image, one toggle โ the conversion node that fills a real gap
- image
- mask
- mask
- image
ComfyUI is strict about types, and the IMAGE vs MASK distinction bites everyone eventually. A node outputs an IMAGE but downstream only accepts a MASK. Or you have a mask and need an IMAGE to feed a composite or a preview. ๐พ Image <> Mask Switch is the pack's answer: one node, one boolean toggle, and it converts in either direction - image-to-mask with proper Rec. 601 grayscale conversion, or mask-to-image by expanding a single channel to RGB.
The two directions
The single control is switch_mode, a boolean labeled clearly on the node: image_to_mask (off) and mask_to_image (on). The optional inputs are image and mask; you feed whichever one matches the mode you're in.
- Image โ Mask (
switch_modeoff): takes the image's RGB channels and computes a grayscale using Rec. 601 luma coefficients -0.299*R + 0.587*G + 0.114*B. That's the weighted brightness formula from broadcast video, and it's the "right" way to collapse color to luminance (a naive average over-brightens and washes out edges). The result is a single-channel MASK. - Mask โ Image (
switch_modeon): takes the single-channel mask and stacks it into 3-channel RGB - the same value in all three channels - producing a grayscale IMAGE you can pipe into any image input, preview, or a composite node.
The part people miss: both outputs stay populated
This node returns two outputs - mask and image - and here's the genuinely useful design choice: both are always populated, no matter the mode. In image-to-mask mode the image output passes the original image through; in mask-to-image mode the mask output passes the original mask through. If you feed nothing, it returns blank 64ร64 tensors rather than erroring. That means you can wire this node into a graph once and never break downstream connections when you flip the mode - the "switch" isn't just converting, it's keeping your pipeline stable while you experiment with which representation a node really wants.
When you'd reach for it
Two common spots. First, feeding a mask-aware node that only takes an image: many ComfyUI nodes (previews, some samplers, compositors) want an IMAGE, so you convert your MASK before it. Second, the reverse - you generated or edited a mask as an image and need a real MASK for a mask-conditioning input or an inpaint setup. Given the inpainting KB's point that masks still uniquely give you bit-identical unmasked pixels, having a clean converter is what keeps those pipelines from stalling on a type error.
Installing it
Part of the MachinePainting Nodes pack. ComfyUI Manager โ search "MachinePaintingNodes", or:
cd ComfyUI/custom_nodes
git clone https://github.com/machinepainting/ComfyUI-MachinePaintingNodes.git
Restart ComfyUI. Pack deps (opencv-python-headless, numpy<3, rembg) don't matter for this one - it's pure tensor math.
Gotchas
- Imageโmask keeps the full tonal range. A soft-edged selection comes out as a soft mask; if you need a hard cut, run the result through a threshold (the pack's Mask Editor has one).
- Both outputs populated means both are wired. ComfyUI will execute anything downstream of either output. If you only need one, leave the other unconnected - it costs you nothing.
- Color becomes brightness. Two different colors with the same luma (red vs. green at certain intensities) collapse to the same gray. If you're converting an image that relies on color to separate regions, expect them to merge.
Simple, typed, and it does exactly what it says - the quiet kind of utility node that saves you a headache every few workflows.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| switch_mode | BOOLEAN | false | โ |
| imageopt | IMAGE | โ | |
| maskopt | MASK | โ |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| mask | MASK | โ |
| image | IMAGE | โ |