Making a photo flow with one fragment shader and a GIF writer
Description and use
OohAlive lets users draw arrows on a photo to create a flow effect and export a GIF. Duplicate frames, shimmering frozen pixels, and a memory‑leaking test were fixed.
Problem
The GIF export produced duplicate frames, shimmering frozen pixels, and a memory‑leaking test.
Outcome
The project now produces correct GIF loops, eliminates shimmering in frozen areas, and runs memory‑safe tests.
Workflow
- 1. Draw arrows on the photo to define flow vectors.
- 2. Render two copies of the photo offset by half a loop and cross‑fade them.
- 3. Apply a freeze brush mask to set flow to zero where needed.
- 4. Export the animation by calling the same draw function used for preview.
- 5. Encode frames to GIF, ensuring a single palette lookup table for the entire GIF.
- 6. Run automated tests using Buffer.compare instead of deepEqual to avoid memory growth.
Evidence
My first GIF had 40 frames, and frame 20 was identical to frame 0.
I measured a window on the frozen boat across the decoded GIF and found 1,070 changed values out of about 4,600.
The exported file went from 2.1 MB to 887 KiB.
A test compared two screenshots with assert.deepEqual. When they differed, Node tried to print both PNG buffers as a diff and the process kept growing until I killed it.
- Record date: 2026-10-09T09:40:52.085Z