JPEG XL

Info

rules 57
github 35276
reddit 647

JPEG XL

tools 4225
website 1655
adoption 20712
image-compression-forum 0

General chat

welcome 3810
introduce-yourself 291
color 1414
photography 3435
other-codecs 23765
on-topic 24923
off-topic 22701

Voice Channels

General 2147

Archived

bot-spam 4380

coverage

Post links to articles, blog posts, reddit / hackernews / forum posts, media coverage about or related to JXL here!

monad
_wb_ The long paper on JXL is publicly available now: https://arxiv.org/abs/2506.05987
2025-06-10 05:09:42
Thank you!
_wb_
2025-06-11 05:44:43
Lol, one of my colleagues wanted to listen to the paper while driving his car, so he AI'ed it into a podcast: https://player.cloudinary.com/embed/?cloud_name=tsi-cl&public_id=JPEG_XL_Image_Format&source[sourceTypes][0]=audio
Quackdoc
2025-06-11 05:46:23
neat, ill give it a listen lol
jonnyawsom3
2025-06-11 05:53:05
Finally, a good use for AI. Maximum JPEG XL information ingestion
2025-06-11 05:55:51
Oh god the AI presenters are even using 'GIF' and 'JIF'
KKT
2025-06-11 07:40:46
The guy sounds slightly drunk.
spider-mario
2025-06-11 08:54:13
that’s NotebookLM, isn’t it?
monad
2025-06-11 08:56:57
\> humans spend months carefully crafting thorough yet accessible technical overview \> AI bastardizes it in seconds
AccessViolation_
2025-06-11 09:16:33
can you turn it into a one minute tiktok with a subway surfers and family guy clip playing at the top
_wb_
spider-mario that’s NotebookLM, isn’t it?
2025-06-12 05:31:56
Correct
CrushedAsian255
KKT The guy sounds slightly drunk.
2025-06-12 07:41:44
welcome to AI TTS models
_wb_
2025-06-12 08:32:03
https://cloudinary.com/blog/the-latest-advancements-in-jpeg-xl
jonnyawsom3
2025-06-12 09:23:46
I wondered why the page was loading so slowly, then I realised it's because I have the Oxide browser extension. Cloudinary was serving me every single image as a JXL, to decode at once, singlethreaded
2025-06-12 09:24:19
Oh... And that profile pic downloaded a 6000*4000 image for some reason
2025-06-12 09:26:19
Okay nevermind, it was only that profile picture. 1GB of memory and 5 seconds to decode
Meow
2025-06-13 02:55:44
Yeah it downloaded that huge for me too
jonnyawsom3
2025-06-13 02:59:25
Seems like it's treating max width as absolute width
Quackdoc
I wondered why the page was loading so slowly, then I realised it's because I have the Oxide browser extension. Cloudinary was serving me every single image as a JXL, to decode at once, singlethreaded
2025-06-13 03:28:03
and thats why wasm is rough lol
2025-06-13 03:28:12
tho the oxide version i thought was multithreaded
2025-06-13 03:28:20
still rough tho
jonnyawsom3
Quackdoc and thats why wasm is rough lol
2025-06-13 03:29:18
The 1GB and 5 seconds were from CLI decoding. WASM is only multithreaded when embedded on the site due to cross origin policy, so the extension is singlethreaded
Quackdoc
2025-06-13 03:29:54
[Hmm](https://cdn.discordapp.com/emojis/1113499891314991275.webp?size=48&name=Hmm)
2025-06-13 03:30:14
i could have sworn that extensions had permissions to be multithreaded globally
jonnyawsom3
Quackdoc i could have sworn that extensions had permissions to be multithreaded globally
2025-06-13 03:31:42
Probably just not configured for it, I can't understand the code
2025-06-13 03:32:15
Thanks Android. That's a 7zip file
Quackdoc
2025-06-13 03:33:04
sadly, afaik decompiling wasm is a pain so i prolly wont be able to tell
jonnyawsom3
2025-06-13 03:33:45
It's the Oxide WASM with java script wrapper calling the functions
Quackdoc
2025-06-13 03:33:48
I do have a mv2 version that could be tried
monad
2025-06-13 03:44:13
everyone being sussy downloading profile pics, nobody complaining about JPEG XL spelling
Meow
2025-06-13 04:01:50
No on my Firefox it downloaded a huge WebP
AccessViolation_
Quackdoc sadly, afaik decompiling wasm is a pain so i prolly wont be able to tell
2025-06-16 02:30:51
decompiling wasm is relatively easy because of the structured control flow. google wrote a decompiler for it too https://v8.dev/blog/wasm-decompile
HCrikki
2025-06-17 06:53:31
https://news.ycombinator.com/item?id=44299970
2025-06-17 06:54:59
not jxl-focused but good discussion to discuss its strengths and correcting old myths
2025-06-17 06:58:54
reminds me a lot of people are confused about the actual nature of 'lossless jpeg transcoding' since almost no app uses the dedicaced conversion path - it'd have been way easier to define as '*reversible* lossless transcoding (or .jxl encoded as a maximum compatibility jpeg and decodable as either jxl or jpg depending on your software's support)
spider-mario
2025-06-17 07:22:49
(do you mean reversible jpeg transcoding?)
jonnyawsom3
2025-06-17 07:33:28
Almost no app uses it because they decode to pixels, so they can't pass the bitstream to libjxl
KKT
2025-06-17 10:45:32
https://mjtsai.com/blog/2025/06/17/chrome-doesnt-support-jpeg-xl/
jonnyawsom3
2025-06-17 10:55:44
I was expecting some good reading, but it's just 3 quotes followed by "JPEG XL seems better, but even Apple’s not supporting it everywhere yet."
KKT
2025-06-18 03:32:22
Yeah, annoying. Was hoping he'd light them up a bit.
_wb_
2025-06-20 05:54:03
https://news.ycombinator.com/item?id=44310619
jonnyawsom3
2025-06-20 05:57:25
The comment about GIF using frame blending to get more colors is pretty ironic. They say they load instantly and have full compatibility, but browsers limit frame duration and Discord has broken GIF transparency for WebP previews
_wb_
2025-06-20 06:44:56
Not to mention that even if applications would actually allow 0-duration frames in GIF, you would get horrible compression when using GIF for full-color images. It would be worse than uncompressed, maybe even twice as large as uncompressed...
jonnyawsom3
2025-06-20 07:33:20
And likely freeze the system for quite a while too. Phones already struggle when normal GIFs are above 1080p
lonjil
2025-06-20 11:49:04
Have you ever seen <@281958058190700546>'s Gif with every single 24 bit color?
jonnyawsom3
2025-06-20 11:59:49
You mean like this? https://cdn.discordapp.com/attachments/794206087879852107/1377161103754399754/24bit.gif?ex=6856eff9&is=68559e79&hm=39a49c789e98473f495e0322e8207257cbdc993d1a94a53815aa9fc0eca75ce5&
2025-06-21 12:00:24
I just spent the past few hours trying to find a tool to create those GIFs, but it seems manually splitting and merging the tiles is the only way
2025-06-21 12:01:34
Gifski says "Thousands of colors per frame", but that's just because previous frames colors remain. Each individual frame is still a full image and only has 255 colors, plus transparency for the last frame's. It quantizes the colors too, so not useful for a still image or low framerate
KKT
2025-06-23 05:42:54
https://youtu.be/UEMiqa5sRZg?si=0hWTBljefxUPQdGc Jump to 2:45
jonnyawsom3
2025-06-23 05:47:57
In what world is Quality 70 considered 'High Quality'... Adobe never ceases to amaze, unfortunately for all the wrong reasons
_wb_
2025-06-23 05:54:28
They do have a different scale than most other stuff - their jpeg quality 30 is something like libjpeg-turbo quality 70 or something like that
2025-06-23 05:54:49
So it could be they map their q70 to libjxl q85 or something like that
jonnyawsom3
2025-06-23 06:43:32
Interesting. A shame they only made a minimal JPEG XL UI but gave AVIF speed and subsampling settings, would've been nice to see effort and progressive
mincerafter42
lonjil Have you ever seen <@281958058190700546>'s Gif with every single 24 bit color?
2025-06-26 03:38:33
oh hello
You mean like this? https://cdn.discordapp.com/attachments/794206087879852107/1377161103754399754/24bit.gif?ex=6856eff9&is=68559e79&hm=39a49c789e98473f495e0322e8207257cbdc993d1a94a53815aa9fc0eca75ce5&
2025-06-26 03:38:42
yeah except with all of them
Gifski says "Thousands of colors per frame", but that's just because previous frames colors remain. Each individual frame is still a full image and only has 255 colors, plus transparency for the last frame's. It quantizes the colors too, so not useful for a still image or low framerate
2025-06-26 03:40:19
correct for a still image technically one could have a non-looping image with more colours added per frame, but gifski does not do that for multiple consecutive instances of the same image
mincerafter42 yeah except with all of them
2025-06-26 03:45:41
have the python script that generates it; this is significantly smaller than the GIF itself
jonnyawsom3
mincerafter42 correct for a still image technically one could have a non-looping image with more colours added per frame, but gifski does not do that for multiple consecutive instances of the same image
2025-06-26 07:12:26
Yeah, gifski quantizes the difference between frames, so trying to add more colors just results in it seeing the same frame and deduplicating it
Demiurge
lonjil Have you ever seen <@281958058190700546>'s Gif with every single 24 bit color?
2025-06-28 08:33:48
Mince rafter?
mincerafter42
Demiurge Mince rafter?
2025-06-28 08:30:24
hello
_wb_
2025-07-08 05:59:12
Was this posted here already? If so, I missed it. https://news.ycombinator.com/item?id=44299970
damian101
_wb_ Was this posted here already? If so, I missed it. https://news.ycombinator.com/item?id=44299970
2025-07-09 04:47:53
https://discord.com/channels/794206087879852103/822105409312653333/1384606907708215296
_wb_
2025-07-09 07:23:08
> At 50 percent of its initial quality Ugh quality does not work like that...
2025-07-09 07:24:53
It is so unfortunate that "quality" and "quantization" both start with the letter q, and to make things worse, popular tools like libjpeg map the quantization setting to a 0..100 scale they call "quality".
2025-07-09 07:25:44
It kind of correlates with quality of course, but it's not the same thing and it's not a percentage of anything
spider-mario
2025-07-09 07:47:46
I’ve seen people argue that Fahrenheit works well as a 0-100 scale, so…
_wb_
2025-07-09 07:59:41
My living room has a temperature of 68 percent.
2025-07-09 08:00:15
Actually currently it's more like 77 percent.
2025-07-09 08:01:01
77 percent Fahrenheit that is. In Celsius that would be only 25%.
2025-07-09 08:01:57
^ this is how silly it is to express image quality in "percent"
jonnyawsom3
2025-07-09 10:03:38
On Saturday England is 33% to boiling
spider-mario
2025-07-09 10:10:46
from freezing
spider-mario I’ve seen people argue that Fahrenheit works well as a 0-100 scale, so…
2025-07-09 10:12:43
(example: https://www.threads.com/@scottedson1/post/DLUoT9HOk7S > The Fahrenheit scale is indefensible as a pure scientific matter but quite intuitive to humans. It is a good rough proxy for “percent hot” and the 0-100 do a good job of covering the overwhelming range of circumstances most people experience. )
2025-07-09 10:15:26
multiply the Butteraugli scale by 10 and I wouldn’t be surprised if some people would say it’s a good rough proxy for “percent quality lost”
JaitinPrakash
2025-07-09 10:18:24
people tend to extremely oversimplify and aggregate concepts if they're even slightly related. Fahrenheit isn't percent hot, just a more granular heat scale for the typical range a human experiences.
VcSaJen
2025-07-10 07:04:33
I always think wtf, how they aren't boiled alive when people on the internet say "it's 100 degrees outside"
CrushedAsian255
_wb_ It kind of correlates with quality of course, but it's not the same thing and it's not a percentage of anything
2025-07-10 07:10:40
what would "0% quality" entail? a purely black image? random static?
spider-mario multiply the Butteraugli scale by 10 and I wouldn’t be surprised if some people would say it’s a good rough proxy for “percent quality lost”
2025-07-10 07:11:17
cause that would make -d 10 mean "0% quality"
2025-07-10 07:11:27
where -d 10 still looks okay
_wb_
2025-07-10 07:12:10
that is one of the problems when thinking of quality as a percent
2025-07-10 07:12:53
just like temperature, quality is a scale with only one endpoint really: absolute zero / mathematically lossless
CrushedAsian255
2025-07-10 07:13:12
and you can make quality as bad as you want really
2025-07-10 07:13:37
good old -d 500
embed
CrushedAsian255 good old -d 500
2025-07-10 07:13:42
https://embed.moe/https://cdn.discordapp.com/attachments/822105409312653333/1392765694164205608/a.jxl?ex=6870b9a1&is=686f6821&hm=5903baec2f58e4e830b837f222f32d0da7101d03cd5407d0137e247c7c728f7f&
_wb_
2025-07-10 07:14:09
in ssimulacra2, the score is on a scale where 100 is lossless and smaller is worse, and the score can go negative too
CrushedAsian255
2025-07-10 07:14:29
strange why they didn't just have 0 be lossless and anything higher be worse
2025-07-10 07:14:36
so like -(currentscore-100)
2025-07-10 07:14:54
100 seems like a seemingly random point for 'lossless'
jonnyawsom3
https://embed.moe/https://cdn.discordapp.com/attachments/822105409312653333/1392765694164205608/a.jxl?ex=6870b9a1&is=686f6821&hm=5903baec2f58e4e830b837f222f32d0da7101d03cd5407d0137e247c7c728f7f&
2025-07-10 07:15:30
Surprisingly that doesn't look bad at all from arms reach. You sure it wasn't capping internally at distance 25?
_wb_
2025-07-10 07:15:45
ssimulacra2 was tuned to match a MOS score that was on a scale from 0 to 100, where 10 is "very low quality" and 90 is "very high quality"
CrushedAsian255
Surprisingly that doesn't look bad at all from arms reach. You sure it wasn't capping internally at distance 25?
2025-07-10 07:15:56
-d 25 looks like this
embed
CrushedAsian255 -d 25 looks like this
2025-07-10 07:16:03
https://embed.moe/https://cdn.discordapp.com/attachments/822105409312653333/1392766273724743761/a.jxl?ex=6870ba2c&is=686f68ac&hm=29f55303b5b6aca0831871ff8ae4fde78037c7a5947fff0c5ace1546b54f324b&
CrushedAsian255
2025-07-10 07:16:15
(i'm on dc8438ad so not quite the newest)
2025-07-10 07:16:20
too lazy to rebuild
_wb_
2025-07-10 07:16:20
plus it was constrained to give mathematically lossless a score of 100 and anything lossy a smaller score
VcSaJen
2025-07-10 07:17:35
VP9 have CRF, JXL have d. Those are all competing standards that only confuse people. I agree that percent scale is sometimes inconvenient, but there should be something universally understandable. At least people understand that 99 quality is good, 50 is bad.
_wb_
CrushedAsian255 strange why they didn't just have 0 be lossless and anything higher be worse
2025-07-10 07:17:42
in the AIC-4 call for proposals we are explicitly requesting metrics to use a JND scale, where 0 is lossless, 1 is one just-noticeable-difference, etc.
CrushedAsian255
VcSaJen VP9 have CRF, JXL have d. Those are all competing standards that only confuse people. I agree that percent scale is sometimes inconvenient, but there should be something universally understandable. At least people understand that 99 quality is good, 50 is bad.
2025-07-10 07:18:15
i think the term "CRF" is used for most video codecs, although its interpreted differently for each one
2025-07-10 07:18:48
it's basically quantization but giving more bits to visually important frames
_wb_
VcSaJen VP9 have CRF, JXL have d. Those are all competing standards that only confuse people. I agree that percent scale is sometimes inconvenient, but there should be something universally understandable. At least people understand that 99 quality is good, 50 is bad.
2025-07-10 07:18:51
those scales wildly differ though. The Photoshop percent scale is not at all the same as the libjpeg-turbo scale. Photoshop q30 is a higher quality than libjpeg-turbo q50, iirc.
jonnyawsom3
2025-07-10 07:19:21
Constant Rate Factor doesn't really matter when you only have 1 frame to rate
CrushedAsian255
2025-07-10 07:19:25
bascially every single software has different "quality" scales, and they are not comparable to each other in any way
VcSaJen
CrushedAsian255 i think the term "CRF" is used for most video codecs, although its interpreted differently for each one
2025-07-10 07:19:27
I remember that XVid had something different, but I may be misremembering
CrushedAsian255
VcSaJen I remember that XVid had something different, but I may be misremembering
2025-07-10 07:19:41
XVid I think just had quantization
2025-07-10 07:19:49
or maybe im thinking of mpeg4
_wb_
CrushedAsian255 bascially every single software has different "quality" scales, and they are not comparable to each other in any way
2025-07-10 07:22:21
Yes. And also it's not just a matter of different scales that measure the same thing. The scale does not _actually_ correspond to quality, it corresponds to some combination of encoder parameters that _might_ result in a certain quality, but in reality each encoder setting corresponds to some range of qualities depending on the image content — for more consistent encoders, it's a smaller range, for less consistent ones, it's a larger range.
CrushedAsian255
2025-07-10 07:22:47
so its more of a 'compression amount' factor?
_wb_
2025-07-10 07:23:09
For example, libjpeg-turbo q50 will usually produce a much higher quality image if it's a picture of nature than if it's a screenshot with text on it.
CrushedAsian255
_wb_ For example, libjpeg-turbo q50 will usually produce a much higher quality image if it's a picture of nature than if it's a screenshot with text on it.
2025-07-10 07:23:37
isn't libjpeg-turbo's 'quality' just defining a set of quantisation tables?
2025-07-10 07:23:54
said tables not being based on the image content
_wb_
2025-07-10 07:25:10
Yes. Most encoders work like that. The q setting just defines a set of encoder parameters.
VcSaJen
_wb_ those scales wildly differ though. The Photoshop percent scale is not at all the same as the libjpeg-turbo scale. Photoshop q30 is a higher quality than libjpeg-turbo q50, iirc.
2025-07-10 07:25:16
The curves are all different, but "99.9... is max", "bigger is better" are all common points. For other scales smaller is sometimes better, max can be INF or 0, etc. When you know exactly what the scale is, that custom scale is more convenient, but when you work with multiple formats each with own scale things can become needlessly complicated.
CrushedAsian255
_wb_ Yes. Most encoders work like that. The q setting just defines a set of encoder parameters.
2025-07-10 07:26:18
don't some formats adapt their parameters to image content? like it detects 'oh this is text/non-photographic, i should do XYZ'?
_wb_
VcSaJen The curves are all different, but "99.9... is max", "bigger is better" are all common points. For other scales smaller is sometimes better, max can be INF or 0, etc. When you know exactly what the scale is, that custom scale is more convenient, but when you work with multiple formats each with own scale things can become needlessly complicated.
2025-07-10 07:27:15
The thing is, people get tempted to do things like comparing webp q70 to jpegli q70 and thinking they only need to compare the file sizes since the quality is the same, "70% of the image quality is preserved".
CrushedAsian255 don't some formats adapt their parameters to image content? like it detects 'oh this is text/non-photographic, i should do XYZ'?
2025-07-10 07:28:37
Yes, some encoders are more consistent than others, which means they do more image-content-specific stuff in order to make a given setting produce a more consistent quality. Still, no encoder is perfectly consistent.
Fox Wizard
CrushedAsian255 good old -d 500
2025-07-10 07:28:56
Didn't even know you can somehow go this low <:KekDog:884736660376535040>
2025-07-10 07:29:01
I just get an error below 25
CrushedAsian255
Fox Wizard I just get an error below 25
2025-07-10 07:32:06
you can't by default
2025-07-10 07:32:15
i compiled it with a patch
Fox Wizard
2025-07-10 07:35:47
And just noticed something funny, -e 1 and -e 2 give the exact same output, -e 3 outputs the same image, but at a smaller size, -e 5 changes how the image looks by a lot (much blurrier), but also reduces the file size by a decent amount, -e 6 has almost the same size, but trades the blur for DCT artifact hell, -e 7 is almost the same as -e 6, -e 8 and -e 9 output the same image, but -e 9 is slightly more efficient and -e 10 changes the images a lot again
CrushedAsian255
2025-07-10 07:36:42
i think the ones that are the same but different sizes are due to different entropy coding
A homosapien
Fox Wizard And just noticed something funny, -e 1 and -e 2 give the exact same output, -e 3 outputs the same image, but at a smaller size, -e 5 changes how the image looks by a lot (much blurrier), but also reduces the file size by a decent amount, -e 6 has almost the same size, but trades the blur for DCT artifact hell, -e 7 is almost the same as -e 6, -e 8 and -e 9 output the same image, but -e 9 is slightly more efficient and -e 10 changes the images a lot again
2025-07-10 07:37:17
Effort 1 is relegated to fast lossless, there is no fast lossy (yet) so it just maps to effort 2
CrushedAsian255
Fox Wizard And just noticed something funny, -e 1 and -e 2 give the exact same output, -e 3 outputs the same image, but at a smaller size, -e 5 changes how the image looks by a lot (much blurrier), but also reduces the file size by a decent amount, -e 6 has almost the same size, but trades the blur for DCT artifact hell, -e 7 is almost the same as -e 6, -e 8 and -e 9 output the same image, but -e 9 is slightly more efficient and -e 10 changes the images a lot again
2025-07-10 07:51:19
what effort?
Fox Wizard
2025-07-10 07:51:55
Do you mean distance?
CrushedAsian255
2025-07-10 07:52:08
yeah
Fox Wizard
2025-07-10 07:52:10
Used -d 25
CrushedAsian255
2025-07-10 07:52:16
ah that makes more sense
Fox Wizard
A homosapien Effort 1 is relegated to fast lossless, there is no fast lossy (yet) so it just maps to effort 2
2025-07-10 07:52:28
Ah, didn't know, but makes sense
CrushedAsian255
2025-07-10 07:52:49
i wonder what 'fast lossy' would look like?
Demiurge
2025-07-10 07:57:42
libjxl-tiny
jonnyawsom3
2025-07-10 09:36:00
Yeah, I was surprised it wasn't added alongside fast lossless
CrushedAsian255 don't some formats adapt their parameters to image content? like it detects 'oh this is text/non-photographic, i should do XYZ'?
2025-07-10 09:39:05
If we can get this working https://discord.com/channels/794206087879852103/794206087879852106/1392658621602729984, we'll do some testing of it's accuracy and best settings for various content types. I already have a few ideas, like enabling Weighted based on photographic content, patches or even lossless for non-photo, ect
_wb_
2025-07-15 07:32:44
https://news.ycombinator.com/item?id=44547686
username
_wb_ https://news.ycombinator.com/item?id=44547686
2025-07-15 09:04:42
so many people here who think JPEG XL support in Chrome was killed because of WebP and that Google is a hivemind that it hurts..
Meow
2025-07-16 02:01:45
I don't support "JPEG**-**XL"
CrushedAsian255
Meow I don't support "JPEG**-**XL"
2025-07-16 11:20:21
JPEG = 1998 XL = 40 JPEG - XL= 1958
_wb_
2025-07-16 01:25:58
Wait how is JPEG = 1998?
𝕰𝖒𝖗𝖊
2025-07-16 07:06:56
Wikipedia states 1986 for the first mention and the initial works; and 1991 for the initialization. But I guess it was between 92 to 94 for encoders/decoders running on Unix
CrushedAsian255
_wb_ Wait how is JPEG = 1998?
2025-07-17 01:50:34
1992 +6
2025-07-17 01:51:52
I don’t remember why I added 6 though
Meow I don't support "JPEG**-**XL"
2025-07-17 01:52:03
JPEG = 1992 XL = 40 JPEG - XL= 1952
2025-07-17 01:52:29
(Wikipedia says 1992 is the introduction )
jonnyawsom3
2025-07-17 11:18:59
I'm on a train right now and out until next week, so I'm calling on fellow nerds to post benchmarks https://www.reddit.com/r/AV1/s/VtA9K5a6AI
Demiurge
username so many people here who think JPEG XL support in Chrome was killed because of WebP and that Google is a hivemind that it hurts..
2025-07-18 08:54:41
To be fair it WAS the webp guy. That's part of why his rationale comes off as so outstandingly outrageous.
2025-07-18 08:55:53
He forces his own shitty webp format through despite objection but now wants to obstruct jxl
novomesk
2025-07-18 06:13:24
https://www.youtube.com/watch?v=tvQYKMPSfSk
Quackdoc
2025-07-30 09:55:24
cosmic-files now uses jxl-oxide for thumbnails, I just need to figure out how to get the preview working, I think its an iced thing
jonnyawsom3
2025-08-05 08:21:26
https://developer.mozilla.org/en-US/blog/image-formats-pixels-graphics/
2025-08-05 08:24:52
Gets mentioned a few times, including being listed as a 'popular format'
Meow
2025-08-05 11:28:11
Why would WebP's compression type "hybrid" in contrast to AVIF and JPEG XL's "lossy or lossless"?
spider-mario
2025-08-05 11:30:10
maybe they mean because of WebP’s “near-lossless” mode?
Exorcist
Meow Why would WebP's compression type "hybrid" in contrast to AVIF and JPEG XL's "lossy or lossless"?
2025-08-05 11:41:58
Maybe author mean the "lossy YUV + lossless alpha" mode in WebP
2025-08-05 11:42:07
I have not read the JXL spec yet
jonnyawsom3
Meow Why would WebP's compression type "hybrid" in contrast to AVIF and JPEG XL's "lossy or lossless"?
2025-08-05 11:46:02
WebP is pre-existing VP8 and Jyrki's custom Lossless mode AVIF only has a Lossy mode, and just brute forces it into Lossless basically JPEG XL can do Lossy and Lossless just with Modular mode (And Lossy with VarDCT but they might not know the difference)
Jarek Duda
2025-08-08 07:45:01
https://developer.mozilla.org/en-US/blog/image-formats-pixels-graphics/ fresh from Mozilla, treating JPEG XL quite mainstream ... how is the Firefox adoption?
Quackdoc
2025-08-08 08:02:43
still waiting on the jxl-rs
2025-08-08 08:02:47
or whatever it was called
jonnyawsom3
https://developer.mozilla.org/en-US/blog/image-formats-pixels-graphics/
2025-08-08 08:04:35
Same as always, it's the most we've heard from them this year I think. jxl-rs is nearly conformant, then it'll be optimization before hopeful implementation in Firefox
HCrikki
2025-08-08 08:06:16
is conformance chart up to date for jxl-rs ?
spider-mario
2025-08-08 08:07:21
which one?
_wb_
2025-08-08 08:17:21
this one I suppose? https://libjxl.github.io/bench/
HCrikki
2025-08-08 09:16:12
'nearly conformant' suggested theres secret progress that doesnt automatically updates that
jonnyawsom3
2025-08-08 09:19:04
Well, it decodes images and doesn't output a black box, so I'd call that progress. Just got some bugs to fix to get it within spec... And not crashing on certain images 😅
spider-mario
_wb_ this one I suppose? https://libjxl.github.io/bench/
2025-08-08 03:06:54
ah, right, this is not up-to-date at all
2025-08-08 03:06:59
it’s all green now
2025-08-08 03:07:10
except png spot
2025-08-08 03:07:42
because we refuse to even try to write 6 channels to a png
jonnyawsom3
2025-08-10 01:41:44
Meow
2025-08-27 08:58:16
https://boards.4chan.org/g/thread/106363363/pornhub-now-serving-jpegxl-thumbnails
CrushedAsian255
Meow https://boards.4chan.org/g/thread/106363363/pornhub-now-serving-jpegxl-thumbnails
2025-08-30 01:52:58
finally a good use case for jpeg xl /j
spider-mario
2025-09-01 02:26:57
https://www.dpreview.com/forums/post/68417283
Meow
2025-09-01 02:39:19
> The lossless compression modes are a different matter, and JPEG-XL is amazingly worse than WebP lossless... but it does support up to 24-bit (or 32-bit floating point).
RaveSteel
2025-09-01 02:49:15
At another point in the thread he complains about JXL being not as predictable as JPEG in terms of colour desaturation
NovaZone
2025-09-01 03:23:44
are they wrong about color desat tho? xD
RaveSteel
2025-09-01 03:39:44
no
2025-09-01 03:40:00
Although it improved
NovaZone
2025-09-01 03:40:39
still waiting for colors in general to be correct
2025-09-01 03:41:00
not 8 ish off
2025-09-01 03:41:30
8, 255, 0
RaveSteel
2025-09-01 03:41:52
Always use lossless, then colours are always correct [galaxy_brain](https://cdn.discordapp.com/emojis/657649371038482482.webp?size=64&name=galaxy_brain) (except for the 16 bit EXR to JXL issue still existing)
NovaZone
2025-09-01 03:42:32
noo we cant just abandon lossy xD
RaveSteel
2025-09-01 03:43:21
I would, but other people want lossy😔
jonnyawsom3
2025-09-01 04:12:38
They also say that JPEG quality 98 is perfect but 97 is unusable, I think at that point they're looking at hashes instead of the actual image
2025-09-01 04:15:05
They are right though, XYB is causing quite severe desaturation in high contrast areas, and lossless occasionally looses due to pallete sorting
RaveSteel
2025-09-01 07:40:28
https://www.phoronix.com/news/GNOME-Glycin-Faster-JPEG-XL
Meow
2025-09-02 02:03:01
STOP THOSE `-` craps!!!
Lilli
2025-09-02 08:08:02
I thought you were talking about em dashes but you're saying we shouldn't write JPEG-XL but JPEG XL ?
_wb_
2025-09-02 08:38:34
The desaturation in high contrast areas is not problematic imo if you can only see it when zooming in until pixels are 1 cm^2, but I do think it's an issue if it is still visible at 1:1 scale — as can be the case with textured saturated yellows.
2025-09-02 08:45:08
Also: just call it JXL. The official name is JPEG XL but that name was not chosen by the people who designed the codec, it was already decided when the call for proposals was launched. I would have chosen a different name myself. Having a space in a name is inconvient for many reasons; both the "JPEG" and the "XL" are confusing because it's not the same format as the old JPEG and it has nothing to do with the t-shirt size XL. In official communication we can only use the official name, JPEG XL, but informally, as a de facto name, I very much prefer JXL (or jxl) which also coincides with the IANA media type (`image/jxl`) and the conventional filename extension (`.jxl`).
Demiurge
_wb_ The desaturation in high contrast areas is not problematic imo if you can only see it when zooming in until pixels are 1 cm^2, but I do think it's an issue if it is still visible at 1:1 scale — as can be the case with textured saturated yellows.
2025-09-02 09:01:14
It's definitely visible at 1:1 ratio and from a distance too. And I'm pretty sure it has to do with nonlinear gamma-space rounding of chroma values.
2025-09-02 09:05:24
When you downscale an image, which is not very different from how the jxl encoding process works, doing it in gamma-space will result in values rounded closer to 0 compared to doing it in linear-encoded values.
2025-09-02 09:06:52
When you round the XYB chroma values and shift them closer to zero, you get major desaturation.
2025-09-02 09:14:14
In linear space, halfway between two quanta is halfway, linear. In gamma space, halfway between two quanta is LESS than halfway after the inverse gamma transformation.
2025-09-02 09:15:33
That's the reason it shifts everything closer to zero.
jonnyawsom3
2025-09-02 10:38:04
Specifically the XYB B channel is changing by 1 or 2, which then translates to a difference of 10-20 in RGB, making reds and yellows whiter due to more blue
ignaloidas
2025-09-03 08:05:43
I feel like this is maybe because of actually storing XYB' instead of XYB, which is somewhat against the fact that blue perceptually has less spatial resolution because by converting it into B' you're mixing it with colors that *do* have higher spatial resolution
Demiurge
2025-09-05 08:54:54
That's a good point.
2025-09-05 08:57:14
Maybe blue quantization is not sufficiently separated from the other colors.
Squid Baron
2025-09-20 08:38:41
HN frontpage: https://news.ycombinator.com/item?id=45316833
Meow
2025-09-21 03:21:53
Chrome Team: who's Philips?
spider-mario
2025-09-21 07:39:31
https://news.ycombinator.com/item?id=45318306 this person seems to think they’re enlightened and have the only objective perception of the situation; meanwhile they also think Chrome has anything to do with the integration of jxl into Firefox
2025-09-21 07:43:09
> If you get _any_ FAANG engineer involved in this mess a beer || truth serum, they'll have 0 idea why this has so much mindshare guess we better tell Apple then
2025-09-21 07:43:37
that comment is pretty much textbook [Bulverism](https://en.wikipedia.org/wiki/Bulverism)
jonnyawsom3
2025-09-21 07:44:22
No doubt they wouldn't take a "we don't work for chrome" comment well
HCrikki
2025-09-21 12:48:49
Lossless reversible trancoding to jxl alone has insane implications for anything web based
2025-09-21 12:50:43
As long as its properly done, its way faster than realtime and consumes almost no ressources. Energy cost for datacenters and compute shot through the roof in the last few years
2025-09-21 12:55:49
My ghetto ryzen can transcode more than 20 thousands photo class images an hour without choking. As suggested by phoronix benchmarks, a server should easily handle 50x that
jonnyawsom3
2025-09-21 01:01:06
Now that we figured out the fast lossless regression too, lossless content can be transcoded by the gigapixel per second to smaller than optimised PNG
Exorcist
2025-09-21 01:12:39
> refulgentis 2 days ago | parent | context | prev | next [–] | on: Meta Ray-Ban Display > I worked at Google on watches some distant time ago, these floated around.
2025-09-21 01:13:57
He is Googler, JXL author is Googler, SVT-AV1-PSY (now become AOM) author is Googler <:FeelsAmazingMan:808826295768449054>
2025-09-21 01:18:22
> If you get _any_ FAANG engineer involved in this mess a beer || truth serum "argument from authority" don't work for here
Meow
2025-09-21 01:57:55
Google's biggest enemy is Google
Exorcist
2025-09-21 02:13:40
I don't think this is workplace politics the reason is simple: AVIF can save more money pure 🤑
2025-09-21 02:14:48
YouTube on Android enforce AV1 (use software decoder if no hardware)
Quackdoc
Exorcist YouTube on Android enforce AV1 (use software decoder if no hardware)
2025-09-21 02:29:23
only in some cases, it still mostly prefers vp9 for me
jonnyawsom3
2025-09-21 02:47:36
Someone at Cloudinary just commented on the old Chromium issue https://issues.chromium.org/issues/40168998#comment489
Foxtrot
2025-09-21 03:56:07
I bet nobody from Chromium will read it. They already forgot any JXL exists.
2025-09-21 03:57:47
I mean, the status is Won't fix (Obsolete), so basically closed. Do comments even ping the people in CC?
jonnyawsom3
2025-09-21 04:01:56
They've certainly been pinging me
Foxtrot
2025-09-21 04:02:58
Oh, didnt expect that 🙂
2025-09-21 04:13:06
btw, interop https://github.com/web-platform-tests/interop/issues/994
Exorcist
2025-09-21 04:15:02
beat a dead horse
jonnyawsom3
They've certainly been pinging me
2025-09-21 04:15:50
Foxtrot
2025-09-21 04:16:00
maybe the horse will come back to life from all the beating 😄
Meow
Foxtrot btw, interop https://github.com/web-platform-tests/interop/issues/994
2025-09-22 02:14:59
Another interflop for JXL
RaveSteel
2025-09-27 02:22:53
https://www.reddit.com/r/Android/comments/1nngrep/upvote_this_issue_to_get_jpeg_xl_back_into_chrome/
HCrikki
2025-09-27 02:27:24
silent upvoting has its limits, itd be a lot more helpful imo for folks to mentions the very tangible benefits they or their projects stand to gain from interoperability for jxl
2025-09-27 02:29:28
for example, reversible lossless transcoding from jpg to jxl consumes almost no ressources, is quasi-instant and completes a migration like 300x faster than to another format, yet still guarantees the resulting jxl will be bother smaller and pixel perfect identical to the source image - no multimedia format accomplishes that, either they arbitrarily sacrifice visual quality without guaranteed smaller filesize (need to sacrifice *more* quality until you hit the target filesize), or for pixel identical lossless the final filesize becomes *several multiples* larger than the original jpg
2025-09-27 02:30:02
people forgot server and compute costs shot through the roof in the last few years
2025-09-27 02:37:01
app makers for mobile and desktop also would benefit from progressive load showing images as soon as just 10% of the image is loaded. gotta tempt them with instantly displayed ads that dont slow a site loading, potentially giving apps that serve themselves jxls an edge over the browser experience - lighter snappy apps loading an ad-enabled experience faster than an adblocked browser
jonnyawsom3
2025-09-27 04:02:05
*0.2% but yeah
Exorcist
Exorcist beat a dead horse
2025-09-27 08:35:33
again
Jarek Duda
2025-10-05 01:52:24
https://www.reddit.com/r/AV1/comments/1nv8oq3/so_many_details_lost_after_converting_jpeg_to/
jonnyawsom3
2025-10-05 02:00:41
A very rough test, but proves we have the defaults set properly for cjxl. Still need to try and get the v0.8 quality back, and fix the desaturation
TheBigBadBoy - 𝙸𝚛
Jarek Duda https://www.reddit.com/r/AV1/comments/1nv8oq3/so_many_details_lost_after_converting_jpeg_to/
2025-10-05 06:06:25
> meanwhile file size reduced more than 100% wtf does that mean? perhaps I'm high, idk, but if the file size difference is 100% then the output is 0 Byte...
2025-10-05 06:07:05
nevermind someone else said it in the comments
2025-10-05 06:07:12
> It's inverted. OP means the original is 100% larger. Similarly, "reduced 2000%" means 95% reduction
Exorcist
2025-10-06 03:13:40
It is not surprise that a people can't correctly math also can't correctly use encoder
Kleis Auke
2025-10-07 06:14:19
https://mastodon.social/@jaffathecake/115333326583200558
username
Kleis Auke https://mastodon.social/@jaffathecake/115333326583200558
2025-10-07 06:21:03
I don't have an account so I can't comment on that site but for me it's that fact that JPEG XL can actually function as a long term useful image format outside of the web unlike WebP and AVIF which both have multiple downsides compared to prevoius image formats like PNG and JPEG
2025-10-07 06:22:36
also the progressive rendering/decoding because holy is it sad that with AVIF you can't even see a single pixel until 100% of the image is done downloading
jonnyawsom3
2025-10-07 06:23:09
It's futureproof and versatile, already breaking limits of old formats with significant features not even being utilized in the encoder yet. People keep mentioning progressive, but I think most have only seen the 1:8 progressive step/demos. If they knew it works all the way down to 0.2% and lower I think they'd be even more amazed
Quackdoc
2025-10-07 06:23:35
lossless compression of PNG and jpeg is dope is all for me lmao
username
2025-10-07 06:24:44
the person who made that post on mastodon seems to be involved with Firefox and the web in some way and most of the current comments on that post are pretty unhelpful so if any of you have an account I would recommend commenting
Quackdoc
2025-10-07 07:45:02
nope lol, I deleted my fediverse account its trash lmao
HCrikki
2025-10-07 09:22:24
for me, reversible lossless transcoding of jpegs works insanely fast and consumes almost no ressources
2025-10-07 09:25:52
super important for servers and web services, especially after the cost of compute and cloud significantly increased
2025-10-07 09:26:53
the savings this generates can mean the difference between operating at a deficit and your operations being profitable *despite* plateauing revenue and rising costs
2025-10-07 09:30:09
mobile and desktop apps in particular can become run even snappier and consume less bandwidth than an adblock-enabled experience in your favorite browser, even if the apps included ads - isnt 'app works better than the site' ideal for serving your own web service's content to your own apps ?
2025-10-07 09:47:14
jxl can *losslessly* converts not just jpg but also png and gif, with guaranteed smaller filesize (barring special cases or unoptimal encoding workflow). reportedly more than 80% of all webpages feature png and jpgs (the offline world features like hundreds times more images than the web)
2025-10-07 09:58:28
for websites though? its the fact its always *progressive* and would simplify web apps since webdevs would no longer need to generate fake blurry-looking progressive images to use as placeholders until the whole image finishes loading
2025-10-07 10:00:35
afaik avif at some point tried cheating at progressiveness by adding a thumbnail-sized small version as the first frame (making images bigger)
Siegfried
Kleis Auke https://jcgt.org/published/0014/01/04/
2025-10-08 07:47:16
Hi, I am one of the authors of this paper, sorry for my very late answer. I hope I can answer some of your questions regarding the technical choices. While the paper was published in 2025, we started the work in 2022 and it was submitted in January 2023. So, my memory is not ultra fresh on some implementation choices we made. The experiments and companion source code of the paper was done back then on libjxl v0.7 (commit f95da13). With this version, we had an issue with one of the files making libjxl crash (related to this issue https://github.com/libjxl/libjxl/issues/2046). When the paper was accepted, we’ve check libjxl updates since the submission and noticed the bug was fixed on v0.11.1 (commit 794a5dc) so updated the results and removed the mention of this bug in the paper. That said, we indeed were not aware of the introduced ability to specify compression parameters on a per framebuffer level. I may recall we tried to specify such parameter on a per layer basis but the parameter was ignored for subimages, maybe it was another API. Could be wrong there.
2025-10-08 07:47:21
Now, regarding the way the file is stored, it is not a subimage per spectral channel like the spectral OpenEXR approach meant to be lossless (https://jcgt.org/published/0010/03/01/). Instead, we use moments to represent the spectral signal per pixel and store those moments. 0th coefficient representing the average of the signal, it is similar to luminance assuming we’re working roughly in the visible domain and assuming E whitepoint. The remaining coefficients are similar to chroma which allow us to use a similar strategy as traditional RGB images by downsampling the subimages representing those coefficients to a lower resolution. This approach also ensures positive values and downgrading the quality of higher frequency components which would not be possible by storing each individual spectral channel. And yes, we’ve reached out but that was a long time ago, the paper took quite a while to be published : https://discord.com/channels/794206087879852103/848189884614705192/1052286164373086218 . Thanks a lot for your answers and for the development of this great format! If I’ve missed questions regarding our work, let me know, I’ll try my best to answer those and keep an eye on the channel 😉
username
Kleis Auke https://mastodon.social/@jaffathecake/115333326583200558
2025-10-08 12:23:40
oh huh it seems like [this](https://github.com/web-platform-tests/interop/issues/994#issuecomment-3380596629) is where the replies ended up getting used
HCrikki
2025-10-08 02:02:54
ms and apple should be reminded to voice their support. even if not in interop, at least in public blogs
2025-10-08 02:03:28
the makers of esoteric browsers, various webviews and browser-based desktop apps depend on the support getting upstreamed and they dont seem represented at all even though much of their sustainability depends on things getting upstreamed instead of added in forks with multiple non-interoperable, incomplete or inefficient implementations
2025-10-08 02:05:45
iinm ms made public their extension just days after last year's rejection in addition to someone's commentary about lack of respect for the concept of voting (ie 'secret vetos' overriding votes entirely) , which gives an idea where they stand
2025-10-08 02:14:31
napkin math: more than 80% of all mac devices that succesfully connected to app store at least once in the last year are jxl-enabled out of the box or jxl-capable (safari, macos, ipados and their apps). in the us/canada/japan, thats almost 40% of all smartphones in active use there
2025-10-08 02:16:02
web apps focusing on mac should work without workarounds on other browsers in some capacity, otherwise itd make little sense for multiple browsers to be allowed on ios if theyre not using jxl-enabled webkit (serious breakage of interoperability requiring costly workarounds *on the same platform*)
_wb_
username oh huh it seems like [this](https://github.com/web-platform-tests/interop/issues/994#issuecomment-3380596629) is where the replies ended up getting used
2025-10-08 04:03:49
I agree with <@710762823986446367>'s sentiment that progressive rendering is an important thing to include in jxl support in browsers, and Safari's support is indeed incomplete in that sense. Probably supporting animated jxl should be a higher priority for Safari though. Having a WPT for progressive decoding would be nice (not just for jxl but also for other formats that allow it), and it could also be a step towards refining LCP to take progressive loading into account, which is something that has been stuck for years now, see https://github.com/w3c/largest-contentful-paint/issues/71
Demiurge
Siegfried Hi, I am one of the authors of this paper, sorry for my very late answer. I hope I can answer some of your questions regarding the technical choices. While the paper was published in 2025, we started the work in 2022 and it was submitted in January 2023. So, my memory is not ultra fresh on some implementation choices we made. The experiments and companion source code of the paper was done back then on libjxl v0.7 (commit f95da13). With this version, we had an issue with one of the files making libjxl crash (related to this issue https://github.com/libjxl/libjxl/issues/2046). When the paper was accepted, we’ve check libjxl updates since the submission and noticed the bug was fixed on v0.11.1 (commit 794a5dc) so updated the results and removed the mention of this bug in the paper. That said, we indeed were not aware of the introduced ability to specify compression parameters on a per framebuffer level. I may recall we tried to specify such parameter on a per layer basis but the parameter was ignored for subimages, maybe it was another API. Could be wrong there.
2025-10-09 02:30:20
Your paper on spectral encoding is cool. I hope you can work something out with one of the developers here, if you are still interested in storing spectral images in a single JXL file. JXL supports a lot of channels so you should theoretically be able to have 3 channels for a regular RGB preview, and however many extra channels for the different bands.
Siegfried
Demiurge Your paper on spectral encoding is cool. I hope you can work something out with one of the developers here, if you are still interested in storing spectral images in a single JXL file. JXL supports a lot of channels so you should theoretically be able to have 3 channels for a regular RGB preview, and however many extra channels for the different bands.
2025-10-09 10:46:17
Thanks! Our code was designed to work with more channels but we restricted it to 1 channel per file to get a better compression ration: at the time we've asked, it wasn't possible to set a specific frame distance on a per-channel basis. If libjxl supports this now, I'll be happy to give it a try. It shall be one define to change (JXL_MAX_FRAMEBUFFERS) on our end : https://github.com/afichet/spectral-compress/blob/master/lib/common/JXLImage.cpp#L260
paperboyo
_wb_ I agree with <@710762823986446367>'s sentiment that progressive rendering is an important thing to include in jxl support in browsers, and Safari's support is indeed incomplete in that sense. Probably supporting animated jxl should be a higher priority for Safari though. Having a WPT for progressive decoding would be nice (not just for jxl but also for other formats that allow it), and it could also be a step towards refining LCP to take progressive loading into account, which is something that has been stuck for years now, see https://github.com/w3c/largest-contentful-paint/issues/71
2025-10-09 10:48:46
FWIW, my web-centric 2gr would be: encoder consistency (better than even `tune=iq`?) and progressive (more a promise than a sad Safari practice) for the bigguns. But, even though they go way above my understanding, I would never make a mistake of dismissing Kornel‘s views on progressive in that thread. 🤔 Not having experimented too much, I would have thought ani AVIF the only sensible animated image format worth looking into. But even so, given utter lack of authoring support and knowing that expecting creators to care for manual optimisation is sadistic (they need fire-and-forget), currently leaning towards video format(s) for these instead…
Demiurge
Siegfried Thanks! Our code was designed to work with more channels but we restricted it to 1 channel per file to get a better compression ration: at the time we've asked, it wasn't possible to set a specific frame distance on a per-channel basis. If libjxl supports this now, I'll be happy to give it a try. It shall be one define to change (JXL_MAX_FRAMEBUFFERS) on our end : https://github.com/afichet/spectral-compress/blob/master/lib/common/JXLImage.cpp#L260
2025-10-10 02:15:07
You will have to work it out with one of the maintainers of libjxl. They might need to make adjustments to the API to make it easier for you to apply it to your use case. It absolutely makes the most sense to store all of the channels in a single file, with 3 channels for the RGB preview, and the extra sub-band channels might even be able to take advantage of inter-channel redundancy.
jonnyawsom3
2025-10-10 07:56:51
I believe this may be the relevant issue, opened by an Intel employee no less https://github.com/libjxl/libjxl/issues/1707
2025-10-10 07:59:52
Though, Jon did say this https://discord.com/channels/794206087879852103/822105409312653333/1346803972576641124 so maybe it already works
Siegfried Thanks! Our code was designed to work with more channels but we restricted it to 1 channel per file to get a better compression ration: at the time we've asked, it wasn't possible to set a specific frame distance on a per-channel basis. If libjxl supports this now, I'll be happy to give it a try. It shall be one define to change (JXL_MAX_FRAMEBUFFERS) on our end : https://github.com/afichet/spectral-compress/blob/master/lib/common/JXLImage.cpp#L260
2025-10-10 08:08:11
I'm not sure if it fulfils your requirements, but this was merged Febuary 10th 2023 https://github.com/libjxl/libjxl/pull/2117
2025-10-10 08:12:41
I'd also recommend setting `JXL_ENC_FRAME_SETTING_MODULAR_NB_PREV_CHANNELS` to 1 It's shown good results on multispectral images before, 10% smaller at effort 2 https://discord.com/channels/794206087879852103/794206087879852106/1246805607877705799 Speed and density scales with higher values by allowing more channels to reference each other, but 1 has a negligible speed cost
Siegfried
I believe this may be the relevant issue, opened by an Intel employee no less https://github.com/libjxl/libjxl/issues/1707
2025-10-10 09:34:09
It's me that opened this issue 😉
jonnyawsom3
2025-10-10 09:41:10
Ah right haha
Demiurge
2025-10-10 09:43:10
lol
2025-10-10 09:44:46
If you need any help with a second attempt of getting spectral images all in one file, I would reach out to Jon if you run into any problems. I could be wrong, but I think he likes helping out the community with stuff like that.
2025-10-10 09:47:48
Stuff like this is exciting, <@597495878764331085>. Novel yet practical applications of image coding.
username
2025-10-16 01:32:16
https://jakearchibald.com/2025/present-and-future-of-progressive-image-rendering/#jpeg-xl
jonnyawsom3
2025-10-16 01:43:56
Somewhat of a follow-up to <https://github.com/libjxl/jxl-rs/issues/387#issuecomment-3385143027> and <https://github.com/web-platform-tests/interop/issues/994#issuecomment-3406845567>
username
2025-10-16 01:51:57
ill say that in practice (for context my internet is slow but pretty stable) I've noticed that when loading web pages in the wild progressive JPEGs cause the least amount of frustration and friction for me when loading large pages as I'm able to visually tell what each image is attempting to show after only a very short time unlike non-progressive images in which I can only see around half of what each image is and I need to sit there waiting for the other halfs to load in to tell what I'm looking at
2025-10-16 01:53:25
progressive also makes cases of "all of the images on the site are *almost* done loading" nicer since It pretty much looks like everything is finished loading rather then having bottom bits of the images cut off
jonnyawsom3
username https://jakearchibald.com/2025/present-and-future-of-progressive-image-rendering/#jpeg-xl
2025-10-16 02:00:22
> I was also surprised to see that, in Safari, JPEG XL takes 150% longer (as in 2.5x) to decode vs an equivalent AVIF. That's 17ms longer on my M4 Pro. Apple hardware tends to be high-end, but this could still be significant. This isn't related to progressive rendering; the decoder is just slow. There's some suggestion that the Apple implementation is running on a single core, so maybe there's room for improvement. > I thought that "fast decoding" was one of the selling points of JPEG XL over AVIF, but now I'm not so sure. The complaints about decode speed are a shame, since it's equal or slightly faster than AVIF decoding on my system with the CLI tools, so it's likely just implementation in Safari slowing it down. > It could use some smoothing, like we saw with the JPEG progressive render in Firefox/Chrome. It was actually part of the Chrome implantation back in the day, using the non-separable upsampling while oxide just does NN IIRC. > Due to its high resolution (1598x1753), and sharp detail, it's 155 kB, even using AVIF. > Thanks to modern image formats (AVIF in this case), the above image is 56.4 kB. That's pretty incredible for a more-than-HD image. The fox image is much larger because of its sharp details, but that isn't true for most images. This means that, for many images, there's little benefit to progressive rendering. Most of the post seems to be based around the assumption that all images can be compressed to 200KB and will only get smaller, so progressive doesn't matter since it's either 10% of the file or the full image is downloaded in 20ms anyway. If you look at a single lossless JXL with progressive, you'd realise we can do a preview at 0.03% and anything in the real world is usually in the megabytes, not kilobytes. Not everyone has gigabit, not everyone has a CDN and not everyone wants to upload low quality versions of their images...
2025-10-16 02:00:36
Damnit it's 3am again
username
2025-10-16 02:03:12
could maybe re-read it when you wake up lol I think some of your arguments might be based on things outside of that blog post though maybe it's just the lack of sleep hitting me as well
jonnyawsom3
2025-10-16 02:04:29
I'll add quotes, I specifically made sure to only critique what's in that blog
HCrikki
2025-10-16 02:07:20
wasnt the *additional* progressivity from progressive dc 1-4 massively improved in 0.12 nightly and not an issue with current code ? especially for lossless outputs
jonnyawsom3
2025-10-16 02:13:16
I made progressive_dc part of the -p flag, and we fixed progressive lossless so it's half the size
username
I'll add quotes, I specifically made sure to only critique what's in that blog
2025-10-16 02:16:19
either way yeah for me personally the comments about speed give me this weird bad feeling. like I know the author doesn't have any bad intentions and is just comparing the current state of things based on personal testing and *maybe* the results might just be due to some bad compiler interactions with libjxl but at the same time I get this weird fear of like some sorta ¿cascading death? I'm really tired (didn't get enough sleep and have been awake way too long plus a headache on top) but ill try to sorta lay out what I mean: >Current decoder implementations show AVIF decoding faster then JXL due to AV1 decoders having more man power put behind them along with just existing for a longer period of time rather then anything format/spec wise holding it back. >People end up calling JXL slow and AVIF fast and use it as a reason to not support JXL >JXL decoders continue to be outpaced speed wise due to lack of adoption causing lack of optimizations. >Cycle continues and JXL dies due to not being considered fast enough to adopt through almost no fault of it's own.
2025-10-16 02:18:58
afaik speed was not a considered factor for AVIF being added to browsers at the time it was just sorta a "yeah this is fine"
2025-10-16 02:30:21
I would have to checkup on the timeline for that though since idk the release distance between AV1 and AVIF
HCrikki
2025-10-16 03:02:53
for images, av1 implementations and their touted manpower are pointless. almost all focus on only lossy since av1 pretty much requires discarding as much data as possible before its compression algos can work without failing (lossless shows why)
2025-10-16 03:03:59
on blog, i cant believe people would really want a transitional placeholder image of such ludicrously poor quality. even on slow networks when jpg was all we had it wouldve been unacceptable
_wb_
2025-10-16 06:27:44
Inherently, decode speed of jxl and avif, at least in the vardct case, should be more or less similar. There isn't really anything in one or the other that causes a substantial difference in the computational complexity of decoding. But of course implementations can vary, e.g. do they decode single-core or use more threads, are they specializing any fast paths for common special cases, etc etc. These type of things tend to make a bigger difference than the inherent computational complexity of the decode process.
HCrikki
2025-10-16 06:45:21
does use of high encoding efforts significantly affect decoding (in both libjxl and its integrations)? i recall e10 and e11 being a consistent mention in exchanges about slown decoding, even when there was no justification to use higher than e7
A homosapien
HCrikki does use of high encoding efforts significantly affect decoding (in both libjxl and its integrations)? i recall e10 and e11 being a consistent mention in exchanges about slown decoding, even when there was no justification to use higher than e7
2025-10-16 08:20:58
Only lossless is affected by higher efforts when it comes to decoding speed. I have some old benchmark numbers here showing that VarDCT is mostly unaffected from efforts 1-10.
2025-10-16 08:23:06
lonjil
2025-10-16 08:24:49
Isn't AVIF decoding faster and faster at lower and lower qualities?
A homosapien
2025-10-16 01:14:59
Yeah, higher qualities decode slower, lower qualities decode faster.
jonnyawsom3
2025-10-16 01:21:06
*technically* JXL decodes a bit faster too if you output to a lower bitdepth, but the difference between 32f and 8int is only around 10% at most
2025-10-16 04:11:18
I really wish they cared about lossless at all... Sapien was part of our overhaul for progressive lossless, and even he was impressed at how well it worked last night
HCrikki
2025-10-17 05:58:08
about progressive decode, waterfox (available for desktops *and* android with jxl out of the box) supposedly supports full progressive decoding for jxl. i wonder if it does better than what jake tested - firefox ignored for long the patches improving the integration
username
HCrikki about progressive decode, waterfox (available for desktops *and* android with jxl out of the box) supposedly supports full progressive decoding for jxl. i wonder if it does better than what jake tested - firefox ignored for long the patches improving the integration
2025-10-17 06:02:13
it's the same as in Thorium/Chromium except it doesn't ignore images with alpha. that's it
jonnyawsom3
2025-10-17 09:33:25
They all use libjxl, which disabled the progressive_dc decoding for performance years ago
Jake Archibald
2025-10-17 03:51:02
Yeah, whereas imo progressive_dc is the most important part, else it performs (in terms of getting something recognisable on screen quickly) worse than JPEG
2025-10-17 03:53:16
<@238552565619359744> in terms of lossless… I'm glad it's something JXL takes seriously (it's shit in AVIF), but I don't see much of a web use case for it. Maybe cases where you're downloading an image, but in that case progressive isn't necessary. The question around decoding performance becomes different too, as you're less likely to decode it in the browser
2025-10-17 03:56:36
Someone on the browser side did some benchmarks on libavif and libjxl more directly and found that the results I see in Safari are representative, even with multithreading involved. However, as you've said, if you test higher quality then JXL can be faster to decode
lonjil
2025-10-17 03:59:49
As a purveyor of digital art, a lot of which compresses quite well losslessly, I wish it was more important for the web 😔
2025-10-17 04:00:34
(for similar reasons, I care more about the upper quartile of typical jpeg qualities found on the web, and equivalent levels of quality in jxl and avif)
Jake Archibald
2025-10-17 04:09:14
Yeah, if I'm downloading an image to print, or use in design work, I want lossless or as close as possible. But in those cases I'm hitting a download button rather than seeing it in page
jonnyawsom3
Jake Archibald Someone on the browser side did some benchmarks on libavif and libjxl more directly and found that the results I see in Safari are representative, even with multithreading involved. However, as you've said, if you test higher quality then JXL can be faster to decode
2025-10-17 04:11:19
The performance results I'm always wary about, since I was using your fox JXL and AVIF, getting similar speeds for each (28ms and 30ms respectively) libjxl has some *issues* with certain compilers, meaning even just using Clang gives a 25% speed boost for decoding
Quackdoc
Jake Archibald <@238552565619359744> in terms of lossless… I'm glad it's something JXL takes seriously (it's shit in AVIF), but I don't see much of a web use case for it. Maybe cases where you're downloading an image, but in that case progressive isn't necessary. The question around decoding performance becomes different too, as you're less likely to decode it in the browser
2025-10-17 04:11:23
for galleries its fairly important to have lossless without needing to download images
2025-10-17 04:11:43
especially for a paid experience
Jake Archibald
2025-10-17 04:12:06
That's fair
2025-10-17 04:12:29
Although that's a fairly niche experience compared to most of the web
jonnyawsom3
2025-10-17 04:12:33
I also just did some minor testing, and v0.6 of libjxl had LQIP decoding while v0.7 lost it. Decode speed also increases the lower the preview size you decode, along with having the smoothing you requested in the blog
2025-10-17 04:12:53
2025-10-17 04:13:50
I'm going to keep looking for the commit that disabled it, hopefully seeing if it's not too hard to re-enable again
Quackdoc
Jake Archibald Although that's a fairly niche experience compared to most of the web
2025-10-17 04:14:18
hmmm possibly, but its still high traffic stuff
Jake Archibald
2025-10-17 04:14:19
Fwiw I was testing the decoding speed for the case where the whole file is available, to see if progressive has an overhead when it isn't needed
2025-10-17 04:15:26
It's harder to measure the cost of doing actual progressive renders. That's something browsers will need to make trade-offs around
jonnyawsom3
2025-10-17 04:22:23
Thankfully djxl has the `-s` flag for decoding lower resolutions (Though only 1:8 works because of LQIP) Full decode ```wintime -- djxl Test.jxl nul --output_format ppm --num_threads 8 --num_reps 10 JPEG XL decoder v0.12.0 6efa0f5a [_AVX2_] {Clang 20.1.8} Decoded to pixels. 7680 x 4320, geomean: 138.672 MP/s [126.520, 147.125], 10 reps, 8 threads.``` 1:8 Decode ```wintime -- djxl Test.jxl nul --output_format ppm --num_threads 8 --num_reps 10 JPEG XL decoder v0.12.0 6efa0f5a [_AVX2_] {Clang 20.1.8} Decoded to pixels. 7680 x 4320, geomean: 231.166 MP/s [217.915, 245.112], 10 reps, 8 threads.```
2025-10-17 04:22:46
(Yes it's a big image, it's the first one I had on hand)
Jake Archibald
2025-10-17 04:23:42
I guess what I'm saying is… it's fine that progressive rendering takes extra time, and it'd be unfair to compare AVIF and JXL on that, because JXL would probably take a lot longer, but it delivers more value
2025-10-17 04:24:09
Browsers need to figure out when it's worth spending that extra time
jonnyawsom3
2025-10-17 04:25:07
Yeah, at the end of the day a lot of the images in circulation won't even be encoded progressively in the first place, but where it matters it can matter a whole lot
Jake Archibald
2025-10-17 04:25:46
I hope that any image intended for display on a web page would have progressive_dc
lonjil
2025-10-17 04:26:00
If the issues progressive_dc had in the past are resolved, hopefully it could become a new default?
_wb_
2025-10-17 04:32:54
There are no real issues, it's just slightly slower to encode/decode and compression is slightly worse than default dc
2025-10-17 04:33:05
the difference is quite small though
2025-10-17 04:34:37
I think we made non-progressive dc the default since in the chrome integration those pre-full-dc passes weren't rendered anyway
Jake Archibald
2025-10-17 04:45:18
Yeah, I saw very little difference between progressive and not, in terms of decode speed
jonnyawsom3
_wb_ I think we made non-progressive dc the default since in the chrome integration those pre-full-dc passes weren't rendered anyway
2025-10-17 04:53:47
It used to change based on quality, but you disabled it for higher encode speed after fixing the balance with non-progressive from what I can tell https://github.com/libjxl/libjxl/pull/1825
lonjil If the issues progressive_dc had in the past are resolved, hopefully it could become a new default?
2025-10-17 05:03:02
We had a small discussion around enabling progressive_dc and centre first group ordering by default, but I decided to just add them to `-p` instead of defaulting to it. Right now the main penalty is 50% more memory use and 25% slower encoding for DC, with group ordering broken below effort 10 https://github.com/libjxl/libjxl/issues/4328
lonjil
2025-10-17 05:03:28
ah
Quackdoc
We had a small discussion around enabling progressive_dc and centre first group ordering by default, but I decided to just add them to `-p` instead of defaulting to it. Right now the main penalty is 50% more memory use and 25% slower encoding for DC, with group ordering broken below effort 10 https://github.com/libjxl/libjxl/issues/4328
2025-10-17 05:31:55
I wonder what the penalty is for low end android dec, 50% memory is a massive deal breaker but I don't recal hitting that
_wb_
2025-10-17 05:38:29
50% for just the DC is not that bad in the overall process, remember that DC is only 1/64th of the image
jonnyawsom3
Quackdoc I wonder what the penalty is for low end android dec, 50% memory is a massive deal breaker but I don't recal hitting that
2025-10-17 05:41:40
Oh this is for encode, progressive DC has no impact on decode... Though `-p` does add 60% to decoding...
Quackdoc
2025-10-17 05:43:31
ahhhh
2025-10-17 05:44:15
what are the current impacts of streaming output and streaming input?
jonnyawsom3
2025-10-17 05:46:20
Encoding a 4K screenshot Normal lossy `PeakWorkingSetSize: 304.8 MiB` Progressive DC only `PeakWorkingSetSize: 521.1 MiB` `-p` `PeakWorkingSetSize: 619.2 MiB` Decoding a 4K screenshot Normal lossy `PeakWorkingSetSize: 75.93 MiB` Progressive DC only `PeakWorkingSetSize: 75.8 MiB` `-p` `PeakWorkingSetSize: 127.1 MiB`
2025-10-17 05:46:43
Actually worse than I thought, double the memory for encode
Quackdoc what are the current impacts of streaming output and streaming input?
2025-10-17 05:59:54
Currently only works for PPM files and gives a flat 30 MB reduction encoding this 4K file
Quackdoc
Currently only works for PPM files and gives a flat 30 MB reduction encoding this 4K file
2025-10-17 06:09:25
yeah <:SadCat:805389277247701002>
jonnyawsom3
2025-10-17 06:10:08
Does a lot more on larger files naturally, I vaguely recall effort 1 using 15MB or something silly
Jake Archibald
2025-10-17 07:31:48
Huh, I didn't realise -p had that much overhead for decoding speed. Maybe -p should just be progressive_dc, and have some other option for the progressive mode that's more decoder-costly
2025-10-17 07:32:42
(also, it feels like the progressive_dc feature, whether it's bundled with something else or not, should be in the main --help of the encoder)
jonnyawsom3
2025-10-17 07:42:11
The help could do with an overhaul in general. Everyone agrees doing `-h -v -v -v -v` is a bit silly, but with so many options we don't want to just flood the screen
RaveSteel
2025-10-17 07:51:07
you can actually just omit the -h :galaxybrain:
_wb_
2025-10-17 08:49:54
more AC passes does have impact on decode time, but I think it's not that useful. Progressive DC plus a good ordering of the AC groups is more effective
2025-10-17 08:51:54
the help should probably be refactored to do topic-based subscreens or something, like `-h modular` or whatever. Though it will be a bit tricky to organize stuff by topic
2025-10-17 08:52:40
(and `-h all` or whatever to get the full thing)
Jake Archibald
2025-10-17 08:59:20
I agree with all of that. Does it make sense then for --progressive_dc to be the default, and -p to add the stuff that impacts decode time? Or, make -p opt into --progressive_dc only, and put that in the main help page. Another option can enable the more expensive progressive stuff.
2025-10-17 08:59:29
(I prefer the former)
username
2025-10-17 09:00:32
how are defaults done for the API? because those would probably directly affect how other software outputs JXL files
jonnyawsom3
2025-10-17 09:04:57
`-p` has always meant 'more progressive', as lossy has the 1:8 DC regardless, so I think re-enabling progressive DC by default with `-p` for progressive AC and progressive lossless could make sense. We'd want fresh numbers to make sure it's not a significant speed/density drop on a larger corpus though
2025-10-17 09:09:11
Actually <@794205442175402004>, I know in cjxl it says that progressive DC adds an 'extra 64x64 low-resolution pass', but since it's a modular sub-image, couldn't we just do squeeze on it instead? Behaviour I see suggests it already is, in which case we could then apply our lessons learnt in our overhaul of progressive lossless to try and mitigate the speed penalties, maybe even gain some density too
_wb_
username how are defaults done for the API? because those would probably directly affect how other software outputs JXL files
2025-10-17 09:10:46
there are cjxl defaults and there are libjxl defaults, generally they both have the same defaults but cjxl also has defaults based on input file format
A homosapien
2025-10-17 09:11:24
I feel like the progressive mode used should be reported in the CLI output, similar to jpegli. Something like this: ```3840 x 2160, geomean: XX.XXX MP/s Progressive Mode DC=1 AC=0```
jonnyawsom3
Actually <@794205442175402004>, I know in cjxl it says that progressive DC adds an 'extra 64x64 low-resolution pass', but since it's a modular sub-image, couldn't we just do squeeze on it instead? Behaviour I see suggests it already is, in which case we could then apply our lessons learnt in our overhaul of progressive lossless to try and mitigate the speed penalties, maybe even gain some density too
2025-10-17 09:11:38
Then jxl-rs/browsers could continue decoding from the current squeeze step/AC group, instead of decoding from scratch every time the browsers requests a pass
_wb_
2025-10-17 09:12:42
progressive_dc=1 encodes the DC as a squeezed modular frame progressive_dc=2 encodes the DC of the main image as a VarDCT image, and the DC of the DC (a 64x64 downscaled image) as a squeezed modular frame
2025-10-17 09:13:20
progressive_dc=2 obviously only makes sense for huge images
jonnyawsom3
2025-10-17 09:14:08
Right, I'll update the help text at some point then, but that matches the visual results
_wb_
2025-10-17 09:16:18
the bitstream allows doing progressive_dc up to 4 levels iirc but that would only make sense for stupendously large images and it would only be usable if we would make a cropped decoding mode and some kind of multi-pass encoder that can encode such a thing without needing to fit the whole image in memory
2025-10-17 09:17:24
i think libjxl only implements progressive_dc encoding up to level 2, even that is already overkill in practice
2025-10-17 09:18:45
especially considering that also with just one level, with the default squeeze it goes all the way to a downscale of only a few pixels
jonnyawsom3
2025-10-17 09:19:04
The DC is lossless isn't it? So the fast path seen in Oxide https://discord.com/channels/794206087879852103/803645746661425173/1428838912217841765 could theoretically give a decent speedup too, assuming libjxl isn't already doing it for the DC and just hasn't been generalised to lossless files too
_wb_ especially considering that also with just one level, with the default squeeze it goes all the way to a downscale of only a few pixels
2025-10-17 09:23:29
I actually tried modifying that value, [`kMaxFirstPreviewSize`](https://github.com/libjxl/libjxl/blob/13dfd6ffee8a342a16b90fb66a024fee27835dbb/lib/jxl/modular/transform/squeeze.h#L36) lowering it to 1 and increasing it to the size of a group, but it just gave corrupt output
2025-10-17 09:33:39
Turns out setting it to 1 works... Sometimes... Not that it's useful anyway (First color pass of default cjxl and with minimum squeeze size set to 1, added 32 bytes to the file)
_wb_
I actually tried modifying that value, [`kMaxFirstPreviewSize`](https://github.com/libjxl/libjxl/blob/13dfd6ffee8a342a16b90fb66a024fee27835dbb/lib/jxl/modular/transform/squeeze.h#L36) lowering it to 1 and increasing it to the size of a group, but it just gave corrupt output
2025-10-18 06:56:52
you cannot just change that value in the code and get conforming bitstreams, the default squeeze script is defined in the spec to have kMaxFirstPreviewSize == 8 so if you want something else, you need to make the code output a custom script explicitly.
jonnyawsom3
2025-10-18 12:25:42
Right, I forgot the default squeeze is actually in the spec and not just a libjxl thing
_wb_
2025-10-18 12:37:08
Spec allows signaling other things but default is free to signal
2025-10-18 01:20:54
But yeah setting it lower will not be useful I think. As it is now, the first previews you can get are already very basic, a downscale down to something that fits in 8x8...
2025-10-18 01:23:12
By the way probably it would be nicer to render these squeeze previews not by doing unsqueeze with all zeroes for what has not yet been decoded, but rather just some upsampling of the image at the resolution that is available (e.g. stop the unsqueeze where the data stops and pass a lower res image to the browser or viewer to be upsampled to image dimensions in some cheap way)
2025-10-18 01:23:35
Both for speed and visually I would assume that will be better
2025-10-18 01:24:47
2025-10-18 01:25:50
These blocks with gradients in them are interesting to get an idea of what the squeeze tendency term is doing but it looks kind of weird
jonnyawsom3
_wb_ But yeah setting it lower will not be useful I think. As it is now, the first previews you can get are already very basic, a downscale down to something that fits in 8x8...
2025-10-18 01:26:17
Yeah, that's why I wondered if setting it to the size of a single group might help efficiency, since you rarely need less and then it doesn't have overhead of another 4-8 squeeze steps/mostly empty groups
_wb_
2025-10-18 01:28:47
Those extra squeeze steps are cheap since they work with very few pixels. What is costly decode side is doing the full unsqueeze at every render for the finest detail last squeeze passes, which are working with more pixels. Better to do some optimized upsampling than unsqueeze with residuals that are set to zero since they're not decoded yet
2025-10-18 01:29:35
(like in progressive JPEG previews you shouldn't be going through the inverse dct if none of the ac is available yet)
2025-10-18 01:30:45
This is not a very big deal if it's only the DC that is squeezed, but for progressive previews of full modular images it will be costly to do the full unsqueeze at every render
jonnyawsom3
_wb_ By the way probably it would be nicer to render these squeeze previews not by doing unsqueeze with all zeroes for what has not yet been decoded, but rather just some upsampling of the image at the resolution that is available (e.g. stop the unsqueeze where the data stops and pass a lower res image to the browser or viewer to be upsampled to image dimensions in some cheap way)
2025-10-18 01:31:17
We have an issue open for that, but you raised points about Gaborish/Patches not being applied to the smaller scale. I think for DC/Squeeze up to the 1:8 it would be fine to just skip those since it's so low res anyway, but once AC starts loading they should be applied https://github.com/libjxl/libjxl/issues/4297
_wb_
2025-10-18 01:44:12
There are a two different things we could imagine having an API for: decoding the image at a lower resolution (returning the image at lower resolution), and returning progressive passes at a lower resolution (instead of always at full image resolution). Both could be useful. Even in the current API, it would be nice to have jxl-oxide style very early progressive renders. I think we had that in libjxl at some point but it probably got lost in the rendering pipeline refactoring. For this it would probably be faster and better looking if we would upsample partial squeezed images using the fancy upsampler instead of going through unsqueeze with the missing residuals set to all-zeroes (or at least specialize that to not actually materialize buffers that are set to all-zeroes and then read by the generic unsqueeze code)
jonnyawsom3
2025-10-18 01:56:13
Here's a comparison of Oxide and v0.6 djxl loading the 1:8 DC. Oxide seems to have a threshold right before AC loading where it swaps from NN to non-seperable upsampling but without filters (I think), so that's in the middle
2025-10-18 01:56:15
For progressive lossless, v0.6 and Oxide give the same decoded result for LQIP, which was removed from libjxl by v0.7. Currently searching for the commit
Tirr
2025-10-18 02:44:05
that's not actually non-separable upsampling; jxl-oxide switches from NN to actual VarDCT right after BlockInfo is fully loaded
2025-10-18 02:44:52
those blockiness are from VarDCT blocks without enough HF coeffs
jonnyawsom3
2025-10-18 02:57:49
Ahh right
HCrikki
2025-10-18 03:04:29
https://old.reddit.com/r/webdev/comments/1o9rlhz/comparison_of_png_with_modern_image_formats_avif/
spider-mario
2025-10-18 04:44:09
funny how all over the place the results for `pschmidt.png` are
jonnyawsom3
2025-10-18 04:53:04
The only time AVIF was actually competitive and beat JXL (On the slowest setting and without extra parameters to cjxl) <https://op111.net/posts/2025/10/png-and-modern-formats-lossless-image-compression/> (Link for fast viewing)
ignaloidas
2025-10-18 06:34:18
pschmidt.png is quite viable to put all into MA trees for around 1302 bytes in total, though results in a massive tree because of how green channel is done
veluca
2025-10-18 06:44:13
you are making me want to make a better lossless encoder, you should not do that 😛
jonnyawsom3
2025-10-18 06:52:28
What better motivation than getting beaten by lossless AVIF xD
ignaloidas
2025-10-18 06:52:36
this could be way smaller if I didn't do it with jxl_from_tree, but idk if there's a way to pass MA for an image so I don't need to encode green channel with a couple hundred nodes as I'm doing right now
jonnyawsom3
ignaloidas pschmidt.png is quite viable to put all into MA trees for around 1302 bytes in total, though results in a massive tree because of how green channel is done
2025-10-18 06:55:13
Yeah, I left a comment linking them to https://allrgb.com/jxls-amazing-1 and [JXL art](https://jxl-art.lucaversari.it/?zcode=dZNBDsIgEEX3nGIuYAIUsd24cOWqaeKiB7DYsjOGmHp7aaUBKn%2FV%2BW9mPkPJXKwbzNNNVLPeDv6reKPZ1dhxcr%2BY2Qfd6UycEYVQ%2BHAVc%2BBBdt3LvBNEdKB%2Bp4SO9Z%2BsdjHY9y897Z%2FWKm0afYesk5LAKpmwSFVGIz%2Fu%2BHLUzTgSMIGcKtQAE%2BVJOfAXyAYmgJNsQAPihb8sVWl2qcGJJ%2BCMOPJBj4J4eUoJ3NFDIY584IMAzllhM7xs1ysrVqrelmLzjLlsQb3oM5fcY11NlvIv) along with higher encoding settings https://www.reddit.com/r/webdev/comments/1o9rlhz/comment/nk5jqcs/
veluca
What better motivation than getting beaten by lossless AVIF xD
2025-10-18 07:01:16
yeah but I should finish jxl-rs first!
jonnyawsom3
2025-10-18 07:02:22
True, we need a fast decoder to view the files after all
_wb_
The only time AVIF was actually competitive and beat JXL (On the slowest setting and without extra parameters to cjxl) <https://op111.net/posts/2025/10/png-and-modern-formats-lossless-image-compression/> (Link for fast viewing)
2025-10-19 07:53:30
This doesn't surprise me. Lossless AVIF works on RGB, which is usually a bad idea but on an image like this it is a very good idea.
ignaloidas this could be way smaller if I didn't do it with jxl_from_tree, but idk if there's a way to pass MA for an image so I don't need to encode green channel with a couple hundred nodes as I'm doing right now
2025-10-19 08:01:08
The code has a way to pass an MA tree to the encoder, but it's not exposed in the API. It would be cool to have an API for getting and setting the MA tree used during encode. This would allow you to do fast fixed-tree encoding using a tree learned from a high-effort encode of another image with similar properties.
Tirr
2025-10-19 08:32:29
yeah tree reusing sounds great
A homosapien
ignaloidas pschmidt.png is quite viable to put all into MA trees for around 1302 bytes in total, though results in a massive tree because of how green channel is done
2025-10-19 08:45:37
I got it down to 704 bytes
veluca
2025-10-19 08:46:19
how did you do that? 😄 smaller tree, lz77 on residuals for the green channel?
2025-10-19 08:48:18
(I imagine if you use something like a TOP or LEFT predictor strategically you can get most of the green channel residuals to be +1 or 0, and then lz77 has a very easy time)
A homosapien
veluca how did you do that? 😄 smaller tree, lz77 on residuals for the green channel?
2025-10-19 08:53:12
```cjxl 16million-pschmidt.png 16million-pschmidt.jxl -d 0 -e 9 -P 14 -g 3 -E 4 -I 100 JPEG XL encoder v0.8.4 aa2df301 [AVX2] Read 4096x4096 image, 57757 bytes, 548.3 MP/s Encoding [Modular, lossless, effort: 9], Compressed to 704 bytes (0.000 bpp). 4096 x 4096, 0.27 MP/s [0.27, 0.27], 1 reps, 12 threads.```
veluca
2025-10-19 08:53:19
oh wow
ignaloidas
2025-10-19 08:53:33
huh, v0.8
veluca
2025-10-19 08:53:44
did *not* expect the encoder to do that good of a job
ignaloidas
2025-10-19 08:54:35
I assume `-I 100` is doing most of the job, and ending up with a similar tree as mine except green is all N/W with small residuals?
A homosapien
2025-10-19 08:55:05
and `-g 3` I think
ignaloidas huh, v0.8
2025-10-19 08:55:21
https://github.com/libjxl/libjxl/issues/4379
2025-10-19 08:55:41
May or may not be related
ignaloidas
2025-10-19 08:56:09
oh, -g 3 is surprising to me, -g 1 is the one that fits the natural repeating pattern with red/blue channels
A homosapien
ignaloidas oh, -g 3 is surprising to me, -g 1 is the one that fits the natural repeating pattern with red/blue channels
2025-10-19 09:14:33
```cjxl 16million-pschmidt.png 16million-pschmidt1.jxl -d 0 -e 9 -P 14 -g 1 -E 4 -I 100 JPEG XL encoder v0.8.4 aa2df301 [AVX2] Read 4096x4096 image, 57757 bytes, 549.0 MP/s Encoding [Modular, lossless, effort: 9], Compressed to 4329 bytes (0.002 bpp). 4096 x 4096, 0.08 MP/s [0.08, 0.08], 1 reps, 12 threads.```
2025-10-19 09:15:22
moving to <#803645746661425173>
jonnyawsom3
A homosapien https://github.com/libjxl/libjxl/issues/4379
2025-10-19 09:38:48
I don't think that's related, a full color image shouldn't be using palette at all, especially not with g3. As you said, moving to https://discord.com/channels/794206087879852103/803645746661425173/1429584227686551724 though
awxkee
> I was also surprised to see that, in Safari, JPEG XL takes 150% longer (as in 2.5x) to decode vs an equivalent AVIF. That's 17ms longer on my M4 Pro. Apple hardware tends to be high-end, but this could still be significant. This isn't related to progressive rendering; the decoder is just slow. There's some suggestion that the Apple implementation is running on a single core, so maybe there's room for improvement. > I thought that "fast decoding" was one of the selling points of JPEG XL over AVIF, but now I'm not so sure. The complaints about decode speed are a shame, since it's equal or slightly faster than AVIF decoding on my system with the CLI tools, so it's likely just implementation in Safari slowing it down. > It could use some smoothing, like we saw with the JPEG progressive render in Firefox/Chrome. It was actually part of the Chrome implantation back in the day, using the non-separable upsampling while oxide just does NN IIRC. > Due to its high resolution (1598x1753), and sharp detail, it's 155 kB, even using AVIF. > Thanks to modern image formats (AVIF in this case), the above image is 56.4 kB. That's pretty incredible for a more-than-HD image. The fox image is much larger because of its sharp details, but that isn't true for most images. This means that, for many images, there's little benefit to progressive rendering. Most of the post seems to be based around the assumption that all images can be compressed to 200KB and will only get smaller, so progressive doesn't matter since it's either 10% of the file or the full image is downloaded in 20ms anyway. If you look at a single lossless JXL with progressive, you'd realise we can do a preview at 0.03% and anything in the real world is usually in the megabytes, not kilobytes. Not everyone has gigabit, not everyone has a CDN and not everyone wants to upload low quality versions of their images...
2025-10-21 12:19:30
I always feel a bit skeptical when I see those “benchmarks” for JXL claiming it’s close to avif ( dav1d ). I’ve never seen it come anywhere near AVIF, neither 3 years ago nor today. The magnitude of the numbers I consistently get looks like this on an iPhone 13: AVIF444 time to frame: 0.040301 seconds AVIF444 time to full decoding: 0.069513 seconds JXL time to frame: 0.148722 seconds AVIF420 time to frame: 0.019829 seconds AVIF420 time to full decoding: 0.059945 seconds JXL time to frame: 0.137363 seconds Mangitudes of the difference on android give or take the same as on iOS, have no idea where idea that jxl decoding have even comparable speed to avif comes from
veluca
2025-10-21 12:24:20
note that decoding on aarch64 is not as optimized as decoding on x86 - we could be using fp16 for most of it, which I think would give a 2x or so speedup at least, and it's possible that we are missing other optimizations
awxkee
2025-10-21 12:28:36
fp16 pipelines on the most CPUs at the moment simply call fp32 uops under the hood, it mostly gives nothing except reducing memory pressure. At some rough average simply reworking something to fp16 rather gives slowdown instead of speeding up.
2025-10-21 12:29:35
So, as I understand it, those benchmarks claim that they are as fast as AVIF, but they don’t state that this is only true for x86. This explains something.
veluca
2025-10-21 12:32:22
> except reducing memory pressure that's definitely not nothing! 🙂
Quackdoc
2025-10-21 01:38:02
on my lower end phones, I have found jxl to usually be around the same speed as avif. where it wins is that it doesn't make my phone overheat and die.
HCrikki
2025-10-21 02:00:15
a shame energy consumption is never benchmarked. more than against other formats, i wonder how the various reference efforts compare
awxkee
2025-10-21 02:04:41
Processing time in Xiaomi Mi Note 10 Lite, which is not the best device processing time looks as so for the same image as I used on iPhone 13: JXL time to frame: 406.44800 ms AVIF time to frame + YUV: 146.05700ms
2025-10-21 02:05:16
This is still quite far from being close
HCrikki a shame energy consumption is never benchmarked. more than against other formats, i wonder how the various reference efforts compare
2025-10-21 02:09:54
Power cores start handling tasks based on a time heuristic, so roughly speaking, the longer the decoding goes on, the more power cores are used and the more energy is drained.
_wb_
2025-10-21 02:10:00
how are you measuring "time to frame"?
2025-10-21 02:10:40
or rather, what is the difference between time to frame and full decoding?
awxkee
2025-10-21 02:10:50
I mean decoding from scratch to the moment when RGBA data is available.
2025-10-21 02:11:26
In case of YUV time to frame is time that needs to decode YUV frame, full decoding is time needed to decoder frame and convert YUV to RGBX
_wb_
2025-10-21 02:11:49
using libjxl and dav1d in some benchmarking code or how are you doing it?
2025-10-21 02:12:54
what output buffer type are you using with libjxl? pixel callback or full buffer decoding? and is this single-core or MT?
awxkee
2025-10-21 02:13:45
Full buffer with multithreaded decoding
_wb_
2025-10-21 02:13:59
and what kind of jxl files and avif files are you using for this? both lossy at similar bpp?
awxkee
2025-10-21 02:14:39
Yes
2025-10-21 02:15:29
I don't think I'm doing wrong decoding time checks
2025-10-21 02:15:36
Everything is reasonably fair
_wb_
2025-10-21 02:15:50
have you tried compiling with `-DJXL_HIGH_PRECISION=0` and decoding to uint8?
Quackdoc
HCrikki a shame energy consumption is never benchmarked. more than against other formats, i wonder how the various reference efforts compare
2025-10-21 02:15:54
true, it can be pretty hard granted without a proper setup but sometimes its just easy enough to tell
awxkee
_wb_ have you tried compiling with `-DJXL_HIGH_PRECISION=0` and decoding to uint8?
2025-10-21 02:16:26
I'm already trying decoding to uint8
2025-10-21 02:16:51
Could try disable JXL_HIGH_PRECISION if you think this might help
_wb_
2025-10-21 02:18:17
yeah but the default codepath does everything in float32 until the very end, with JXL_HIGH_PRECISION disabled it's also all float32 for most of the stuff but at least the final XYB to RGB conversion is done a bit more optimized
2025-10-21 02:19:05
for a somewhat more fair comparison, try comparing with a 12-bit AVIF file instead of an 8-bit one
awxkee
2025-10-21 02:24:48
This isn’t really fair, considering I’m not using 12-bit or 10-bit AVIFs 🙂 This is some sort of synthetic benchmark where a special configuration is required, and the comparison only applies to specific cases 🙂
_wb_
2025-10-21 02:24:55
we should probably at some point implement a cheaper rendering pipeline that does everything or at least most stuff in fixedpoint int16 arithmetic (except maybe the largest inverse dct transforms which require more precision than that), to reduce memory pressure and double the simd lanes... at least for Level 5 conformance this should be possible I think.
awxkee
2025-10-21 02:24:57
I'll try later with high precision disabled
veluca
_wb_ we should probably at some point implement a cheaper rendering pipeline that does everything or at least most stuff in fixedpoint int16 arithmetic (except maybe the largest inverse dct transforms which require more precision than that), to reduce memory pressure and double the simd lanes... at least for Level 5 conformance this should be possible I think.
2025-10-21 02:28:55
and if not int16, fp16 😛
2025-10-21 02:29:08
large DCTs are a bit tricky to do in fixpoint int16
2025-10-21 02:29:41
but I guess nothing stopping us from just doing large ones in fp16
jonnyawsom3
2025-10-21 02:30:37
Isn't that the plan for jxl-rs?
veluca
2025-10-21 02:30:49
also int16 is much faster than even fp16 for things like addition
2025-10-21 02:30:51
yup
_wb_
2025-10-21 02:32:07
also for things like kAdd blending of frames or patches, it is actually nice to have commutative addition 🙂
veluca
2025-10-21 02:33:06
add/fixpoint mul are 1/5 cycles on intel, but for f32 they are 4/4 cycles, so unless there's *lots* of multiplications ...
_wb_
2025-10-21 02:35:50
(in float32, it's not guaranteed that A+B-B == A which is slightly annoying, we need nonzero conformance thresholds for lossless because patches can introduce tiny errors because of this — smaller than the integer quantization step of uint16 but still...)
veluca
2025-10-21 02:37:43
TIL that AVX512 includes on most reasonable CPUs `_mm*_dpbf16_ps`, which does some interesting stuff (ax+by+c, with a, b, x and y being fp16 and c being fp32)
2025-10-21 02:38:02
no idea how easy it is to make a DCT out of that
awxkee
2025-10-21 03:00:16
With `JXL_HIGH_PRECISION=0` it gives: `JXL time to frame: 295.45300 ms`, what is about 25% better.
2025-10-21 03:00:31
On Xiaomi Mi Note 10 Lite
_wb_
2025-10-21 03:02:24
not bad, considering it only affects the xyb2rgb part of the decoding, iirc
2025-10-21 03:04:02
what kind of quality are you using? libjxl tends to get slightly slower with lower quality (e.g. when EPF iterations go up), while avif tends to get faster with lower quality
awxkee
2025-10-21 03:04:10
AVIF 12-bit Xiaomi Mi Note 10 Lite : `AVIF time to frame + YUV: 207.26900 ms` still much better
2025-10-21 03:04:18
-q 62
_wb_
2025-10-21 03:04:37
that's not a very high quality
awxkee
2025-10-21 03:05:24
Yes, but I’m mostly using these quality settings, so it’s not a big deal how fast it is at 100% 🙂
_wb_
2025-10-21 03:05:34
what if you do something around cjxl -q 80 and some similar filesize for avif?
2025-10-21 03:06:14
why are you using such low quality settings? even social media use a higher setting than that...
awxkee
2025-10-21 03:07:08
I'm doing mostly everything for mobile, this is not the same thing as a desktop
2025-10-21 03:08:30
I typically want lesser size, faster decoding, less resource consumption and 5-10% quality most of users, especially on lower end devices simply can't distinguish
2025-10-21 03:09:39
Some where about this point on mobile screens higher quality doesn't add any quality that could be perceived by eye
2025-10-21 03:09:43
At least for my eyes
_wb_
2025-10-21 03:12:15
If that's true, then maybe consider using lower resolution images. That will speed things up a lot in any codec. Too often images are used at a higher resolution than how they get displayed, which is wasteful.
awxkee
2025-10-21 03:13:35
12-bit q80 AVIF, q80 JXL, Xiaomi Mi Note 10 Lite : JXL time to frame: 300.32000 ms AVIF time to frame + YUV: 236.74400 ms
2025-10-21 03:16:02
AVIF q80 8-bit same phone: AVIF time to frame + YUV: 99.58600 ms
2025-10-21 03:29:15
AVIF and JXL are actually interesting only in cases where you need high resolution images on mobile with reasonable quality and a high compression ratio. For icons or simple graphics, JPEGs and PNGs are sufficient. Apple also provides decent hardware codecs for these formats, so unless one want to display a high resolution image, it’s usually not worth going beyond JPEG.
A homosapien
2025-10-21 03:41:33
For icons and simple graphics, why not use lossless WebP or JXL?
Meow
2025-10-21 03:43:41
why not SVG
A homosapien
2025-10-21 03:46:34
That would be best, but some are keen on using bitmap images for some reason
jonnyawsom3
2025-10-21 03:57:58
Last I checked hardware codecs are only relevant for encoding, as it's too slow to initialise for decoding. That was one of the points raised for AVIF years ago, but it was never used
HCrikki
2025-10-21 05:09:19
hw codecs are really wasteful of bits and require high bpp to give acceptable quality, imo negating a lot of the advantages of a new format the average 16 megapixel hw-jpg photo is like 8 megabytes, what point Is there to to use another codec when you could just compress the jpg better? a 5 megabyte avif weights exactly the same as a 5 megabyte jpg
awxkee
2025-10-21 05:10:46
Rendering on mobile is a bit different from desktop, so formats like PDF and SVG are integrated into Xcode and rasterized to PNG during the build process. Drawing vector graphics a lot more expensive than drawing simple raster. WebP is integrated in android studio only, some people are using it, some are not. This is still about impossible to use WebP easily in iOS development. JXL is not integrated in any build tools. This is mostly a productivity issue, even if WebP, JXL or any format is better in something, but it's not integrated in building tools and OS, no one is going to use it unless there is a strong motivation to do so. In the most cases any advantages of advanced image formats is eliminated by complexity of integrating them. It’s also worth noting that most Android and iOS developers are not familiar with C++, C, Rust, or other system programming languages.
2025-10-21 05:11:26
Therefore, for some typical developer who decided to try out some "advanced codec" they have to at first investigate which format, then learn some completely mad build systems like CMake, then investigate how to integrate it and learn "how all these works".
2025-10-21 05:12:00
Whatever advantages any new codecs have, most of developers won't do so.
Exorcist
2025-10-21 05:23:36
If "hardware" encoder means [disable almost all tools](https://gitlab.com/AOMediaCodec/SVT-AV1/-/commit/428d96689b2b05a4b634d658bac137260e964dbd), the advantage of new spec are meaningless
_wb_
2025-10-21 05:44:36
hardware encoding is useful for something like a camera where you need high-fidelity (not web quality) and there are quite a lot of pixels to encode, i.e. high-effort software encoding would be bad for your battery life
jonnyawsom3
2025-10-21 05:48:42
On a side note, I wonder if a hardware lossless JXL encoder will happen, or if fast/simple lossless is already considered fast enough for cameras/DNGs
Quackdoc
awxkee Rendering on mobile is a bit different from desktop, so formats like PDF and SVG are integrated into Xcode and rasterized to PNG during the build process. Drawing vector graphics a lot more expensive than drawing simple raster. WebP is integrated in android studio only, some people are using it, some are not. This is still about impossible to use WebP easily in iOS development. JXL is not integrated in any build tools. This is mostly a productivity issue, even if WebP, JXL or any format is better in something, but it's not integrated in building tools and OS, no one is going to use it unless there is a strong motivation to do so. In the most cases any advantages of advanced image formats is eliminated by complexity of integrating them. It’s also worth noting that most Android and iOS developers are not familiar with C++, C, Rust, or other system programming languages.
2025-10-21 05:48:50
integrating new formats into android is painful
_wb_
2025-10-21 05:59:20
Instead of a 10 MB JPEG + a 90 MB raw file for every photo, you could do a 10 MB JXL file that has enough precision to cover most of the use cases of raw (i.e. you can adjust exposure etc without revealing compression artifacts), but at only 1/10th of the storage cost. I think that is significant. (these are just ballpark numbers, the actual sizes depend on camera resolution and the actual amount of entropy in the image) Doing fully lossless would also be an option but that would be like 60 MB or so, so it wouldn't be as significant a win, and I think for most use cases it's overkill. JPEG for sure doesn't have enough precision for most use cases (8-bit YCbCr is just not enough if you want to have room for postproduction), which is why people prefer to use raw, but fully lossless raw is overkill. Most of the filesize goes to noisy least significant bits that you probably don't really need anyway. Lossy JXL at the size of current camera JPEGs can basically eliminate 95% of the use cases for camera raw.
RaveSteel
2025-10-21 06:03:18
Even "high quality lossy raw" is noticeably worse than full lossless if zooming in to spot edit. Give people the option for lossy raw, but full lossless will remain the better solution if every detail matters
2025-10-21 06:04:08
By noticeable I don't mean significant, but still a difference
lonjil
2025-10-21 06:06:01
> Even "high quality lossy raw" is noticeably worse than full lossless if zooming in to spot edit. depends on what you mean by high quality
_wb_
2025-10-21 06:09:24
you can do something like d0.1 - d0.2 JXL at the filesizes of camera JPEGs
jonnyawsom3
2025-10-21 06:10:56
At those distances doesn't lossy modular start to become useful? Or am I thinking of 0.01
_wb_
2025-10-21 06:11:21
lossy modular is probably annoying to implement in hardware
lonjil
2025-10-21 06:11:55
lossy modular with a guaranteed maximum error of like 1-3 would be interesting
RaveSteel
lonjil > Even "high quality lossy raw" is noticeably worse than full lossless if zooming in to spot edit. depends on what you mean by high quality
2025-10-21 06:12:19
Good question, because it isn't defined. "High quality" is whatever the vendor or software developer declares to be high quality High quality may also be default quality, with other settings offering more compression
2025-10-21 06:12:52
Anyways, give me full lossless, I don't care about filesize lul
lonjil
_wb_ Instead of a 10 MB JPEG + a 90 MB raw file for every photo, you could do a 10 MB JXL file that has enough precision to cover most of the use cases of raw (i.e. you can adjust exposure etc without revealing compression artifacts), but at only 1/10th of the storage cost. I think that is significant. (these are just ballpark numbers, the actual sizes depend on camera resolution and the actual amount of entropy in the image) Doing fully lossless would also be an option but that would be like 60 MB or so, so it wouldn't be as significant a win, and I think for most use cases it's overkill. JPEG for sure doesn't have enough precision for most use cases (8-bit YCbCr is just not enough if you want to have room for postproduction), which is why people prefer to use raw, but fully lossless raw is overkill. Most of the filesize goes to noisy least significant bits that you probably don't really need anyway. Lossy JXL at the size of current camera JPEGs can basically eliminate 95% of the use cases for camera raw.
2025-10-21 06:13:11
> which is why people prefer to use raw, but fully lossless raw is overkill I've seen a few photographers who don't trust lossless compression, and so shoot in uncompressed raw 😄
_wb_
lonjil lossy modular with a guaranteed maximum error of like 1-3 would be interesting
2025-10-21 06:15:04
that's not hard to do, just do squeeze in YCoCg (not XYB, if you want to limit the max error per RGB channel) and quantize the least significant bit away of the last few squeeze residuals. We should probably add an option to do this to cjxl/libjxl.
lonjil > which is why people prefer to use raw, but fully lossless raw is overkill I've seen a few photographers who don't trust lossless compression, and so shoot in uncompressed raw 😄
2025-10-21 06:17:08
that's silly, but there are some raw formats that are compressing not losslessly so I can imagine that people don't want to risk it
lonjil
2025-10-21 06:17:19
aye
_wb_ that's not hard to do, just do squeeze in YCoCg (not XYB, if you want to limit the max error per RGB channel) and quantize the least significant bit away of the last few squeeze residuals. We should probably add an option to do this to cjxl/libjxl.
2025-10-21 06:21:55
I'm also pondering if something like webp's "near lossless" would be a good idea for jxl.
_wb_
2025-10-21 06:29:46
i'm not sure if I know exactly how webp's near lossless works
2025-10-21 06:33:13
just doing normal lossless and quantizing predictor residuals (carefully though, making sure the next prediction is based on the decoded values, not the original ones) should work too, I wonder what that looks like actually in jxl where the predictor choice can vary every pixel
2025-10-21 06:34:45
in PNG you can apply that trick but it only makes sense for the AvgN+W predictor in PNG (the other predictors just replicate neighbors so if you quantize the residuals it's the same as just reducing bit depth, so you immediately get banding)