JPEG XL in PDF: Bringing JXL to PDFium with Rust

โšก PDFium ๐Ÿ”ง Rust / C++ ๐Ÿ‘ค Helmut Januschka

Decoding JPEG XL images embedded in PDF documents using the pure Rust decoder jxl-rs

๐Ÿงช PROOF OF CONCEPT

JXL-in-PDF decoding for standalone PDFium builds

CL: pdfium-review.googlesource.com/c/pdfium/+/142070

Background

With JPEG XL landing in Chromium via the Rust decoder jxl-rs, it's natural to ask: what about PDF?

JPEG XL is poised to become the preferred format for HDR images in PDF (per ISO 32000-2:2020 discussions). While the PDF spec doesn't yet have a standardized filter name, this experiment uses /JXLDecode as a bring-up name to prove the concept works.

The Challenge

PDFium is Chromium's PDF renderer, but it's also used standalone (e.g., in other browsers, document viewers, server-side rendering). The challenge:

  1. Rust integration โ€” PDFium's standalone build needed Rust toolchain support
  2. Alpha handling โ€” JXL images can have alpha, but PDF expects a separate /SMask
  3. Animation โ€” JXL supports animation, but PDF image XObjects are static

Implementation

Approach

Build Integration

Added a new GN flag for standalone builds:

# In pdfium.gni
declare_args() {
  pdf_enable_rust_jxl = false
}

The decoder glue lives in core/fxcodec/jxl/:

core/fxcodec/jxl/
โ”œโ”€โ”€ BUILD.gn
โ”œโ”€โ”€ DEPS
โ”œโ”€โ”€ jxl_decoder.cc
โ”œโ”€โ”€ jxl_decoder.h
โ””โ”€โ”€ jxl_rs_stub.cc

Decoder Flow

// In cpdf_dib.cpp
bool CPDF_DIB::LoadJxlBitmap(pdfium::span<const uint8_t> data) {
  auto info = pdfium::jxl::ParseInfo(data);
  if (!info) return false;

  auto decoded = pdfium::jxl::DecodeFrame0(data, info->width, info->height);
  if (!decoded) return false;

  // Extract RGB
  // If has_alpha: synthesize SMask via jpx_inline_data_ mechanism

  return true;
}

The integration hooks into CreateDecoder() to handle the /JXLDecode filter:

if (decoder == "JXLDecode") {
  return LoadJxlBitmap(src_span) ? LoadState::kSuccess : LoadState::kFail;
}

Demo Artifacts

Sample PDFs with embedded JXL images, rendered by the patched PDFium:

Zoltan (RGB Photo)

Large RGB JPEG XL embedded in PDF.

Zoltan rendered
๐Ÿ“„ Download PDF ๐Ÿ–ผ๏ธ Rendered PNG

Dice (Alpha)

RGBA JPEG XL with transparency. PDFium synthesizes an /SMask and composites over a checkerboard background (baked into the PDF to visualize alpha).

Dice rendered with alpha
๐Ÿ“„ Download PDF ๐Ÿ–ผ๏ธ Rendered PNG

Animated Icons (Frame 0)

Animated RGBA JPEG XL. PDFium decodes only the first frame.

Animated icons frame 0
๐Ÿ“„ Download PDF ๐Ÿ–ผ๏ธ Rendered PNG

Code Changes

IN REVIEW CL 142070 โ€” Add experimental JXLDecode support via Rust jxl-rs

Building

To build PDFium with JXL support:

# In args.gn
enable_rust = true
pdf_enable_rust_jxl = true

# Requires rust_revision pointing to a version with jxl-rs v0.3 wrapper

Related


This is an experimental feature exploring JXL-in-PDF before standardization. The filter name /JXLDecode is a placeholder and may change.