mostlylucid.consoleimage.spectre
2.5.1
See the version list below for details.
dotnet add package mostlylucid.consoleimage.spectre --version 2.5.1
NuGet\Install-Package mostlylucid.consoleimage.spectre -Version 2.5.1
<PackageReference Include="mostlylucid.consoleimage.spectre" Version="2.5.1" />
<PackageVersion Include="mostlylucid.consoleimage.spectre" Version="2.5.1" />
<PackageReference Include="mostlylucid.consoleimage.spectre" />
paket add mostlylucid.consoleimage.spectre --version 2.5.1
#r "nuget: mostlylucid.consoleimage.spectre, 2.5.1"
#:package mostlylucid.consoleimage.spectre@2.5.1
#addin nuget:?package=mostlylucid.consoleimage.spectre&version=2.5.1
#tool nuget:?package=mostlylucid.consoleimage.spectre&version=2.5.1
mostlylucid.consoleimage
Version 2.5 - High-quality ASCII art renderer for .NET 10 using shape-matching algorithm.
Based on Alex Harri's excellent article on ASCII rendering techniques.
What's New in 2.5
- Matrix Mode -
--matrixdigital rain effect with color presets, full color mode, custom alphabets - Edge Detection Reveal -
--matrix-edge-detectreveals image shape through rain - FFmpeg Auto-Download - Zero setup, FFmpeg downloads automatically on first use
- Smart Keyframes - Scene detection for representative frame extraction
- Memory Efficient - Streaming GIF output, only 1 frame in memory
What's New in 2.0
- Video superset -
consolevideonow handles images AND videos - URL support - Load images directly from HTTP/HTTPS URLs
- Native terminal protocols - iTerm2, Kitty, Sixel auto-detection
- JSON document format - Save/load rendered output as portable JSON-LD documents
- Streaming JSON - Write frames incrementally for long videos (NDJSON format)
- GIF output - Save rendered output as animated GIF files
- Dynamic resize - Animations re-render when you resize the console
- Flicker-free - DECSET 2026 synchronized output with diff-based rendering
- Performance - Parallel rendering, pre-computed lookup tables
See CHANGELOG.md for full details.
| ASCII Mode | ColorBlocks Mode | Braille Mode |
|---|---|---|
| <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/wiggum_ascii.gif" width="250" alt="ASCII Mode"> | <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/wiggum_blocks.gif" width="250" alt="ColorBlocks Mode"> | <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/wiggum_braille.gif" width="250" alt="Braille Mode"> |
Original GIF → Three rendering modes (shape-matched ASCII, Unicode half-blocks, braille dots)
Note: These example images are rendered to GIF using the tool's
-o gif:output option with a consistent monospace font. Actual terminal display may vary depending on your terminal emulator, font choice, and color support. GIF output typically produces cleaner results than live terminal display.
Video to ASCII
| ASCII | ColorBlocks | Braille |
|---|---|---|
| <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/familyguy_ascii.gif" width="250" alt="Video ASCII"> | <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/familyguy_blocks.gif" width="250" alt="Video Blocks"> | <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/familyguy_braille.gif" width="250" alt="Video Braille"> |
Video playback with ConsoleImage.Video (FFmpeg-powered, hardware accelerated)
Still Images
| Landscape | Portrait |
|---|---|
| <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/demo_mountain_blocks.gif" width="350" alt="Mountain Landscape"> | <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/demo_portrait_blocks.gif" width="250" alt="Portrait"> |
High-fidelity ColorBlocks mode - 2x vertical resolution with 24-bit color
Edge Detection
| Standard | With Edge Detection |
|---|---|
| <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/demo_portrait_ascii.gif" width="250" alt="Standard"> | <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/demo_portrait_edge.gif" width="250" alt="Edge Detection"> |
Enhanced foreground visibility - --edge option uses Sobel edge detection
Character Set Presets
| Extended (default) | Simple | Block |
|---|---|---|
| <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/demo_portrait_ascii.gif" width="200" alt="Extended"> | <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/demo_portrait_simple.gif" width="200" alt="Simple"> | <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/demo_portrait_block.gif" width="200" alt="Block"> |
Multiple presets - -p simple, -p block, -p classic, or -p extended (default)
Gamma Correction (Brightness)
| No Gamma (1.0) | Default (0.85) | Brighter (0.7) |
|---|---|---|
| <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/demo_gamma_1.0.gif" width="200" alt="Gamma 1.0"> | <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/demo_gamma_0.85.gif" width="200" alt="Gamma 0.85"> | <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/demo_gamma_0.7.gif" width="200" alt="Gamma 0.7"> |
Automatic brightness compensation - --gamma adjusts output brightness. Values < 1.0 brighten, > 1.0 darken. Default 0.85 compensates for character/dot density.
Animated GIF - Earth Rotation
| ASCII | ColorBlocks | Braille |
|---|---|---|
| <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/earth_ascii.gif" width="200" alt="Earth ASCII"> | <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/earth_blocks.gif" width="200" alt="Earth Blocks"> | <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/earth_braille.gif" width="200" alt="Earth Braille"> |
Smooth animation - DECSET 2026 synchronized output with diff-based rendering
Matrix Mode (Digital Rain)
| Classic Green | Full Color | Edge Reveal |
|---|---|---|
| <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/matrix_portrait_final.gif" width="200" alt="Matrix Classic"> | <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/matrix_mountain_fullcolor.gif" width="200" alt="Matrix Full Color"> | <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/matrix_edge_reveal.gif" width="200" alt="Matrix Edge Reveal"> |
The Matrix digital rain effect - --matrix option with color presets (green, red, blue, amber, purple) or full color from source image.
Edge Detection Reveal - --matrix-edge-detect --matrix-bright-persist makes rain "flash" brightly when crossing image edges, revealing the shape through the rain. Characters slow down and collect on horizontal edges like rain on shoulders.
| Binary Rain | Custom Alphabet |
|---|---|
| <img src="https://github.com/scottgal/mostlylucid.consoleimage/raw/master/samples/matrix_binary.gif" width="200" alt="Matrix Binary"> | --matrix-alphabet "HELLO" |
Custom alphabets - --matrix-alphabet "01" for binary rain, or any custom string like "HELLO".
Features
- Shape-matching algorithm: Characters selected by visual shape similarity, not just brightness
- 3×2 staggered sampling grid: 6 sampling circles arranged per Alex Harri's article for accurate shape matching
- K-D tree optimization: Fast nearest-neighbor search in 6D vector space
- Contrast enhancement: Global power function + directional contrast with 10 external sampling circles
- Animated GIF support: Smooth flicker-free playback with DECSET 2026 synchronized output and diff-based rendering
- Dynamic resize: Animations automatically re-render when you resize the console window
- URL support: Load images directly from HTTP/HTTPS URLs with download progress
- Multiple render modes:
- ANSI colored ASCII characters (extended 91-char set by default)
- High-fidelity color blocks using Unicode half-blocks (▀▄)
- Ultra-high resolution braille characters (2×4 dots per cell, UTF-8 auto-enabled)
- Native terminal protocols: iTerm2, Kitty, Sixel (auto-detected)
- Auto background detection: Automatically detects dark/light backgrounds
- Floyd-Steinberg dithering: Error diffusion for smoother gradient rendering
- Adaptive thresholding: Otsu's method for optimal braille binarization
- Edge-direction characters: Uses directional chars (/ \ | -) based on detected edges
- AOT compatible: Works with Native AOT compilation
- Cross-platform: Windows, Linux, macOS (x64 and ARM64)
Installation
NuGet Package (Library)
dotnet add package mostlylucid.consoleimage
CLI Tool (Standalone Binaries)
Download from GitHub Releases:
| Platform | Download |
|---|---|
| Windows x64 | consoleimage-win-x64.zip |
| Linux x64 | consoleimage-linux-x64.tar.gz |
| Linux ARM64 | consoleimage-linux-arm64.tar.gz |
| macOS ARM64 | consoleimage-osx-arm64.tar.gz |
Requirements
- .NET 10 runtime (or use standalone binaries)
- Terminal with ANSI support (Windows Terminal, iTerm2, any modern terminal)
- 24-bit color recommended for
--mode blocksand--mode braille - Unicode font for braille mode (most terminals include this)
Quick Start
CLI
# Render an image
consoleimage photo.jpg
# Play animated GIF
consoleimage animation.gif
# Load from URL
consoleimage https://example.com/photo.jpg
# High-fidelity color blocks (2x vertical resolution)
consoleimage photo.jpg --mode blocks
# Ultra-high resolution braille (2x4 dots per cell)
consoleimage photo.jpg --mode braille
# Calibrate for your terminal (run once)
consoleimage --calibrate --aspect-ratio 0.5 --save
# Save as animated GIF
consoleimage animation.gif -o gif:output.gif
# Save as JSON document (portable, no source needed)
consoleimage animation.gif -o json:output.json
# Play back saved JSON document
consoleimage output.json
Library
using ConsoleImage.Core;
// One line - just works with sensible defaults!
Console.WriteLine(AsciiArt.Render("photo.jpg"));
Example Output
::::::::::::::::::::::::::::::::::::::vhhhh_:::::::
:::::::::::::::::::::::::::::::::::::Q&&&MQ:::::::
:::::::::::::::::::::::::::::::::::::Q@@@MQ:::::::
::::::vhhhhh:::_hhhhhh::::::_hhhhhh::Q@@@MQ:::::::
::::::K&&&MQKhnM&Q@@&&O\:KhnO&Q@@&&\\Q@@@MQ:::::::
:::::KM@@@@hMQMzy@@@@@@\KMQgyy@@@@@@QQ@@@MQ:::::::
:::::K@@@@@MKh*:|\@@@@@@MKh*:|\@@@@@QQ@@@MQ:::::::
::::vM@@@@MK:::::QM@@@@KK:::::QM@@@@QQ@@@MQ:::::::
::::QM@@@MQ::::::K@@@@MK::::::K@@@@M7Q@@@MQ:::::::
:::^K@@@@K^::::: G@@@@K^:::::KM@@@@K:Q@@@MQ:::::::
:::QM@@@MQ::::::QM@@@MQ::::::K@@@@MK:Q@@@MQ:::::::
:::K@@@@M7:::::^K@@@@K^:::::*G@@@@K^:Q@@@MQ:::::::
::KM@@@@K::::::QM@@@@Q::::::QM@@@MQ::Q@@@@\hhh\:::
::QMQ%%MQ::::::K%Q%%M7:::::^K%Q%%K^::.\yQ@@@QQE\::
Render Modes
| Mode | CLI Option | Description | Best For |
|---|---|---|---|
| ASCII | --mode ascii (default) |
Shape-matched ASCII characters with ANSI colors | General use, widest compatibility |
| ColorBlocks | --mode blocks or -b |
Unicode half-blocks (▀▄) with 24-bit color | High fidelity, photos |
| Braille | --mode braille or -B |
Braille patterns (2×4 dots per cell) | Maximum resolution |
| iTerm2 | --mode iterm2 |
Native inline image protocol | iTerm2, WezTerm |
| Kitty | --mode kitty |
Native graphics protocol | Kitty terminal |
| Sixel | --mode sixel |
DEC Sixel graphics | xterm, mlterm, foot |
Note: Protocol modes (iTerm2, Kitty, Sixel) display true images in supported terminals. Use --mode list to see all available modes.
CLI Usage
# Basic - color and animation ON by default
consoleimage photo.jpg
# Load image from URL
consoleimage https://example.com/photo.jpg
# Specify width
consoleimage photo.jpg -w 80
# Disable color (monochrome)
consoleimage photo.jpg --no-color
# High-fidelity color blocks (requires 24-bit color terminal)
consoleimage photo.jpg --blocks
# Ultra-high resolution braille mode (2x4 dots per cell)
consoleimage photo.jpg --braille
# Play animated GIF (animates by default)
consoleimage animation.gif
# Braille animation
consoleimage animation.gif --braille
# Don't animate, just show first frame
consoleimage animation.gif --no-animate
# Control animation loops (0 = infinite, default)
consoleimage animation.gif --loop 3
# Speed up animation
consoleimage animation.gif --speed 2.0
# For light terminal backgrounds
consoleimage photo.jpg --no-invert
# Edge detection for enhanced foreground
consoleimage photo.jpg --edge
# Manual background suppression
consoleimage photo.jpg --bg-threshold 0.85 # Suppress light backgrounds
consoleimage photo.jpg --dark-bg-threshold 0.15 # Suppress dark backgrounds
# Save to text file
consoleimage photo.jpg -o output.txt
# Save as animated GIF
consoleimage animation.gif -o gif:output.gif
# Save as JSON document (self-contained, portable)
consoleimage animation.gif -o json:output.json
# Play saved JSON document
consoleimage output.json
# GIF with compression options
consoleimage animation.gif -o gif:output.gif --gif-scale 0.5 --gif-colors 32
# Disable dithering (ON by default for smoother gradients)
consoleimage photo.jpg --no-dither
# Disable edge-direction characters (ON by default)
consoleimage photo.jpg --no-edge-chars
# Custom aspect ratio (default: 0.5, meaning chars are 2x taller than wide)
consoleimage photo.jpg --aspect-ratio 0.6
# Character set presets
consoleimage photo.jpg -p simple # Minimal: .:-=+*#%@
consoleimage photo.jpg -p block # Unicode blocks: ░▒▓█
consoleimage photo.jpg -p classic # Original 71-char set
# (extended 91-char set is the default)
CLI Options
| Option | Description | Default |
|---|---|---|
-w, --width |
Output width in characters | Auto |
-h, --height |
Output height in characters | Auto |
--max-width |
Maximum output width | Console width |
--max-height |
Maximum output height | Console height |
--no-color |
Disable colored output | Color ON |
--no-invert |
Don't invert (for light backgrounds) | Invert ON |
--contrast |
Contrast power (1.0 = none) | 2.5 |
--gamma |
Gamma correction (< 1.0 brightens, > 1.0 darkens) | 0.85 |
--charset |
Custom character set | - |
-p, --preset |
Preset: extended, simple, block, classic | extended |
-o, --output |
Output: file, gif:file.gif, json:file.json |
Console |
--no-animate |
Don't animate GIFs | Animate ON |
-s, --speed |
Animation speed multiplier | 1.0 |
-l, --loop |
Animation loop count (0 = infinite) | 0 |
-r, --framerate |
Fixed framerate in FPS (overrides GIF timing) | GIF timing |
-f, --frame-sample |
Frame sampling rate (skip frames) | 1 |
-e, --edge |
Enable edge detection | OFF |
--bg-threshold |
Light background threshold (0.0-1.0) | Auto |
--dark-bg-threshold |
Dark background threshold (0.0-1.0) | Auto |
--auto-bg |
Auto-detect background | ON |
-b, --blocks |
Use colored Unicode half-blocks | OFF |
-B, --braille |
Use braille characters (2×4 dots/cell) | OFF |
--no-alt-screen |
Keep animation in scrollback | Alt screen ON |
--no-parallel |
Disable parallel processing | Parallel ON |
-a, --aspect-ratio |
Character aspect ratio (width/height) | 0.5 |
--no-dither |
Disable Floyd-Steinberg dithering | Dither ON |
--no-edge-chars |
Disable edge-direction characters | Edge chars ON |
-j, --json |
Output as JSON (for LLM tool calls) | OFF |
--dark-cutoff |
Dark terminal: skip colors below brightness (0.0-1.0) | 0.1 |
--light-cutoff |
Light terminal: skip colors above brightness (0.0-1.0) | 0.9 |
-m, --mode |
Render mode: ascii, blocks, braille, iterm2, kitty, sixel | ascii |
--mode list |
List all available render modes | - |
--gif-scale |
GIF output scale factor (0.25-2.0) | 1.0 |
--gif-colors |
GIF palette size (16-256) | 64 |
--gif-fps |
GIF framerate | 10 |
--gif-font-size |
GIF font size in pixels | 10 |
--gif-length |
Max GIF length in seconds | - |
--gif-frames |
Max GIF frames | - |
JSON Document Format
Save rendered ASCII art to self-contained JSON documents that can be played back without the original source file. See docs/JSON-FORMAT.md for the full specification.
Quick Usage
# Save to JSON while displaying
consoleimage animation.gif -o json:movie.json
# Save braille mode
consoleimage photo.jpg --braille -o json:photo.json
# Play back saved document
consoleimage movie.json
# Stream long video to JSON (frames written incrementally)
consolevideo long_movie.mp4 -o json:movie.ndjson
Library API
using ConsoleImage.Core;
// Save rendered frames to document
var doc = ConsoleImageDocument.FromAsciiFrames(frames, options, "source.gif");
await doc.SaveAsync("output.json");
// Load and play
var loaded = await ConsoleImageDocument.LoadAsync("output.json");
using var player = new DocumentPlayer(loaded);
await player.PlayAsync();
// Streaming write for long videos (NDJSON format)
await using var writer = new StreamingDocumentWriter("output.ndjson", "ASCII", options, "source.mp4");
await writer.WriteHeaderAsync();
foreach (var frame in frames)
{
await writer.WriteFrameAsync(frame.Content, frame.DelayMs);
}
await writer.FinalizeAsync(); // Or let dispose auto-finalize
Format Features
- JSON-LD compatible - Uses
@contextand@typefor semantic structure - Self-contained - All render settings preserved for reproducible output
- Two formats supported:
- Standard JSON (
.json) - Single JSON object with all frames - Streaming NDJSON (
.jsonor.ndjson) - JSON Lines format, one record per line
- Standard JSON (
- Auto-detection -
LoadAsync()automatically detects which format - Stop anytime - Streaming format auto-finalizes on Ctrl+C, always valid
Library API
Simple API
using ConsoleImage.Core;
// Basic - just works
Console.WriteLine(AsciiArt.Render("photo.jpg"));
// With width
Console.WriteLine(AsciiArt.Render("photo.jpg", 80));
// Colored output
Console.WriteLine(AsciiArt.RenderColored("photo.jpg"));
// For light terminal backgrounds
Console.WriteLine(AsciiArt.RenderForLightBackground("photo.jpg"));
// Play animated GIF
await AsciiArt.PlayGif("animation.gif");
Full Options API
using ConsoleImage.Core;
// Use presets
var options = RenderOptions.Default; // Sensible defaults
var options = RenderOptions.HighDetail; // Maximum detail
var options = RenderOptions.Monochrome; // No color
var options = RenderOptions.ForLightBackground; // For light terminals
var options = RenderOptions.ForDarkBackground; // Enhanced for dark images
var options = RenderOptions.ForAnimation(loopCount: 3);
// Or customize everything
var options = new RenderOptions
{
MaxWidth = 100,
MaxHeight = 50,
UseColor = true,
Invert = true, // Dark terminals (default)
ContrastPower = 3.0f,
DirectionalContrastStrength = 0.3f,
CharacterSetPreset = "extended",
UseParallelProcessing = true
};
using var renderer = new AsciiRenderer(options);
var frame = renderer.RenderFile("photo.jpg");
Console.WriteLine(frame.ToAnsiString()); // Colored
Console.WriteLine(frame.ToString()); // Plain
High-Fidelity Color Blocks
using ConsoleImage.Core;
// Enable ANSI support on Windows (call once at startup)
ConsoleHelper.EnableAnsiSupport();
// Uses Unicode half-blocks (▀▄) for 2x vertical resolution
using var renderer = new ColorBlockRenderer(options);
string output = renderer.RenderFile("photo.jpg");
Console.WriteLine(output);
// For animated GIFs
var frames = renderer.RenderGif("animation.gif");
foreach (var frame in frames)
{
Console.WriteLine(frame.Content);
Thread.Sleep(frame.DelayMs);
}
ANSI Support on Windows
For colored output and animations to work correctly on Windows, you may need to enable virtual terminal processing:
using ConsoleImage.Core;
// Call once at application startup
ConsoleHelper.EnableAnsiSupport();
// Now ANSI colors and cursor control will work
Console.WriteLine(AsciiArt.RenderColored("photo.jpg"));
Modern terminals like Windows Terminal have this enabled by default, but older consoles (cmd.exe, older PowerShell) may need this call.
Spectre.Console Integration
Install the dedicated Spectre.Console package for native IRenderable support:
dotnet add package mostlylucid.consoleimage.spectre
using ConsoleImage.Core;
using ConsoleImage.Spectre;
using Spectre.Console;
// Static images as native Spectre renderables
AnsiConsole.Write(new AsciiImage("photo.png"));
AnsiConsole.Write(new ColorBlockImage("photo.png")); // High-fidelity
AnsiConsole.Write(new BrailleImage("photo.png")); // Ultra-high res
// Use in any Spectre layout
AnsiConsole.Write(new Panel(new AsciiImage("photo.png"))
.Header("My Image")
.Border(BoxBorder.Rounded));
// Side-by-side images
AnsiConsole.Write(new Columns(
new Panel(new AsciiImage("a.png")).Header("Image A"),
new Panel(new AsciiImage("b.png")).Header("Image B")
));
// Animated GIFs with Live display
var animation = new AnimatedImage("clip.gif", AnimationMode.ColorBlock);
await animation.PlayAsync(cancellationToken);
// Side-by-side animations
var anim1 = new AnimatedImage("a.gif");
var anim2 = new AnimatedImage("b.gif");
await AnsiConsole.Live(new Columns(anim1, anim2))
.StartAsync(async ctx => {
while (!token.IsCancellationRequested) {
anim1.TryAdvanceFrame();
anim2.TryAdvanceFrame();
ctx.Refresh();
await Task.Delay(16);
}
});
Without the Spectre package
The core library output is also compatible with Spectre.Console directly:
using Spectre.Console;
using ConsoleImage.Core;
// Spectre.Console handles ANSI escape codes automatically
AnsiConsole.Write(new Text(AsciiArt.RenderColored("photo.jpg")));
Animated GIFs
using ConsoleImage.Core;
// Simple playback (infinite loop by default)
await AsciiArt.PlayGif("animation.gif");
// With options
var options = new RenderOptions
{
LoopCount = 3,
AnimationSpeedMultiplier = 1.5f,
UseColor = true
};
await AsciiArt.PlayGif("animation.gif", options);
// Manual frame control
using var renderer = new AsciiRenderer(options);
var frames = renderer.RenderGif("animation.gif");
using var player = new AsciiAnimationPlayer(frames, useColor: true, loopCount: 0);
await player.PlayAsync(cancellationToken);
Configuration from appsettings.json
{
"AsciiRenderer": {
"MaxWidth": 120,
"MaxHeight": 60,
"ContrastPower": 2.5,
"DirectionalContrastStrength": 0.3,
"UseColor": true,
"Invert": true,
"CharacterSetPreset": "default"
}
}
var config = builder.Configuration.GetSection("AsciiRenderer").Get<RenderOptions>();
Console.WriteLine(AsciiArt.FromFile("photo.jpg", config));
Character Set Presets
| Preset | Characters | Use Case |
|---|---|---|
extended |
91 ASCII chars | Default - Maximum detail |
simple |
.:-=+*#%@ |
Quick renders |
block |
░▒▓█ |
High density blocks |
classic |
71 ASCII chars | Original algorithm set |
Documentation
| Component | Description | Documentation |
|---|---|---|
| consoleimage | CLI for images & GIFs | ConsoleImage/README.md |
| consolevideo | CLI for video playback | ConsoleImage.Video/README.md |
| mostlylucid.consoleimage | Core library (NuGet) | ConsoleImage.Core/README.md |
| mostlylucid.consoleimage.video | Video library (NuGet) | ConsoleImage.Video.Core/README.md |
| JSON Format | Document format spec | docs/JSON-FORMAT.md |
| Changelog | Version history | CHANGELOG.md |
Architecture
ConsoleImage.Core # Core library (NuGet: mostlylucid.consoleimage)
├── AsciiRenderer # Shape-matching ASCII renderer
├── ColorBlockRenderer # Unicode half-block renderer
├── BrailleRenderer # 2×4 dot braille renderer
├── MatrixRenderer # Digital rain effect
├── Protocol renderers # iTerm2, Kitty, Sixel support
├── AsciiAnimationPlayer # Flicker-free GIF playback
├── GifWriter # Animated GIF output
└── ConsoleHelper # Windows ANSI support
ConsoleImage # CLI tool (consoleimage)
ConsoleImage.Spectre # Spectre.Console integration
ConsoleImage.Video.Core # FFmpeg video decoding
ConsoleImage.Video # Video CLI (consolevideo)
How It Works
This library implements Alex Harri's shape-matching approach:
1. Character Analysis
Each ASCII character is rendered and analyzed using 6 sampling circles in a 3×2 staggered grid:
[0] [1] [2] ← Top row (staggered vertically)
[3] [4] [5] ← Bottom row
Left circles are lowered, right circles are raised to minimize gaps while avoiding overlap. Each circle samples "ink coverage" to create a 6D shape vector.
2. Normalization
All character vectors are normalized by dividing by the maximum component value across ALL characters, ensuring comparable magnitudes.
3. Image Sampling
Input images are sampled the same way, creating shape vectors for each output cell.
4. Contrast Enhancement
Global contrast (power function):
value = (value / max)^power × max
This "crunches" lower values toward zero while preserving lighter areas.
Directional contrast (10 external circles): External sampling circles reach outside each cell. For each internal component:
maxValue = max(internal, external)
result = applyContrast(maxValue)
This enhances edges where content meets empty space.
5. K-D Tree Matching
Fast nearest-neighbor search in 6D space finds the character whose shape vector best matches each image cell. Results are cached for repeated lookups.
6. Animation Optimization
For GIFs, frame differencing computes only changed pixels between frames, using ANSI cursor positioning to update efficiently.
Performance
- SIMD optimized: Uses
Vector128/Vector256/Vector512for distance calculations - Parallel processing: Multi-threaded rendering for ASCII, ColorBlock, and Braille modes
- Pre-computed trigonometry: Circle sampling uses lookup tables (eliminates ~216 trig calls per cell)
- Caching: Quantized vector lookups cached with 5-bit precision
- Optimized bounds checking: Branchless
(uint)x < (uint)widthpattern
Animation Smoothness
Multiple techniques ensure flicker-free animation:
- DECSET 2026 Synchronized Output: Batches frame output for atomic rendering (supported by Windows Terminal, WezTerm, Ghostty, Alacritty, iTerm2)
- Diff-based rendering: Only updates changed lines between frames - no per-line clearing that causes black flashes
- Overwrite with padding: Lines are overwritten in place with space padding, eliminating flicker completely
- Dynamic resize: Animations automatically re-render when you resize the console window
- Smooth loop transitions: Automatic interpolation between last and first frames creates seamless loops
- Cursor hiding:
\x1b[?25lhides cursor during playback - Pre-buffering: All frames, diffs, and transitions converted to strings before playback
- Immediate flush:
Console.Out.Flush()after each frame
Building from Source
git clone https://github.com/scottgal/mostlylucid.consoleimage.git
cd ConsoleImage
dotnet build
dotnet run --project ConsoleImage -- path/to/image.jpg
Publishing AOT Binary
dotnet publish ConsoleImage/ConsoleImage.csproj \
-c Release \
-r win-x64 \
--self-contained true \
-p:PublishAot=true
Credits
- Algorithm: Alex Harri's ASCII Rendering article
- Image processing: SixLabors.ImageSharp
License
This is free and unencumbered software released into the public domain. See UNLICENSE for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- mostlylucid.consoleimage (>= 2.5.1)
- Spectre.Console (>= 0.54.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 5.0.0 | 119 | 3/16/2026 |
| 4.6.0 | 121 | 2/18/2026 |
| 4.5.1 | 116 | 2/1/2026 |
| 4.5.0 | 108 | 2/1/2026 |
| 4.5.0-rc0 | 105 | 2/1/2026 |
| 4.5.0-alpha5 | 97 | 2/1/2026 |
| 4.5.0-alpha2 | 102 | 2/1/2026 |
| 4.5.0-alpha1 | 101 | 2/1/2026 |
| 4.5.0-alpha0 | 99 | 2/1/2026 |
| 4.1.2 | 117 | 1/26/2026 |
| 4.1.2-rc4 | 105 | 1/26/2026 |
| 4.1.2-rc3 | 99 | 1/26/2026 |
| 4.1.2-rc2 | 100 | 1/26/2026 |
| 4.1.2-rc1 | 99 | 1/26/2026 |
| 4.1.2-rc0 | 103 | 1/26/2026 |
| 4.1.1-alpha2 | 100 | 1/26/2026 |
| 4.1.1-alpha1 | 98 | 1/26/2026 |
| 4.1.1-alpha0 | 99 | 1/26/2026 |
| 4.1.0-alpha3 | 100 | 1/26/2026 |
| 2.5.1 | 96 | 1/22/2026 |