Layer Effects (C2C)
Your cutout looks pasted on. Layer Effects (C2C) is the fix
- layer_image
- background_image
- layer_mask
- image
- effect_mask
- report
Every cutout looks pasted on. You run BiRefNet or SAM, drop the subject on a new background, and something is wrong that you can't quite name: no shadow telling you it's standing on anything, a hard edge, colour that doesn't belong. Compositors fix this with layer styles - the drop-shadow/glow/stroke stack Photoshop has had for twenty years. In ComfyUI you can approximate it with a blur, a composite and a colour-match, or run one node that does the whole stack in an order you choose.
What it actually is
Layer Effects (C2C) is a single node holding eight Photoshop-style effects: drop shadow, outer glow, gradient map, gradient overlay, colour overlay, inner glow, inner shadow and stroke. Each has an on/off switch and its own prefixed controls, and they're applied to the result of the previous one in the order you write into the order string.
It comes from chflame163's ComfyUI_LayerStyle (MIT), where those eight were separate nodes with three variants each (V1/V2/V3). This is the union of all of them collapsed into one node with a text field for ordering. If you've used LayerStyle, you already know the controls; the difference is you're not installing three nodes to get a stroke.
How the effects stack works
layer_image is your foreground. The effects land where its alpha is white - or, if you connect layer_mask, where that is white, since a connected matte overrides the layer's own alpha.
invert_mask defaults to true, and that's correct for the common case: a SAM or BiRefNet matte arrives white-on-black. Set it false if your mask is already "white = paint the effect here". Getting it backwards is the number one "nothing happened" report.
Geometry for shadows and glows is grow → blur → offset. drop_shadow_grow expands the shadow matte before the blur; set it negative and the shadow pulls inside the subject edge, which is how you get a tight contact shadow without a grey halo. Glows get outer_glow_brightness (how many glow passes run from core outward) and outer_glow_range (initial spread, clamped to the frame).
The 30 blend modes (normal through color burn, linear light) are ported from LayerStyle's blendmodes.py, which credits the Virtuoso pack. They're reimplemented in torch rather than importing the blend_modes pip package, so there's nothing extra to install and the batch runs in one pass instead of a PIL round-trip per frame. dissolve_seed exists because dissolve is a random dot pattern: upstream reseeded every frame so it flickered through a sequence, and a fixed seed holds it still.
The inputs you'll actually touch
layer_image- the subject. Just the RGB, the matte rides in the alpha or inlayer_mask.invert_mask- leave at true for a standard white-on-black matte.order- the composition. This is a real sequence, and puttingstrokebeforedrop_shadowgets you a shadow offset off the stroke rather than off the subject.background_image- an optional plate to composite onto. Leave it empty and the effects sit on transparency, which is right for an alpha handoff and confusing in a preview, because transparency previews as black.- One boolean per effect (
drop_shadowis on by default, the rest off), then that effect's own colour, opacity, blend mode and size controls.
Outputs
image is the layer with its effects over the background. effect_mask is the union footprint of every effect that ran - genuinely useful, because it lets you grade or darken just the glow without touching the subject. report is one line per effect applied, with anything worth knowing: clamped sizes, resized masks.
Installing it
ComfyUI Manager → search "CustomNodePacks", or:
cd ComfyUI/custom_nodes
git clone https://github.com/Code2Collapse/ComfyUI-CustomNodePacks
Restart and check the console for [C2C] CustomNodePacks: 112 nodes loaded ... 0 failed - this is one node out of a very large pack.
Take the README's own warning seriously: pip install -r requirements.txt can overwrite ComfyUI's bundled torch, numpy and Pillow. Read the file and install only what's missing, and for this node that's nothing - no models, no cv2, pure torch.
Where it bites
The distance sign is deliberately not upstream's. Here, drop_shadow_distance_x positive moves the shadow right and drop_shadow_distance_y positive moves it down; LayerStyle negated both. If you're porting an old LayerStyle workflow, expect your shadows to jump to the opposite side.
Four upstream defects are fixed here, and the source names them: zero distance used to raise UnboundLocalError, a mask of a mismatched size got replaced with solid white (the shadow becomes a full-frame rectangle), a missing mask returned a Python list into an IMAGE socket, and RGBA came back where [B,H,W,3] was expected.
Is it worth it
If all you want is a drop shadow, blur-and-composite is fewer nodes than learning eight prefixed control groups. The value shows up when you're building a title card, a thumbnail or a product comp and want the whole stack at once - inner shadow and outer glow and a gradient map and a stroke - without leaving the graph or re-rolling a seed for a look you already had in your head.
Inputs (63)
| Name | Type | Default | Description |
|---|---|---|---|
| layer_image | IMAGE | Foreground layer; its alpha or layer_mask defines where the effects go. | |
| invert_mask | BOOLEAN | true | Flip mask polarity when your matte is white-on-black. |
| order | STRING | drop_shadow, outer_glow, gradient_map, gradient_overlay, color_overlay, inner_glow, inner_shadow, stroke | The order the switched-on effects are applied in, comma separated; each is applied to the result of the one before. An effect that is on but not listed runs after the listed ones, in the default order. |
| dissolve_seed | INT | 00–2147483647 | Only used by the 'dissolve' blend mode. Upstream reseeds every frame, so a dissolve flickers through a sequence; a fixed seed here holds still. |
| drop_shadow | BOOLEAN | true | Drop shadow: switch it on to show and use its controls. |
| drop_shadow_blend_mode | COMBO | Drop shadow | |
| drop_shadow_opacity | INT | 500–100 | Drop shadow |
| drop_shadow_distance_x | INT | 25-9999–9999 | Drop shadow: Horizontal offset in pixels. Positive moves the shadow right — the opposite of the upstream LayerStyle node, which negated it. |
| drop_shadow_distance_y | INT | 25-9999–9999 | Drop shadow: Vertical offset in pixels. Positive moves the shadow down — the opposite of the upstream LayerStyle node, which negated it. |
| drop_shadow_grow | INT | 6-9999–9999 | Drop shadow: Expand the shadow before blurring. Positive spreads it past the subject edge; negative pulls it inside, which keeps a tight contact shadow from haloing. |
| drop_shadow_blur | INT | 180–1000 | Drop shadow: Gaussian blur radius on the shadow matte. |
| drop_shadow_color | STRING | #000000 | Drop shadow |
| outer_glow | BOOLEAN | false | Outer glow: switch it on to show and use its controls. |
| outer_glow_blend_mode | COMBO | Outer glow | |
| outer_glow_opacity | INT | 1000–100 | Outer glow |
| outer_glow_brightness | INT | 52–20 | Outer glow: Number of glow passes from core to edge. |
| outer_glow_range | INT | 48-9999–9999 | Outer glow: Initial spread for the outer glow; clamped to frame size. |
| outer_glow_blur | INT | 250–9999 | Outer glow |
| outer_glow_light_color | STRING | #FFBF30 | Outer glow |
| outer_glow_color | STRING | #FE0000 | Outer glow |
| gradient_map | BOOLEAN | false | Gradient map: switch it on to show and use its controls. |
| gradient_map_start_color | STRING | #015A52 | Gradient map |
| gradient_map_mid_color | STRING | #02AF9F | Gradient map |
| gradient_map_end_color | STRING | #7FFFEC | Gradient map |
| gradient_map_mid_point | FLOAT | 0.600–1 | Gradient map |
| gradient_map_opacity | INT | 1000–100 | Gradient map |
| gradient_overlay | BOOLEAN | false | Gradient overlay: switch it on to show and use its controls. |
| gradient_overlay_blend_mode | COMBO | Gradient overlay | |
| gradient_overlay_opacity | INT | 1000–100 | Gradient overlay |
| gradient_overlay_start_color | STRING | #FFBF30 | Gradient overlay |
| gradient_overlay_start_alpha | INT | 2550–255 | Gradient overlay |
| gradient_overlay_end_color | STRING | #FE0000 | Gradient overlay |
| gradient_overlay_end_alpha | INT | 2550–255 | Gradient overlay |
| gradient_overlay_angle | INT | 0-180–180 | Gradient overlay |
| color_overlay | BOOLEAN | false | Colour overlay: switch it on to show and use its controls. |
| color_overlay_blend_mode | COMBO | Colour overlay | |
| color_overlay_opacity | INT | 1000–100 | Colour overlay |
| color_overlay_color | STRING | #FFBF30 | Colour overlay |
| inner_glow | BOOLEAN | false | Inner glow: switch it on to show and use its controls. |
| inner_glow_blend_mode | COMBO | Inner glow | |
| inner_glow_opacity | INT | 1000–100 | Inner glow |
| inner_glow_brightness | INT | 52–20 | Inner glow: Number of glow passes from core to edge. |
| inner_glow_range | INT | 48-9999–9999 | Inner glow: Initial spread for the outer glow; clamped to frame size. |
| inner_glow_blur | INT | 250–9999 | Inner glow |
| inner_glow_light_color | STRING | #FFBF30 | Inner glow |
| inner_glow_color | STRING | #FE0000 | Inner glow |
| inner_shadow | BOOLEAN | false | Inner shadow: switch it on to show and use its controls. |
| inner_shadow_blend_mode | COMBO | Inner shadow | |
| inner_shadow_opacity | INT | 500–100 | Inner shadow |
| inner_shadow_distance_x | INT | 5-9999–9999 | Inner shadow: Horizontal offset in pixels. Positive moves the shadow right — the opposite of the upstream LayerStyle node, which negated it. |
| inner_shadow_distance_y | INT | 5-9999–9999 | Inner shadow: Vertical offset in pixels. Positive moves the shadow down — the opposite of the upstream LayerStyle node, which negated it. |
| inner_shadow_grow | INT | 2-9999–9999 | Inner shadow: Expand the shadow before blurring. Positive spreads it past the subject edge; negative pulls it inside, which keeps a tight contact shadow from haloing. |
| inner_shadow_blur | INT | 150–1000 | Inner shadow: Gaussian blur radius on the shadow matte. |
| inner_shadow_color | STRING | #000000 | Inner shadow |
| stroke | BOOLEAN | false | Stroke: switch it on to show and use its controls. |
| stroke_blend_mode | COMBO | Stroke | |
| stroke_opacity | INT | 1000–100 | Stroke |
| stroke_grow | INT | 0-999–999 | Stroke |
| stroke_width | INT | 80–999 | Stroke |
| stroke_blur | INT | 00–100 | Stroke |
| stroke_color | STRING | #FF0000 | Stroke |
| background_imageopt | IMAGE | Plate to composite onto; empty = transparent canvas. | |
| layer_maskopt | MASK | Optional matte; overrides the layer's alpha when connected. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | The layer with its effects, over the background. |
| effect_mask | MASK | Where the effects landed: the union of every switched-on effect's footprint. |
| report | STRING | One line per effect applied, with anything worth knowing (clamped sizes, resized masks). |