Latent-Aligned Mask (with VAE)
Masks that line up with the latent grid
- mask
- vae
- aligned_mask
- latent_preview
- compression_factor
Diffusion doesn't work on pixels. It works on a compressed latent grid - typically 8× smaller than your image - and when you hand a mask to a latent inpainting sampler, that mask gets downsampled to the latent resolution. Here's the thing nobody warns you about: a clean pixel-space mask edge lands between latent cells when it's scaled down, and the result is the classic "black edge" or halo around your inpainted region. Latent-Aligned Mask (with VAE) is the fix: it processes your mask in latent space so the edges land exactly on the latent grid, then resizes back to full resolution with no artifacts.
It's the flagship of four mask variants in this pack, and the only one that needs a VAE plugged in - because it uses the VAE to measure the exact compression factor instead of assuming.
How it works
The mechanism is the interesting part. It's five steps, all on the GPU:
- Downsample the mask to latent resolution with
areaaveraging (the "correct" way to shrink a mask - it respects coverage). - Expand in latent space using max-pooling, so the mask grows enough to swallow the latent cells at its boundary. This is what prevents black edges.
- Blur the boundary with a small Gaussian - in latent units, which is the right scale.
- Threshold back to binary.
- Upsample with nearest-neighbor, so the final pixel-space mask has perfectly blocky, latent-aligned edges.
Because the mask's edge after all that always falls on a latent-cell boundary, the sampler never sees a half-occupied cell, and the "black fringe" class of artifact just stops happening.
Inputs that matter
- mask - your source mask.
- vae - the VAE whose latent space you're targeting. The node auto-detects the compression factor by probing the VAE (it handles Wan's 3D video VAE and standard 2D ones, falling back to 8×).
override_compressionlets you force a value (0 = auto). - expansion_pixels - how much to grow the mask, in latent units. Default 8 is a good start; bump it for loose inpaint regions.
- blur_latent_units - softness of the boundary. 1 is subtle, fine for most work.
- threshold - the binary cutoff, 0.5 default.
Outputs: aligned_mask (the ready-to-use mask), latent_preview (a look at what the latent actually saw), and compression_factor - an INT telling you what it detected, which is genuinely useful when you're debugging why a mask feels blockier or smoother than expected.
Install
Part of TrentNodes:
cd ComfyUI/custom_nodes
git clone https://github.com/TrentHunter82/TrentNodes.git
cd TrentNodes
pip install -r requirements.txt
Restart, look under Trent/Masks. No extra weights - this is torch tensor math against your existing VAE.
Gotchas
The auto-detect isn't magic. For standard VAEs it's reliable, but a VAE that doesn't expose its compression cleanly makes it fall back to the 8× default - which is right for Wan and most SD-family models but wrong for a 4× or 16× VAE. If your inpaint seams look weird, check the compression_factor output and pass it back in via override_compression. Also: the mask comes back binary after thresholding. If you wanted a soft, feathered mask, you'll want to blur it after - this node's output is meant for latent inpaint, not compositing.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| mask | MASK | — | |
| vae | VAE | — | |
| expansion_pixels | INT | 80–64 | Expand mask in LATENT space (prevents black edges) |
| blur_latent_units | INT | 10–8 | Blur amount in latent units (softens boundaries) |
| threshold | FLOAT | 0.500–1 | Binary threshold after processing |
| override_compressionopt | INT | 00–16 | Manual compression factor (0=auto-detect, typically 8) |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| aligned_mask | MASK | — |
| latent_preview | MASK | — |
| compression_factor | INT | — |