ComfyUI Node

AOI_Processing_Zho

One still image that secretly holds an entire animation

By ZHO-ZHO-ZHO·Created 2 years ago·Updated 2 years ago· 21
AOI_Processing_Zho
  • images
  • image
  • mask
width1

If you've ever scrolled past one of those posts where a photo seems to wink, spin, or wave as it moves across your screen, you've seen what this node does. AOI_Processing_Zho takes a batch of animation frames and fuses them into a single image that plays the whole animation back when you slide a striped mask over it - the classic slit-scan / lenticular trick, wrapped up as one ComfyUI node. No model, no weights, no GPU work. It's a small, oddly charming utility from ZHO-ZHO-ZHO, the same author behind ComfyUI-PuLID-ZHO and dozens of other wrapper packs.

What it actually does

You feed it images, a batch of frames (say 8 or 16), and it slices every frame into thin vertical strips, then interleaves them into one frame: strip 0 of frame 0, strip 0 of frame 1, strip 0 of frame 2, then strip 1 of frame 0, and so on. Because each group of strips is laid out in frame order, a mask that reveals exactly one strip per group shows frame 0 - slide that mask one strip-width sideways and it shows frame 1. Keep sliding and you get a full animation living inside a static picture. That's the whole illusion.

It also hands you the mask that does the revealing: an RGBA overlay with the first frame's strips transparent and everything else black, so you don't have to build the striping yourself. Wire image and mask into a compositing setup (or a MaskToImage → alpha merge) and you've got the "animated optical illusion" effect, ready to animate with whatever mask movement your display method supports - scroll position, a sliding overlay, an AnimateDiff-style mask shift, you name it.

The inputs that matter

Only two, and you'll fiddle with one of them:

  • images - your frames, as an IMAGE batch. Anything that outputs a batch works: Load Video (or the VHS pack), frames pulled out of AnimateDiff, or just stacked images. The frames should be the same size.
  • width - strip width in pixels, default 1. This is the fun knob. 1 gives pixel-thin strips: the smoothest illusion, but the image looks like dense static and any small misalignment shows. Crank it to 5–20 and the strips get chunky and visible - closer to a legit lenticular print, but the animation gets coarser. Start at 1, go up only if the result looks broken or moiré-y.

The outputs are image (the interleaved still) and mask (the reveal mask), both IMAGE.

Installing it

The README keeps it blessedly simple, and there are no dependencies to chase - no requirements.txt, no model downloads, nothing. It only uses PIL, numpy, and torch, all of which ship with ComfyUI already.

  • ComfyUI Manager: search "Animated-optical-illusions" (or "AOI") and install.
  • Manual: cd ComfyUI/custom_nodes && git clone https://github.com/ZHO-ZHO-ZHO/ComfyUI-Animated-optical-illusions, then restart ComfyUI.

Look under Zho模块组/AOI in the node menu.

Where people get burned

  • Frames get silently dropped. The node slices each frame into image_width / width strips, and interleave truncates to the shortest batch. If you feed more frames than there are strips per frame, the trailing frames vanish without a warning. With a 512px-wide image and width=1 that's 512 strips - fine. But a 64px-wide image with 100 frames and width=2 will quietly eat most of your animation. Fewer frames, or wider images, or bigger width, all fix it.
  • It's a still, not a GIF. A lot of people expect a video out. You get an image plus a mask; you have to supply the sliding. If you just stare at the output image, it looks like noise.
  • All frames must be the same dimensions. The code assumes it; mismatched sizes will throw or produce garbage.

For a one-trick pack this is a genuinely tidy one - and refreshingly, it's the rare ZHO node with zero auto-downloading and zero heavy deps. If you're making a "secret animation" image for a profile picture or a party trick, it's a five-minute setup and hard to mess up once you respect the frame-count gotcha.

CategoryZho模块组/AOI

Inputs (2)

NameTypeDefaultDescription
imagesIMAGE
widthINT11–100

Outputs (2)

NameTypeDescription
imageIMAGE
maskIMAGE