Mask Hard Blend
The full toolkit for turning 'protected' into 'free to repaint'
- inpainting_mask
- conditioning_mask
- updated_inpainting_mask
This is the grown-up version of MaskConditionalPaint. Where the simple node just paints white into an inpainting mask wherever a conditioning mask is low, Mask Hard Blend (the display name; the class is MaskUpdateInpaintFromConditioning) gives you four blend modes, an optional feathered edge, and a soft-transition option. Same core idea - translate "this region is not protected" into "this region is free to be regenerated" - but with the controls to make the boundary behave.
How it works
The core is unchanged from its little sibling: it finds everywhere the conditioning_mask sits in the range 0 to threshold (default 0.2) and treats those pixels as candidates for the inpaint region. What you can then do with those candidates is the mode dropdown:
- paint_white (default) - set those pixels to white (1.0) in the inpainting mask. Hard, simple, the original behavior.
- add_to_existing - add the candidate region to whatever was already in the inpainting mask, clamped to 1.0. Use it when you want to expand an existing selection rather than rewrite it.
- union - max of the existing mask and the candidate region. Similar spirit to add, but keeps the original mask values instead of pushing everything to white.
- replace_only_range - only replace pixels that fall within the conditioning range, with
smooth_transitiongiving you a gradual ramp (based on the conditioning values) instead of a hard 0/1 cut.
Two more knobs: feather_amount (0–10) blurs the candidate region before it's applied, and smooth_transition only matters in replace_only_range mode. Inputs inpainting_mask, conditioning_mask, and threshold are required; the rest are optional. Output is updated_inpainting_mask.
When the extra modes earn their keep
The hard-paint mode is right when your "free to repaint" boundary is also a hard boundary - say, a face you don't want touched at all. But in tiled refinement, hard boundaries are usually the problem, not the solution: the inpainting guidance around mask blur and feathered edges because a hard mask edge shows up in the final image as a visible seam. So the real workflow looks like: run the paint in add_to_existing or replace_only_range, turn on feather_amount (start at 2–4), and let the refiner blend across the transition instead of stitching a sharp line.
Installing it
Part of the TBG ETUR pack:
cd ComfyUI/custom_nodes
git clone https://github.com/Ltamann/ComfyUI-TBG-ETUR
cd ComfyUI-TBG-ETUR
pip install -r requirements.txt
Or ComfyUI Manager → search "TBG" → TBG_Enhanced Tiled Upscaler & Refiner FLUX PRO, restart.
Notes
Don't over-feather. feather_amount is in pixels of Gaussian blur on the candidate region, and 10 is a lot - on a small mask it can pull the soft edge so far out that the "protected" area starts getting denoised anyway. Also keep the two masks in similar resolution; the node resizes the conditioning mask to match, but a big upscale makes the candidate region mushy. And if all you ever need is the plain paint, MaskConditionalPaint is the same operation with one third of the inputs - this node is for when you're doing real inpainting-adjacent work where the boundary quality decides whether the result looks composited or looks made.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| inpainting_mask | MASK | — | |
| conditioning_mask | MASK | — | |
| threshold | FLOAT | 0.200–1 | — |
| modeopt | COMBO | paint_white | 4 options: paint_white, add_to_existing, union, replace_only_range |
| smooth_transitionopt | BOOLEAN | false | — |
| feather_amountopt | INT | 00–10 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| updated_inpainting_mask | MASK | — |