Skip to content

imazen/zenjxl

Repository files navigation

zenjxl CI MSRV License

zenjxl is a JPEG XL encoding and decoding library combining zenjxl-decoder and jxl-encoder with resource limits, cancellation, and gain map support.

zenjxl-decoder is Imazen's fork of jxl-rs with additional metadata extraction, gain map parsing, and resource limiting. jxl-encoder is a pure Rust JPEG XL encoder supporting both lossless (modular) and lossy (VarDCT) modes. zenjxl wraps both behind a unified API and provides zencodec integration for use in zenpipe pipelines.

#![forbid(unsafe_code)], no_std + alloc, edition 2024.

Quick start

Decode

use zenjxl::{decode, probe, JxlLimits};
use zenpixels::PixelDescriptor;

let jxl_bytes: &[u8] = &std::fs::read("photo.jxl").unwrap();

// Metadata-only probe (no pixel decode).
let info = probe(jxl_bytes).unwrap();
println!("{}x{}, alpha={}, gray={}", info.width, info.height, info.has_alpha, info.is_gray);

// Full decode with resource limits. The 3rd arg is a pixel-format preference
// list (`&[zenpixels::PixelDescriptor]`); `&[]` lets the decoder pick natively.
let limits = JxlLimits {
    max_pixels: Some(120_000_000),                  // 108 MP photos are common
    max_memory_bytes: Some(2 * 1024 * 1024 * 1024),
};
let output = decode(jxl_bytes, Some(&limits), &[]).unwrap();

// `output.pixels` is a `zenpixels::PixelBuffer` in the image's NATIVE format
// (opaque → RGB8, with alpha → RGBA8). Normalize to packed RGBA8 bytes with the
// `zenpixels-convert` extension trait:
use zenpixels_convert::PixelBufferConvertTypedExt;
let rgba: Vec<u8> = output.pixels.to_rgba8().copy_to_contiguous_bytes(); // w*h*4, R,G,B,A

Dependencies & errors. Besides zenjxl, add zenpixels (PixelBuffer/ PixelDescriptor), zenpixels-convert (the .to_rgba8() trait), and enough (cancellation). decode/probe/encode_* return Result<_, whereat::At<E>> (At<JxlError>): the At<…> adds a build-time source location for logs — get the underlying error with err.error() (borrow) or err.decompose().0 (owned), then match the [JxlError] enum (it is #[non_exhaustive], so keep a wildcard arm).

Encode

use zenjxl::{encode_rgb8, encode_rgb8_lossless, calibrated_jxl_quality};

let rgb: &[u8] = &[0u8; 256 * 256 * 3]; // RGB pixels

// Lossy encode -- calibrated_jxl_quality maps 0..=100 to JXL distance.
let distance = calibrated_jxl_quality(85);
let lossy = encode_rgb8(rgb, 256, 256, distance).unwrap();

// Lossless encode.
let lossless = encode_rgb8_lossless(rgb, 256, 256).unwrap();

Features

Decode -- probe() returns JxlInfo with dimensions, bit depth, ICC profile, CICP signaling, EXIF orientation, raw EXIF/XMP bytes, extra channel metadata, HDR tone mapping fields, preview size, and gain map bundles. decode() returns a PixelBuffer with automatic format negotiation. decode_with_parallel() enables multithreaded decoding; decode_with_options() adds cancellation via enough::Stop.

Encode -- Convenience functions for RGB, RGBA, BGRA, and grayscale u8 data in both lossy and lossless modes. calibrated_jxl_quality() maps a 0--100 quality scale to JXL distance. Container utilities (append_gain_map_box, is_bare_codestream) for gain map authoring.

Gain maps -- Decode extracts GainMapBundle from jhgm container boxes (ISO 21496-1). Encode can append gain map boxes to existing codestreams.

HDR metadata -- JxlInfo exposes intensity_target, min_nits, relative_to_max_display, and linear_below from the JXL tone mapping header.

Feature flags

Flag Default Description
decode yes JPEG XL decoding via zenjxl-decoder
encode yes JPEG XL encoding via jxl-encoder
threads no Multithreaded decoding via rayon (requires decode)
parallel no Per-frame parallelism inside the encoder via rayon (requires encode)
butteraugli-loop no Perceptual quality tuning (requires encode)
zencodec no Config/Job/Executor trait integration for zen codec pipelines

Limitations

  • Not published to crates.io. Depend on it via git or path.
  • Encoder is u8-only for the convenience API. The zencodec path supports wider bit depths.
  • zenjxl-decoder does not yet support all JPEG XL features (e.g., some edge cases in progressive decoding).

Image tech I maintain

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

General Rust awesomeness

archmage · magetypes · enough · whereat · zenbench · cargo-copter

And other projects · GitHub @imazen · GitHub @lilith · lib.rs/~lilith · NuGet (over 30 million downloads / 87 packages)

License

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.

Our open-source products

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.

Upstream code from libjxl/libjxl is licensed under BSD-3-Clause. Our additions and improvements are dual-licensed (AGPL-3.0 or commercial) as above.

Upstream contribution

We are willing to release our improvements under the original BSD-3-Clause license if upstream takes over maintenance of those improvements. We'd rather contribute back than maintain a parallel codebase. Open an issue or reach out.

About

No description, website, or topics provided.

Resources

License

AGPL-3.0, Unknown licenses found

Licenses found

AGPL-3.0
LICENSE-AGPL3
Unknown
LICENSE-COMMERCIAL

Stars

Watchers

Forks

Packages

 
 
 

Contributors