devtake.dev

Mozilla made Google rewrite the JPEG XL decoder in Rust before Firefox would ship it

Firefox turns JPEG XL on by default in version 157. Mozilla refused to ship 100,000 lines of C++, so Google Research wrote the decoder again in Rust.

Naomi Park · · 7 min read · 10 sources
The same photo of a curled-up red fox shown in four vertical slices, blurry at 4% downloaded and sharp at 100%, demonstrating JPEG XL progressive rendering
Image via Mozilla Hacks · Source

Mozilla wouldn’t ship Google’s JPEG XL decoder. The C++ version runs to 100,000 lines, and Firefox engineers didn’t want that much fresh parsing code standing between the network and the screen. So they set a price: rewrite it in Rust, and Firefox turns the format on.

Google took the deal. The JPEG XL team at Google Research built jxl-rs, and on Monday Mozilla’s Timothy Nikkel filed the intent to ship: decoding goes on by default for every Firefox user in version 157, due at the end of September. Chromium filed its own intent the same day, and Safari has had partial support since 2023. A format Chrome deleted in 2023 for lack of interest is now weeks from working in every major browser, and the thing that unblocked it was one vendor refusing to ship somebody else’s C++.

What JPEG XL actually is

JPEG XL is a still-image format, standardized as ISO/IEC 18181 in 2022, with the extension .jxl and the MIME type image/jxl. Think of it as one container trying to cover every job the older formats split between them: lossy compression like JPEG and AVIF, lossless compression like PNG and lossless WebP, animation like GIF. Two capabilities set it apart. The first is lossless JPEG transcoding: it repacks an existing JPEG into a smaller .jxl file and reconstructs the original bit for bit, so an archive shrinks with no re-encode argument to have. The second is that it decodes progressively, which in practice means a large photo becomes recognizable long before it finishes downloading. That second one is the feature Mozilla pushed hardest for.

The demo makes the progressive point better than a spec sheet can. Jake Archibald’s post shows a fox photo that weighs 135 kB in full, and with a few kB pulled down the subject is already obvious. “Progressive rendering means the image can render as it’s downloading,” he writes. AVIF has only basic progressive support, so on very large images Mozilla says it may be worth taking the file-size hit with JPEG XL. Safari, which shipped JPEG XL back in 2023, has neither progressive rendering nor animation.

On file size the picture is mixed, and Mozilla published the numbers instead of a marketing line. Its comparison scores both formats with SSIMULACRA 2 and reports what each one weighs at matched quality:

Test imageAVIFJPEG XLLossless WebP
Photo, score 62.8116 kB134 kBn/a
Photo, score 80227 kB264 kBn/a
Photo, lossless1.76 MB1.45 MB1.55 MB
Screenshot, score 7811.6 kB23.8 kBn/a
Screenshot, lossless164 kB92 kB96 kB

The split is clean. AVIF wins on lossy photos and wins by half on lossy screenshots. JPEG XL wins on lossless, and on that screenshot it wins by 44%.

Why 100,000 lines of C++ scared Mozilla

Image decoders are the softest target a browser exposes. They parse bytes from any origin automatically, with no click required, and they carry decades of accumulated format complexity. CVE-2023-4863, a heap buffer overflow in Google’s own libwebp, is the reference case: Apple’s security engineering team and Citizen Lab reported it in September 2023, attackers were already using it, and Google, Mozilla, and Microsoft all shipped out-of-band patches within roughly two days.

So Mozilla drew a line. Firefox had experimental JPEG XL support behind a flag as far back as 2021, but “at 100,000 lines of multithreaded C++, we were concerned about the attack surface this added to Firefox,” Archibald writes. What followed was a dare rather than a veto: “So, we laid down a challenge to the JPEG XL team at Google Research: Build a safe, performant, compact, and compatible JPEG XL decoder in Rust, and we’ll ship it. That challenge was met; Google Research built jxl-rs, and it’s the core of our JPEG XL support in Firefox.”

jxl-rs is blunt in its own README about where the safety comes from. “The vast majority of the code uses safe Rust,” it reads. “Where unsafe is needed for performance benefits (including SIMD), we require unsafe code to have extensive safety comments and to be reviewed by a non-author Unsafe Rust expert.” It decodes only. Anything that writes a .jxl file still runs the C++ library.

Performance was the obvious counter-argument, and Nikkel answered it with numbers. jxl-rs 0.6.0 added multithreaded decoding, and with Firefox’s patches to hook that up, he ran “a five-format decode benchmark over the same pictures at a range of sizes: we were slightly ahead of Safari (using C++ libjxl) on my machine.” The caveat sits in his next line: “Compared to our other image format decoders, JXL is close on large images, but shows a bigger gap on small ones.”

Test coverage isn’t thin. The web-platform-tests suite checks decode correctness across bit depths, alpha, grayscale, CMYK, color management and the coding tools, and Nikkel added about 30 Gecko tests of his own for chunked decoding, animation frame counts, downscale-during-decode and corrupt files. Mozilla’s fuzzing team already ran the decoder before it went on in Nightly and will run it again before the pref flips. This is the same play Mozilla has been making for a decade, from Stylo to the Servo engine now passing 65.9% of the web platform tests. What’s new is that the code getting rewritten belonged to somebody else.

Chrome killed it, then reversed

Chrome’s history here is the strangest part of the story. Google shipped experimental JPEG XL behind a flag, then announced on October 31, 2022 that the code was coming out in Chrome 110, which reached stable in February 2023. The bug gave four reasons, two of which aged badly: “There is not enough interest from the entire ecosystem to continue experimenting with JPEG XL,” and “The new image format does not bring sufficient incremental benefits over existing formats to warrant enabling it by default.”

Interest turned out to exist. The Chromium issue collected more than 500 comments disputing that first claim, with objections from people at Intel, Adobe, Meta, Shopify, The Guardian, Flickr and the Krita Foundation. Intel’s Roland Wooster wrote that “JPEG XL appears to be the only format with suitable compression for images on the web.” heise reports the thread passed 1,000 upvotes, that the Free Software Foundation called the removal a restriction of user choice, and that JPEG XL co-developer Jon Sneyers suspected an internal fight at Google between the JPEG XL people and the AVIF and WebP camps.

The reversal came in stages. Google signaled in November 2025 that it would put a memory-safe decoder into Chromium, landed jxl-rs in third_party in January 2026, and had the format behind an #enable-jxl-image-format flag by Chrome 145 in February. When Nikkel posted his intent to ship at 4:15 a.m. Pacific on Monday, he described Chrome as having “no intent to ship yet.” Twenty-two minutes later he replied to his own thread with a link: Chromium had filed one.

Can I use still puts JPEG XL at 15.02% global support, all of it Safari’s partial implementation. That figure is about to move a long way in a single quarter.

What this means for you

Don’t re-encode your image library yet. The <picture> element already handles this: put a <source type="image/jxl"> ahead of your AVIF or WebP source and any browser that doesn’t understand it skips past. That pattern works today, it works after 157 lands, and it keeps working if adoption stalls again.

The case with a real payoff is the lossless one. If you’re sitting on a large JPEG archive, JPEG XL repacks it smaller and hands the original back bit for bit, so the usual argument about generation loss doesn’t apply. Screenshots and UI captures are the other clear win, and Mozilla’s own numbers show why: 164 kB as lossless AVIF, 92 kB as lossless JPEG XL.

There’s a sharp objection on the table, and it came from inside the thread. On Tuesday, Sergey Davidoff replied to Nikkel with hyperfine results: lossless JPEG XL took a mean 20.632 seconds to decode against 667.0 milliseconds for lossless WebP on his test image. “In my measurements it is 30x slower to decode than lossless WebP, in exchange for a 10% reduction in file size,” he wrote, and asked Mozilla to ship only lossy JPEG XL in 157. That lands on exactly the use case JPEG XL is supposed to own, and it’s worth benchmarking your own assets before you commit to the lossless path.

My read: wire up the <picture> source now, because it’s a few lines and it degrades safely. Hold the archive transcode until Chrome’s default flip has a version number attached. Rust keeps arriving in codebases that were C or C++ by default, from Linux’s core commands on Windows to Bun’s million-line rewrite, and a browser vendor using a ship decision as the forcing function is a version of that worth watching. Two dates carry the rest of this story. Nikkel flips image.jxl.enabled for Firefox 157, which lands at the end of September on Mozilla’s new two-week release cadence, with one more fuzzing pass first. Chromium’s intent to ship has no milestone attached yet, and until it does, JPEG XL is a format two browsers can read and almost nobody serves.

Share this article

Quick reference

SSIMULACRA 2
An open image-quality score where higher is better and 100 is the ceiling. Mozilla reads 62.8 as medium-high quality and 80 as very high.
lossless JPEG transcoding
Repacking an existing JPEG as a JPEG XL file with no re-encoding. The pixels stay bit-identical and the original JPEG can be reconstructed exactly.
fuzzing
Throwing huge volumes of malformed input at a program to crash it and expose memory bugs. It's cheap to run and the main way modern parsers get audited.

Sources

Frequently Asked

When does Firefox turn JPEG XL on?
Firefox 157, due at the end of September 2026, enables JPEG XL decoding by default on all platforms. Nightly already has it on, and every channel has carried a Firefox Labs checkbox since Firefox 152.
Is JPEG XL better than AVIF?
It depends on the image. AVIF produces smaller files at web quality, sometimes by half on screenshots. JPEG XL wins at lossless, repacks existing JPEGs without quality loss, and has real progressive rendering.
Can I use JPEG XL on a production site today?
Yes, inside a picture element with an AVIF or WebP fallback. Can I use still counts JPEG XL at 15.02% global support, all of it Safari's partial implementation, so the fallback carries most traffic until Chrome flips its default.
Why did Chrome remove JPEG XL in 2023?
Google gave four reasons in the Chromium bug, including not enough ecosystem interest and insufficient benefit over existing formats. The issue drew more than 500 comments in protest before Google reversed course in 2026.
Is jxl-rs written entirely in safe Rust?
No. The README says the vast majority is safe Rust, and any unsafe code needed for SIMD performance requires extensive safety comments plus review by a non-author unsafe Rust expert.

Mentioned in this article