v155 · graphics · image formats
JPEG XL decoding support (image/jxl)
Chrome 155 decodes JPEG XL, using jxl-rs — a memory-safe decoder written in Rust rather than the C++ one that was reverted in 2023. The format brings progressive decoding, wide gamut, high bit depth and animation; the safety of the decoder is what made it shippable this time.
concepts
-
Decode probe
Four ways to ask whether this browser decodes JPEG XL — an
<img>,createImageBitmap, a canvas draw, and theAcceptheader the browser sends — run against a real.jxlfile. They do not always agree, and the disagreement is the interesting part. -
Format showdown
One source image encoded as JPEG XL, AVIF, WebP and JPEG, with real byte counts and decode timings measured in your browser. No claims from a blog post — the files are in this repo and the numbers come from your machine.
-
Serving it safely
How to actually ship it: a
<picture>with a JXL source and fallbacks, and a readout of which source the browser chose. Includes the mistakes that make the fallback never fire.
why it shipped
Chromium had a JPEG XL decoder behind a flag and removed it in 2023, citing the maintenance burden of another C++ image parser — the class of code where a malformed file becomes a memory-safety bug, and where the attack surface is every image on the web. The format's technical case was never really the problem.
jxl-rs changes that calculation: a pure-Rust decoder, memory-safe by construction, so a malformed file is a decode error rather than a vulnerability. This is a decode-only shipment — Chrome reads JPEG XL, it does not write it.
the API
<!-- Content negotiation, so older browsers never see the .jxl -->
<picture>
<source srcset="photo.jxl" type="image/jxl">
<source srcset="photo.avif" type="image/avif">
<img src="photo.jpg" alt="…" width="960" height="600">
</picture>
// Feature detection, if you need it in script: decode a tiny file and
// see whether it produces pixels. There is no format registry to ask.
const supported = await createImageBitmap(jxlBlob).then(() => true, () => false);