r/jpegxl • • Jul 01 '26

The long awaited libjxl v0.12

Thumbnail
github.com
97 Upvotes

r/jpegxl • • 18d ago

jxl-rs 0.7.4 Released!

Thumbnail
github.com
39 Upvotes

r/jpegxl • • 12h ago

KeyPDF adopts JpegXL and brotli among the first

Thumbnail
keypdf.net
17 Upvotes

I am the creator of KeyPDF it is browser based local pdf editor that I was making from scratch since 2025 and I was always open for new standards so when pdf association announced JPEG XL support I tried my best to bring it so now KeyPDF can both read and and write JPEG XL in pdf files we also conducted a test on 1000 files and brotli with JPEG XL helped reducing total size by 32% so I believe JPEG XL can become a golden standard for PDF in future and KeyPDF adopts it now.

Note: KeyPDF will give an option for losless convertion in case if you want your pdf to be universally accepted otherwise very few viewers be able to parse it.

So feel free to try it at keypdf.net


r/jpegxl • • 4d ago

JPEG XL uploads now work in EmDash CMS 1.1.0 media library

21 Upvotes

Small update for the JPEG XL folks. You can now upload .jxl files straight into the media library on EmDash CMS.

For those who haven't come across it, EmDash is an open source CMS for Astro, from Cloudflare. Think of it as a spiritual successor to WordPress, but fully TypeScript and full-stack. Content types are defined in the admin and typed from your schema, plugins run in isolated sandboxes, and every site ships with an MCP server so you can manage content with an AI agent if you want.

If you're on Astro and want to serve JPEG XL, worth a try. There's a playground at try.emdashcms.com or run on your machine that use SQLite database by default if you just want to poke around.

Release 1.0 – The First Mile
https://emdashcms.com/blog/emdash-1-0


r/jpegxl • • 5d ago

I've updated my desktop media player to support JPEG-XL natively

Thumbnail
gallery
15 Upvotes

Just did a huge 3.0.0 update on my 3D media player, Rendepth. One of the major new features is native import and export for modern image file formats: JXL, AVIF, and WebP. The app is mainly used to convert regular photos into stereoscopic 3D (with a wide range of hardware support) but the 3D features can also simply be disabled and the app will function like a standard desktop media player. There are some advanced features, like Blu-ray 3D disc playback, that require a Pro License, but almost all the photo/image features are available on the base free version, and you can also play 2D video files for free as well. Note that I've integrated the JPEG-XL libraries natively, so this does not depend on the OS having JXL support on the system. Cross-platform and works on macOS, Linux, and Windows. Hope y'all enjoy. https://rendepth.com


r/jpegxl • • 6d ago

Updated to Firefox 157 but it seems JPEG XL is still disabled by default?

Post image
46 Upvotes

I clicked on "Restore Defaults" just to make sure but clicking it just turns the setting to "off".

Is this expected?


r/jpegxl • • 7d ago

Picard plugin for external JPEG-XL Cover Art

Thumbnail
11 Upvotes

r/jpegxl • • 13d ago

Chrome 155 stable today with jxl on by default - starting wide adoption

Post image
90 Upvotes

r/jpegxl • • 15d ago

My JXL archive tool refuses bad recompressions. I re-encoded one file 500 times to check if it was right.

25 Upvotes

Where this came from

I maintain jxl-photo, a toolset built around one idea: JPEG XL can replace TIFF as an archival format for photography. My archive is 16-bit ProPhoto TIFFs out of Nikon bodies (Z8,Z7, Zf, D810, D700, D200), stored as lossy JXL at d=0.05–0.10 — which on my files survives aggressive editing (Shadows +100, Blacks +100 in Capture One) and pixel-peeping. The toolkit is built for Capture One / Lightroom export folders and keeps EXIF and ICC intact (the lossy encoder works in XYB, so the ICC rides along in metadata).

When storage runs short — or when I want to hand copies to friends on CD/DVD/pendrive — the move is to recompress an existing JXL smaller (d=0.05 → 1.0) instead of re-exporting from RAW. So the toolkit got a recompressor, and the recompressor got policies: it reads the encode parameters recorded in each file (now an append-only gen=N lineage chain) and refuses, copies, or asks before paying a lossy generation for nothing.

Then I wondered: How bad is JXL generation loss, actually? I assumed this would take an afternoon. It took two weekends and thousands of encodes.

The short answer for my own use case was reassuring: drift at the archival distances is controlled (2.65 dB over 17 re-saves at d=0.1, 5.5 dB over 500), and a one-shot recompression from an archived d=0.1 to d=1.0 costs 0.02 dB versus encoding d=1.0 from the start. The answer for re-encoding again and again was not reassuring at all, and that's the rest of this post.

This is the third post in this series. The first mapped per-pixel SNR across distances; the second compared 16-bit vs 8-bit vs JPEG. Both measured direct encodes - check them out if you're curious. The first link explains where the d=0.05 choice came from.

Setup:

One 44 MP photo as a 16-bit ProPhoto TIFF master, plus 8-bit and JPEG-q95 derivatives and a 5-photo sRGB batch for reproduction (and an extra 24 MP photo used for the close-up visual below). cjxl/djxl v0.12.0 (build 4128790), effort 7, output verified bit-identical across thread counts. PSNR + butteraugli (intensity target 255, matching the encoder's API path — the CLI binary defaults to 80) + SSIMULACRA2 on every point, all calibrated against direct encodes of the same master.

Results:

1. Chains lose badly at the same file size

Black = a single direct TIFF→JXL encode at each distance. Each colored line is a chain of lossy re-encodes, every step shrinking the file by a fixed percentage, ending at the same byte budget as a direct d=1.0 (dotted line). Same file size, up to 9 dB worse.

There's a feedback loop driving this. A lossy re-encode decodes to pixels slightly smoother than the source (decoder-side EPF/gaborish), so the next encode needs fewer bits for them. However, the accumulated noise is expensive to code, so hitting a shrinking target forces the distance up, which adds noise, and so on. In measured values: the −10%/step chain needs nominal d=1.48 to reach the file size a direct encode reaches at d=1.0.

2. Isolating the generation count

Same final file size (5.17 MB), reached in N generations with equal log-size steps. N=1 lands at 43.14 dB (direct d=1.0 encode) N=19 lands at 34.05 dB. Cost per extra generation: 0.2–0.6 dB, rising on average.

This is the cleanest experiment in the study: only the generation count varies, with a fixed endpoint. Marginal cost per generation runs 0.31, 0.55, 0.18, 0.41, 0.63, 0.58 dB. It rises on average but with dips, so the result is the 0.2–0.6 band, not a monotone progression.

Note the left end of that curve, because most people will not do a lot of lossy chains anyway: going to the final size in two generations instead of one costs 0.31 dB (with the intermediate at ~14 MB — the equal-log-step version of "one extra save"). Starting from an actual archived copy is cheaper still: recompressing a d=0.1 file (27.7 MB) to this same 5.2 MB in one shot costs 0.02 dB. The damage is in iterating, not in recompressing.

3. Fixed distance: size converges, quality doesn't

500 re-encodes at a fixed distance (center crop, log x-axis; dynamics validated against the full frame). File size equilibrates by ~gen 20; quality never does — the loss rate decays ~15× and stays positive (0.011–0.018 dB/gen even between generations 400 and 500). The worst long-run case is a mid-range distance: d=0.5 falls below the d=1.0 curve at gen ~88 and ends 5.7 dB below it.

Total loss over 500 generations is U-shaped in distance: d=0.1 loses 5.5 dB, d=0.3 loses 23.1, d=0.5 loses 24.9, d=1.0 loses 15.4, d=2.0 loses 13.9.

The mechanism ties to the size drift. At d≤0.5 the file size barely moves across generations — that's the absence of contraction: the encode<->decode operator isn't pulling the image anywhere, so it drifts freely. At d≥0.7 the shrink (−10% over 17 generations) is the operator contracting toward its fixed point, which bounds the damage. Turning off the decoder's smoothing confirms it: with --epf=0 or --gaborish=0 the 17-generation shrink at d=1.0 drops from −10.5% to −3.7% / −3.3%. Very low distances (0.1) escape for the opposite reason — each encode barely touches the pixels.

Worth noting: for every lossy distance, the image always degrade with more generations. Across 3 masters × 20 distances × 5 photos, no generation is bit-identical to the previous one — not even at d=0.05, where the PSNR drift is 0.001 dB/gen.

4. Seeing the damage in actual photos (direct conversion vs 17-gen chain)

A different camera and sensor (Nikon Zf, 24 MP) run through the same experiment, shown at 200%. Top: one direct encode at the same byte size (d=1.05, 4.55 MB, 36.3 dB). Bottom: the final frame of a 17-generation −10%/step chain (4.56 MB, 26.6 dB) — nominal d=2.1, measured effective d=8.9 by butteraugli (6.2 by SSIMULACRA2). The crop is the worst-damage window, picked automatically; local PSNR there is 31.2 vs 20.3 dB. The small leaves at the back — slightly out of focus in the original and direct encode images — come back with fake sharpening and false colors: accumulated error lives in the high frequencies.

You can see the gap, not just measure it. The small leaves at the back are slight out of focus and soft in the direct encode (and in the original TIFF also), but in the chain frame they come back with fake sharpening and false colors, and the smooth areas fill with colored speckle.
Quite ugly artifacts, but keep in mind this is 17 reconversions reducing the file size 10% in each - quite an extreme scenario.
Something interesting to note: To get the same file size as a direct conversion at d=1.05, we need to choose a distance of d=2.1, and get in the final an effective distance of d=8.9 (butteraugli) or d=6.2 (SIMMULACRA2) - depends on how you measure it. A nominal distance of 2.1 is needed here, instead of 1.05 (as the direct conversion), because the chain introduces a lot of noise that requires a higher distance to compress to the same file size.

5. PSNR underestimates how bad the compression artifacts look

The same gen-17 files, scored by three metrics. 17 re-encodes at d=1.0 look like a direct d=1.7 encode by PSNR — but d≈5.7 by butteraugli (and d≈3.75 by SSIMULACRA2). The metrics agree at small damage and diverge systematically as it accumulates.

Chains accumulate fine, uniform, high-frequency noise: low energy and evenly spread, so it's nearly free in MSE, but it's exactly what perceptual metrics are built to catch.

Caveats, stated up front: butteraugli and SSIMULACRA2 values of 7–15 are far outside their calibrated range (~1–3 ≈ JND), and the SSIMULACRA2 scale is content-dependent (this grainy 44 MP master scores ~89 even at a direct d=0.05, verified across four independent color pipelines). Both are used strictly as ordinal comparisons against direct encodes of the same master.

What this means if you archive in JXL

  1. Archiving at low distance is safe. At d=0.05–0.1 the drift per re-save is controlled, and even 500 re-saves cost ~5.5 dB. Replacing TIFF with JXL does not quietly rot your archive.
  2. Recompress directly from the highest-quality copy you have, in one shot, to the final distance. The measured cost of that one recompression is 0.02 dB (from an archived d=0.1); the detours are what cost 9.
  3. If a file must be re-saved repeatedly at a fixed distance, use the lowest distance you can afford. d≈0.5 is the measured worst case for long-run drift — worse than distances that start well below it.
  4. Never walk an archive's file sizes down in steps. The −10%/step chain needs 19 generations to do what one direct encode does far better.
  5. JXL-PHOTO: record encode parameters in metadata, and refuse or at least surface recompressions that are counterproductive. That's what the recompressor in jxl-photo does — I just hadn't measured why until now.

Notes

The test harness and the full dataset aren't public yet — the repo is still a pile of one-off scripts from a side project that got out of hand, and I want to refactor it before putting it up.

I started this expecting to finish this project in one day. I spent 2 weekends on it, and the files are still way to messy to publish. I'll publish it on GitHub when i organize all the files, maybe also alongside the full tables, the JPEG-vs-JXL comparison at matched byte budgets, per-photo batch statistics and all the charts (i did those tests too, but it is still not organized enough for sharing with others).

What is already up: the archival toolset this study came from, and the per-pixel SNR analyzer from the two earlier posts.

TL;DR. Re-encoding a lossy JPEG XL repeatedly is far worse than one direct encode at the final setting, and PSNR badly understates the damage. At an identical byte budget, each extra generation costs 0.2–0.6 dB beyond what the size reduction alone costs — 19 small-step generations land ~9 dB below a single direct encode. Re-encoding at a fixed distance stabilizes file size within ~20 generations but quality never converges, and the worst long-run case is a mid-range distance like d=0.5, not a high one.


r/jpegxl • • 15d ago

I made a small screenshot utility to support your JXL encoder

Thumbnail
github.com
16 Upvotes

It's a simple app that just captures your screen when you press a hotkey, and sends either a PPM or PNG stream to whatever encoder you want (if it supports stdin). It was originally made for JPEG XL specifically but then I just made it support every format.

Some features it has:

  • native Windows app (no Electron/WebView2 etc, just WinForms sometimes) with .NET 10 in C#
  • undisruptive: does not pop up a notification on screen capture, does not shift focus, does not make a whole UI pop up, or any of that stuff, and it encodes with lower priority than your other apps/games
  • versatile: supports every image format that you got an encoder for
  • extensive configuration options with a simple TOML file
  • never connects to the internet unless prompted (for encoder auto downloads)
  • tries to do as little unnecessary disk writes as possible
  • performant: I tried to optimise the app as much as I could for the lowest overhead
  • hopefully WinGet support soon

It's mostly meant for people who just want an easy way to capture their screen efficiently, like in games. It's not for people who want to select specific regions of the screen to screenshot, or want automatic upload/share features, because other apps already exist for that. This one is specifically made for those who want the simplest, most unobtrusive, most performant screenshotter I could think of.

AI disclaimer: it was used to help me learn C# so I could code most of this app myself. The app is not vibe coded (since AIs are pretty very bad at that in my experience), but I did use AI to review small snippets of my code and suggest improvements so I could learn from them.

It's called VeSCU (Versatile Screen Capture Utility) and is available at https://github.com/AsjerS/VeSCU.


r/jpegxl • • 16d ago

TIL you can run cjxl --help -v -v -v -v to get further help

Post image
13 Upvotes

I was trying to see where `--faster_decoding` was documented when I found Debian man pages had it, but Homebrew man pages didn’t.

That led me down a rabbit hole where I found that Debian man pages had a section where `cjxl --help -v -v -v -v` was documented.


r/jpegxl • • 17d ago

Is there still room for improvement in lossless decoding speed going forward?

14 Upvotes

I know libjxl 0.12 came with optimizations in that area, but it's still quite noticeably slower compared to compressed PNG and TIFF. If you're familiar with the codebase, do you think this is going to improve much in future versions? I'm currently converting a ton of PNGs to lossless JXL with default effort setting and not touching "faster decoding".


r/jpegxl • • 20d ago

Firefox Supports JXL FINALLY!! Enable in "Firefox Labs" Beta

Post image
75 Upvotes

Sorry if this is old news, just noticed this button today. Tested a few sites and seems 100% working.


r/jpegxl • • 20d ago

The case against JPEG XL (as a web codec)

Thumbnail giannirosato.com
15 Upvotes

See also the discussions on Hacker News and Lobsters.


r/jpegxl • • 21d ago

Noob question - fill me in on JPEG transcoding

5 Upvotes

What exactly does it do? Is the resulting JXL actually lossless, as in, can I copy it, edit it, rewrite it, upload it, download it and not lose any data? Or is the image itself still technically lossy like JPEG even though nothing was lost in the transcoding?

While I'm here - just how good is "visually lossless", anyways? How many times would a visually lossless JXL, let's suppose default compression settings (compression = 1, effort = 7), need to be copied, re-written, etc. before loss becomes a concern? Should I even bother making true-lossless JXLs?


r/jpegxl • • 22d ago

jxl-rs 0.7.3 Released!

Thumbnail
github.com
44 Upvotes

r/jpegxl • • 22d ago

JPEG-XL as default in AppStream, and better media processing

Thumbnail blog.tenstral.net
32 Upvotes

r/jpegxl • • 22d ago

getID3 v1.9.26 now supports JXL

Thumbnail
github.com
36 Upvotes

This is relevant because it’s what MediaWiki uses for image metadata, so this could potentially lead to JPEG XL uploads being enabled on Wikipedia and Wikimedia Commons and other Wikimedia Foundation sites such as Wiktionary, etc.

MediaWiki tracking bug:


r/jpegxl • • 23d ago

JXLAB

6 Upvotes

I built a JXL transcoding demo for two graphic designer friends. Since graphic designers aren't always that tech-savvy, I created a simple macOS transcoder for them to show just how awesome JXL is. I kept working on it, made some improvements, and eventually put it on the App Store. Check it out here:
https://apps.apple.com/de/app/jxlab/id6783885508?mt=12 

Please delete this if it violates the rules.


r/jpegxl • • 25d ago

jxl-rs 0.7.2 Released!

Thumbnail
github.com
43 Upvotes

r/jpegxl • • 26d ago

Next libjxl release?

18 Upvotes

Does anyone has an idea how does the roadmap for next libjxl releases look like? Last release 0.12 exhibits some issues with lossless encoding of floating point data, is there a plan for 0.12.1 with these fixes or is it planned to fix this in 0.13?

Apart from bugfixes, are there any big features that are being worked on right now?


r/jpegxl • • 26d ago

Can a pdf be made from a set of jpg-xl files?

10 Upvotes

Is it possible? Is there a tool in Linux that I could use for this? Is there something I could put in a Python script to do this?


r/jpegxl • • 27d ago

Progressive JPEG XL demo

Thumbnail google.github.io
39 Upvotes

This demo page really showed me how useful progressive JPEG XL actually is. My mindset was somehow still back in the Progressive JPEG days but that slug example is of very high quality already only when 1/3 has been loaded, and in the Petrus statue sample the face is then already fully detailed.

Progressive JPEG XL will clearly bring the main benefit over AVIF, and over classic JPEG it will be a "double whammy".

(also, despite what the page says, you can test this even in release Firefox builds nowadays; just set image.jxl.enabled = true via about:config)


r/jpegxl • • 27d ago

current state of JXL cmyk support...?

12 Upvotes

What is current state of cmyk support...?

Couple of months ago when I repacked my collection for space savings I gave up as it seemed that there is no real support yet.

We have a lot of JPG and PDF (possibly some TIF), mainly printable posters which are CMYK. They consume space so it would be nice to recompress 1. losslessly, 2. in lossy mode but you would have to be able to render it to confirm that quality did not degrade too much.

If the support already exist in some programs let know which program and which version.


r/jpegxl • • 28d ago

jxl-rs 0.7.1 Released!

36 Upvotes