Skip to content

Latest commit

 

History

History
412 lines (304 loc) · 15.9 KB

File metadata and controls

412 lines (304 loc) · 15.9 KB

mostlylucid.consoleimage

Version 2.0 - High-quality ASCII art renderer for .NET 10 using shape-matching algorithm.

NuGet License: Unlicense

Animation

ASCII Mode ColorBlocks Mode Braille Mode
ASCII Blocks Braille

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.

Still Images

Landscape (ColorBlocks) Landscape (Braille)
Landscape Blocks Landscape Braille

Monochrome Braille (Compact & Fast)

Monochrome (~265 KB) Full Color (~884 KB)
Boingball Mono Boingball Braille

Monochrome braille produces files 3-5x smaller than color modes - ideal for SSH, low bandwidth, or quick previews.

Quick Start

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");

Render Modes

ASCII (Shape-Matched Characters)

ASCII Mode

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 text

ColorBlocks (Unicode Half-Blocks)

ColorBlocks Mode

2x 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);

Braille (Ultra-High Resolution)

Braille Mode

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.

Matrix Mode (Digital Rain Effect)

Matrix Mode

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 colors

Custom Alphabets:

  • Default: Half-width katakana + numbers + symbols (authentic Matrix style)
  • UseAsciiOnly = true: ASCII letters + numbers + symbols
  • CustomAlphabet = "01": Binary rain
  • CustomAlphabet = "HELLO": Custom message characters

Terminal Protocols (Native Images)

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);

Edge Detection

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

Contrast and Dithering

Contrast Enhancement

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

Floyd-Steinberg Dithering

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

Background Handling

Automatic Background Suppression

Use manual thresholds for better control over backgrounds:

Manual Threshold Control

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
};

RenderOptions Reference

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
};

Presets

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);

Animated GIFs

// 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 handling

GIF Output

Save 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");

Loading from URLs

// 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);

Windows ANSI Support

// Call once at startup for Windows console ANSI support
ConsoleHelper.EnableAnsiSupport();

Character Set Presets

Preset Characters Description
extended 91 chars Default - maximum detail
simple .:-=+*#%@ Fast, minimal
block ░▒▓█ Unicode density blocks
classic 71 chars Original algorithm set

Terminal Protocol Support

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();

Performance

  • 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

Related Packages

Attribution

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)

License

Public domain - see UNLICENSE