Convert static images and animated GIFs to ASCII art with terminal playback and export capabilities.
- Multi-format support: JPEG, PNG, GIF (including animated)
- Terminal animation playback: Smooth ASCII animations with proper timing
- Export options: Individual frames, ANSI files, animated ASCII GIFs
- Customizable rendering: Character sets, colors, dithering
- GUI and CLI interfaces: Choose your preferred interaction method
- Floyd-Steinberg dithering: Optional luminance dithering for better quality
- Python 3.8+
- PIL (Pillow) for image processing
- PyQt6 for GUI (optional)
pip install -r requirements.txtPillow>=10.0.0
PyQt6>=6.4.0
./pyascii.py <imagePath> [options]# Convert static image to ASCII
./pyascii.py photo.jpg --width 120
# Play animated GIF in terminal with color
./pyascii.py dance.gif --width 90 --color --play
# Export GIF frames to directory
./pyascii.py loader.gif --width 80 --export-dir ./frames
# Create ANSI animation file
./pyascii.py banner.gif --width 100 --export-ansi animation.ansi
# Export as animated GIF
./pyascii.py dance.gif --width 80 --color --export-gif ascii_dance.gif
# Export terminal-parrot animation (.animation) with description
./pyascii.py dance.gif --width 80 --for-terminal-parrot "ASCII party parrot" --export-gif ascii_dance
# Use dithering on an animated GIF
./pyascii.py sprite.gif --width 100 --dither floyd --loop 3| Option | Description | Default |
|---|---|---|
--width W |
Target character width (20-400) | 100 |
--charset "chars" |
Character set from light to dark | " .:-=+*#%@" |
--invert |
Invert brightness mapping | false |
--color |
Enable 24-bit ANSI colors | false |
--play |
Play animation in terminal | true for GIFs |
--loop N |
Animation loops (0=infinite) | from GIF metadata |
--fps-limit FPS |
Max playback FPS | 60 |
--export-dir PATH |
Export frames to directory | none |
--export-ansi PATH |
Export ANSI animation file | none |
--export-gif PATH |
Export ASCII animation as GIF file | none |
--for-terminal-parrot DESC |
With --export-gif, write [basename].animation for terminal-parrot using the provided description |
none |
--dither METHOD |
Dithering: none, floyd | none |
--pause-once |
Wait for keypress after finite loops | false |
./pyascii_gui.pyThe GUI provides:
- File browser with image preview
- Real-time parameter adjustment with auto-generation
- Animation controls: play/pause/stop, frame scrubbing, speed control
- Export tools: save frames, create ANSI files, export ASCII GIFs
- Visual feedback: progress bars, frame counters, loop indicators
- Animation playback: Built-in player with speed control (0.25x to 4.0x)
- Frame navigation: Scrub through frames manually with slider
- Loop control: Set custom loop counts or infinite playback
- Export options: Individual frames with manifest.json, ANSI files, or ASCII GIFs
- Color preview: HTML rendering of ANSI color codes
- Auto-regeneration: Updates ASCII art as you adjust parameters
The tool uses standard ANSI escape sequences for animation:
\x1b[?25l- Hide cursor during playback\x1b[H- Move cursor to home position\x1b[0m- Reset color attributes\x1b[?25h- Show cursor after playback
- Ctrl+C: Stop animation and restore cursor
- Enter: Continue after
--pause-once(CLI only)
- Modern terminals: Full ANSI support (most Linux/macOS terminals)
- Windows: Windows Terminal, PowerShell (requires VT processing)
- Legacy: May need VT100 emulation enabled
Creates directory structure:
frames/
├── 00001.txt
├── 00002.txt
├── ...
└── manifest.json
manifest.json contains:
{
"width": 100,
"height": 55,
"frame_count": 24,
"durations_ms": [100, 100, 150, ...],
"loop": 0,
"charset": " .:-=+*#%@",
"color": true
}Single file with embedded control codes:
# frame 1, duration 100ms
\x1b[H[ASCII content]
# frame 2, duration 100ms
\x1b[H[ASCII content]
...
Can be played back with: cat animation.ansi
Creates an animated GIF file from ASCII frames:
- Font selection: Automatically tries multiple monospace fonts (Consolas, DejaVu Sans Mono, etc.)
- Color support: Renders ANSI color codes as colored pixels
- Timing preservation: Maintains original frame durations and loop count
- Dimension matching: Exported GIF maintains original image aspect ratio
- Quality: Uses PIL for high-quality GIF generation with proper font metrics
Example output can be shared on social media, embedded in websites, or used anywhere animated GIFs are supported. The exported GIF dimensions closely match the input image dimensions.
Creates a .animation file compatible with the terminal-parrot CLI:
- Output name: Uses the
--export-gifvalue as a basename; writes[basename].animation. - Header: First line is
description: <text>from--for-terminal-parrot "...". - Frames: Second line is
!--FRAME--!, then one iteration of frames, separated by!--FRAME--!between frames. - Colors: Preserves ANSI color codes if
--coloris used.
- Width: Lower values (50-80) for faster processing
- FPS limit: Cap at display refresh rate (30-60 FPS)
- Character set: Shorter sets process faster
- Dithering: Disable for speed, enable for quality
- Large GIFs: Memory usage = width × height × frame_count
- Precomputation: All frames cached in memory for smooth playback
- Estimated usage: ~1MB per 100×55 frame for typical character sets
- Static images: Near-instantaneous
- Animated GIFs: ~0.1-0.5s per frame depending on size and effects
- Large animations: Consider reducing width or using
--precompute false(hidden option)
- Variable frame sizes: Resized to uniform dimensions
- Disposal methods: Simplified handling, some complex animations may flicker
- Palette handling: Limited to RGB conversion, may lose some color fidelity
- Transparency: Background filled with black before processing
- Color accuracy: Depends on terminal 24-bit color support
- Refresh rate: Limited by terminal scrollback and rendering speed
- Size constraints: Very large outputs may exceed terminal buffer limits
- Large files: Memory usage scales with frame count and dimensions
- Network paths: No direct support for URLs, download files locally first
- Concurrent processing: Single-threaded, one image at a time
# Fast preview of an animated GIF
./pyascii.py animation.gif --width 60 --fps-limit 15# Best quality for presentation
./pyascii.py image.png --width 200 --color --dither floyd --charset " .'`^\",:;Il!i~+_-?][}{1)(|/*tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$"# Export all frames for external processing
./pyascii.py complex.gif --width 100 --export-dir ./output --no-play# Infinite loop with slow animation
./pyascii.py abstract.gif --width 80 --loop 0 --fps-limit 10# Create shareable ANSI file
./pyascii.py meme.gif --width 80 --color --export-ansi shareable.ansiAnimation not playing: Check if input is actually animated (file animation.gif)
Colors not showing: Verify terminal supports 24-bit color
Slow performance: Reduce width, disable dithering, lower FPS limit
Memory errors: Use smaller width or shorter character sets
Broken output: Reduce width or check image integrity
Run with verbose output by redirecting stderr:
./pyascii.py problematic.gif 2> debug.logTest ANSI support:
echo -e "\x1b[38;2;255;0;0mRed\x1b[0m Normal"MIT License - see LICENSE file for details.