zenjpeg/lib.rs
1#![forbid(unsafe_code)]
2#![cfg_attr(not(feature = "std"), no_std)]
3
4//! # zenjpeg
5//!
6//! Pure Rust JPEG encoder and decoder with perceptual optimizations.
7//!
8//! Provides enhanced compression quality compared to standard JPEG through
9//! adaptive quantization, optional XYB color space, and other perceptual
10//! optimizations.
11//!
12//! ## Feature Requirements
13//!
14//! > **Important:** The decoder requires a feature flag. Add to `Cargo.toml`:
15//! > ```toml
16//! > [dependencies]
17//! > zenjpeg = { version = "0.6", features = ["decoder"] }
18//! > ```
19//!
20//! **Available features:**
21//! - `decoder` - Enable JPEG decoding (required for `zenjpeg::decoder` module)
22//! - `parallel` - Multi-threaded encoding via rayon
23//! - `archmage-simd` - Safe SIMD acceleration (default, ~10-20% faster)
24//! - `cms-lcms2` - ICC color management via lcms2 (default)
25//! - `ultrahdr` - UltraHDR gain map support
26//!
27//! See [Feature Flags](#feature-flags) section below for details.
28//!
29//! ## Quick Start
30//!
31//! ```rust,ignore
32//! use zenjpeg::encoder::{EncoderConfig, ChromaSubsampling, PixelLayout, Unstoppable};
33//!
34//! // Create reusable config (quality + color mode in constructor)
35//! let config = EncoderConfig::ycbcr(85, ChromaSubsampling::Quarter)
36//! .progressive(true);
37//!
38//! // Encode from raw bytes
39//! let mut enc = config.encode_from_bytes(1920, 1080, PixelLayout::Rgb8Srgb)?;
40//! enc.push_packed(&rgb_bytes, Unstoppable)?;
41//! let jpeg = enc.finish()?;
42//! ```
43//!
44//! ## Encoder API
45//!
46//! All encoder types are in [`encoder`]:
47//!
48//! ```rust,ignore
49//! use zenjpeg::encoder::{
50//! // Core types
51//! EncoderConfig, // Builder for encoder configuration
52//! BytesEncoder, // Encoder for raw byte buffers
53//! RgbEncoder, // Encoder for rgb crate types
54//! YCbCrPlanarEncoder, // Encoder for planar YCbCr
55//!
56//! // Configuration
57//! Quality, // Quality settings (ApproxJpegli, ApproxMozjpeg, etc.)
58//! PixelLayout, // Pixel format for raw bytes
59//! ChromaSubsampling, // 4:4:4, 4:2:0, 4:2:2, 4:4:0
60//! ColorMode, // YCbCr, XYB, Grayscale
61//! DownsamplingMethod, // Box, GammaAware, GammaAwareIterative
62//!
63//! // Cancellation
64//! Stop, // Trait for cancellation tokens
65//! Unstoppable, // Use when no cancellation needed
66//!
67//! // Results
68//! Error, Result, // Error handling
69//! };
70//! ```
71//!
72//! ### Three Entry Points
73//!
74//! | Method | Input Type | Use Case |
75//! |--------|------------|----------|
76//! | [`encoder::EncoderConfig::encode_from_bytes`] | `&[u8]` | Raw byte buffers |
77//! | [`encoder::EncoderConfig::encode_from_rgb`] | `rgb` crate types | Type-safe pixels |
78//! | [`encoder::EncoderConfig::encode_from_ycbcr_planar`] | [`YCbCrPlanes`](encoder::YCbCrPlanes) | Video pipelines |
79//!
80//! ### Configuration Options
81//!
82//! ```rust,ignore
83//! // YCbCr mode (standard JPEG - most compatible)
84//! let config = EncoderConfig::ycbcr(85, ChromaSubsampling::Quarter)
85//! .progressive(true) // Progressive JPEG (~3% smaller)
86//! .sharp_yuv(true) // Better color edges (~3x slower)
87//! .icc_profile(bytes); // Attach ICC profile
88//!
89//! // XYB mode (perceptual color space - better quality)
90//! let config = EncoderConfig::xyb(85, XybSubsampling::BQuarter)
91//! .progressive(true);
92//!
93//! // Grayscale mode
94//! let config = EncoderConfig::grayscale(85);
95//!
96//! // Quality can also use enum variants:
97//! let config = EncoderConfig::ycbcr(Quality::ApproxSsim2(90.0), ChromaSubsampling::None);
98//! let config = EncoderConfig::ycbcr(Quality::ApproxButteraugli(1.0), ChromaSubsampling::Quarter);
99//! ```
100//!
101//! ## Decoder API
102//!
103//! The decoder is in prerelease. Enable with `features = ["decoder"]`.
104//!
105//! ```rust,ignore
106//! #[cfg(feature = "decoder")]
107//! use zenjpeg::decoder::{Decoder, DecodedImage};
108//!
109//! let image = Decoder::new().decode(&jpeg_data)?;
110//! let pixels: &[u8] = image.pixels();
111//! ```
112//!
113//! ## Feature Flags
114//!
115//! | Feature | Default | Description | When to Use |
116//! |---------|---------|-------------|-------------|
117//! | `decoder` | ❌ No | **JPEG decoding** - Enables `zenjpeg::decoder` module | **Required** for any decode operations |
118//! | `std` | ✅ Yes | Standard library support | Disable for `no_std` embedded targets |
119//! | `archmage-simd` | ✅ Yes | Safe SIMD via archmage (~10-20% faster) | Keep enabled for best performance |
120//! | `cms-lcms2` | ✅ Yes | ICC color management via lcms2 | XYB decoding, wide-gamut images |
121//! | `cms-moxcms` | ❌ No | Pure Rust color management (alternative to lcms2) | `no_std` or avoid C dependencies |
122//! | `parallel` | ❌ No | Multi-threaded encoding via rayon | Large images (4K+), server workloads |
123//! | `ultrahdr` | ❌ No | UltraHDR HDR gain map support | Encoding/decoding HDR JPEGs |
124//! | `trellis` | ✅ Yes | Trellis quantization (mozjpeg-style) | Keep enabled for best compression |
125//! | `yuv` | ✅ Yes | SharpYUV chroma downsampling | Keep enabled for quality |
126//!
127//! ### Common Configurations
128//!
129//! ```toml
130//! # Decode + encode (most common)
131//! zenjpeg = { version = "0.6", features = ["decoder"] }
132//!
133//! # Encode only (default)
134//! zenjpeg = "0.6"
135//!
136//! # High-performance server
137//! zenjpeg = { version = "0.6", features = ["decoder", "parallel"] }
138//!
139//! # Embedded / no_std
140//! zenjpeg = { version = "0.6", default-features = false, features = ["cms-moxcms"] }
141//!
142//! # UltraHDR support
143//! zenjpeg = { version = "0.6", features = ["decoder", "ultrahdr"] }
144//! ```
145//!
146//! ## Capabilities
147//!
148//! - **Baseline JPEG**: Standard 8-bit JPEG encoding
149//! - **Progressive JPEG**: Multi-scan encoding (~3% smaller files)
150//! - **XYB Color Space**: Perceptually optimized for better quality
151//! - **Adaptive Quantization**: Content-aware bit allocation
152//! - **16-bit / f32 Input**: High bit-depth source support
153//! - **Streaming API**: Memory-efficient row-by-row encoding
154//! - **Parallel Encoding**: Multi-threaded for large images
155
156// Lint configuration is in workspace Cargo.toml [workspace.lints.clippy]
157#![allow(missing_docs)]
158#![allow(clippy::module_name_repetitions)]
159
160extern crate alloc;
161
162// Error tracing with location tracking
163whereat::define_at_crate_info!(path = "zenjpeg/");
164
165// ============================================================================
166// Public API Modules
167// ============================================================================
168
169/// JPEG encoder - public API.
170///
171/// Contains: `EncoderConfig`, `BytesEncoder`, `RgbEncoder`, `Error`, `Result`, etc.
172pub mod encoder;
173
174/// Resource estimation heuristics for encoding and decoding.
175///
176/// Provides min/typical/max estimates for peak memory and time.
177pub mod heuristics;
178
179/// JPEG decoder - public API.
180///
181/// Contains: `Decoder`, `DecodeResult`, `Error`, `Result`, etc.
182///
183/// **Note:** The decoder is in prerelease and the API will have breaking changes.
184/// Enable with the `decoder` feature flag:
185///
186/// ```toml
187/// [dependencies]
188/// zenjpeg = { version = "0.6", features = ["decoder"] }
189/// ```
190#[cfg(feature = "decoder")]
191pub mod decoder;
192
193/// Decoder module is behind a feature flag.
194///
195/// Enable the decoder with:
196/// ```toml
197/// [dependencies]
198/// zenjpeg = { version = "0.6", features = ["decoder"] }
199/// ```
200///
201/// See the [decoder module documentation](decoder/index.html) for usage examples.
202#[cfg(not(feature = "decoder"))]
203pub mod decoder {
204 /// The decoder module requires the `decoder` feature flag.
205 ///
206 /// # How to enable
207 ///
208 /// Add to your `Cargo.toml`:
209 /// ```toml
210 /// [dependencies]
211 /// zenjpeg = { version = "0.6", features = ["decoder"] }
212 /// ```
213 ///
214 /// # What you'll get
215 ///
216 /// - `Decoder` - Main decoder configuration and execution
217 /// - `DecodeResult` - Unified decode output (u8 or f32)
218 /// - `ScanlineReader` - Streaming row-by-row decoding
219 /// - `UltraHdrReader` - HDR gain map decoding
220 /// - `JpegInfo` - Header metadata extraction
221 ///
222 /// # Example
223 ///
224 /// ```ignore
225 /// use zenjpeg::decoder::Decoder;
226 /// use enough::Unstoppable;
227 ///
228 /// let result = Decoder::new().decode(&jpeg_data, Unstoppable)?;
229 /// let pixels = result.pixels_u8().expect("u8 output");
230 /// ```
231 #[doc(hidden)]
232 pub struct DecoderRequiresFeatureFlag;
233}
234
235/// UltraHDR support - HDR gain map encoding and decoding.
236///
237/// Provides integration with `ultrahdr-core` for:
238/// - HDR to SDR tonemapping
239/// - Gain map computation and application
240/// - XMP metadata generation and parsing
241/// - Adaptive tonemapper for re-encoding
242///
243/// Enable with the `ultrahdr` feature flag.
244#[cfg(feature = "ultrahdr")]
245pub mod ultrahdr;
246
247// ============================================================================
248// Internal Implementation Modules
249// ============================================================================
250
251// Internal encoder implementation (exposed via test-utils for benchmarks)
252#[cfg(feature = "test-utils")]
253pub mod encode;
254#[cfg(not(feature = "test-utils"))]
255pub(crate) mod encode;
256
257// Internal decoder implementation
258#[cfg(all(feature = "decoder", feature = "test-utils"))]
259pub mod decode;
260#[cfg(all(feature = "decoder", not(feature = "test-utils")))]
261pub(crate) mod decode;
262
263// Internal shared error type (encoder/decoder have their own public errors)
264pub(crate) mod error;
265
266// Internal modules (exposed via test-utils for debugging tools and benchmarks)
267#[cfg(feature = "test-utils")]
268pub mod color;
269#[cfg(not(feature = "test-utils"))]
270pub(crate) mod color;
271
272pub(crate) mod encode_simd;
273
274#[cfg(feature = "test-utils")]
275pub mod entropy;
276#[cfg(not(feature = "test-utils"))]
277pub(crate) mod entropy;
278
279#[cfg(feature = "test-utils")]
280pub mod foundation;
281#[cfg(not(feature = "test-utils"))]
282pub(crate) mod foundation;
283
284#[cfg(feature = "test-utils")]
285pub mod huffman;
286#[cfg(not(feature = "test-utils"))]
287pub(crate) mod huffman;
288
289// Make quant accessible for benchmarks when test-utils enabled
290#[cfg(feature = "test-utils")]
291#[doc(hidden)]
292pub mod quant;
293#[cfg(not(feature = "test-utils"))]
294pub(crate) mod quant;
295
296#[cfg(feature = "test-utils")]
297pub mod types;
298#[cfg(not(feature = "test-utils"))]
299pub(crate) mod types;
300
301// Test utilities - only compiled when feature enabled (requires std)
302#[cfg(feature = "test-utils")]
303pub mod test_utils;
304
305// Lossless JPEG transforms (requires decoder for coefficient access)
306#[cfg(feature = "decoder")]
307pub mod lossless;
308
309// Profiling instrumentation (zero-cost when disabled)
310pub mod profile;