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 17 days ago· 120
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 🌱/Mask

    Inputs (12)

    NameTypeDefaultDescription
    widthINT51224–9223372036854776000Output width in pixels.
    heightINT51224–9223372036854776000Output height in pixels.
    total_framesINT641–9223372036854776000Number of frames in the animation.
    num_shadesINT22–256Gray levels. 2 = hard black/white mask; use 16+ to see gradients.
    modeCOMBOShape and motion direction (td/bu = top-down/bottom-up, lr/rl = left-right/right-left).
    invert_maskBOOLEANfalseSwap shape and background shades.
    band_thickness_ratioFLOAT0.200.01–1Band thickness as a fraction of the frame (moving_band modes).
    wave_amplitude_ratioFLOAT0.100–0.5Wave amplitude as a fraction of the frame (sine_wave modes).
    wave_frequencyFLOAT2.00.1–20Number of wave periods across the frame (sine_wave modes).
    wave_thickness_ratioFLOAT0.050.01–0.5Wave line thickness as a fraction of the frame (sine_wave modes).
    gradient_typeCOMBOnoneSoft edge style: around all edges, or only behind the direction of motion.
    gradient_width_ratioFLOAT0.000–1Gradient width relative to the shape size. 0 = hard edges.

    Outputs (4)

    NameTypeDescription
    IMAGEIMAGEMask animation frames (grayscale IMAGE).
    num_shadesINTNumber of gray levels used.
    widthINTWidth in pixels.
    heightINTHeight in pixels.