A high-level, parallel ASCII-art media pipeline built on top of
iascii. Turn images, video, GIFs, and
plain text into colored (or plain) ANSI terminal art — with Floyd–Steinberg
/ Atkinson / Bayer dithering, animated text and banners, per-region
segment styling, non-Latin character ramps, and procedurally generated
optical illusions, all sharing one rendering pipeline.
[dependencies]
eger = "1"use eger::prelude::*;
let config = Config::builder(MediaType::Image)
.from_file("cat.png")
.max_width(120)
.color_depth(ColorDepth::TrueColor)
.build()?;
let ascii = eger::image::image_to_string(std::path::Path::new("cat.png"), &config)?;
println!("{ascii}");| Module | What it does |
|---|---|
config |
Fluent Config/ConfigBuilder for input, output, sizing, and parallelism |
style |
One-knob color treatments: plain ASCII, full color, black-and-white grayscale, single-color mono, 1-bit bilevel — set via ConfigBuilder::style, honored by image, batch, GIF, and video pipelines |
image |
Single-image and Rayon-parallel batch image → ASCII rendering |
video (feature video) |
Video → ASCII frame-sequence rendering, streamed through ffmpeg |
render |
Output targets (stdout / file / String / Vec<String>), terminal-size detection, cursor-addressed diffed playback |
text |
Text → ANSI coloring/animation: Typewriter, Rainbow, Wave, Blink, Marquee, Pulse, plus custom program/closure animations |
banner |
Multi-line "big text" block-letter banners, same animation styles as text |
colorize |
Per-cell color animation for any block of plain ASCII text (converted image, GIF/video frame, banner, ...), including a static two-color Gradient, a Transformed wrapper for layering a ColorTransform on any animation, and fully custom coloring functions |
color |
Reusable ColorTransforms — grayscale, invert, sepia, brightness/contrast/saturation, hue rotation, tinting, composition — shared by dither, colorize, and wasm |
segment |
Partitions a converted frame into numbered/named structures so one region can be bolded, colored, or animated independently |
dither |
Floyd–Steinberg / Atkinson error diffusion and Bayer ordered dithering, for reducing banding on coarse ANSI palettes |
canvas |
Efficient ASCII frame building/presentation on its own: a flat, clipping Canvas of colored Cells (text, panels, bars, lines, circles, sprite blits) with damage tracking (dirty rows, render cache, cell snapshot dedupe), zero-allocation frame paths (write_into/write_dirty_into), and cursor-addressed patch-only presentation (present_dirty_into — ~1 µs per moved cell on a 4K grid); full-color Sprites from text, pictures, or any rendered frame; present_diff/screen helpers |
game |
Realtime game loop layer on top of canvas (which it re-exports): backend-free Input/Key, Camera, rects_overlap, fixed-step TickClock, the Game trait with a headless runner, and effect helpers jump_arc/perspective_scale/shake_offset |
system |
System-aware resource scaling: detected CPUs size thread pools, detected RAM sizes decode-chunk buffering (both manually overridable, both conservative when detection fails) |
script |
Ready-made non-Latin character ramps — Cyrillic, Greek, CJK, Devanagari, Hebrew, Arabic, Braille, block/shade |
illusions |
Procedurally generated optical illusions (café wall, Hermann grid, twisted cord, animated rotating rings) rendered through the same pipeline |
wasm (feature wasm, wasm32 only) |
Thin wasm-bindgen wrapper for rendering ASCII art in a browser |
error |
Unified EgerError / Result |
video also enables GIF playback (video::play_gif); GIF decoding
(image::gif_to_lines) is available without the video feature.
Modules are opt-out, not clubbed together. default = ["standard"] is
today's build; default-features = false gives the lean core (grid
rendering, config, styles, system detection, raw-buffer conversion — no
image decoders, no tokio, no animation/effects modules):
[dependencies]
eger = { version = "1", default-features = false } # core only
eger = { version = "1", default-features = false, features = ["image", "dither"] } # + file/GIF decode, ditheringstandard(on by default) — every module below exceptvideo/wasm:image,text,banner,color,colorize,dither,segment,script,illusions,canvas,game.full—standard+video+wasm(absolutely everything).video(off by default) — pulls intokio(plusimage,colorize,text), enables thevideomodule (requiresffmpeg/ffprobeonPATHat runtime), plus the async (_async) variants of the image API.wasm(off by default) — pulls inwasm-bindgen(plusimage,banner,color,colorize,dither,script,text,illusions), enables thewasmmodule. Only meaningful when targetingwasm32.parallel(off by default) — row-level split within a single image/frame conversion (viaiascii/parallel'sconvert_with_pool). Across-file/frame batching is always on regardless of this flag.- Granular:
image(file/GIF decoding — buffer APIs stay in the core),text,banner(impliestext),color,colorize,dither,segment(impliescolorize),script,illusions(impliesimagecolorize),canvas(efficient frame building/presentation, usable standalone for dashboards/monitors/custom renderers),game(impliescanvas;colorizeis optional forCanvas::apply_animation).
Always on (small, no system services): iascii, rayon (shared thread
pool), regex (directory input patterns), thiserror,
terminal_size.
See TESTS_AND_BENCHMARKS.md for the full
integration-test and Criterion-benchmark suite, and what's verified where.
cargo test # unit + integration tests
cargo test --features video # + video pipeline tests (needs ffmpeg)
cargo bench # full benchmark suiteLicensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.