EncoderConfig

Struct EncoderConfig 

Source
pub struct EncoderConfig { /* private fields */ }
Expand description

JPEG encoder configuration. Dimension-independent, reusable across images.

Implementations§

Source§

impl EncoderConfig

Source

pub fn ycbcr( quality: impl Into<Quality>, subsampling: ChromaSubsampling, ) -> Self

Create a YCbCr encoder configuration.

YCbCr is the standard JPEG color space, compatible with all decoders.

§Arguments
  • quality: Quality level (0-100 for jpegli scale, or use Quality::* variants)
  • subsampling: Chroma subsampling mode
    • ChromaSubsampling::None (4:4:4) - best quality, larger files
    • ChromaSubsampling::Quarter (4:2:0) - good compression, smaller files
    • ChromaSubsampling::HalfHorizontal (4:2:2) - horizontal only
    • ChromaSubsampling::HalfVertical (4:4:0) - vertical only
§Example
use jpegli::encoder::{EncoderConfig, ChromaSubsampling};

let config = EncoderConfig::ycbcr(85, ChromaSubsampling::Quarter)
    .progressive(true);
Source

pub fn xyb(quality: impl Into<Quality>, b_subsampling: XybSubsampling) -> Self

Create an XYB encoder configuration.

XYB is a perceptual color space that can achieve better quality at the same file size for some images. The B (blue-yellow) channel can optionally be subsampled since it’s less perceptually important.

§Arguments
  • quality: Quality level (0-100 for jpegli scale, or use Quality::* variants)
  • b_subsampling: B channel subsampling
    • XybSubsampling::Full - all channels at full resolution
    • XybSubsampling::BQuarter - B channel at quarter resolution (default, recommended)
§Notes
  • Requires linear RGB input (f32 or u16 pixel formats)
  • Embeds an ICC profile for proper color reproduction
  • Not all decoders support XYB JPEGs correctly
§Example
use jpegli::encoder::{EncoderConfig, XybSubsampling};

let config = EncoderConfig::xyb(85, XybSubsampling::BQuarter)
    .progressive(true);
Source

pub fn grayscale(quality: impl Into<Quality>) -> Self

Create a grayscale encoder configuration.

Only the luminance channel is encoded. Works with any input format; color inputs are converted to grayscale.

§Arguments
  • quality: Quality level (0-100 for jpegli scale, or use Quality::* variants)
§Example
use jpegli::encoder::EncoderConfig;

let config = EncoderConfig::grayscale(85)
    .progressive(true);
Source

pub fn quality(self, q: impl Into<Quality>) -> Self

Override the quality level.

Accepts any type that converts to Quality:

  • f32 or u8 for ApproxJpegli scale
  • Quality::ApproxMozjpeg(u8) for mozjpeg-like quality
  • Quality::ApproxSsim2(f32) for SSIMULACRA2 target
  • Quality::ApproxButteraugli(f32) for Butteraugli target
Source

pub fn progressive(self, enable: bool) -> Self

Enable or disable progressive encoding.

Progressive encoding produces multiple scans for incremental display. Automatically enables optimized Huffman tables (required for progressive).

Source

pub fn optimize_huffman(self, enable: bool) -> Self

Enable or disable Huffman table optimization.

When enabled (default), computes optimal Huffman tables from image data. When disabled, uses standard JPEG Huffman tables (faster but larger files).

Note: Progressive mode requires optimized Huffman tables.

Source

pub fn allow_16bit_quant_tables(self, enable: bool) -> Self

Allow 16-bit quantization tables (extended sequential JPEG, SOF1).

When enabled (default), quantization values can exceed 255, producing extended sequential JPEGs (SOF1 marker) for better low-quality precision.

When disabled, quantization values are clamped to 255, producing baseline-compatible JPEGs (SOF0 marker) that work with all decoders.

Most modern decoders support 16-bit quant tables. Only disable this for maximum compatibility with legacy software.

Source

pub fn separate_chroma_tables(self, enable: bool) -> Self

Use separate quantization tables for Cb and Cr components.

When enabled (default), uses 3 quantization tables:

  • Table 0: Y (luma)
  • Table 1: Cb (blue chroma)
  • Table 2: Cr (red chroma)

When disabled, uses 2 quantization tables:

  • Table 0: Y (luma)
  • Table 1: Cb and Cr (shared chroma)
§Compatibility
  • 3 tables (default): Matches C++ jpegli’s jpegli_set_distance() behavior
  • 2 tables: Matches C++ jpegli’s jpeg_set_quality() behavior

Use 2 tables when you need exact output parity with tools that use jpeg_set_quality() (most libjpeg-based encoders).

§Example
// Match jpeg_set_quality() behavior (2 tables)
let config = EncoderConfig::ycbcr(85, ChromaSubsampling::Quarter)
    .separate_chroma_tables(false);
Source

pub fn force_baseline(self) -> Self

Force baseline JPEG compatibility.

This is a convenience method equivalent to:

config.progressive(false).allow_16bit_quant_tables(false)

Baseline JPEGs (SOF0) are the most compatible format, supported by all JPEG decoders. Use this when targeting legacy software or when maximum compatibility is required.

Source

pub fn restart_interval(self, interval: u16) -> Self

Set the restart interval (MCUs between restart markers).

Restart markers allow partial decoding and error recovery. Set to 0 to disable restart markers (default).

Source

pub fn icc_profile(self, profile: impl Into<Vec<u8>>) -> Self

Attach an ICC color profile to the output JPEG.

The profile will be written as APP2 marker segments with the standard “ICC_PROFILE” signature. Large profiles are automatically chunked (max 65519 bytes per segment) as required by the ICC profile embedding spec.

Common profiles:

  • sRGB IEC61966-2.1 (~3KB)
  • Display P3 (~0.5KB)
  • Adobe RGB 1998 (~0.5KB)
§Example
use jpegli::{EncoderConfig, ChromaSubsampling};
let srgb_profile = std::fs::read("sRGB.icc")?;
let config = EncoderConfig::ycbcr(85.0, ChromaSubsampling::Quarter)
    .icc_profile(srgb_profile);
Source

pub fn exif(self, exif: impl Into<Exif>) -> Self

Attach EXIF metadata to the output JPEG.

Use Exif::raw for raw EXIF bytes, or Exif::build to construct from common fields.

The two modes are mutually exclusive at compile time - you cannot mix raw bytes with field-based building.

§Examples

Build from fields (orientation and copyright):

use jpegli::encoder::{EncoderConfig, ChromaSubsampling, Exif, Orientation};

let config = EncoderConfig::ycbcr(85, ChromaSubsampling::Quarter)
    .exif(Exif::build()
        .orientation(Orientation::Rotate90)
        .copyright("© 2024 Example Corp"));

Use raw EXIF bytes:

use jpegli::encoder::{EncoderConfig, ChromaSubsampling, Exif};

let config = EncoderConfig::ycbcr(85, ChromaSubsampling::Quarter)
    .exif(Exif::raw(my_exif_bytes));
§Notes
  • EXIF is placed immediately after SOI, before any other markers
  • Raw bytes should be TIFF data without the “Exif\0\0” prefix (added automatically)
  • Maximum size: 65527 bytes (larger data will be truncated)
Source

pub fn xmp(self, data: impl Into<Vec<u8>>) -> Self

Attach XMP metadata to the output JPEG.

The data will be written as an APP1 marker segment with the standard Adobe XMP namespace signature. The provided bytes should be the raw XMP XML data without the APP1 marker or namespace prefix.

XMP is placed after EXIF (if present) but before ICC profile.

§Maximum Size

Standard XMP is limited to 65502 bytes (65535 - 2 length - 29 namespace - 2 padding). For larger XMP data, use Extended XMP (not yet supported).

Source

pub fn color_mode(self, mode: ColorMode) -> Self

Set the output color mode.

Source

pub fn downsampling_method(self, method: DownsamplingMethod) -> Self

Set the chroma downsampling method.

Only affects RGB/RGBX input with chroma subsampling enabled. Ignored for grayscale, YCbCr input, or 4:4:4 subsampling.

Source

pub fn tables(self, tables: Box<EncodingTables>) -> Self

Apply custom encoding tables for experimentation.

This replaces both quantization tables and zero-bias configuration with values from the provided EncodingTables.

Takes Box<EncodingTables> since custom tables are rarely used and the struct is ~1.5KB. This keeps EncoderConfig small by default.

§Notes
  • Tables must match the color mode (YCbCr or XYB)
  • When using ScalingParams::Exact, quality scaling is bypassed
  • When using ScalingParams::Scaled, tables are scaled by quality
§Example
use jpegli::encode::{EncoderConfig, ChromaSubsampling};
use jpegli::encode::tuning::EncodingTables;

let mut tables = EncodingTables::default_ycbcr();
tables.scale_quant(0, 0, 0.8);  // Reduce DC quantization

let config = EncoderConfig::ycbcr(85, ChromaSubsampling::Quarter)
    .tables(Box::new(tables));
Source

pub fn sharp_yuv(self, enable: bool) -> Self

Enable or disable SharpYUV (GammaAwareIterative) downsampling.

SharpYUV produces better color preservation on edges and thin lines, at the cost of ~3x slower encoding.

Source

pub fn deringing(self, enable: bool) -> Self

Enable or disable overshoot deringing (enabled by default).

Deringing reduces ringing artifacts on white backgrounds by smoothing hard edges. It allows pixel values to “overshoot” beyond the displayable range. Since JPEG decoders clamp values to 0-255, the overshoot is invisible but the smoother curve compresses better with fewer artifacts.

This technique was pioneered by @kornel in mozjpeg and significantly improves quality for documents, graphics, and text without degrading photographic content.

Particularly effective for:

  • Documents and screenshots with white backgrounds
  • Text and graphics with hard edges
  • Any image with saturated regions (pixels at 0 or 255)

There is no quality downside to leaving this enabled for photos.

Source

pub fn validate(&self) -> Result<()>

Validate the configuration, returning an error for invalid combinations.

Invalid combinations:

  • Progressive mode with disabled Huffman optimization
Source

pub fn encode_from_bytes( &self, width: u32, height: u32, layout: PixelLayout, ) -> Result<BytesEncoder>

Create an encoder from raw bytes with explicit pixel layout.

Use this when working with raw byte buffers and you know the pixel layout.

§Arguments
  • width: Image width in pixels
  • height: Image height in pixels
  • layout: Pixel data layout (channel order, depth, color space)
§Example
use jpegli::{EncoderConfig, ChromaSubsampling, PixelLayout, Unstoppable};
let config = EncoderConfig::ycbcr(85.0, ChromaSubsampling::Quarter);
let mut enc = config.encode_from_bytes(1920, 1080, PixelLayout::Rgb8Srgb)?;
enc.push_packed(&rgb_bytes, Unstoppable)?;
let jpeg = enc.finish()?;
Source

pub fn encode_from_rgb<P: Pixel>( &self, width: u32, height: u32, ) -> Result<RgbEncoder<P>>

Create an encoder from rgb crate pixel types.

Layout is inferred from the type parameter. For RGBA/BGRA types, the 4th channel is ignored.

§Type Parameter
  • P: Pixel type from the rgb crate (e.g., RGB<u8>, RGBA<f32>)
§Example
use rgb::RGB;
use jpegli::{EncoderConfig, ChromaSubsampling, Unstoppable};

let config = EncoderConfig::ycbcr(85.0, ChromaSubsampling::Quarter);
let mut enc = config.encode_from_rgb::<RGB<u8>>(1920, 1080)?;
enc.push_packed(&pixels, Unstoppable)?;
let jpeg = enc.finish()?;
Source

pub fn encode_from_ycbcr_planar( &self, width: u32, height: u32, ) -> Result<YCbCrPlanarEncoder>

Create an encoder from planar YCbCr data.

Use this when you have pre-converted YCbCr from video decoders, etc. Skips RGB->YCbCr conversion entirely.

Only valid with ColorMode::YCbCr. XYB mode requires RGB input.

§Example
use jpegli::{EncoderConfig, ChromaSubsampling, Unstoppable};

let config = EncoderConfig::ycbcr(85.0, ChromaSubsampling::Quarter);
let mut enc = config.encode_from_ycbcr_planar(1920, 1080)?;
enc.push(&planes, height, Unstoppable)?;
let jpeg = enc.finish()?;
Source

pub fn estimate_memory(&self, width: u32, height: u32) -> usize

Estimate peak memory usage for encoding an image of the given dimensions.

Returns estimated bytes based on color mode, subsampling, and dimensions. Delegates to the streaming encoder’s estimate which accounts for all internal buffers.

Source

pub fn estimate_memory_ceiling(&self, width: u32, height: u32) -> usize

Returns an absolute ceiling on memory usage.

Unlike estimate_memory, this returns a guaranteed upper bound that actual peak memory will never exceed. Use this for resource reservation when you need certainty rather than a close estimate.

The ceiling accounts for:

  • Worst-case token counts per block (high-frequency content)
  • Maximum output buffer size (incompressible images)
  • Vec capacity overhead (allocator rounding)
  • All intermediate buffers at their maximum sizes
§Example
use jpegli::encoder::{EncoderConfig, ChromaSubsampling};

let config = EncoderConfig::ycbcr(85.0, ChromaSubsampling::Quarter);
let ceiling = config.estimate_memory_ceiling(1920, 1080);

// Reserve this much memory - actual usage guaranteed to be less
let buffer = Vec::with_capacity(ceiling);
Source

pub fn get_quality(&self) -> Quality

Get the configured quality.

Source

pub fn get_color_mode(&self) -> ColorMode

Get the configured color mode.

Source

pub fn is_progressive(&self) -> bool

Check if progressive mode is enabled.

Source

pub fn is_optimize_huffman(&self) -> bool

Check if Huffman optimization is enabled.

Source

pub fn is_allow_16bit_quant_tables(&self) -> bool

Check if 16-bit quantization tables are allowed.

Source

pub fn is_separate_chroma_tables(&self) -> bool

Check if separate chroma tables are enabled (3 tables vs 2).

Source

pub fn get_icc_profile(&self) -> Option<&[u8]>

Get the ICC profile, if set.

Source

pub fn get_exif(&self) -> Option<&Exif>

Get the EXIF data, if set.

Source

pub fn get_xmp(&self) -> Option<&[u8]>

Get the XMP data, if set.

Source

pub fn with_segments(self, segments: EncoderSegments) -> Self

Add prepared segments for injection into output.

Use this to preserve metadata during round-trip encoding or to inject custom metadata and MPF secondary images.

§Example
use jpegli::decoder::Decoder;
use jpegli::encoder::{EncoderConfig, ChromaSubsampling};

// Decode with metadata preservation
let decoded = Decoder::new().decode(&original)?;
let extras = decoded.extras().unwrap();

// Re-encode with same metadata
let config = EncoderConfig::ycbcr(90.0, ChromaSubsampling::Quarter)
    .with_segments(extras.to_encoder_segments());
Source

pub fn add_segment(self, marker: u8, data: Vec<u8>) -> Self

Add a single segment (convenience method).

The segment type is inferred from the marker and data.

Source

pub fn add_mpf_image(self, jpeg: Vec<u8>, typ: MpfImageType) -> Self

Add an MPF secondary image (gain map, depth map, etc.).

The image data must be a complete JPEG file. An MPF directory will be automatically generated during encoding.

§Example
use jpegli::encoder::{EncoderConfig, ChromaSubsampling, MpfImageType};

let config = EncoderConfig::ycbcr(90.0, ChromaSubsampling::Quarter)
    .add_mpf_image(gainmap_jpeg, MpfImageType::Undefined);
Source

pub fn add_gainmap(self, jpeg: Vec<u8>) -> Self

Add a gain map (convenience for MpfImageType::Undefined).

Gain maps are used by UltraHDR for HDR rendering. The image data must be a complete JPEG file (typically grayscale).

Source

pub fn get_segments(&self) -> Option<&EncoderSegments>

Get the configured segments, if any.

Trait Implementations§

Source§

impl Clone for EncoderConfig

Source§

fn clone(&self) -> EncoderConfig

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for EncoderConfig

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.