Unified image codec dispatch for Rust. Thin layer over format-specific encoders and decoders: zenjpeg, zenwebp, zengif, zenavif, zenpng, zenjxl, and heic-decoder (Imazen fork).
use zencodecs::{ImageFormat, DecodeRequest, EncodeRequest, PixelBufferConvertExt};
use zencodecs::pixel::{ImgVec, Rgba};
// Detect format from magic bytes and decode
let data: &[u8] = todo!(); // your image bytes
let decoded = DecodeRequest::new(data).decode()?;
println!("{}x{}", decoded.width(), decoded.height());
// Convert to RGBA8 for processing
let rgba = decoded.into_buffer().to_rgba8();
// Encode as WebP from typed pixel data
let pixels = ImgVec::new(vec![Rgba { r: 0u8, g: 0, b: 0, a: 255 }; 100*100], 100, 100);
let webp = EncodeRequest::new(ImageFormat::WebP)
.with_quality(85.0)
.encode_rgba8(pixels.as_ref())?;
println!("Encoded {} bytes", webp.len());
# Ok::<(), zencodecs::CodecError>(())Each encode method takes a typed ImgRef<P>:
req.encode_rgb8(img) // ImgRef<Rgb<u8>>
req.encode_rgba8(img) // ImgRef<Rgba<u8>>
req.encode_bgra8(img) // ImgRef<Bgra<u8>>
req.encode_bgrx8(img) // ImgRef<Bgra<u8>> — alpha ignored
req.encode_gray8(img) // ImgRef<Gray<u8>>
req.encode_rgb_f32(img) // ImgRef<Rgb<f32>> — linear light
req.encode_rgba_f32(img) // ImgRef<Rgba<f32>> — linear light
req.encode_gray_f32(img) // ImgRef<Gray<f32>> — linear lightThe dispatch layer handles pixel format conversion to whatever the codec needs natively.
use zencodecs::from_bytes;
let info = from_bytes(data)?;
println!("{:?} {}x{}", info.format, info.width, info.height);
# Ok::<(), zencodecs::CodecError>(())use zencodecs::{CodecRegistry, ImageFormat, DecodeRequest};
let registry = CodecRegistry::none()
.with_decode(ImageFormat::Jpeg, true)
.with_decode(ImageFormat::WebP, true);
let decoded = DecodeRequest::new(data)
.with_registry(®istry)
.decode()?;
# Ok::<(), zencodecs::CodecError>(())use zencodecs::{EncodeRequest, ImageFormat};
use zencodecs::config::CodecConfig;
let config = CodecConfig::default();
// .with_jpeg_encoder(...)
// .with_avif_speed(...)
// etc.
let request = EncodeRequest::new(ImageFormat::Jpeg)
.with_codec_config(&config)
.with_quality(92.0);use zencodecs::{DecodeRequest, Limits};
let limits = Limits {
max_width: Some(4096),
max_height: Some(4096),
max_pixels: Some(16_000_000),
max_memory_bytes: Some(256_000_000),
..Default::default()
};
let decoded = DecodeRequest::new(data)
.with_limits(&limits)
.decode()?;
# Ok::<(), zencodecs::CodecError>(())Stop tokens (enough::Stop) are forwarded to codecs that support cooperative cancellation.
Every codec is feature-gated. Enable only what you need:
[dependencies]
zencodecs = { version = "0.1", features = ["jpeg", "webp", "png"] }| Feature | Codec | Decode | Encode | Notes |
|---|---|---|---|---|
jpeg |
zenjpeg | Yes | Yes | |
jpeg-ultrahdr |
zenjpeg | Yes | Yes | UltraHDR gain map support |
webp |
zenwebp | Yes | Yes | |
gif |
zengif | Yes | Yes | |
gif-zenquant |
zengif + zenquant | Yes | Yes | Palette quantization via zenquant |
gif-quantizr |
zengif + quantizr | Yes | Yes | Palette quantization via quantizr |
gif-imagequant |
zengif + imagequant | Yes | Yes | Palette quantization via imagequant |
png |
zenpng | Yes | Yes | |
png-zenquant |
zenpng + zenquant | Yes | Yes | Palette quantization |
avif-decode |
zenavif | Yes | No | |
avif-encode |
zenavif | No | Yes | |
jxl-decode |
zenjxl | Yes | No | |
jxl-encode |
zenjxl | No | Yes | |
heic-decode |
heic-decoder (Imazen fork) | Yes | No | |
bitmaps |
zenbitmaps | Yes | Yes | PNM/PAM/PFM, BMP, Farbfeld |
bitmaps-bmp |
zenbitmaps | Yes | Yes | BMP only |
tiff |
zentiff | Yes | Yes | |
raw-decode |
zenraw | Yes | No | RAW/DNG via rawloader (LGPL) |
raw-decode-exif |
zenraw | Yes | No | EXIF metadata for RAW/DNG |
raw-decode-xmp |
zenraw | Yes | No | XMP metadata for RAW/DNG |
raw-decode-gainmap |
zenraw | Yes | No | Gain map from DNG/AMPF |
riapi |
— | — | — | RIAPI codec key parsing |
zennode |
zennode | — | — | Pipeline node definitions |
calibrate |
(meta) | — | — | All lossy encoders for quality calibration |
all |
(meta) | Yes | Yes | All codecs and features |
Default features: jpeg, webp, gif, gif-zenquant, png, png-zenquant, avif-decode, avif-encode, jxl-decode, heic-decode, bitmaps-bmp.
- Format detection from magic bytes
- Image probing (dimensions, format, color info) without full decode
- Typed pixel buffer encode/decode with automatic format negotiation
- Runtime codec registry for per-request codec control
- Resource limits and cooperative cancellation forwarded to codecs
- Format-specific codec configuration via
CodecConfig
- Image processing (resize, crop, rotate)
- Color management (ICC profile application)
| State of the art codecs* | zenjpeg · zenpng · zenwebp · zengif · zenavif (rav1d-safe · zenrav1e · zenavif-parse · zenavif-serialize) · zenjxl (jxl-encoder · zenjxl-decoder) · zentiff · zenbitmaps · heic · zenraw · zenpdf · ultrahdr · mozjpeg-rs · webpx |
| Compression | zenflate · zenzop |
| Processing | zenresize · zenfilters · zenquant · zenblend |
| Metrics | zensim · fast-ssim2 · butteraugli · resamplescope-rs · codec-eval · codec-corpus |
| Pixel types & color | zenpixels · zenpixels-convert · linear-srgb · garb |
| Pipeline | zenpipe · zencodec · zencodecs · zenlayout · zennode |
| ImageResizer | ImageResizer (C#) — 24M+ NuGet downloads across all packages |
| Imageflow | Image optimization engine (Rust) — .NET · node · go — 9M+ NuGet downloads across all packages |
| Imageflow Server | The fast, safe image server (Rust+C#) — 552K+ NuGet downloads, deployed by Fortune 500s and major brands |
* as of 2026
archmage · magetypes · enough · whereat · zenbench · cargo-copter
And other projects · GitHub @imazen · GitHub @lilith · lib.rs/~lilith · NuGet (over 30 million downloads / 87 packages)
Dual-licensed: AGPL-3.0 or commercial.
I've maintained and developed open-source image server software — and the 40+ library ecosystem it depends on — full-time since 2011. Fifteen years of continual maintenance, backwards compatibility, support, and the (very rare) security patch. That kind of stability requires sustainable funding, and dual-licensing is how we make it work without venture capital or rug-pulls. Support sustainable and secure software; swap patch tuesday for patch leap-year.
Your options:
- Startup license — $1 if your company has under $1M revenue and fewer than 5 employees. Get a key →
- Commercial subscription — Governed by the Imazen Site-wide Subscription License v1.1 or later. Apache 2.0-like terms, no source-sharing requirement. Sliding scale by company size. Pricing & 60-day free trial →
- AGPL v3 — Free and open. Share your source if you distribute.
See LICENSE-COMMERCIAL for details.