Nodes/ComfyUI-CustomNodePacks/Layer Effects (C2C)
ComfyUI Node

Layer Effects (C2C)

Your cutout looks pasted on. Layer Effects (C2C) is the fix

By Code2Collapse·Created 8 months ago·Updated about 18 hours ago· 60
Layer Effects (C2C)
  • layer_image
  • background_image
  • layer_mask
  • image
  • effect_mask
  • report
◄invert_masktrue►
◄orderdrop_shadow, outer_glow, gradient_map, gradient_overlay, color_overlay, inner_glow, inner_shadow, stroke►
◄dissolve_seed0►
◄drop_shadowtrue►
◄drop_shadow_blend_mode▾►
◄drop_shadow_opacity50►
◄drop_shadow_distance_x25►
◄drop_shadow_distance_y25►
◄drop_shadow_grow6►
◄drop_shadow_blur18►
◄drop_shadow_color#000000►
◄outer_glowfalse►
◄outer_glow_blend_mode▾►
◄outer_glow_opacity100►
◄outer_glow_brightness5►
◄outer_glow_range48►
◄outer_glow_blur25►
◄outer_glow_light_color#FFBF30►
◄outer_glow_color#FE0000►
◄gradient_mapfalse►
◄gradient_map_start_color#015A52►
◄gradient_map_mid_color#02AF9F►
◄gradient_map_end_color#7FFFEC►
◄gradient_map_mid_point0.60►
◄gradient_map_opacity100►
◄gradient_overlayfalse►
◄gradient_overlay_blend_mode▾►
◄gradient_overlay_opacity100►
◄gradient_overlay_start_color#FFBF30►
◄gradient_overlay_start_alpha255►
◄gradient_overlay_end_color#FE0000►
◄gradient_overlay_end_alpha255►
◄gradient_overlay_angle0►
◄color_overlayfalse►
◄color_overlay_blend_mode▾►
◄color_overlay_opacity100►
◄color_overlay_color#FFBF30►
◄inner_glowfalse►
◄inner_glow_blend_mode▾►
◄inner_glow_opacity100►
◄inner_glow_brightness5►
◄inner_glow_range48►
◄inner_glow_blur25►
◄inner_glow_light_color#FFBF30►
◄inner_glow_color#FE0000►
◄inner_shadowfalse►
◄inner_shadow_blend_mode▾►
◄inner_shadow_opacity50►
◄inner_shadow_distance_x5►
◄inner_shadow_distance_y5►
◄inner_shadow_grow2►
◄inner_shadow_blur15►
◄inner_shadow_color#000000►
◄strokefalse►
◄stroke_blend_mode▾►
◄stroke_opacity100►
◄stroke_grow0►
◄stroke_width8►
◄stroke_blur0►
◄stroke_color#FF0000►

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 in layer_mask.
  • invert_mask - leave at true for a standard white-on-black matte.
  • order - the composition. This is a real sequence, and putting stroke before drop_shadow gets 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_shadow is 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.

Category🐺 C2C/🧰 Core/Layer Effects

Inputs (63)

NameTypeDefaultDescription
layer_imageIMAGEForeground layer; its alpha or layer_mask defines where the effects go.
invert_maskBOOLEANtrueFlip mask polarity when your matte is white-on-black.
orderSTRINGdrop_shadow, outer_glow, gradient_map, gradient_overlay, color_overlay, inner_glow, inner_shadow, strokeThe 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_seedINT00–2147483647Only used by the 'dissolve' blend mode. Upstream reseeds every frame, so a dissolve flickers through a sequence; a fixed seed here holds still.
drop_shadowBOOLEANtrueDrop shadow: switch it on to show and use its controls.
drop_shadow_blend_modeCOMBODrop shadow
drop_shadow_opacityINT500–100Drop shadow
drop_shadow_distance_xINT25-9999–9999Drop shadow: Horizontal offset in pixels. Positive moves the shadow right — the opposite of the upstream LayerStyle node, which negated it.
drop_shadow_distance_yINT25-9999–9999Drop shadow: Vertical offset in pixels. Positive moves the shadow down — the opposite of the upstream LayerStyle node, which negated it.
drop_shadow_growINT6-9999–9999Drop 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_blurINT180–1000Drop shadow: Gaussian blur radius on the shadow matte.
drop_shadow_colorSTRING#000000Drop shadow
outer_glowBOOLEANfalseOuter glow: switch it on to show and use its controls.
outer_glow_blend_modeCOMBOOuter glow
outer_glow_opacityINT1000–100Outer glow
outer_glow_brightnessINT52–20Outer glow: Number of glow passes from core to edge.
outer_glow_rangeINT48-9999–9999Outer glow: Initial spread for the outer glow; clamped to frame size.
outer_glow_blurINT250–9999Outer glow
outer_glow_light_colorSTRING#FFBF30Outer glow
outer_glow_colorSTRING#FE0000Outer glow
gradient_mapBOOLEANfalseGradient map: switch it on to show and use its controls.
gradient_map_start_colorSTRING#015A52Gradient map
gradient_map_mid_colorSTRING#02AF9FGradient map
gradient_map_end_colorSTRING#7FFFECGradient map
gradient_map_mid_pointFLOAT0.600–1Gradient map
gradient_map_opacityINT1000–100Gradient map
gradient_overlayBOOLEANfalseGradient overlay: switch it on to show and use its controls.
gradient_overlay_blend_modeCOMBOGradient overlay
gradient_overlay_opacityINT1000–100Gradient overlay
gradient_overlay_start_colorSTRING#FFBF30Gradient overlay
gradient_overlay_start_alphaINT2550–255Gradient overlay
gradient_overlay_end_colorSTRING#FE0000Gradient overlay
gradient_overlay_end_alphaINT2550–255Gradient overlay
gradient_overlay_angleINT0-180–180Gradient overlay
color_overlayBOOLEANfalseColour overlay: switch it on to show and use its controls.
color_overlay_blend_modeCOMBOColour overlay
color_overlay_opacityINT1000–100Colour overlay
color_overlay_colorSTRING#FFBF30Colour overlay
inner_glowBOOLEANfalseInner glow: switch it on to show and use its controls.
inner_glow_blend_modeCOMBOInner glow
inner_glow_opacityINT1000–100Inner glow
inner_glow_brightnessINT52–20Inner glow: Number of glow passes from core to edge.
inner_glow_rangeINT48-9999–9999Inner glow: Initial spread for the outer glow; clamped to frame size.
inner_glow_blurINT250–9999Inner glow
inner_glow_light_colorSTRING#FFBF30Inner glow
inner_glow_colorSTRING#FE0000Inner glow
inner_shadowBOOLEANfalseInner shadow: switch it on to show and use its controls.
inner_shadow_blend_modeCOMBOInner shadow
inner_shadow_opacityINT500–100Inner shadow
inner_shadow_distance_xINT5-9999–9999Inner shadow: Horizontal offset in pixels. Positive moves the shadow right — the opposite of the upstream LayerStyle node, which negated it.
inner_shadow_distance_yINT5-9999–9999Inner shadow: Vertical offset in pixels. Positive moves the shadow down — the opposite of the upstream LayerStyle node, which negated it.
inner_shadow_growINT2-9999–9999Inner 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_blurINT150–1000Inner shadow: Gaussian blur radius on the shadow matte.
inner_shadow_colorSTRING#000000Inner shadow
strokeBOOLEANfalseStroke: switch it on to show and use its controls.
stroke_blend_modeCOMBOStroke
stroke_opacityINT1000–100Stroke
stroke_growINT0-999–999Stroke
stroke_widthINT80–999Stroke
stroke_blurINT00–100Stroke
stroke_colorSTRING#FF0000Stroke
background_imageoptIMAGEPlate to composite onto; empty = transparent canvas.
layer_maskoptMASKOptional matte; overrides the layer's alpha when connected.

Outputs (3)

NameTypeDescription
imageIMAGEThe layer with its effects, over the background.
effect_maskMASKWhere the effects landed: the union of every switched-on effect's footprint.
reportSTRINGOne line per effect applied, with anything worth knowing (clamped sizes, resized masks).