Nodes/Eden.art nodesuite/Animated Shape Mask
ComfyUI Node Runs on cloud

Animated Shape Mask

Procedural mask reveals, no drawing required

By edenartlabΒ·Created 3 years agoΒ·Updated 6 months agoΒ· 119
Animated Shape Mask
    • IMAGE
    • num_shades
    • width
    • height
    β—„width512β–Ί
    β—„height512β–Ί
    β—„total_frames64β–Ί
    β—„num_shades2β–Ί
    β—„modeβ–Ύβ–Ί
    β—„invert_maskfalseβ–Ί
    β—„band_thickness_ratio0.20β–Ί
    β—„wave_amplitude_ratio0.10β–Ί
    β—„wave_frequency2.0β–Ί
    β—„wave_thickness_ratio0.05β–Ί
    β—„gradient_typenoneβ–Ί
    β—„gradient_width_ratio0.00β–Ί

    Animating a mask is one of those things that sounds easy until you try it - you need a moving region that changes every frame, and drawing 64 of them by hand is miserable. Animated Shape Mask is the cheat code: it generates a whole mask animation procedurally from a handful of parameters. Moving bands, traveling sine waves, expanding or contracting circles - pick a mode, pick a resolution, and out comes an image sequence where each frame is a mask you can drive an inpainting reveal with.

    This is the sibling of Animation_RGB_Mask in the Eden pack, and the family resemblance shows: one generates color-coded region animations, this one generates grayscale shape masks. If your goal is a clean binary or shaded mask sweep - like a cinematic reveal where content is masked in as a band moves across - this is the node.

    How it works

    Under the hood it's a MaskAnimationGenerator that renders each frame's mask at your chosen width/height, then stacks the frames into an IMAGE batch. The modes break into three families:

    • moving_band_ - a solid band sweeping across the frame (top-down, bottom-up, left-right, right-left).
    • sine_wave_ - a wavy band, with wave_frequency controlling ripple and wave_amplitude_ratio controlling wobble, sweeping across in one of four directions.
    • expanding_circle / contracting_circle - a circle growing from or shrinking to the center.

    Two knobs matter more than the rest. num_shades (default 2) sets how many grayscale levels the mask uses - 2 gives hard black/white, which is what you want for feeding a real inpainting mask. Crank it to 16–64 and you get smooth gradient shades instead, which looks great composited but behaves differently when a KSampler treats it as a mask. invert_mask flips which side is active, useful when you want content to leave instead of arrive.

    There's also a gradient_type (none / all_edges / trailing_edge) plus gradient_width_ratio that softens mask edges with a distance-based falloff (via OpenCV's distance transform) - all_edges fades every boundary, trailing_edge fades only the moving edge, which gives a lovely blur-sweep reveal effect.

    The outputs

    • IMAGE - the mask animation, total_frames frames of widthΓ—height.
    • num_shades, width, height - echoed back as INTs so downstream nodes can use them without guessing.

    Wire the IMAGE into a mask-conversion node and then into Set Latent Noise Mask on an inpaint KSampler, and you've got a frame-consistent animated reveal. The KB's inpainting essay is worth a re-read here: masked inpainting still owns bit-identical unmasked pixels, which is exactly the property an animated reveal needs - the already-revealed area stays frozen while only the newly exposed band regenerates.

    Installing

    It's part of edenartlab/eden_comfy_pipelines (Eden.art nodesuite):

    cd ComfyUI/custom_nodes
    git clone https://github.com/edenartlab/eden_comfy_pipelines.git
    cd eden_comfy_pipelines
    pip install -r requirements.txt
    

    Or ComfyUI Manager β†’ search "Eden". It needs opencv-python (in the pack's requirements) for the gradient falloff, but nothing else exotic.

    Gotchas

    Two real ones. First, the binary-mask trap: the pack prints a warning if you set gradient_type to anything but none while num_shades is 2 - gradients need multiple shades to exist, so you'll get a hard mask and wonder why your soft fade didn't happen. Second, remember the output is IMAGE, not MASK - most inpainting nodes want a MASK, so throw it through a converter (or use it as IMAGE conditioning) before it hits a KSampler. And don't forget the obvious: a total_frames of 64 at 512Γ—512 is a chunk of VRAM when it's stacked as a single batch, so keep resolutions sane for long sweeps.

    CategoryEden 🌱/Masks

    Inputs (12)

    NameTypeDefaultDescription
    widthINT51224–9223372036854776000β€”
    heightINT51224–9223372036854776000β€”
    total_framesINT641–9223372036854776000β€”
    num_shadesINT22–256β€”
    modeCOMBO10 options: moving_band_horizontal_td, moving_band_horizontal_bu, moving_band_vertical_lr, moving_band_vertical_rl, sine_wave_vertical_lr, sine_wave_vertical_rl, +4
    invert_maskBOOLEANfalseβ€”
    band_thickness_ratioFLOAT0.200.01–1β€”
    wave_amplitude_ratioFLOAT0.100–0.5β€”
    wave_frequencyFLOAT2.00.1–20β€”
    wave_thickness_ratioFLOAT0.050.01–0.5β€”
    gradient_typeCOMBOnone3 options: none, all_edges, trailing_edge
    gradient_width_ratioFLOAT0.000–1β€”

    Outputs (4)

    NameTypeDescription
    IMAGEIMAGEβ€”
    num_shadesINTβ€”
    widthINTβ€”
    heightINTβ€”