JXR: JPEG XR for Rust
JXR decodes JPEG XR images in Rust, with optional Apple GPU (Metal) and NVIDIA GPU (CUDA) reconstruction. The default build runs on the CPU and needs no GPU runtime or reference codec.
It reads raw JPEG XR codestreams and Annex-A still-image files, decodes full images or regions, and preserves high-bit-depth samples, alpha, and embedded ICC profiles. It can also wrap an existing codestream in an Annex-A file; pixel-to-codestream encoding is not implemented.
Requires Rust 1.99.0 or newer. The current release is 0.3.1; see the release notes for migration details.
What it does
- Inspect without decoding pixels. Read dimensions, color format, bit
depth, tiling, orientation, alpha, and container metadata through
JxrView. - Decode a whole image or a region. Region requests limit reconstruction to the required tiles and overlap halo.
- Decode thumbnails at native resolution. Frequency-mode images support quarter-width/height and sixteenth-width/height CPU decode, skipping the higher-frequency bands that the output does not need.
- Keep the sample representation you need. Supported outputs include grayscale, RGB/BGR, CMYK, multichannel, planar YUV, integer and floating-point samples, packed RGB/RGBE, and integrated or separate alpha.
- Decode batches. Prepare inputs once, group compatible output shapes, and reuse CPU workers or GPU sessions. CPU batches support native and NCHW layouts; GPU output can remain in device memory.
- Connect to other libraries.
jxr-imagetransfers supported buffers intoimage::DynamicImage;jxr-mpsgraphhands Metal batches to Apple's MPSGraph. - Write Annex-A containers.
write_annex_apackages an existing raw codestream with validated metadata and optional separate alpha.
The supported format boundary is Main-profile syntax. Advanced-only output
syntax, JPEG 2000 .jpx wrappers, Annex-F/HEIF sequences, and transcoding are
outside the scope. See the full support guide.
Quick start
Decode a compatible 8-bit color image to RGB, explicitly dropping any alpha:
use ;
image.samples holds typed pixel storage, and image.planes describes its
layout. ICC bytes are available through view.icc_profile(); applying the
profile is the application's responsibility. Use decode_oriented to apply
the file's presentation orientation for supported full-image host outputs.
Choose an output format
For an unfamiliar file, inspect view.info() before choosing a request. Replace
the request and decode portion of main above with this to select grayscale or
RGB output for common unsigned 8- and 16-bit sources, retaining alpha:
use ;
let info = view.info;
println!;
let has_alpha = info.alpha_mode != None;
let layout = match ;
let output = match info.primary.sample_format ;
let request = new; // Preserve alpha by default.
let image = view.decoder.decode?;
primary.color_format describes the coded planes: an RGB image commonly uses
YUV internally, which is why both branches request RGB output. The container's
declared pixel representation, when present, is available separately through
info.metadata.annex_a_pixel_format.
This example handles a common subset, not every JXR output. CMYK, multichannel,
signed, floating-point, and packed formats need an explicit PixelFormat;
see the supported formats. Decoding validates the full
source/output combination and returns an error if it is unsupported.
Use with image::DynamicImage
Add the adapter alongside jxr:
Using the view and format-aware request above, decode into the image crate
and create a preview that fits within 256 × 256 pixels:
let frame = decode_view?;
let image: &DynamicImage = frame.image;
let preview = image.thumbnail;
println!;
Use this in place of the preceding decoder.decode call to avoid decoding
twice. The adapter transfers the decoded pixel allocation without copying it;
thumbnail then creates a resized image after a full decode. For frequency-mode
inputs, the native thumbnail route below can skip higher-frequency bands.
Keep frame when you need its ICC profile or straight/premultiplied alpha
metadata; frame.into_image() returns only the DynamicImage and discards that
extra metadata. The adapter does not apply ICC transforms or presentation
orientation. It supports Luma/LumaA/RGB/RGBA at U8 and U16, plus RGB/RGBA at
F32. See the adapter guide for details.
Regions and thumbnails
With the same view and request, decode a 256 × 256 region within the image:
use Rect;
let region = Rect ;
let crop = view.decoder.decode?;
For a frequency-mode image, decode a thumbnail at one sixteenth of the width and height:
use ;
let thumbnail_request = request.clone
.with_scale
.with_backend;
let thumbnail = view.decoder.decode?;
DecodeScale::Quarter is also available. Region coordinates remain in
full-resolution pixels. Native reduced decode currently requires frequency-mode
input and the CPU backend; spatial-mode and GPU reduction are not implemented.
Inspect a file
From a repository checkout:
This prints parsed metadata without decoding pixels. JXR currently provides a library and this inspection example, rather than a standalone conversion CLI.
GPU support
The CPU parses the container and decodes entropy; Metal or CUDA can run the reconstruction and output stages. Both support host output, resident device buffers, caller-owned destinations, and batches.
| Backend | Enable | Runtime requirements |
|---|---|---|
| CPU | Default; no features needed | No GPU runtime |
| Metal | cargo add jxr --features metal |
Apple-silicon macOS (M1 or newer) |
| CUDA | cargo add jxr --features cuda |
Compatible NVIDIA GPU, driver, and NVRTC; hardware validation currently covers Linux |
For single-image GPU decoding, attach a reusable session to the decoder; enabling a feature alone does not attach one. See the Metal and CUDA session example. Building the CUDA feature does not require CUDA libraries or an NVIDIA driver.
BackendRequest::Cpu keeps work on the CPU. The default Auto may use an
attached GPU session or choose the CPU before submission. Explicit Metal and
Cuda requests return an error when unavailable or unsupported. GPU failures
after submission are returned without a CPU retry.
Automatic routing uses workload thresholds (measured for Metal, provisional for CUDA). No general CPU-versus-GPU speedup is claimed. See the routing model, CUDA backend guide, and hardware reports for release 0.3.0.
Which crate do I need?
Most applications only need jxr.
| You want to | Use |
|---|---|
| Inspect or decode JPEG XR; wrap existing codestreams | jxr |
| Decode with an Apple or NVIDIA GPU | jxr with metal or cuda |
Transfer decoded pixels to image::DynamicImage |
jxr-image |
| Feed Metal-resident batches to MPSGraph | jxr-mpsgraph |
| Manage device sessions and buffers directly | jxr-metal or jxr-cuda |
jxr-core, jxr-native, and jxr-math provide the shared types, CPU engine,
and exact arithmetic behind those APIs. jxr-test-support is an unpublished
validation package. See architecture for how they fit
together.
Correctness and limits
Reference comparisons. For release 0.3.0, CPU, Metal, and CUDA output each
byte-matched the T.835 reference software on all 517 in-scope T.834 cases.
Annex-A writer comparisons passed the same cases. Another 179 entries were
excluded for Advanced-only output syntax or .jpx wrappers. This is scoped
differential evidence, not a claim of complete JPEG XR conformance. The
release notes link to the validation runs.
Input handling. The public facade forbids unsafe Rust. Decode requests
include configurable DecodeLimits for dimensions, compressed input,
coefficients, and host allocations. Parser, decode, and output/batch fuzz targets
live in the repository; ordinary CI checks that the fuzz package builds.
Color and metadata. JXR exposes ICC profiles without applying color transforms. It preserves explicit alpha and output-format semantics, and rejects unsupported combinations instead of approximating another format.
API status. JXR is under active development on the 0.x release line.
The 0.3 line uses exact J2K 0.12.0 dependencies; applications using the shared
J2K types must update those dependencies together. Check the release notes
before upgrading.
Documentation and contributing
- API reference
- Supported formats and known limitations
- Architecture and batch decoding
- CUDA backend and validation
imageintegration- MPSGraph integration
- Release history and migration notes
- Contributing, local checks, and bug reports
- Issues
License
Licensed under either Apache-2.0 or MIT, at your option. See third-party notices for attribution and reference-software boundaries.