Metadata-Version: 2.4
Name: chuda-ansi
Version: 0.2.5
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Rust
Classifier: Operating System :: POSIX :: Linux
Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
License-File: LICENSE
License-File: NOTICE
Summary: CPU and CUDA high-quality truecolour ANSI image renderer
Author-email: Gareth Davidson <gaz@bitplane.net>
License-Expression: LGPL-3.0-or-later
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM

# chuda

A CPU and CUDA high-quality truecolour ANSI renderer for image-training
pipelines. It implements the expensive part of Chafa's effort-9 symbol mode:
exhaustive foreground/background fitting and error scoring over the narrow
symbol atlas. PNG decode, high-quality resize and stateful ANSI emission stay
in Rust; independent cell/symbol evaluation runs on CUDA.

RGBA images are optimized jointly for either a detailed opaque foreground and
background cell or a composable foreground-only cell. Alpha-mask agreement is
part of symbol scoring, so antialiased sprite edges do not require two renders
and a cell-level merge pass. `--transparent-threshold` controls the bias toward
opaque interior detail and defaults to `0.10`.

The atlas is generated from the vendored Chafa reference source and checked
into the Rust binary. Chafa is not a build-time or runtime dependency.

## Requirements

- Rust
- CUDA Toolkit and an NVIDIA driver only when building or selecting the optional CUDA backend

## Build and run

```sh
cargo build --release
cargo run --release -- --size 80 image.png > image.ansi
cargo run --release --features cuda -- --backend cuda --size 80 image.png > image.ansi
```

Directory mode recursively mirrors PNG paths and changes their suffix to
`.ansi`. It skips directory symlinks and accepts symlinks to PNG files:

```sh
cargo run --release -- --size 80 corpus --output rendered
```

Only ANSI is written. Directory mode does not leave resized images or other
intermediates behind.

Each rendered frame is limited to 1,048,576 terminal cells. Oversized dimensions
return an error before resizing; `max_batch_cells` controls grouping of frames
and does not split an individual frame.

## Architecture note

The public Rust and Python APIs share decoding, resizing, structured frames,
and ANSI emission. Rayon and CUDA implement interchangeable cell scorers.

## Python

The PyPI distribution is `chuda-ansi` and its import name is `chuda`:

```python
import chuda

renderer = chuda.Renderer("auto")
image = chuda.Image.open("image.png")
frame = renderer.render(image, 80)
ansi = frame.to_ansi()
```

## Updating the symbol atlas

After updating the Chafa sources in `vendor/chafa`, run:

```sh
python3 tools/generate_symbols.py
cargo fmt
```

The generated atlas is LGPL-derived and this project is correspondingly
licensed LGPL-3.0-or-later. See `LICENSE` and `NOTICE`.

## Benchmark against Chafa

The benchmark excludes compilation, warms both programs once, and reports the
median end-to-end batch time. It also writes one output from each renderer for
visual inspection:

```sh
python3 tools/benchmark.py ../ansi-scaler/data/artifacts/rasters \
  --width 80 --images 100 --repeats 3
less -R benchmark-results/sample-chuda.ansi
less -R benchmark-results/sample-chafa.ansi
```

Machine-readable measurements are saved in `benchmark-results/report.json`.

