Version 2.0 - High-quality ASCII art renderer for .NET 10 using shape-matching algorithm.
| ASCII Mode | ColorBlocks Mode | Braille Mode |
|---|---|---|
![]() |
![]() |
![]() |
Note: These images are rendered using the tool's GIF output with a consistent monospace font. Actual terminal display varies by terminal emulator, font, and color support.
| Landscape (ColorBlocks) | Landscape (Braille) |
|---|---|
![]() |
![]() |
| Monochrome (~265 KB) | Full Color (~884 KB) |
|---|---|
![]() |
![]() |
Monochrome braille produces files 3-5x smaller than color modes - ideal for SSH, low bandwidth, or quick previews.
using ConsoleImage.Core;
// One line - just works!
Console.WriteLine(AsciiArt.Render("photo.jpg"));
// Colored output
Console.WriteLine(AsciiArt.RenderColored("photo.jpg"));
// Play animated GIF
await AsciiArt.PlayGif("animation.gif");Characters selected by visual shape similarity using 6-point sampling grid.
using var renderer = new AsciiRenderer(new RenderOptions { MaxWidth = 80 });
var frame = renderer.RenderFile("photo.jpg");
Console.WriteLine(frame.ToAnsiString()); // Colored
Console.WriteLine(frame.ToString()); // Plain text2x vertical resolution using ▀▄█ characters with 24-bit color.
using var renderer = new ColorBlockRenderer(new RenderOptions { MaxWidth = 80 });
string output = renderer.RenderFile("photo.jpg");
Console.WriteLine(output);2x4 dots per character cell (8 dots total) for maximum detail. Uses advanced rendering techniques:
- Atkinson dithering: Bill Atkinson's algorithm (from MacPaint) produces higher contrast and reduced speckling compared to Floyd-Steinberg - ideal for binary braille output
- Otsu's threshold: Automatic optimal threshold for monochrome mode by maximizing between-class variance
- Generous thresholds for color: Shows most dots (85%) so colors remain visible, only hiding truly dark pixels
- Color boost: Automatic 25% saturation and 15% brightness boost to compensate for sparse dot coverage
- 24-bit color support: Each braille cell colored by the visible dots
using var renderer = new BrailleRenderer(new RenderOptions { MaxWidth = 80, UseColor = true });
string output = renderer.RenderFile("photo.jpg");
Console.WriteLine(output);Best results with: photographs, animations, and colorful images. Monochrome mode uses Otsu's threshold for optimal contrast.
The iconic Matrix digital rain effect with authentic color scheme - white glowing heads fading through bright green to dark green trails. Works on both static images and animations.
var options = new RenderOptions { MaxWidth = 80 };
var matrixOpts = new MatrixOptions
{
BaseColor = new Rgba32(0, 255, 65, 255), // Classic green (#00FF41)
Density = 0.5f, // Rain density (0.1-2.0)
SpeedMultiplier = 1.0f, // Animation speed
TargetFps = 20, // Frames per second
UseAsciiOnly = false, // Set true for ASCII (no katakana)
CustomAlphabet = null // Or "01" for binary, "HELLO" for custom
};
using var renderer = new MatrixRenderer(options, matrixOpts);
// Static image with animated rain overlay
var frame = renderer.RenderImage(image);
Console.WriteLine(frame.Content);
// Animated GIF with Matrix effect
var frames = renderer.RenderGif("animation.gif");Color Presets:
MatrixOptions.ClassicGreen // Default authentic green
MatrixOptions.RedPill // Red tint
MatrixOptions.BluePill // Blue tint
MatrixOptions.Amber // Retro amber terminal
MatrixOptions.FullColor // Uses source image colorsCustom Alphabets:
- Default: Half-width katakana + numbers + symbols (authentic Matrix style)
UseAsciiOnly = true: ASCII letters + numbers + symbolsCustomAlphabet = "01": Binary rainCustomAlphabet = "HELLO": Custom message characters
For terminals that support native image protocols:
using var renderer = new UnifiedRenderer(new RenderOptions { MaxWidth = 80 });
// Auto-detect best protocol
string output = renderer.RenderFile("photo.jpg", TerminalProtocol.Auto);
// Or specify explicitly
string sixel = renderer.RenderFile("photo.jpg", TerminalProtocol.Sixel);
string iterm = renderer.RenderFile("photo.jpg", TerminalProtocol.ITerm2);
string kitty = renderer.RenderFile("photo.jpg", TerminalProtocol.Kitty);Enhance foreground visibility with Sobel edge detection:
var options = new RenderOptions
{
EnableEdgeDetection = true, // Sobel edge detection
EnableEdgeDirectionChars = true // Use /\|- for edge directions
};
using var renderer = new AsciiRenderer(options);
var frame = renderer.RenderFile("photo.jpg");Edge detection is particularly effective for:
- Images with complex backgrounds
- Line art and diagrams
- Photos where subject separation is important
Control contrast with power curve (S-curve):
var options = new RenderOptions
{
ContrastPower = 2.5f, // Default. Higher = more contrast
DirectionalContrastStrength = 0.3f // Edge emphasis
};| Value | Effect |
|---|---|
| 1.0 | No enhancement |
| 2.0 | Moderate contrast |
| 2.5 | Default - good balance |
| 3.0+ | High contrast, dramatic |
Error-diffusion dithering for smooth gradients:
var options = new RenderOptions
{
EnableDithering = true // Default. Smooth gradients
};Dithering is particularly effective for:
- Photographs with subtle gradients
- Skin tones and natural imagery
- ColorBlocks mode for maximum quality
Use manual thresholds for better control over backgrounds:
Fine-tune for specific images:
var options = new RenderOptions
{
// For light backgrounds (white, light gray)
BackgroundThreshold = 0.85f, // Suppress above this brightness
// For dark backgrounds (black, dark gray)
DarkBackgroundThreshold = 0.15f, // Suppress below this brightness
// Terminal optimization (skip near-black/white for blending)
DarkTerminalBrightnessThreshold = 0.1f,
LightTerminalBrightnessThreshold = 0.9f
};var options = new RenderOptions
{
// Dimensions
Width = null, // Exact width (null = auto)
Height = null, // Exact height (null = auto)
MaxWidth = 120, // Maximum width constraint
MaxHeight = 40, // Maximum height constraint
CharacterAspectRatio = 0.5f, // Width/height of terminal chars
// Appearance
UseColor = true, // Enable ANSI colors
Invert = true, // For dark terminals (default)
ContrastPower = 2.5f, // Contrast enhancement (1.0-4.0)
DirectionalContrastStrength = 0.3f,
// Character sets
CharacterSet = null, // Custom chars (light to dark)
CharacterSetPreset = "extended", // extended|simple|block|classic
// Animation
AnimationSpeedMultiplier = 1.0f,
LoopCount = 0, // 0 = infinite
FrameSampleRate = 1, // Skip frames (2 = every 2nd)
// Features
EnableDithering = true, // Floyd-Steinberg dithering
EnableEdgeDirectionChars = false, // Use /\|- for edges (experimental)
EnableEdgeDetection = false, // Sobel edge detection (experimental)
UseParallelProcessing = true, // Multi-threaded rendering
// Background handling (manual thresholds)
BackgroundThreshold = null, // Light bg threshold (0-1)
DarkBackgroundThreshold = null, // Dark bg threshold (0-1)
// Terminal optimization
DarkTerminalBrightnessThreshold = 0.1f, // Skip very dark colors
LightTerminalBrightnessThreshold = 0.9f // Skip very bright colors
};var options = RenderOptions.Default; // Sensible defaults
var options = RenderOptions.HighDetail; // Maximum quality
var options = RenderOptions.Monochrome; // No color
var options = RenderOptions.ForLightBackground; // Light terminals
var options = RenderOptions.ForDarkBackground; // Dark image enhancement
var options = RenderOptions.ForAnimation(loopCount: 3);// Simple playback
await AsciiArt.PlayGif("animation.gif");
// With options
var options = RenderOptions.ForAnimation(loopCount: 3);
options.AnimationSpeedMultiplier = 1.5f;
await AsciiArt.PlayGif("animation.gif", options);
// Manual control
using var renderer = new AsciiRenderer(options);
var frames = renderer.RenderGif("animation.gif");
using var player = new AsciiAnimationPlayer(frames, useColor: true);
await player.PlayAsync(cancellationToken);
// ColorBlocks animation
using var blockRenderer = new ColorBlockRenderer(options);
var blockFrames = blockRenderer.RenderGif("animation.gif");
// frames implement IAnimationFrame for unified handlingSave rendered output as animated GIF:
using var gifWriter = new GifWriter(new GifWriterOptions
{
FontSize = 10, // Text size in pixels
Scale = 1.0f, // Output scale factor
MaxColors = 128, // GIF palette size (16-256)
LoopCount = 0, // 0 = infinite loop
MaxFrames = null, // Limit frames
MaxLengthSeconds = null
});
using var renderer = new AsciiRenderer(options);
foreach (var frame in renderer.RenderGif("input.gif"))
{
gifWriter.AddFrame(frame, frame.DelayMs);
}
await gifWriter.SaveAsync("output.gif");// Download and render
using var stream = await UrlHelper.DownloadAsync(
"https://example.com/image.jpg",
(downloaded, total) => Console.Write($"\r{downloaded}/{total}"));
using var renderer = new AsciiRenderer(options);
var frame = renderer.RenderStream(stream);// Call once at startup for Windows console ANSI support
ConsoleHelper.EnableAnsiSupport();| Preset | Characters | Description |
|---|---|---|
extended |
91 chars | Default - maximum detail |
simple |
.:-=+*#%@ |
Fast, minimal |
block |
░▒▓█ |
Unicode density blocks |
classic |
71 chars | Original algorithm set |
| Protocol | Terminals | Detection |
|---|---|---|
| Sixel | xterm, mlterm, foot, WezTerm | TERM + query |
| iTerm2 | iTerm2, WezTerm, Mintty | ITERM_SESSION_ID |
| Kitty | Kitty | KITTY_WINDOW_ID |
// Check what's supported
var protocol = TerminalCapabilities.DetectBestProtocol();
bool hasSixel = TerminalCapabilities.SupportsSixel();
bool hasKitty = TerminalCapabilities.SupportsKitty();
bool hasITerm = TerminalCapabilities.SupportsITerm2();- SIMD optimized: Vector128/256/512 for distance calculations
- Parallel processing: Multi-threaded rendering
- Pre-computed tables: Eliminates trig calls in sampling
- K-D tree matching: Fast nearest-neighbor in 6D space
- Result caching: Quantized lookups cached
- mostlylucid.consoleimage.video - FFmpeg video playback
- mostlylucid.consoleimage.spectre - Spectre.Console integration
This library implements techniques and algorithms from various sources:
- ASCII shape-matching: Based on Alex Harri's ASCII rendering approach
- Braille autocontrast: Inspired by img2braille
- Floyd-Steinberg dithering: Classic error-diffusion algorithm for smooth gradients (ASCII/ColorBlocks)
- Atkinson dithering: Bill Atkinson's MacPaint algorithm for high-contrast braille output
- Braille Unicode mapping: Standard Unicode Braille Patterns block (U+2800-U+28FF)
Public domain - see UNLICENSE







