chisel is a Rust CLI for the CHISEL (.csl) image format — a compact, lossless RGBA image codec.
- Encoding
.jpg/.jpeg/.pnginto.csl(V2.0/V2.1/V2.3) - Strict decoding from
.csl(version bytes0x20,0x21,0x22,0x23) - Native viewing of decoded images in a window (using
minifb) - Native GNOME integration through
glycin(GNOME image loader stack) - YCoCg transform support (for photographic content)
- Scanline/Morton traversal support
- Grayscale support
- Rust (latest stable version)
- Cargo
cd chisel
cargo build --releaseThe compiled binary will be available at:
./target/release/chiselchisel encode <input.{jpg,jpeg,png}> -o <output.csl>Example:
./target/release/chisel encode /path/to/input.png -o /tmp/output.cslchisel decode <input.csl> -o <output.png>Example:
./target/release/chisel decode /tmp/output.csl -o /tmp/decoded.pngchisel view <input.csl>Example:
./target/release/chisel view /tmp/output.cslBuild and install a user-level glycin loader for .csl:
./scripts/install-glycin-csl-user.shUninstall:
./scripts/uninstall-glycin-csl-user.shIntegration details:
docs/GLYCIN_INTEGRATION.md- Loader config template:
integrations/glycin/glycin-csl.conf.in - MIME definition:
integrations/mime/chisel-csl.xml
- Full format specification:
docs/CSL_SPEC.md - Conformance checklist:
docs/SPEC_CONFORMANCE.md
The implementation is strict-decoder oriented: malformed streams fail with explicit errors.
| Encoder | Features Added |
|---|---|
| v1.0 | Core pipeline: row skip/clone, LZ77, solid runs, cache, Z-delta, Luma (F4) |
| v1.1 | 2D Block-Ref (`0xF6): copies rectangular blocks from prior decoded pixels |
| v1.3 | Photographic Compression: Chroma Lock (0xF7), Paeth Predictor (0xF8), Dense YCoCg (`0xF9) |
| v2.0 | Architectural Overhaul: 1-byte Repeat-Last-Run (0xE2) replaces Ditto, Split Literal RGB/RGBA runs (0xC0..0xCF) |
| v2.1 | Experimental features |
| v2.2 | Alpha prediction |
| v2.3 | Scanline/Morton traversal selection, YCoCg support, CRC32 checksum, grayscale support |
Run the test suite:
cargo testThe suite includes V2.0 opcode boundary tests, LZ77 back-references, Luma shifts, Repeat-Last-Run (0xE2), 2D Block-Ref (0xF6), Literal RGBA (0xC8..0xCF), Chroma Lock (0xF7), and encode/decode roundtrip checks.
The following table shows file size comparisons between CSL, PNG, and QOI formats for various test images:
| Image | PNG (bytes) | CSL (bytes) | QOI (bytes) | CSL vs PNG (%) | QOI vs PNG (%) | CSL vs QOI (%) |
|---|---|---|---|---|---|---|
| pngs/manga_page.png | 1,082,374 | 1,734,294 | 2,451,249 | 160.23 | 226.47 | 70.75 |
| pngs/photography.png | 40,673,701 | 49,328,083 | 48,494,880 | 121.28 | 119.23 | 101.72 |
| pngs/transparent_image.png | 6,518,746 | 7,457,298 | 7,801,000 | 114.40 | 119.67 | 95.59 |
To run benchmarks yourself, use:
# Compare CSL vs PNG
python scripts/benchmark_csl_vs_png.py \
--bin ./target/release/chisel \
--inputs /path/to/image1.png /path/to/image2.png \
--out /tmp/csl_bench.json
# Compare CSL vs PNG vs QOI
python scripts/benchmark_csl_png_qoi.py \
--bin ./target/release/chisel \
--inputs /path/to/image1.png /path/to/image2.png \
--out /tmp/full_bench.jsonIMG="/absolute/path/to/sample.png"
BIN="./target/release/chisel"
/usr/bin/time -f "encode_sec=%e rss_kb=%M" "$BIN" encode "$IMG" -o /tmp/sample.csl
/usr/bin/time -f "decode_sec=%e rss_kb=%M" "$BIN" decode /tmp/sample.csl -o /tmp/sample.decoded.pngchisel/
├── src/ # Source code
│ ├── bin/ # Binary executables
│ ├── cli.rs # CLI argument parsing
│ ├── codec.rs # Core encoding/decoding logic
│ ├── lib.rs # Library entry point
│ └── main.rs # Main CLI entry point
├── tests/ # Test suite
├── scripts/ # Benchmark and installation scripts
├── docs/ # Documentation
└── integrations/ # Glycin and MIME type integrations