mozjpeg-oxide 0.1.0

Pure Rust JPEG encoder based on Mozilla's mozjpeg with trellis quantization
Documentation

mozjpeg-oxide

Pure Rust JPEG encoder based on Mozilla's mozjpeg, featuring trellis quantization for optimal compression.

Crates.io Documentation License

Why mozjpeg-oxide?

mozjpeg-oxide C mozjpeg libjpeg-turbo
Language Pure Rust C C/asm
Memory safety Compile-time guaranteed Manual Manual
Trellis quantization Yes Yes No
File size ~Same as C Baseline 5-15% larger
Build complexity cargo add cmake + nasm + C toolchain cmake + nasm

Choose mozjpeg-oxide when you want:

  • Memory-safe JPEG encoding without C dependencies
  • Smaller files than libjpeg-turbo (trellis quantization)
  • Simple integration via Cargo

Choose C mozjpeg when you need:

  • Maximum baseline encoding speed (SIMD-optimized)
  • Established C ABI for FFI

Benchmark Results

Tested on Kodak + CLIC corpora (56 images total). Settings: progressive mode, trellis quantization, optimized Huffman, 4:2:0 subsampling.

Quality Rust BPP C BPP Size Δ Rust SSIM2 C SSIM2 Quality Δ
20 0.251 0.252 -0.3% 21.5 21.8 -0.30
50 0.534 0.532 +0.4% 57.3 57.5 -0.18
75 0.881 0.870 +1.3% 71.8 72.0 -0.13
85 1.251 1.224 +2.2% 77.8 77.9 -0.08
95 2.367 2.270 +4.3% 86.1 86.1 -0.03

Summary: Files are 0-4% larger than C mozjpeg with imperceptible quality difference (SSIM2 within 0.3 points).

Reproduce Benchmarks

# Fetch test corpus (Kodak images, ~15MB)
./scripts/fetch-corpus.sh

# Run benchmark
cargo bench-corpus

# Or just Kodak images
cargo bench-kodak

Results written to benchmark_results.csv. See also cargo bench-micro for criterion microbenchmarks.

Usage

use mozjpeg_oxide::{Encoder, Subsampling};

// Default: trellis quantization + Huffman optimization
let jpeg = Encoder::new()
    .quality(85)
    .encode_rgb(&pixels, width, height)?;

// Maximum compression: progressive + trellis + scan optimization
let jpeg = Encoder::max_compression()
    .quality(85)
    .encode_rgb(&pixels, width, height)?;

// Fastest: no optimizations (libjpeg-turbo compatible output)
let jpeg = Encoder::fastest()
    .quality(85)
    .encode_rgb(&pixels, width, height)?;

// Custom configuration
let jpeg = Encoder::new()
    .quality(75)
    .progressive(true)
    .subsampling(Subsampling::S420)
    .optimize_huffman(true)
    .encode_rgb(&pixels, width, height)?;

Features

  • Trellis quantization - Rate-distortion optimized coefficient selection
  • Progressive JPEG - Multi-scan encoding with spectral selection
  • Huffman optimization - 2-pass encoding for optimal entropy coding
  • Overshoot deringing - Reduces ringing artifacts at sharp edges
  • Chroma subsampling - 4:4:4, 4:2:2, 4:2:0 modes
  • Safe Rust - #![deny(unsafe_code)] with exceptions only for SIMD intrinsics

Performance

Configuration vs C mozjpeg Notes
Baseline (no opts) ~4x slower C has SIMD entropy coding
Trellis enabled 0.9x (faster) Trellis dominates runtime
Max compression 0.6x (faster) Progressive + trellis

With trellis quantization enabled (the default), mozjpeg-oxide matches or exceeds C mozjpeg performance.

License

BSD-3-Clause - Same license as the original mozjpeg.

Acknowledgments

Based on Mozilla's mozjpeg, which builds on libjpeg-turbo and the Independent JPEG Group's libjpeg.