Mask & Latent
Depth-derived masks, NaN guards, and latent surgery without the VAE roundtrip
- image
- mask
- a
- latent
- mask
- latent
- info
The Mask & Latent node packs fourteen operations onto one dropdown, split between the two kinds of data that live between "image in" and "image out" in a ComfyUI graph: masks (the grayscale selection maps that drive inpainting and compositing) and latents (the compressed tensors your sampler actually denoises). The mode dropdown covers mask-from-color, mask-from-depth/luma, invert, erode, dilate, blur, combine (union/intersect/diff/xor), and inspect on the mask side; latent inspect, math, noise inject, smart upscale, a NaN guard, and pad/crop on the latent side. Outputs are mask, latent, and info (a DICT).
The two modes I'd actually install this pack for: mask_from_depth and latent_nan_guard. Depth maps (from MiDaS, ZoeDepth, or any of the depth estimators floating around) encode "close is bright, far is dark." mask_from_depth thresholds that map by a min_value/max_value range - default 0 to 0.5 grabs the foreground - and hands you a selection you can feed straight into inpaint or a denoise-masked KSampler. It's the same trick that powers a lot of the background-removal and depth-driven workflows in the ecosystem, done in a single node. And latent_nan_guard is the one to reach for when SDXL FP16 spits out NaNs and your VAE decode renders a pure black image: set on_nan to raise to fail fast with a clear message, or zero_out/clamp to recover and keep going.
How it works
Standard pack architecture: mode picks the operation, irrelevant widgets hide, unused outputs pad. Key inputs:
mask_from_color:imageplusr/g/bandtolerance- mask is 1 where pixels are within tolerance of that RGB.mask_from_depth:image,min_value,max_value,invert.- Erode/dilate use
kernel_size; blur usesradius; combine takes two masksa/band acombine_op. - Latent ops take a
latent:latent_math(add/subtract/blend withweight),latent_noise_inject(strength+seed),latent_upscale_smart(scale- picks bilinear under 2×, bicubic above),latent_pad_crop(target_h/target_w/fill_value).
The latent ops have a detail worth knowing: they preserve the auxiliary keys in your latent dict - things like noise_mask, which inpainting pipelines attach to the latent. Older versions of the pack silently dropped those and broke masked inpainting; current releases shallow-copy the dict and only swap the samples. latent_pad_crop also deserves a shout-out: it pads or center-crops a latent to a target size in latent space, so you can align two latents for compositing or snap to an SDXL bucket without decoding to pixels and back - that saves a whole VAE roundtrip.
Installing it
One node from the pack - install the pack:
cd ComfyUI/custom_nodes
git clone https://github.com/IxMxAMAR/ComfyUI-Utility-MegaPack
Restart ComfyUI or use ComfyUI Manager → "Utility-MegaPack". No model files; dependencies are the usual light set.
Where people get tripped up
Erode and dilate force odd kernel sizes under the hood - an even kernel_size used to produce asymmetric padding and crash downstream nodes with off-by-one shapes, so the pack just bumps even numbers up. Don't fight it. mask_combine requires a and b to have identical shapes or it raises; if they don't match, resize first. And the NaN-guard raise option is deliberately loud: a NaN latent decodes to a black image no matter how much GPU you spend, so stopping is the feature. One aside: the info output is where all the inspect modes land - mask_inspect gives you coverage percentage, bounding box, and centroid, which is handy if you're auto-cropping to a subject instead of eyeballing it.
Inputs (25)
| Name | Type | Default | Description |
|---|---|---|---|
| mode | COMBO | latent_inspect | 14 options: latent_inspect, latent_math, latent_nan_guard, latent_noise_inject, latent_pad_crop, latent_upscale_smart, +8 |
| theme | COMBO | (use pack default) | 17 options: (use pack default), (use ComfyUI default), cyberpunk, minimalist, glassmorphic, retro_terminal, +11 |
| imageopt | IMAGE | — | |
| ropt | FLOAT | 1.000–1 | — |
| gopt | FLOAT | 0.000–1 | — |
| bopt | FLOAT | 0.000–1 | — |
| toleranceopt | FLOAT | 0.050–1 | — |
| maskopt | MASK | — | |
| kernel_sizeopt | INT | 31–32 | — |
| radiusopt | FLOAT | 4.000.1–100 | — |
| aopt | MASK | — | |
| combine_opopt | COMBO | union | 4 options: union, intersect, diff, xor |
| min_valueopt | FLOAT | 0.000–1 | — |
| max_valueopt | FLOAT | 0.500–1 | — |
| invertopt | BOOLEAN | false | — |
| latentopt | LATENT | — | |
| math_opopt | COMBO | blend | 3 options: add, subtract, blend |
| weightopt | FLOAT | 0.500–1 | — |
| strengthopt | FLOAT | 0.100–2 | — |
| seedopt | INT | -1-1–4294967295 | — |
| scaleopt | FLOAT | 1.500.25–8 | — |
| on_nanopt | COMBO | raise | 3 options: raise, zero_out, clamp |
| target_hopt | INT | 641–4096 | — |
| target_wopt | INT | 641–4096 | — |
| fill_valueopt | FLOAT | 0.00-10–10 | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| mask | MASK | — |
| latent | LATENT | — |
| info | DICT | — |