Skip to main content

otf_pixels_codec_jpeg/
lib.rs

1//! Baseline JPEG codec for `otf-pixels`, implemented from scratch.
2//!
3//! "Baseline" here means what the format means by it: 8-bit samples, sequential
4//! DCT, Huffman entropy coding. Progressive JPEG is a different enough decoder
5//! that ADR-0004 puts it behind a wrapped codec instead; this crate reports it
6//! as [`PixelsError::Unsupported`] rather than half-decoding it.
7//!
8//! [`PixelsError::Unsupported`]: otf_pixels_core::PixelsError::Unsupported
9//!
10//! # Memory
11//!
12//! Decode is streaming, at one MCU row. A JPEG's entropy stream is a single
13//! run of bits with no per-row structure, but it is *ordered*: every block of
14//! MCU row `n` precedes every block of row `n + 1`. So the decoder keeps one
15//! band of component planes — 8 or 16 pixel rows — converts it to interleaved
16//! output, serves those rows, and reuses the band. Nothing scales with image
17//! height, which is what makes a thumbnail of a 24 MP photograph affordable.
18//!
19//! # Safety
20//!
21//! Every parser here reads attacker-controlled bytes. Malformed input is a
22//! value, never a panic: `unsafe_code = "forbid"` and the workspace's ban on
23//! `unwrap`/`expect`/`panic!` mean the classic decoder failures — a Huffman
24//! table indexing past its symbols, an MCU count overflowing, a block written
25//! outside its plane — are unrepresentable rather than merely avoided.
26
27mod decoder;
28mod encoder;
29mod entropy;
30mod fdct;
31mod format;
32mod huffman;
33mod idct;
34#[cfg(feature = "progressive")]
35mod progressive;
36mod tables;
37
38pub use decoder::{JpegCodec, JpegDecoder, probe};
39pub use encoder::{JpegEncoder, Subsampling};
40pub use format::{Component, Frame, SIGNATURE, Scan, ScanComponent};
41pub use idct::Scale;