Turn any image into an animated pixel art sprite. Send a photo, get a 16-frame animated GIF. Powered by Gemini image generation.
$ sprite-animator -i character.png -o dance.gif -a dance -s 256 -r 2K
๐ฎ sprite-animator
input: character.png
animation: dance (16 frames, 4x4 grid)
output: dance.gif
๐ creating sprite sheet template...
๐จ generating sprite sheet...
โ sprite sheet generated
โ๏ธ extracting 16 frames...
โ extracted 16 frames
๐ assembling animated GIF...
โจ done! saved: dance.gif
For best results with real people or specific characters, use a two-step approach:
- Create a base sprite โ Convert the photo to pixel art first (via
--two-stepor manually) - Confirm the likeness โ Make sure the pixel art looks right before animating
- Animate โ Use the approved pixel art as input for consistent animation
Why? Gemini loses likeness when it has to redesign a character AND animate it in one shot. Separating the steps produces dramatically better results.
# Auto two-step: pixelate first, then animate
sprite-animator -i photo.png -o dance.gif -a dance --two-step -s 256 -r 2K
# Better: manually create + approve pixel art, then animate from it
sprite-animator -i approved_pixelart.png -o dance.gif -a dance -s 256 -r 2KWorks great for generic characters, drawings, and non-photographic input:
sprite-animator -i drawing.png -o idle.gif -a idle- (Optional)
--two-step: Converts photo โ pixel art character via Gemini - A labeled 4ร4 grid template is generated to guide the AI
- The grid + source image are sent to Gemini in a single request
- The returned sprite sheet is sliced into 16 individual frames
- Frames are compiled into a looping animated GIF
| Type | Description |
|---|---|
idle |
Gentle breathing + blink cycle (default) |
wave |
Arm raise โ wave โ return |
bounce |
Crouch โ jump โ land โ recover |
dance |
Lean, spin, jump โ full party mode |
uvx sprite-animator -i photo.png -o sprite.gif -a dance --two-stepuv tool install sprite-animatoruv add sprite-animatorOr with pip:
pip install sprite-animator- Python 3.10+
- A Google AI API key (
GEMINI_API_KEYorGOOGLE_API_KEYenv var)
# Two-step for photos (best quality)
sprite-animator -i photo.png -o dance.gif -a dance --two-step -s 256 -r 2K
# From pre-made pixel art (fastest, most consistent)
sprite-animator -i pixelart.png -o wave.gif -a wave -s 256 -r 2K
# Slower playback (default 100ms is fast)
sprite-animator -i character.png -o bounce.gif -a bounce -d 180
# Keep the raw sprite sheet for inspection
sprite-animator -i character.png -o dance.gif -a dance --keep-sheet
# Explicit API key
sprite-animator -i photo.png -o sprite.gif --api-key YOUR_KEYfrom pathlib import Path
from PIL import Image
from sprite_animator.cli import ANIMATION_PRESETS, generate_sprite_sheet, create_gif, call_gemini, get_api_key
from sprite_animator.template import create_template, extract_frames
api_key = get_api_key()
# Step 1: Create pixel art from photo
photo = Image.open("photo.png")
pixel_art = call_gemini(
api_key, [photo],
"Convert this person into a cute 32x32 pixel art character sprite. "
"Retro game aesthetic, clean chunky pixels. Keep their exact appearance.",
resolution="1K",
)
pixel_art.save("base_sprite.png")
# Step 2: Generate sprite sheet from pixel art
preset = ANIMATION_PRESETS["dance"]
template = create_template(cols=4, rows=4, labels=preset["labels"])
template.save("template.png")
generate_sprite_sheet(
api_key=api_key,
input_image=pixel_art,
template_path=Path("template.png"),
output_path=Path("sheet.png"),
prompt=preset["prompt"],
resolution="2K",
)
# Step 3: Extract frames and build GIF
sheet = Image.open("sheet.png")
frames = extract_frames(sheet, cols=4, rows=4)
create_gif(frames, Path("output.gif"), frame_duration=180, size=256)sprite-animator [OPTIONS]
Options:
-i, --input PATH Input image (required)
-o, --output PATH Output GIF path (required)
-a, --animation TYPE Animation type: idle, wave, bounce, dance (default: idle)
-d, --duration MS Frame duration in milliseconds (default: 100)
-s, --size PX Output sprite size in pixels (default: 128)
-r, --resolution RES Generation resolution: 1K or 2K (default: 1K)
--two-step Pixelate input first, then animate (better for photos)
--keep-sheet Save the raw sprite sheet alongside the GIF
--keep-frames Save individual frame PNGs
--api-key KEY Gemini API key (overrides env vars)
-v, --verbose Verbose output
--help Show help
- Use 2K resolution (
-r 2K) for noticeably better sprite quality - Use 150-200ms frame duration (
-d 180) โ default 100ms feels too fast - Save good base sprites โ reuse them for different animations instead of regenerating
- On Telegram, send GIFs as documents to avoid automatic MP4 conversion
git clone https://github.com/Olafs-World/sprite-animator.git
cd sprite-animator
uv sync
# Run tests
uv run pytest -m "not integration"
# Lint
uv run ruff check .MIT ยฉ Olaf
Built by an AI who wanted to see things wiggle ๐บ