SKILL.md
SKILL.mdBrowse 7 files
2,076 tokens
7,587 bytes
Token encoding: o200k_base
Snapshot 24fd22b
1---2name: pixel-art3description: "Pixel art w/ era palettes (NES, Game Boy, PICO-8)."4version: 2.0.05author: dodo-reach6license: MIT7platforms: [linux, macos, windows]8metadata:9 hermes:10 tags: [creative, pixel-art, arcade, snes, nes, gameboy, retro, image, video]11 category: creative12 credits:13 - "Hardware palettes and animation loops ported from Synero/pixel-art-studio (MIT) — https://github.com/Synero/pixel-art-studio"14---15 16# Pixel Art17 18Convert any image into retro pixel art, then optionally animate it into a short19MP4 or GIF with era-appropriate effects (rain, fireflies, snow, embers).20 21Two scripts ship with this skill:22 23- `scripts/pixel_art.py` — photo → pixel-art PNG (Floyd-Steinberg dithering)24- `scripts/pixel_art_video.py` — pixel-art PNG → animated MP4 (+ optional GIF)25 26Each is importable or runnable directly. Presets snap to hardware palettes27when you want era-accurate colors (NES, Game Boy, PICO-8, etc.), or use28adaptive N-color quantization for arcade/SNES-style looks.29 30## When to Use31 32- User wants retro pixel art from a source image33- User asks for NES / Game Boy / PICO-8 / C64 / arcade / SNES styling34- User wants a short looping animation (rain scene, night sky, snow, etc.)35- Posters, album covers, social posts, sprites, characters, avatars36 37## Workflow38 39Before generating, confirm the style with the user. Different presets produce40very different outputs and regenerating is costly.41 42### Step 1 — Offer a style43 44Call `clarify` with 4 representative presets. Pick the set based on what the45user asked for — don't just dump all 14.46 47Default menu when the user's intent is unclear:48 49```python50clarify(51 question="Which pixel-art style do you want?",52 choices=[53 "arcade — bold, chunky 80s cabinet feel (16 colors, 8px)",54 "nes — Nintendo 8-bit hardware palette (54 colors, 8px)",55 "gameboy — 4-shade green Game Boy DMG",56 "snes — cleaner 16-bit look (32 colors, 4px)",57 ],58)59```60 61When the user already named an era (e.g. "80s arcade", "Gameboy"), skip62`clarify` and use the matching preset directly.63 64### Step 2 — Offer animation (optional)65 66If the user asked for a video/GIF, or the output might benefit from motion,67ask which scene:68 69```python70clarify(71 question="Want to animate it? Pick a scene or skip.",72 choices=[73 "night — stars + fireflies + leaves",74 "urban — rain + neon pulse",75 "snow — falling snowflakes",76 "skip — just the image",77 ],78)79```80 81Do NOT call `clarify` more than twice in a row. One for style, one for scene if82animation is on the table. If the user explicitly asked for a specific style83and scene in their message, skip `clarify` entirely.84 85### Step 3 — Generate86 87Run `pixel_art()` first; if animation was requested, chain into88`pixel_art_video()` on the result.89 90## Preset Catalog91 92| Preset | Era | Palette | Block | Best for |93|--------|-----|---------|-------|----------|94| `arcade` | 80s arcade | adaptive 16 | 8px | Bold posters, hero art |95| `snes` | 16-bit | adaptive 32 | 4px | Characters, detailed scenes |96| `nes` | 8-bit | NES (54) | 8px | True NES look |97| `gameboy` | DMG handheld | 4 green shades | 8px | Monochrome Game Boy |98| `gameboy_pocket` | Pocket handheld | 4 grey shades | 8px | Mono GB Pocket |99| `pico8` | PICO-8 | 16 fixed | 6px | Fantasy-console look |100| `c64` | Commodore 64 | 16 fixed | 8px | 8-bit home computer |101| `apple2` | Apple II hi-res | 6 fixed | 10px | Extreme retro, 6 colors |102| `teletext` | BBC Teletext | 8 pure | 10px | Chunky primary colors |103| `mspaint` | Windows MS Paint | 24 fixed | 8px | Nostalgic desktop |104| `mono_green` | CRT phosphor | 2 green | 6px | Terminal/CRT aesthetic |105| `mono_amber` | CRT amber | 2 amber | 6px | Amber monitor look |106| `neon` | Cyberpunk | 10 neons | 6px | Vaporwave/cyber |107| `pastel` | Soft pastel | 10 pastels | 6px | Kawaii / gentle |108 109Named palettes live in `scripts/palettes.py` (see `references/palettes.md` for110the complete list — 28 named palettes total). Any preset can be overridden:111 112```python113pixel_art("in.png", "out.png", preset="snes", palette="PICO_8", block=6)114```115 116## Scene Catalog (for video)117 118| Scene | Effects |119|-------|---------|120| `night` | Twinkling stars + fireflies + drifting leaves |121| `dusk` | Fireflies + sparkles |122| `tavern` | Dust motes + warm sparkles |123| `indoor` | Dust motes |124| `urban` | Rain + neon pulse |125| `nature` | Leaves + fireflies |126| `magic` | Sparkles + fireflies |127| `storm` | Rain + lightning |128| `underwater` | Bubbles + light sparkles |129| `fire` | Embers + sparkles |130| `snow` | Snowflakes + sparkles |131| `desert` | Heat shimmer + dust |132 133## Invocation Patterns134 135### Python (import)136 137```python138import sys139import os140sys.path.insert(0, os.path.expanduser("~/.hermes/skills/creative/pixel-art/scripts"))141from pixel_art import pixel_art142from pixel_art_video import pixel_art_video143 144# 1. Convert to pixel art145pixel_art("/path/to/photo.jpg", "/tmp/pixel.png", preset="nes")146 147# 2. Animate (optional)148pixel_art_video(149 "/tmp/pixel.png",150 "/tmp/pixel.mp4",151 scene="night",152 duration=6,153 fps=15,154 seed=42,155 export_gif=True,156)157```158 159### CLI160 161```bash162cd ~/.hermes/skills/creative/pixel-art/scripts163 164python pixel_art.py in.jpg out.png --preset gameboy165python pixel_art.py in.jpg out.png --preset snes --palette PICO_8 --block 6166 167python pixel_art_video.py out.png out.mp4 --scene night --duration 6 --gif168```169 170## Pipeline Rationale171 172**Pixel conversion:**1731. Boost contrast/color/sharpness (stronger for smaller palettes)1742. Posterize to simplify tonal regions before quantization1753. Downscale by `block` with `Image.NEAREST` (hard pixels, no interpolation)1764. Quantize with Floyd-Steinberg dithering — against either an adaptive177 N-color palette OR a named hardware palette1785. Upscale back with `Image.NEAREST`179 180Quantizing AFTER downscale keeps dithering aligned with the final pixel grid.181Quantizing before would waste error-diffusion on detail that disappears.182 183**Video overlay:**184- Copies the base frame each tick (static background)185- Overlays stateless-per-frame particle draws (one function per effect)186- Encodes via ffmpeg `libx264 -pix_fmt yuv420p -crf 18`187- Optional GIF via `palettegen` + `paletteuse`188 189## Dependencies190 191- Python 3.9+192- Pillow (`pip install Pillow`)193- ffmpeg on PATH (only needed for video — Hermes installs package this)194 195## Pitfalls196 197- Pallet keys are case-sensitive (`"NES"`, `"PICO_8"`, `"GAMEBOY_ORIGINAL"`).198- Very small sources (<100px wide) collapse under 8-10px blocks. Upscale the199 source first if it's tiny.200- Fractional `block` or `palette` will break quantization — keep them positive ints.201- Animation particle counts are tuned for ~640x480 canvases. On very large202 images you may want a second pass with a different seed for density.203- `mono_green` / `mono_amber` force `color=0.0` (desaturate). If you override204 and keep chroma, the 2-color palette can produce stripes on smooth regions.205- `clarify` loop: call it at most twice per turn (style, then scene). Don't206 pepper the user with more picks.207 208## Verification209 210- PNG is created at the output path211- Clear square pixel blocks visible at the preset's block size212- Color count matches preset (eyeball the image or run `Image.open(p).getcolors()`)213- Video is a valid MP4 (`ffprobe` can open it) with non-zero size214 215## Attribution216 217Named hardware palettes and the procedural animation loops in `pixel_art_video.py`218are ported from [pixel-art-studio](https://github.com/Synero/pixel-art-studio)219(MIT). See `ATTRIBUTION.md` in this skill directory for details.220 Discovery context
Discovered by repository scan. No exact path reference found in the snapshot’s root AGENTS.md.