NanoBanana Latent Mask
The soft-mask builder that makes FLUX ghosts look embedded, not stamped
- image
- mask
- preview
If you've tried to hide a pattern inside a FLUX image the honest way, you know the problem: a hard-edged mask makes the pattern look like a sticker pasted on top, not a watermark living inside the image. The Latent Mask node is the pack's answer to that. It takes any image - your text render, a logo, a photo - and turns it into a soft luminance mask with graded edges, the kind that disappears into the sampling process instead of sitting on top of it.
Let's clear up the name first, because it will trip you: it's called "Latent Mask" but it doesn't create, touch, or return a latent. It outputs a mask tensor and an image preview. "Latent" describes where you use it - driving latent-space conditioning so the pattern is baked in during denoising - not what it produces. Feed it into a ConditioningSetMask, not an EmptyLatent.
How it works
The source shows it's a gentler cousin of the pack's Pattern Preprocessor. That node thresholds to hard black-and-white; this one never thresholds. The image is grayscaled, optionally inverted, Gaussian-blurred, then run through a levels remap controlled by midpoint and contrast, and finally scaled by mask_strength. Values stay continuous between 0 and 1 - soft edges, no cutoffs. That continuity is the whole point: it's what lets a pattern fade out along its edges instead of slicing through the image with a hard boundary.
mask_strength (default 0.55) is the global gain - how visible the ghost is. midpoint (default 0.5) decides which gray level counts as the halfway point of your mask, and contrast (default 1.8) stretches the gradient. blur_radius defaults high at 12 because you want smooth falloff here; drop it if the pattern's fine details matter more than the fade.
Outputs
- mask - the soft MASK tensor. Wire it into a ConditioningSetMask (with a strength you'll often want low, 0.3–0.6 territory) or pair it with this pack's Magic Scheduler's
latent_mask_strengthoutput. - preview - the same mask as a visible image, so you can eyeball what you're about to condition with before you queue it. This one actually earns its existence.
Installing it
The pack again - ComfyUI Manager, search "ComfyUI-HiddenImages", or clone into custom_nodes and run ./install.sh --preset ghost. The ghost preset is the FLUX setup: it pulls the FLUX.1-dev Canny ControlNet (InstantX) weights and clones the helper nodes, and it will tell you (via the manifest) that the base FLUX.1-dev model itself stays manual because it needs upstream license acceptance. The node's own dependencies are just Pillow and numpy.
Troubleshooting
Ghost invisible? Raise mask_strength or contrast. Ghost looks like a hard decal? Lower contrast, raise blur_radius, and check the ConditioningSetMask strength - with the latent path you want subtle, and the Magic Scheduler's FLUX ranges (strength topping out at 0.55) are a good ceiling to respect. And if you see a type error when you connect it somewhere, it's almost certainly the name trap: you've fed a MASK into something expecting a LATENT. The node is telling you what it is - a mask - believe it.
For the FLUX hidden-image workflow specifically, this is the node you'd reach for over the pattern preprocessor, because ghosts need gradients and the preprocessor only knows edges.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| blur_radius | FLOAT | 12.00–64 | — |
| contrast | FLOAT | 1.800.1–4 | — |
| midpoint | FLOAT | 0.500–1 | — |
| mask_strength | FLOAT | 0.550–1 | — |
| invert | BOOLEAN | false | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| mask | MASK | — |
| preview | IMAGE | — |