π BV Apply LUT
One LUT, masked to the bits that actually matter
- image
- lut
- mask
- image
- applied_mask
This is the node that actually does the thing. Everything else in BV Node Pack's LUT corner - the loader, the registry, the loop machinery - exists to hand this node a lut and a mask. You'll wire it once, then forget it's there.
A LUT (lookup table) is how film colorists apply a grade to every pixel consistently: instead of eyeballing a curve, you swap in a 3D table that remaps color, and the look stays identical across shots. BV Apply LUT takes an image and one of those tables and mixes the graded result over the original by a strength you control. The twist that makes it more than a filter is the optional mask: with a mask connected, the grade only lands where the mask says so, which is how you give the subject "Dustfire" while the background stays neutral.
How it works
The math is straightforward and worth knowing because it explains every knob. The node computes the fully graded copy, then blends using alpha = normalized_mask Γ strength:
result = image Γ (1 - alpha) + graded Γ alpha
No mask? Alpha is all ones times strength, so it's a clean global grade. Strength 0 leaves the image untouched, 1.0 applies the full look. The blend happens in float32 and clamps back to the original dtype, so you don't get banding or overflow from stacking grades in a loop.
The inputs and outputs that matter
image- anything with an IMAGE type: a VAE decode, an upscale pass, another LUT's output.lut- aBV_LUT_PROTOTYPE. Get one from BV LUT Loader, BV LUT Registry, or a loop's resolver.strength- float 0β1. The tooltip is the author telling you the one thing people trip on: "In LUT loops, connect the resolver's strength output. Leave unconnected only for a manual standalone override." If you wire a resolver's strength in and your per-job strengths seem ignored, you left this widget connected too.mask- optional MASK. Wire it from a region renderer, an inpainting mask, or BV Impact Detector Mask if you want the grade to hug a detected face or object.
Outputs: image (the graded result) and applied_mask, the actual alpha that got used. The second one is a genuinely useful preview - hook it to a preview node and you see exactly what your mask and strength resolved to, which beats guessing why a grade landed where it did.
How to install
The whole pack installs together; there's no standalone version of this node.
cd ComfyUI/custom_nodes
git clone https://github.com/BlackVortexAI/bv_nodepack.git
Then restart ComfyUI and hard-refresh the browser (Ctrl+Shift+R). Easier still: ComfyUI Manager β search "BV Node Pack" β Install. No model files to download for any of the LUT nodes - the built-in looks are generated in code, and .cube files you add yourself go in ComfyUI/models/luts.
Common issues
- Grade has no effect - strength is 0, or you're running a loop job whose resolver strength isn't wired and the widget says 0. Check the resolver wiring first.
- Harsh edges on a masked grade - the mask is sharp. Feather it before this node (mask_grow/mask_feather on the detector node, or a feather node in between).
- Mask size mismatch - the mask is assumed to match the image's HxW. If your mask came from a differently-sized crop, resize it upstream or you'll get subtle misalignment on the edges.
This is the one LUT node you'll actually reach for every time. Load something, apply it, tune strength until it looks like intent rather than a filter.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | β | |
| lut | BV_LUT_PROTOTYPE | β | |
| strength | FLOAT | 1.000β1 | In LUT loops, connect the resolver's strength output. Leave unconnected only for a manual standalone override. |
| maskopt | MASK | β |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | β |
| applied_mask | MASK | β |