Stroke Reveal Animation
Make a pen literally draw your image open — no models, no API, just math
- reveal_image
- mask
- brush
- cover_image
- brush_mask
- images
You know those intro animations where a pen or brush sweeps across a blank page and the artwork magically appears behind it? This node does exactly that inside ComfyUI. You feed it a final image, a mask that says "reveal this region," and a PNG of a pen tip - and out comes a batch of frames of the pen scribbling the image into view. No checkpoint, no model download, no API key. It's pure pixel math, runs on CPU, and takes about two seconds to set up.
It's not a "generation" node at all. It's a post-processing/compositing node, the same family as mask compositors and image-batch utilities. You'd reach for it when you want a product shot, logo, or character render to arrive rather than just appear - as an animated intro, a GIF, or a social post. Drop it after your normal generation workflow and feed the output to a SaveAnimatedWEBP or video encoder.
How it actually works
The mechanism is simpler than the demo suggests. Internally, every pixel gets projected onto a direction defined by draw_angle (0 = left-to-right, 90 = top-to-bottom, 60 = a diagonal). Crucially, the projection range is normalized to the mask's own boundaries, not the image corners - so the reveal is paced across the masked area, which is why a small mask animates in sync with the shape rather than the frame.
Each frame computes a "reveal mask": how much of the sweep has happened at that point in num_frames. Your cover_image sits on top of the unrevealed parts, blended through a Gaussian blur controlled by feather_radius, and reveal_image shows through behind the pen. The final frame is the full image, pen removed.
The pen itself doesn't trace one smooth stroke. It hops along the current reveal line in a 5-position cycle (left edge → 1/3 → 2/3 → right edge → middle), holding each spot for two frames, then repeating. So over a 100-frame animation you get that "scratchy, redrawing" look rather than a clean single pass. That's by design - expect it.
The inputs that matter
Honestly, you'll fiddle with maybe four of them:
- reveal_image and mask - the picture being revealed, and where. The mask is the whole show; it bounds both the sweep and the pen's path.
- brush - your pen-tip PNG. It needs transparency (RGBA), or supply a brush_mask with its alpha instead.
- draw_angle - the reveal direction. This is a continuous 0–360 float, not the 8 preset arrows the README's older version listed.
Worth knowing: cover_image (optional) is what shows before the reveal. Skip it and you get a plain white backdrop. It must match your reveal image's exact pixel dimensions, or the node throws a ValueError.
Output is a single images batch - the full frame stack, ready for a GIF/WEBP/MP4 encoder.
Installing it
The easy way: ComfyUI Manager, search "ComfyUI-StrokeReveal", install, restart. Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/licanhua/ComfyUI-StrokeReveal
cd ComfyUI-StrokeReveal
pip install -r requirements.txt
Then restart ComfyUI. There's a ready-made workflow in the template browser under Workflow → Browse Templates → ComfyUI-StrokeReveal if you'd rather start from a working graph.
Gotchas
A few things that'll trip you up, mostly learned from reading the code:
- An all-black mask does nothing. The sweep projection needs mask pixels to exist; feed an empty mask and you get a static cover frame and no pen.
- The requirements.txt lists
opencv-pythonandscipy- the shipped code never imports either. It's all NumPy, torch, and Pillow, which ComfyUI already bundles. If you're installing by hand you can skip those two and skip a hefty download; just know the README and requirements are a bit rotty. - The README is stale. It describes an older API (
draw_direction,pen_scale,background_image); the shipped node usesdraw_angle,brush_scale, andcover_image. Trust the node, not the docs. - The author's a one-man shop and this pack has essentially no community footprint - don't expect a support thread to exist when something breaks.
It's a small, niche, MIT-licensed utility, but for a specific job - animated pen reveals - it's the shortest path from idea to frames.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| reveal_image | IMAGE | The image to be revealed through the animation | |
| mask | MASK | The mask defining the area where the reveal effect takes place | |
| brush | IMAGE | The brush/pen image (PNG with transparency) that animates along the reveal path | |
| num_frames | INT | 1002–500 | Total number of frames in the output animation |
| draw_angle | FLOAT | 600–360 | Angle in degrees for the scratch/reveal direction (0=left-to-right, 90=top-to-bottom, 60=diagonal) |
| feather_radius | INT | 100–100 | Blur radius for softening the reveal edge transition |
| brush_scale | FLOAT | 1.00.1–5 | Scale factor to resize the brush image |
| brush_anchor | COMBO | left_top | Which corner of the brush aligns with the drawing point |
| cover_imageopt | IMAGE | Optional: The image that covers the reveal area initially. If not provided, a white background is used. | |
| brush_maskopt | MASK | Optional: Alpha mask for the brush image. If provided, uses this as the brush transparency. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |