Blend If
Composite by brightness range, not a flat opacity slider
- top_layer
- bottom_layer
- mask
- IMAGE
- MASK
Blend If is one of Photoshop's most powerful and most fiddly layer tools, and this node ports it over pretty much intact. Instead of a flat opacity slider deciding how much a top layer shows through everywhere equally, Blend If decides per pixel based on how bright that pixel is on either the top or bottom layer - so you can, say, make a texture layer only show up in the shadows of the image beneath it, or only in the highlights. It's the tool behind a lot of "how did they blend that so seamlessly" composites, and it's genuinely deep once you get past the number of fields on it.
How it works
You pick which layer's brightness gets analyzed (blend_if_layer: top or bottom) and which channel of that layer (blend_if_channel: gray, or a specific color). Then four thresholds - start_rise, end_rise, start_fall, end_fall - define the brightness range that ends up opaque: anything darker than start_rise or brighter than end_fall is fully transparent, anything between end_rise and start_fall is fully opaque, and the two gaps in between feather smoothly from one to the other. The pack's own README is upfront that ComfyUI's plain number fields are a downgrade from Photoshop's split-triangle sliders for this feature - you're typing four numbers instead of dragging two handles - but the underlying math is the same.
The inputs and outputs that matter
top_layer- the layer being composited on ("current layer" in Photoshop terms). Resized to coverbottom_layerif the sizes don't match.bottom_layer- the base layer ("underlying layer"). Output dimensions match this.blend_if_layer-toporbottom: which layer's brightness drives the transparency calculation.blend_if_channel-gray,red,green, orblue: which channel of the chosen layer is analyzed.start_rise,end_rise,start_fall,end_fall(0–1 each) - the four thresholds described above. Defaults (0, 0, 1, 1) mean fully opaque everywhere, since the "always-transparent" and "always-opaque" ranges cover the whole 0–1 span.opacity(0–1, default 1) - an overall opacity multiplier on top of whatever Blend If calculates.match_size-croporstretch, resize method iftop_layerandbottom_layerdiffer in size.invert_mask-yes(the default, per the README, "as it seems to be the more common situation") orno; flips an optionalmaskinput before it's applied.mask(optional) - adds further transparency totop_layeron top of whatever Blend If itself calculates.
Two outputs: IMAGE, the composited result, and MASK, the transparency mask Blend If actually generated - check this to confirm you're selecting the pixels you think you are.
How to install it
ComfyUI Manager: search Virtuoso Nodes for ComfyUI, install, restart. By hand:
cd ComfyUI/custom_nodes
git clone https://github.com/chrisfreilich/virtuoso-nodes
pip install -r virtuoso-nodes/requirements.txt
Restart, find it under Virtuoso. No model files needed.
Common issues & troubleshooting
Top layer shows through everywhere, no selective blending happening. Check your four threshold values - the defaults (start_rise=0, end_rise=0, start_fall=1, end_fall=1) leave the entire brightness range opaque, which is a fully-visible top layer, not a starting point that's "off." You need to actually move start_rise/end_rise up from 0 or start_fall/end_fall down from 1 to carve out a transparent range.
The mask seems inverted from what you expected. invert_mask defaults to yes. That's deliberate per the author, but it does mean if you feed in a mask expecting it to work like most other ComfyUI mask inputs (unmodified), you'll get the opposite of what you wanted until you flip this to no.
Confusing which layer is "top" and which is analyzed. blend_if_layer and the top_layer/bottom_layer inputs are separate decisions - you can analyze the bottom layer's brightness to decide where the top layer shows through, which is a common and intentional combination, not a mistake. If results look backwards, check that you set blend_if_layer to the one you actually meant to key off.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| top_layer | IMAGE | — | |
| bottom_layer | IMAGE | — | |
| blend_if_layer | COMBO | 2 options: top, bottom | |
| blend_if_channel | COMBO | 4 options: gray, red, green, blue | |
| start_rise | FLOAT | 0.000–1 | — |
| end_rise | FLOAT | 0.000–1 | — |
| start_fall | FLOAT | 1.000–1 | — |
| end_fall | FLOAT | 1.000–1 | — |
| opacity | FLOAT | 1.000–1 | — |
| match_size | COMBO | 2 options: crop, stretch | |
| invert_mask | COMBO | 2 options: yes, no | |
| maskopt | MASK | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |
| MASK | MASK | — |