Rectangles of Regret
Feb 23, 2026 · live
A tiny tool that turns your images into an animated 16:9 matrix of rotating rectangles in SVG.
Because nothing says “art” like 3,600 little bars spinning in synchronized misery.
What it does
- Samples each input image into a grid (default 80×45, roughly 16:9).
- Each sample becomes a white rectangle bar inside a spaced cell.
- Dark → thin + vertical, Light → thick + horizontal.
- Animates between images using a synchronized sweep:
- During the transition, all moving pixels share the same angle at any instant.
- Each cell starts moving when the sweep reaches its start angle, and stops when it reaches the target angle.
- Rotation is clockwise-only, and each transition can be forced to do at least N full rotations.
- Output is a single
out.svgthat loops forever.
Why it’s interesting (beyond looking cursed)
Most image-to-grid effects cheat by fading or cross-dissolving. This one behaves more like a clocked mechanical system: one sweep drives everything, and the “image change” is encoded as synchronized rotation states.
Quickstart
Requirements
- Python 3
- Pillow
- numpy
Install
macOS / Linux
python3 -m pip install pillow numpy
Windows
py -m pip install pillow numpy
Run
Generator script:
animated_rect_matrix_generator_v5_syncsweep_minrot_timing.py
macOS / Linux
python3 animated_rect_matrix_generator_v5_syncsweep_minrot_timing.py out.svg img1.jpg img2.jpg img3.png
Windows
py animated_rect_matrix_generator_v5_syncsweep_minrot_timing.py out.svg img1.jpg img2.jpg img3.png
Common settings
-
--transition_s
Seconds spent rotating/morphing between images (default: 2.0) -
--hold_s
Seconds resting on each image (default: 2.0) -
--min_full_rotations
Minimum full clockwise rotations per transition (default: 1)
Example (faster transitions, longer rest, extra spin):
python3 animated_rect_matrix_generator_v5_syncsweep_minrot_timing.py out.svg a.jpg b.jpg c.jpg \
--transition_s 1.2 --hold_s 3.0 --min_full_rotations 2
Other knobs (for people who enjoy tweaking endlessly):
--cols,--rows(default: 80 45)--render_w,--render_h(default: 1280 720)--gap_ratio(default: 0.5)--gamma(default: 1.15)--fill(default: white)
Viewing locally
Some SVG renderers don’t animate SMIL consistently. If it looks frozen, open it in a modern browser.
You can also serve a folder locally:
python3 -m http.server 8000
Then open:
http://localhost:8000/out.svg
License
Informal “do whatever you want” vibes. If it breaks, you keep both pieces.
Links
- GitHub repo: https://github.com/unusable-ai/Rectangles-of-Regret