Image Overlay
Composite one image onto another with real blend modes
- source_image
- overlay_image
- optional_mask
- images
Layering is a core ComfyUI operation with surprisingly few good nodes. ImageOverlay_lhy is one of them: it takes a source image, a second image on top, and composites them with a proper set of Photoshop-style blend modes - not just "paste and call it a day." It's the node you reach for when you're putting a logo or watermark over a render, compositing a refined face crop back onto a detailer output, or blending a texture onto a photo with multiply so the shading sticks.
It's in the ComfyUI-lhyNodes pack's image category, and it handles the things that make overlay annoying elsewhere: batches, mismatched sizes, RGBA alpha, and masks.
How it works
The overlay is centered on the source, and with scale_to_fill on (the default) it's scaled to cover the source - the larger of the two scale factors - so a square overlay fills a portrait source and gets center-cropped. The overlay's own alpha channel (if it has one) plus the opacity slider plus an optional optional_mask all combine into the effective alpha, so you can feather where the overlay lands. invert_mask defaults to true - the mask you feed in is inverted, which matches how ComfyUI masks conventionally work (white = keep source, or here: white = keep the overlay hidden... the practical effect is you flip it if the result looks backwards).
Blending happens per-pixel with torch ops: normal, multiply, screen, overlay, soft_light, difference, exclusion, linear_dodge_add, linear_burn, subtract. The overlay's alpha is multiplied into the blend, then the result is alpha-composited over the source. RGBA sources keep their alpha channel, updated correctly where the overlay lands.
Inputs and outputs
source_image(IMAGE) - the base.overlay_image(IMAGE) - the layer on top. Single overlay applies to every source frame; matching batch counts pair up frame-by-frame.blend_mode- 11 modes, defaultnormal.opacity(FLOAT, 0–1, default 1) - overall layer strength.scale_to_fill(BOOLEAN, default true) - scale the overlay to cover the source.invert_mask(BOOLEAN, default true) - invertoptional_mask.optional_mask(MASK, optional) - where the overlay is allowed to show.
One output: images (IMAGE), same size as the source.
Installing it
Part of ComfyUI-lhyNodes:
- ComfyUI Manager → search
lhyNodes→ Install, restart. - Or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/lihaoyun6/ComfyUI-lhyNodes.git
python -m pip install -r ComfyUI-lhyNodes/requirements.txt
Restart ComfyUI.
Where people get burned
Two source-level quirks worth knowing. First, hard_light is listed in the dropdown but not implemented - look at the code and it falls through to normal, so picking it silently gives you a normal blend. Use overlay instead, which is actually implemented. Second, invert_mask defaulting to true confuses everyone the first time: if your overlay is invisible or the mask seems backwards, flip it before chasing anything else. And if you're compositing a detailer crop, remember the overlay is centered - if your refined region isn't centered in its crop, align the crop first or the patch lands in the wrong place.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| source_image | IMAGE | — | |
| overlay_image | IMAGE | — | |
| blend_mode | COMBO | normal | 11 options: normal, multiply, screen, overlay, soft_light, hard_light, +5 |
| opacity | FLOAT | 1.000–1 | — |
| scale_to_fill | BOOLEAN | true | Scale the overlay image to fill the source. |
| invert_mask | BOOLEAN | true | — |
| optional_maskopt | MASK | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |