Mask Fill Combined
Solid masks, plus two knobs that quietly do nothing
- mask
- mask
Sooner or later you have a mask that isn't quite a mask. It came from a contour pass and it's an outline with a hollow middle. It's a batch of cropped, off-canvas masks from a detector. Or it's a single region that a tool split into three disconnected blobs and you want one solid object back. Mask Fill Combined takes a MASK in and hands you back one full-canvas mask per input plane, with the option to fill the bounding box of each region so the gaps close.
What it actually does
Read the source and it's short. For each plane in the input mask, the node finds the nonzero pixel bounds. It then computes a crop window three times the bbox in each direction, centred on that bbox, and clamped to the canvas edges. bbox_fill optionally sets that bbox rectangle to 1.0 inside the crop. The crop is copied into a brand-new blank canvas at the right offset, converted to 8-bit and back, and stacked. If no plane had a single nonzero pixel, you get one blank full-canvas mask.
So the honest description is: per input plane, one full-canvas mask containing that plane's pixels, optionally hardened into a solid block over its bounding box. The "combined" in the name is the important word - it is the opposite of a splitting node.
And here's the thing nobody will tell you, because there's no documentation: drop_size and contour_fill are accepted and then explicitly discarded in the shipped code (del drop_size, contour_fill). In version 1.4.0 they do nothing at all. Only bbox_fill changes the output. Set them if you like; you'll get identical pixels. If you actually want contour-based separation and a size filter, that's Mask to Mask Batch from the same pack, where all four fields are live.
Inputs and output
mask- the MASK. Rank-2 or rank-3, and planes are processed independently.bbox_fill- off by default. Turn it on and each plane's output becomes everything inside the bounding box of all its nonzero pixels. This is how you weld a fragmented region into one block. It is also how you accidentally mask out a huge rectangle when your mask had two small blobs at opposite corners of the frame, so look before you trust it.drop_size,contour_fill- inert as described above.
One output, mask, a MASK. Wire it into anything that wants a mask: an inpaint, SetLatentNoiseMask, a composite, or straight into Preview Image to eyeball it.
Why you'd reach for it
The strongest use is the middle of a crop-and-refine workflow. Automatic detailing routinely hands you masks that are either cropped to a region (so they're not canvas-shaped) or hollow (a segmentation outline rather than a filled polygon), and both break naive compositing. Converting to full-canvas and filling the bbox is the cheapest fix, and it's the same "get the mask into the shape the next node expects" job the mask tooling in masking-detection-detailing.md describes - masks are the currency of the whole detection layer, but everyone's node expects a slightly different denomination.
Install
Manager: search ComfyUI Utility Suite (publisher tom-m) and install, then restart. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/tom-m-2020/ComfyUI-Utility-Suite
No models, no downloads. The pack's only listed dependency is opencv-python-headless, and this particular node doesn't even use it - it's pure NumPy and torch. The bigger practical note is version currency: the pack is built on ComfyUI's V3 node API, so an old ComfyUI will import the folder and register nothing. Update ComfyUI first if the nodes never appear in the search menu.
Troubleshooting
It returns a blank mask. Your input had no nonzero pixels, or you're looking at the wrong plane - an empty plane is skipped, not preserved, so a batch of five planes where only two had content comes out as two planes. The blank one-plane fallback only happens when nothing had content.
The output is a giant rectangle. That's bbox_fill doing its job. It fills the bbox of every nonzero pixel across the plane, not per disconnected region.
Your values got chunky. The output round-trips through 8-bit, so a soft gradient mask comes back quantized to 1/255 steps. Irrelevant for hard masks and hard mask edges, mildly visible if you were feathering with smooth ramp values.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| mask | MASK | — | |
| bbox_fill | BOOLEAN | false | — |
| drop_size | INT | 101–16384 | — |
| contour_fill | BOOLEAN | false | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| mask | MASK | — |