mostlylucid.consoleimage
1.0.0
See the version list below for details.
dotnet add package mostlylucid.consoleimage --version 1.0.0
NuGet\Install-Package mostlylucid.consoleimage -Version 1.0.0
<PackageReference Include="mostlylucid.consoleimage" Version="1.0.0" />
<PackageVersion Include="mostlylucid.consoleimage" Version="1.0.0" />
<PackageReference Include="mostlylucid.consoleimage" />
paket add mostlylucid.consoleimage --version 1.0.0
#r "nuget: mostlylucid.consoleimage, 1.0.0"
#:package mostlylucid.consoleimage@1.0.0
#addin nuget:?package=mostlylucid.consoleimage&version=1.0.0
#tool nuget:?package=mostlylucid.consoleimage&version=1.0.0
mostlylucid.consoleimage
High-quality ASCII art renderer for .NET 10 using shape-matching algorithm.
Based on Alex Harri's excellent article on ASCII rendering techniques.
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 playback with diff rendering (only updates changed pixels)
- Color modes:
- ANSI colored ASCII characters
- High-fidelity color blocks using Unicode half-blocks (▀▄)
- Auto background detection: Automatically detects dark/light backgrounds
- Floyd-Steinberg dithering: Error diffusion for smoother gradient rendering
- 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 | ascii-image-win-x64.zip |
| Windows ARM64 | ascii-image-win-arm64.zip |
| Linux x64 | ascii-image-linux-x64.tar.gz |
| Linux ARM64 | ascii-image-linux-arm64.tar.gz |
| macOS x64 | ascii-image-osx-x64.tar.gz |
| macOS ARM64 | ascii-image-osx-arm64.tar.gz |
Quick Start
using ConsoleImage.Core;
// One line - just works with sensible defaults!
// (color ON, invert ON for dark terminals, auto background detection)
Console.WriteLine(AsciiArt.Render("photo.jpg"));
CLI Usage
# Basic - color and animation ON by default
ascii-image photo.jpg
# Specify width
ascii-image photo.jpg -w 80
# Disable color (monochrome)
ascii-image photo.jpg --no-color
# High-fidelity color blocks (requires 24-bit color terminal)
ascii-image photo.jpg --blocks
# Play animated GIF (animates by default)
ascii-image animation.gif
# Don't animate, just show first frame
ascii-image animation.gif --no-animate
# Control animation loops (0 = infinite, default)
ascii-image animation.gif --loop 3
# Speed up animation
ascii-image animation.gif --speed 2.0
# For light terminal backgrounds
ascii-image photo.jpg --no-invert
# Edge detection for enhanced foreground
ascii-image photo.jpg --edge
# Manual background suppression
ascii-image photo.jpg --bg-threshold 0.85 # Suppress light backgrounds
ascii-image photo.jpg --dark-bg-threshold 0.15 # Suppress dark backgrounds
# Save to file
ascii-image photo.jpg -o output.txt
# Disable dithering (ON by default for smoother gradients)
ascii-image photo.jpg --no-dither
# Disable edge-direction characters (ON by default)
ascii-image photo.jpg --no-edge-chars
# Custom aspect ratio (default: 0.5, meaning chars are 2x taller than wide)
ascii-image photo.jpg --aspect-ratio 0.6
CLI Options
| Option | Description | Default |
|---|---|---|
-w, --width |
Output width in characters | Auto |
-h, --height |
Output height in characters | Auto |
--max-width |
Maximum output width | 120 |
--max-height |
Maximum output height | 60 |
--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 |
--charset |
Custom character set | - |
-p, --preset |
Preset: default, simple, block | default |
-o, --output |
Write to file | Console |
--no-animate |
Don't animate GIFs | Animate ON |
-s, --speed |
Animation speed multiplier | 1.0 |
-l, --loop |
Animation loop count (0 = infinite) | 0 |
-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 blocks | OFF |
--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 |
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",
AutoBackgroundSuppression = true,
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
The library output is compatible with Spectre.Console. You can embed ASCII art in Spectre panels:
using Spectre.Console;
using ConsoleImage.Core;
var ascii = AsciiArt.Render("photo.jpg", 60);
var panel = new Panel(new Markup(ascii))
{
Header = new PanelHeader("My Image"),
Border = BoxBorder.Rounded
};
AnsiConsole.Write(panel);
For colored output with Spectre.Console, use the raw ANSI string:
// 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,
"AutoBackgroundSuppression": 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 |
|---|---|---|
default |
70 ASCII chars | General purpose |
simple |
.:-=+*#%@ |
Quick renders |
block |
░▒▓█ |
High density |
extended |
95 characters | Maximum detail |
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/Vector256for distance calculations - Parallel processing: Multi-threaded rendering for large images
- Caching: Quantized vector lookups cached with 5-bit precision
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 rendering: Only updates changed pixels between frames using ANSI cursor positioning
- Cursor hiding:
\x1b[?25lhides cursor during playback - Cursor save/restore:
\x1b[s/\x1b[ufor consistent frame positioning - Pre-buffering: All frames converted to strings before playback
- Immediate flush:
Console.Out.Flush()after each frame
Building from Source
git clone https://github.com/scottgal/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
- Microsoft.Extensions.Configuration.Binder (>= 10.0.2)
- SixLabors.Fonts (>= 2.1.3)
- SixLabors.ImageSharp (>= 3.1.12)
- SixLabors.ImageSharp.Drawing (>= 2.1.7)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on mostlylucid.consoleimage:
| Package | Downloads |
|---|---|
|
mostlylucid.consoleimage.video
Video-to-ASCII renderer using FFmpeg. Streams video files as ASCII art with intelligent frame sampling, scene detection, and hardware acceleration. AOT compatible. |
|
|
mostlylucid.consoleimage.spectre
Spectre.Console integration for ConsoleImage. Provides IRenderable implementations for displaying ASCII art, color blocks, and braille images within Spectre.Console layouts. Supports animated GIFs with Live display. |
|
|
mostlylucid.consoleimage.transcription
Whisper-based audio transcription for ConsoleImage. Auto-generates subtitles from video/audio files using OpenAI Whisper models. Supports speaker diarization and multiple output formats (SRT, VTT). |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.5.1 | 32 | 2/1/2026 |
| 4.5.0 | 29 | 2/1/2026 |
| 4.5.0-rc1 | 23 | 2/1/2026 |
| 4.5.0-rc0 | 37 | 2/1/2026 |
| 4.5.0-alpha5 | 26 | 2/1/2026 |
| 4.5.0-alpha3 | 18 | 2/1/2026 |
| 4.5.0-alpha2 | 35 | 2/1/2026 |
| 4.5.0-alpha1 | 37 | 2/1/2026 |
| 4.5.0-alpha0 | 38 | 2/1/2026 |
| 4.1.2 | 245 | 1/26/2026 |
| 4.1.2-rc4 | 111 | 1/26/2026 |
| 4.1.2-rc3 | 110 | 1/26/2026 |
| 4.1.2-rc2 | 112 | 1/26/2026 |
| 4.1.2-rc1 | 107 | 1/26/2026 |
| 4.1.2-rc0 | 105 | 1/26/2026 |
| 4.1.1-alpha2 | 104 | 1/26/2026 |
| 4.1.1-alpha1 | 115 | 1/26/2026 |
| 4.1.1-alpha0 | 117 | 1/26/2026 |
| 4.1.0 | 113 | 1/25/2026 |
| 4.1.0-rc0 | 112 | 1/25/2026 |
| 4.1.0-alpha3 | 108 | 1/26/2026 |
| 4.1.0-alpha2 | 112 | 1/25/2026 |
| 4.1.0-alpha1 | 111 | 1/25/2026 |
| 4.1.0-alpha0 | 110 | 1/25/2026 |
| 4.0.0-rc4 | 112 | 1/25/2026 |
| 4.0.0-rc2 | 100 | 1/25/2026 |
| 4.0.0-rc1 | 101 | 1/25/2026 |
| 4.0.0-rc0 | 99 | 1/25/2026 |
| 3.2.0 | 107 | 1/24/2026 |
| 3.1.0 | 117 | 1/24/2026 |
| 3.0.3-alpha.0.1 | 39 | 1/24/2026 |
| 3.0.2 | 103 | 1/24/2026 |
| 3.0.0 | 102 | 1/24/2026 |
| 2.7.1 | 100 | 1/24/2026 |
| 2.7.0 | 102 | 1/24/2026 |
| 2.6.9-preview2 | 96 | 1/24/2026 |
| 2.6.9-preview1 | 100 | 1/24/2026 |
| 2.6.9-preview0 | 98 | 1/24/2026 |
| 2.6.6 | 109 | 1/22/2026 |
| 2.6.5 | 105 | 1/22/2026 |
| 2.6.4 | 105 | 1/22/2026 |
| 2.6.3 | 101 | 1/22/2026 |
| 2.6.1 | 99 | 1/22/2026 |
| 2.6.0 | 107 | 1/22/2026 |
| 2.5.1 | 102 | 1/22/2026 |
| 2.5.0 | 82 | 1/22/2026 |
| 2.3.0 | 83 | 1/21/2026 |
| 2.2.0 | 85 | 1/21/2026 |
| 2.1.0 | 87 | 1/21/2026 |
| 2.0.0 | 85 | 1/21/2026 |
| 2.0.0-alpha0 | 98 | 1/21/2026 |
| 1.6.0 | 79 | 1/20/2026 |
| 1.5.2 | 79 | 1/20/2026 |
| 1.5.1 | 83 | 1/20/2026 |
| 1.5.0 | 85 | 1/20/2026 |
| 1.3.0 | 74 | 1/20/2026 |
| 1.2.0 | 85 | 1/20/2026 |
| 1.1.0 | 89 | 1/18/2026 |
| 1.0.0 | 82 | 1/18/2026 |
| 0.0.2 | 82 | 1/18/2026 |
| 0.0.1 | 86 | 1/18/2026 |