Crate jxl_oxide

source ·
Expand description

jxl-oxide is a JPEG XL decoder written in pure Rust. It’s internally organized into a few small crates. This crate acts as a blanket and provides a simple interface made from those crates to decode the actual image.

§Decoding an image

Decoding a JPEG XL image starts with constructing JxlImage. First create a builder using JxlImage::builder, and use open to read a file:

let image = JxlImage::builder().open("input.jxl").expect("Failed to read image header");
println!("{:?}", image.image_header()); // Prints the image header

Or, if you’re reading from a reader that implements Read, you can use read:

let image = JxlImage::builder().read(reader).expect("Failed to read image header");
println!("{:?}", image.image_header()); // Prints the image header

In async context, you’ll probably want to feed byte buffers directly. In this case, create an image struct with uninitialized state using build_uninit, and call feed_bytes and try_init:

let mut uninit_image = JxlImage::builder().build_uninit();
let image = loop {
    uninit_image.feed_bytes(reader.read().await?);
    match uninit_image.try_init()? {
        InitializeResult::NeedMoreData(uninit) => {
            uninit_image = uninit;
        }
        InitializeResult::Initialized(image) => {
            break image;
        }
    }
};
println!("{:?}", image.image_header()); // Prints the image header

JxlImage parses the image header and embedded ICC profile (if there’s any). Use JxlImage::render_frame to render the image.

use jxl_oxide::{JxlImage, RenderResult};

for keyframe_idx in 0..image.num_loaded_keyframes() {
    let render = image.render_frame(keyframe_idx)?;
    present_image(render);
}

§Color management

jxl-oxide has basic color management support, which enables color transformation between well-known color encodings and parsing simple, matrix-based ICC profiles. However, jxl-oxide alone does not support conversion to and from arbitrary ICC profiles, notably CMYK profiles. This includes converting from embedded ICC profiles.

Use JxlImage::request_color_encoding or JxlImage::request_icc to set color encoding of rendered images. Conversion to and/or from ICC profiles may occur if you do this; in that case, external CMS need to be set using JxlImage::set_cms.

let mut image = JxlImage::builder().read(reader).expect("Failed to read image header");
image.set_cms(MyCustomCms);

let color_encoding = EnumColourEncoding::display_p3(RenderingIntent::Perceptual);
image.request_color_encoding(color_encoding);

External CMS is set to Little CMS 2 by default if lcms2 feature is enabled. You can explicitly disable this by setting CMS to NullCms.

let mut image = JxlImage::builder().read(reader).expect("Failed to read image header");
image.set_cms(NullCms);

§Not using set_cms for color management

If implementing ColorManagementSystem is difficult for your use case, color management can be done separately using ICC profile of rendered images. JxlImage::rendered_icc returns ICC profile for further processing.

use jxl_oxide::{JxlImage, RenderResult};

let icc_profile = image.rendered_icc();
for keyframe_idx in 0..image.num_loaded_keyframes() {
    let render = image.render_frame(keyframe_idx)?;
    present_image_with_cms(render, &icc_profile);
}

§Feature flags

  • rayon: Enable multithreading with Rayon. (default)
  • lcms2: Enable integration with Little CMS 2.

Re-exports§

Modules§

Structs§

Enums§

Traits§

Type Aliases§