pith-jpeg 0.1.0

pith jpeg lane: baseline and progressive JPEG decoding, byte-exact with libjpeg islow (zero-dep Rust)
Documentation

The pith suite contract

pith-jpeg is part of the pith suite (pith-hash). Every suite repository follows the same rules; CI enforces them mechanically:

  • Naming: a library is always pith-<domain> (pith-image, pith-audio, pith-zip, ...). The curator/repository of repositories is the bare pith-hash. Never invent a second naming scheme inside the suite.
  • Version pinning: cross-library dependencies pin ~0.1 (e.g. pith-image = { version = "~0.1", path = "../pith-image" }). The whole suite moves together inside 0.1.x; breaking changes require a suite-wide version bump, never a silent minor drift.
  • Zero third-party dependencies: every crate depends only on other pith-* crates plus std. scripts/check-zero-deps.py (run in CI) fails the build on any other crate, for normal, build and dev dependencies alike.
  • No unsafe: every crate root carries #![forbid(unsafe_code)].
  • Hex-exact vectors: reference.json at the repo root is the cross-language source of truth. The gen-reference binary regenerates it; CI verifies the committed copy is current (gen-reference verify), and CD ships the regenerated file with every SDK artifact. Python, Node and Go SDKs MUST test against the same bytes.

Repository layout

crates/            one published crate per suite lib (pith-<domain>)
tools/gen-reference  the vector generator binary (bin name: gen-reference)
sdk/python         ctypes wheel; build backend reads PITH_CDYLIB_DIR
sdk/node           koffi-based package; prebuilds/<os-arch>/ carry the cdylib
sdk/go             cgo binding; go.mod carries the module's cgo flags
fuzz/corpus        fuzz inputs, replayed by tests/fuzz_corpus.rs (parser crates)
reference.json     hex-exact cross-SDK test vectors

Overview

JPEG decoding per ITU T.81: baseline (SOF0), extended sequential (SOF1) and progressive (SOF2) Huffman-coded frames — spectral selection, successive approximation and EOBRUN included — with restart markers, 4:4:4/4:2:2/4:4:0/4:2:0 and other integral sampling factors, and 1- or 3-component output as pith_image::raster::Image (Gray/Rgb, 8-bit).

The pixel pipeline is a byte-exact transcription of libjpeg-turbo's islow integer IDCT, fancy triangle chroma upsampling and fixed-point YCbCr→RGB, validated against Pillow 12.3.0 fixtures byte for byte (see tests/fixtures/PROVENANCE.md). Arithmetic-coded, lossless, differential, hierarchical, 12-bit and CMYK/YCCK streams are refused with Error::Unsupported naming the coding process.

Install

Rust (the core library):

cargo add pith-jpeg

Python / Node / Go SDKs are published from the same cdylib on every release; see the release assets or the package registries for the matching version.

Quick start

Rust (the core library):

let img = pith_jpeg::decode(&bytes)?;

match img {
    pith_jpeg::Jpeg::Gray(g) => println!("{}x{}", g.width(), g.height()),
    pith_jpeg::Jpeg::Rgb(rgb) => println!("{}x{}", rgb.width(), rgb.height()),
}

decode never panics on untrusted input: malformed structure surfaces as Error::Truncated / Error::BadValue, refusals as Error::Unsupported. Hex-exact cross-SDK vectors — decode digests for every committed fixture plus the DCT/dequant numerics — live in reference.json (regenerate with cargo run --bin gen-reference, verify with cargo run --bin gen-reference -- verify).

Contributing

See CONTRIBUTING.md.

Security

See SECURITY.md.

License

MIT © pith-hash