eger 1.2.0

A high-level, parallel ASCII-art media pipeline built on top of iascii: images, video, GIFs, dithering, animated text/banners, and procedural illusions, all rendered to ANSI.
Documentation
# eger

[![Crates.io](https://img.shields.io/crates/v/eger.svg)](https://crates.io/crates/eger)
[![Documentation](https://docs.rs/eger/badge.svg)](https://docs.rs/eger)
[![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](#license)

A high-level, parallel ASCII-art media pipeline built on top of
[`iascii`](https://crates.io/crates/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.

```toml
[dependencies]
eger = "1"
```

```rust
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}");
```

## What's inside

| Module | What it does |
|---|---|
| [`config`](src/config.rs) | Fluent `Config`/`ConfigBuilder` for input, output, sizing, and parallelism |
| [`style`](src/style.rs) | 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`](src/image.rs) | Single-image and Rayon-parallel batch image → ASCII rendering |
| `video` *(feature `video`)* | Video → ASCII frame-sequence rendering, streamed through `ffmpeg` |
| [`render`](src/render.rs) | Output targets (stdout / file / `String` / `Vec<String>`), terminal-size detection, cursor-addressed diffed playback |
| [`text`](src/text.rs) | Text → ANSI coloring/animation: `Typewriter`, `Rainbow`, `Wave`, `Blink`, `Marquee`, `Pulse`, plus custom program/closure animations |
| [`banner`](src/banner.rs) | Multi-line "big text" block-letter banners, same animation styles as `text` |
| [`colorize`](src/colorize.rs) | 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`](src/color.rs) | Reusable `ColorTransform`s — grayscale, invert, sepia, brightness/contrast/saturation, hue rotation, tinting, composition — shared by `dither`, `colorize`, and `wasm` |
| [`segment`](src/segment.rs) | Partitions a converted frame into numbered/named structures so one region can be bolded, colored, or animated independently |
| [`dither`](src/dither.rs) | Floyd–Steinberg / Atkinson error diffusion and Bayer ordered dithering, for reducing banding on coarse ANSI palettes |
| [`canvas`](src/canvas.rs) | Efficient ASCII frame building/presentation on its own: a flat, clipping `Canvas` of colored `Cell`s (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 `Sprite`s from text, pictures, or any rendered frame; `present_diff`/`screen` helpers |
| [`game`](src/game.rs) | 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`](src/system.rs) | System-aware resource scaling: detected CPUs size thread pools, detected RAM sizes decode-chunk buffering (both manually overridable, both conservative when detection fails) |
| [`script`](src/script.rs) | Ready-made non-Latin character ramps — Cyrillic, Greek, CJK, Devanagari, Hebrew, Arabic, Braille, block/shade |
| [`illusions`](src/illusions.rs) | 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`](src/error.rs) | Unified `EgerError` / `Result` |

`video` also enables GIF playback (`video::play_gif`); GIF decoding
(`image::gif_to_lines`) is available without the `video` feature.

## Feature flags

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

```toml
[dependencies]
eger = { version = "1", default-features = false }                              # core only
eger = { version = "1", default-features = false, features = ["image", "dither"] } # + file/GIF decode, dithering
```

- **`standard`** *(on by default)* — every module below except
  `video`/`wasm`: `image`, `text`, `banner`, `color`, `colorize`,
  `dither`, `segment`, `script`, `illusions`, `canvas`, `game`.
- **`full`** — `standard` + `video` + `wasm` (absolutely everything).
- **`video`** *(off by default)* — pulls in `tokio` (plus `image`,
  `colorize`, `text`), enables the `video` module (requires
  `ffmpeg`/`ffprobe` on `PATH` at runtime), plus the async (`_async`)
  variants of the image API.
- **`wasm`** *(off by default)* — pulls in `wasm-bindgen` (plus `image`,
  `banner`, `color`, `colorize`, `dither`, `script`, `text`, `illusions`),
  enables the `wasm` module. Only meaningful when targeting `wasm32`.
- **`parallel`** *(off by default)* — row-level split *within* a single
  image/frame conversion (via `iascii/parallel`'s `convert_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` (implies `text`), `color`, `colorize`, `dither`,
  `segment` (implies `colorize`), `script`, `illusions` (implies `image`
  + `colorize`), `canvas` (efficient frame building/presentation, usable
  standalone for dashboards/monitors/custom renderers), `game` (implies
  `canvas`; `colorize` is optional for `Canvas::apply_animation`).

Always on (small, no system services): `iascii`, `rayon` (shared thread
pool), `regex` (directory input patterns), `thiserror`,
`terminal_size`.

## Testing & benchmarks

See [`TESTS_AND_BENCHMARKS.md`](TESTS_AND_BENCHMARKS.md) for the full
integration-test and Criterion-benchmark suite, and what's verified where.

```sh
cargo test                    # unit + integration tests
cargo test --features video   # + video pipeline tests (needs ffmpeg)
cargo bench                   # full benchmark suite
```

## License

Licensed under either of

- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)

at your option.