1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
//! JPEG Encoder - Public API.
//!
//! This module provides everything needed for JPEG encoding.
//!
//! # Quick Start
//!
//! ```rust,ignore
//! use zenjpeg::encoder::{EncoderConfig, ChromaSubsampling, PixelLayout, Unstoppable};
//!
//! let config = EncoderConfig::ycbcr(85, ChromaSubsampling::Quarter);
//! let mut enc = config.encode_from_bytes(1920, 1080, PixelLayout::Rgb8Srgb)?;
//! enc.push_packed(&rgb_bytes, Unstoppable)?;
//! let jpeg = enc.finish()?;
//! ```
//!
//! # Entry Points
//!
//! `EncoderConfig` provides three constructors for different color modes:
//!
//! | Constructor | Color Mode | Use Case |
//! |-------------|------------|----------|
//! | `EncoderConfig::ycbcr(q, sub)` | YCbCr | Standard JPEG (most compatible) |
//! | `EncoderConfig::xyb(q, b_sub)` | XYB | Perceptual color space |
//! | `EncoderConfig::grayscale(q)` | Grayscale | Single-channel output |
//!
//! Then use `encode_from_bytes()`, `encode_from_rgb()`, or `encode_from_ycbcr_planar()`.
//!
//! # Configuration
//!
//! ```rust,ignore
//! use zenjpeg::encoder::{EncoderConfig, Quality, ChromaSubsampling, XybSubsampling};
//!
//! // YCbCr (standard JPEG) - reusable config
//! let config = EncoderConfig::ycbcr(85, ChromaSubsampling::Quarter)
//! .progressive(true) // Progressive JPEG (~3% smaller)
//! .optimize_huffman(true) // Optimal Huffman tables (default)
//! .sharp_yuv(true) // Better color edges (~3x slower)
//! .restart_mcu_rows(4); // MCU rows between restart markers (default)
//!
//! // XYB (perceptual color space)
//! let config = EncoderConfig::xyb(85, XybSubsampling::BQuarter)
//! .progressive(true);
//!
//! // Grayscale
//! let config = EncoderConfig::grayscale(85);
//!
//! // Quality can also use enum variants:
//! let config = EncoderConfig::ycbcr(Quality::ApproxMozjpeg(80), ChromaSubsampling::Quarter);
//! let config = EncoderConfig::ycbcr(Quality::ApproxSsim2(90.0), ChromaSubsampling::None);
//! let config = EncoderConfig::ycbcr(Quality::ApproxButteraugli(1.0), ChromaSubsampling::Quarter);
//! ```
//!
//! # Per-Image Metadata (Three-Layer Pattern)
//!
//! For encoding multiple images with different metadata:
//!
//! ```rust,ignore
//! use zenjpeg::encoder::{EncoderConfig, ChromaSubsampling, Exif, Orientation};
//!
//! // Layer 1: Reusable config (quality, color mode)
//! let config = EncoderConfig::ycbcr(85, ChromaSubsampling::Quarter)
//! .auto_optimize(true)
//! .progressive(true);
//!
//! // Layer 2: Per-image request (metadata)
//! let jpeg1 = config.request()
//! .icc_profile(&srgb_bytes)
//! .exif(Exif::build()
//! .orientation(Orientation::Rotate90)
//! .copyright("© 2024 Corp"))
//! .encode(&pixels1, 1920, 1080)?;
//!
//! // Different metadata for each image
//! let jpeg2 = config.request()
//! .icc_profile(&p3_bytes)
//! .exif(Exif::build().copyright("Public Domain"))
//! .encode(&pixels2, 3840, 2160)?;
//! ```
//!
//! # Pixel Layouts
//!
//! `PixelLayout` describes the format of raw byte input:
//!
//! | Layout | Bytes/px | Description |
//! |--------|----------|-------------|
//! | `Rgb8Srgb` | 3 | RGB, sRGB gamma (default) |
//! | `Bgr8Srgb` | 3 | BGR, sRGB gamma (Windows/GDI) |
//! | `Rgba8Srgb` / `Rgbx8Srgb` | 4 | RGBA/RGBX, alpha/pad ignored |
//! | `Bgra8Srgb` / `Bgrx8Srgb` | 4 | BGRA/BGRX, alpha/pad ignored |
//! | `Gray8Srgb` | 1 | Grayscale, sRGB gamma |
//! | `Rgb16Linear` / `Rgba16Linear` | 6/8 | 16-bit linear (alpha ignored) |
//! | `RgbF32Linear` / `RgbaF32Linear` | 12/16 | Float linear 0.0-1.0 (alpha ignored) |
//! | `YCbCr8` / `YCbCrF32` | 3/12 | Pre-converted YCbCr |
//!
//! # Cancellation
//!
//! All `push*` methods accept an `impl Stop` parameter for cooperative cancellation:
//!
//! ```rust,ignore
//! use zenjpeg::encoder::Unstoppable;
//! use std::sync::atomic::AtomicBool;
//!
//! // No cancellation
//! enc.push_packed(&data, Unstoppable)?;
//!
//! // With AtomicBool
//! let cancel = AtomicBool::new(false);
//! enc.push_packed(&data, &cancel)?;
//! ```
//!
//! # Memory Estimation
//!
//! ```rust,ignore
//! use zenjpeg::{EncoderConfig, ChromaSubsampling};
//!
//! let config = EncoderConfig::ycbcr(85.0, ChromaSubsampling::Quarter);
//!
//! // Typical estimate
//! let estimate = config.estimate_memory(1920, 1080);
//!
//! // Guaranteed upper bound
//! let ceiling = config.estimate_memory_ceiling(1920, 1080);
//! ```
//!
//! # Parallel Encoding
//!
//! With the `parallel` feature:
//!
//! ```rust,ignore
//! #[cfg(feature = "parallel")]
//! use zenjpeg::encoder::{EncoderConfig, ChromaSubsampling, ParallelEncoding};
//!
//! let config = EncoderConfig::ycbcr(85.0, ChromaSubsampling::Quarter)
//! .parallel(ParallelEncoding::Auto);
//! ```
// Note: Currently re-exporting internal error types since the encoder
// types we re-export from crate::encode use them internally.
// === Error types ===
/// Errors that can occur during JPEG encoding.
pub type EncodeError = crateError;
/// Result type for encoder operations.
pub type EncodeResult<T> = Result;
// Keep legacy aliases for backward compatibility
pub use crate;
// === Main encoder types (from encode root modules) ===
pub use crateStop;
pub use crate;
pub use crateEncoderConfig;
pub use crate;
pub use crate;
pub use crateEncodeRequest;
pub use crateEncodeStats;
pub use crateLimits;
// === Default tables for customization ===
/// Default quantization and zero-bias tables.
///
/// Use these as starting points when creating custom tables.
pub use cratetables;
pub use crateParallelEncoding;
// === mozjpeg-compatible quantization tables ===
pub use crate;
// === Huffman table types ===
/// Pre-built Huffman table set for single-pass encoding.
///
/// By default, the encoder uses general-purpose trained tables that are
/// ~5-12% more efficient than the JPEG Annex K tables.
///
/// Use [`HuffmanTableSet::annex_k()`] for the original JPEG standard tables,
/// or pass custom tables to [`EncoderConfig::custom_huffman_tables()`].
pub use crateHuffmanTableSet;
pub use crateHuffmanMethod;
// === Cancellation support ===
/// Re-exported from `enough` crate. Pass this to `push*` methods when you
/// don't need cancellation support.
pub use Unstoppable;