Addressing the JXL or JPegXL format floating around the internet.
We’re going to do something we usually do not do for ANY of our blog articles. We’re going to purposefully STOP all optimization of our files in this entry and only use ONLY PNG files (Blog article only, navigation, footer, and backgrounds will still be processed. It may sound totally counterproductive to do when making an article about a new format that the developers insist that you use. However, in order to graphically demonstrate my points about the “New kid on the image war block,” we must go totally lossless with a codec we trust and has been proven for almost 20 years.
Now, for those users running nightly builds of Chrome or Firefox that want to test out JXL Good news! Every article EXCEPT this one has already been encoded thanks to scripting mentioned in this blog article. So once you’ve enabled JXL in your browser (details described below) you can explore this site with it and see if it’s really all of the hype it’s meant to be!
Read on if you care about my rants and opinions of this format.
Faster, harder, stronger…… Right?
When we first heard of this new image format which is under consideration for release in browsers at the time of this posting under CanIUse. As a blogger who loves tech and the general art of speeding up how a website and its content is delivered to you the user.
Fuck yeah, sign me up. – S
I set up my scripts to do the batch conversion process of all of the images on s-config.com (Except this article, of course.)
Testing JpegXL/JXL for yourselves.
At the time of this blog article only nightly builds support JXL and it has to be enabled by the end-user.
At the time of this posting JXL is not available in the main chrome distributive file but in Google Chrome Canary, which is a nightly build of Google for people to test out new features like JXL in.
Once you have installed this version you can simply type into the address bar:
And you will be presented with a window like the one posted above. Simply click the drop-down box for JXL support and enable it. then, you could clear your browser cache and cookies and load up our site again and suddenly my NGINX server will start to server you JXL files.
You can download the nightly beta from firefox and even select ‘custom’ so it does not overwrite your existing Firefox installation if it is your main browser. Remember to download the nightly edition and not the beta edition!
Type the following into the address bar:
and from here a window like the one above will appear allowing you to check the box to enable JXL Media.
Microsoft Edge Canary.
Unlike Google Chrome you have to modify the shortcut for the “Canary” version of Edge! The download is here! Not the regular one. Then, you modify the shortcut of the executable with the following command.
Just like how it appears in the window above. Except once again, you will be doing this to “Canary” and not your regular Microsoft Edge as the regular edition will do nothing.
We’re not software engineers or graphic arts experts. We’re users and readers just like 99 percent of you out there. The only thing we did a little differently is we have our own server to deploy this. As such, take whatever information you find here as an opinion. Any scripting or commands that mention you do at your own risk! Always check your code. Any modification you make to your software is your own responsibility as well and s-config.com will not be held liable for any damages.
Test 1: 15 color PNG with transparency.
In just about every blog we’ve seen the story is unchanged. They claim massive Benefits over JPG pictures which are typically high colors with millions of colors. Fair enough. But what about a low-fidelity PNG file? After all, if JXL can work wonders with millions of colors it should have no problems with just a few in a locked pallet right?
We’re attaching my 512×512 FavIcon logo that is normally saved in .SVG format. I took the vector and output to raster at 512px-512px 4-bit color. 15 colors + transparency just to make things interesting.
after optimizing with optiPNG, and passing it through my script. Here is the results.
-rw-r--r-- 1 user group 13830 Sep 22 01:14 Bintu-Logo-2.png.webp -rw-r--r-- 1 user group 15344 Sep 22 01:12 Bintu-Logo.png -rw-r--r-- 1 user group 20317 Sep 22 01:12 Bintu-Logo.png.avif -rw-r--r-- 1 user group 81911 Sep 22 01:19 Bintu-Logo.png.jxl -rw-r--r-- 1 user group 7450 Sep 24 19:28 Bintu-Logo.png-2.jxl -rw-r--r-- 1 user group 31510 Sep 22 01:15 Bintu-Logo.png.webp -rw-r--r-- 1 user group 21370 Sep 22 01:21 Bintu-Logo.svg
- So, my original vector weighs in at around 21KB for Bintu-Logo.svg which isn’t bad and it was designed in InkScape 0.9.0.
- My 4-bit PNG Bintu-Logo.png is coming in at 15KB! Using OptiPNG version 0.7.7.
- My WebP Bintu-Logo.png.webp is coming in at 31KB! Double the size using the flags -q 85 -m 6 -pass 10 -o. Using CWebP version 1.2.0
- AVIF Bintu-Logo.png.avif cannot beat PNG and comes in at 20KB using flags –min 0 –max 63 –minalpha 0 –maxalpha 63 -a end-usage=q -a cq-level=18 -a tune=ssim -s 0 -j 1 also using CWebP version 1.2.0
- JXL Bintu-Logo-png.jxl comes in at a horrific 80KB! Flags passed are -q 85 -e 9 -p Using cjxl Version 0.7.0 95cb570
- JXL Bintu-Logo-2.png.jxl – comes in at an excellent 10.6KB! Flags passed are -d 0.0 -e 9 -p Using cjxl Version 0.7.0 95cb570
- The only one that could possibly dethrone my 4-bit PNG was a different WebP at 14KB. And that’s only because of the -near_lossless 40 flag that does not work all of the time! Especially on pictures! Even with smaller PNG files such as system icons that flag sometimes does not stand a chance.
09/09/2022 – Version check time!
- JXL Bintu-Logo-png.jxl comes in at a horrific 81KB! Using cjxl Version v0.8.0 8c7c9a0c with flags -d 1.0 –lossless_jpeg=1 -e 9 –brotli_effort=11 – it actually went UP in latest version.
- HOWEVER!!!! JXL Bintu-Logo-png-2.jxl comes in at a horrific 80KB! Using cjxl Version v0.8.0 8c7c9a0c with flags -d 0.0 –lossless_jpeg=1 -e 9 –brotli_effort=11 – going down by another 3Kb in size! amazing!
Now, just like WebP. Different algorithms must be deployed in order to work with limited palette images and JXF. In this case, actually setting the JXF lossless with the -d 0.0 flag destroyed AVIF while still making the image look great! This is awesome!
Also, note that we discovered the -p flag was pushing up the size of some of our JXLs. We will be removing it from the files on our site and will see what happens.
Animated GIFs anyone?
Cherry Red keyboard animation!
-rwxr--r-- 1 user group 111374 Sep 23 03:48 Cherry-MX-Red.gif -rwxr--r-- 1 user group 97014 Sep 23 03:48 Cherry-MX-Red.gif.apng -rw-r--r-- 1 user group 13371 Sep 23 03:48 Cherry-MX-Red.gif.avif -rw-r--r-- 1 user group 450947 Sep 23 03:50 Cherry-MX-Red.gif.jxl -rw-r--r-- 1 user group 100912 Sep 25 02:27 Cherry-MX-Red-d0-no-p.gif-.jxl -rw-r--r-- 1 user group 106052 Sep 23 03:48 Cherry-MX-Red.gif.webp
Every codec has varying success rates based on our optimization script EXCEPT for JXL! Which exploded the file to 4 times its original size using lossy -q 85 ! And 2x its size using lossless -d 0.0 . However! If you drop the -p progressive flag. it comes in at 6k lower than the original GIF! Which hey! At least it’s something!
09/09/2022 – Version check time!
- JXL Cherry-MX-Red-d0-no-p.gif-.jxl is at 101KB Using cjxl Version v0.8.0 8c7c9a0c with flags -d 0.0 –lossless_jpeg=1 -e 9 –brotli_effort=11 – going up by 1KB from previous version
- JXL Cherry-MX-Red-d0-no-p.gif-.jxl just crashes Using cjxl Version v0.8.0 8c7c9a0c with flags -d 1.0 –lossless_jpeg=1 -e 9 –brotli_effort=11 :
JPEG XL encoder v0.8.0 8c7c9a0c [AVX3,AVX2,SSE4,SSSE3,Unknown]
Read 200x200 image, 111374 bytes, 6.3 MP/s Encoding [VarDCT, d1.000, effort: 9], ./lib/jxl/image.h:57: JXL_CHECK: xsize <= orig_xsize_ Illegal instruction
Huh, we weren’t expecting that one. Perhaps this is for the best since -q 85 in the last version wasn’t doing so hot.
We begin to question if perhaps we’re doing something wrong. Is there a command we’re supposed to set like what we discovered with WEBP where playing with the -near_lossless flag improves performance? Sadly, we found nothing in the cjxl encoding manual.
So, JXL cannot replace certain 8-bit PNGs from 1995 nor can it replace GIFS from the 1980s. There are a few things going on here.
First, the way GIFs optimize themselves is via subtractive imaging. That it keeps what pixels have not changed, and moves what pixels have changed in order to maintain a low filesize. JXL doesn’t really work like that.
Second, AVIF is piggybacking onto the AV1 standard to produce high compression files off of an already established video codec. This is why in my script we have to go through a lot of loopholes to make an AVIF animation such as converting GIF to Y2M with FFMPEG and then bringing it into AVIF! So, from a user-friendly standpoint AVIF kind of sucks to work with. But AVIF won this round in terms of animated image compression.
S, JXL is supposed to replace JPEGs! Compare it to the right codec!!!
Okay! bare in mind we cannot put complete allegiance to JXL as there are times where regardless of algorithm PNG sometimes beats it (very rare! But it does happen!) Thanks to the newly discovered -d 0.0 flag it’s certainly a positive step!
JPG to JXL conversion.
Okay! We’ll compare our sample set we’ll be using titles off of our website because in many cases they were saved as a jpg with a quality of 80. If you drill down to the pixel level on the original JPG you will of course find artifact distortion. Which is actually common for a website! But it’s a real-world scenario as web admins like us will be doing the same to migrate away from old standards and onto the new.
-rw-r--r-- 1 user group 132142 Sep 23 04:06 YouTube-Monopoly-title.jpg -rw-r--r-- 1 user group 39452 Sep 23 04:06 YouTube-Monopoly-title.jpg.avif -rw-r--r-- 1 user group 36505 Sep 23 04:06 YouTube-Monopoly-title.jpg.jxl -rw-r--r-- 1 user group 111140 Sep 25 18:51 YouTube-Monopoly-title-d0.jpg.jxl -rw-r--r-- 1 user group 63560 Sep 25 18:51 YouTube-Monopoly-title-d1.jpg.jxl -rw-r--r-- 1 user group 60542 Sep 23 04:06 YouTube-Monopoly-title.jpg.webp
Now because we’re playing with a legit 8-bit/channel jpg. JXL starts to shine, blasting away WEBP and even pushing past AVIF!
Side-by-side image comparison.
Each of the images was decoded BACK to PNG files using their native conversion program for making the file in the first place. dwebp, djxl, and decavif. Then, they were merged using a graphic program and saved as a lossless 24-bit PNG for you the reader to look at.
While the YouTube-Monopoly-title.jpg is not fantastic, as you could tell by looking at the YouTube Logo on the monopoly board as well as the demonetized logos. It’s perfect because this would be your typical image that JXL would be converting for website operators.
With WEBP the differences are subtle but some edge dithering is present around the monopoly board. Overall it did a good job retaining the quality while giving us a 50 percent gain over JPG.
It gets super interesting! Because AVIF subtracts detail in order to achieve a better encode. It inadvertently cleaned up the JPG artifacts from the original file! Although the explosion dulled a little in the AVIF. It did result in very small file size at 39KB.
In order to test this out more. I’ve re-run this test several times passing out different flags.
Quality compression mode -85
You’ll see the JXL actually made it MUCH WORSE with the 85 quality level! Meaning that when it comes to ‘quality’ JXL is using a different scale then native JPG.
On the upside! File size quality is crazy-low for a quality 85 encode and beats AVIF!
Distance / MaxError -d 0.0
This is the command to make a JXL mathematically lossless. This is impressive in the respect that doing this in PNG would result in a 450KB file. And yet, it STILL beats JPG -q80 by 21KB. So, if you’re a web admin who wants to be ultra-conservative with converting your entire site to JXL. Using -d 0.0 is the way to go!
Distance / MaxError -d 1.0
This is what is described as ‘visually lossless’ or perhaps a quality 95 scale. Either way, it goes it comes in at 63KB which is only 3KB higher than WebP in our test example. Which is very good! When we looked at it ultra-close (We are talking pixel by pixel here kids) the only thing that’s slightly noticeable is the JPG artifacts that were already there getting messed with a little more. Which is what’s the worst that happens then JXL lives up to its statement of ‘visually lossless’
We don’t really care. We didn’t bother to measure it. Sure, cjxl is rather fast when it comes to encoding a file. Of course much faster than AVIF being the slowest in some cases taking almost a minute to encode. (Or 5-10 minutes for that animated GIF above.) But at the end of the day is that really important? I have a multi-core VPS that idles at 5-10 percent most of the day. With the way, the Cron.daily file works you have 24 hours to make the very best file. To us encoding, time is irrelevant as the end result is everything. Is it small? Does it look good?
We did find out that if you add the command –num_reps=XX to cjxl that it’s supposed to give you a better file. So in our script, we set it for 16 reps just to give our VPS something to do!:)
Download these files.
I have provided a link to the images we used in this article file so that you may download it and compare yourself just in case you think we’re pulling the file-size numbers out of our ass. You can also check my data too! The file was compressed with 7-zip to save space and also includes the following files:
We are also well aware thanks to jpeg.info that its resolution can go up to 1 billion which no other codec can do! But what’s that going to do for me the web administrator really? Do we really have the technology to edit a 1-billion by 1-billion pixel picture? Is there such a beast online as a 1-billion by 1-billion picture to test the limits of both browser and codec?
We will even admit that we did not test out HDR 10-bit/channel functionality or if it can really go up to 32-bit/channel color. We feel there are photography blogs that will probably dive into that aspect immediately for the lossy and lossless encoding of such files. After all, we feel all the new generation codecs are attacking the photography world for dominance which is why they’ll most certainly do better than codecs from the mid-90s.
If you go to their site they talk about making artwork off of the JXL library which produces very large and colorful abstract art pieces for only several bytes of data. And as impressive as that may be the practical use for website presentation is a little lacking. Perhaps using the JXL art generator for hyper-efficient user icons? Or placeholder images for blogging? Just some ideas we guess! They’re at least cool to look at so go check them out!
Finally, unlike just about every blog we’ve read. We’re not here to give you some fluff pieces about JpegXL and walk away. We are using it! Right now! Run a VPS and got Nginx? you can use it too by setting up a CRON.Daily job like we did in this article! Once you get Google Canary rocking. go to the home page and smash that “F12” button. Clear out Cache and Cookies and reload that bad boy and watch the JXLs come at you. The next question is, will we keep JXL as the first file to try during decoding out blog files?
The answer is:
Yes….. For now! – S
It will only affect nightly releases and we feel it’s important for users to test new standards out. JXL still feels like it needs to work out some of the defects happening when mapping high-quality lossy files. It’s a coin toss if JXL remains my script or AVIF, then WebP, and finally the 1990s standards.
We’d like to thank commenters BlueSwordM and Fabulous Monkey for setting us straight on limited palette JXL files with quickness by using lossless encode. Never really put ‘lossless’ together with ‘great for limited colors’ but hey. The more you know! Please understand that this is a developing technology. As such we may not have all of the information to carry out the decision right away. In fact, at the time of publishing this article new information has arrived which will allow us to test again.
Until next time, may server protect you!
+++END OF LINE!
8 thoughts on “JXL – JPEGXL and the web experience here.”
Hi It’s a very interesting blogpost :-)
JPEG-xl uses FUIF…Responsive Design – download only what is needed.
“…responsive by design implies that different people get a different final image depending on the resolution they need…”
From here –> https://cloudinary.com/blog/introducing_fuif_responsive_images_by_design#responsive_web_design
Though “YouTube-Monopoly-title.jpg.jxl” is 36505 bytes the jxl download might be even less than that when accessed from a small screen.
So the -p “progressive” flag has a usage especially if you are displaying high resolution images within a webspace.
Currently, i have progressive rendering turned off on my cron scripting right now. thus, whatever is compressed to is what is delivered. Even then the numbers are still impressive over traditional JPG!
Thanks for checking out this blog!
No, I think “-p progressive” is a different thing from “Responsive Design” in this case.
Not relevant imho.
Though the filesize might be 36505 bytes
Something in the jxl file header says…
send all of it for full size screen…
or send only half of it for half size screen…
or send only quarter of it for quarter size screen…
Instead of scrset…
srcset=”foo.bar 250w, foo.bar 400w,….. foo.bar 1600w” etc…
Maybe it would be necessary to monitor network traffic to see how many bytes are actually downloaded with a PC monitor, laptop, smartphone.
Jon Sneyers is the expert, not me :-)
Hello S-Config. I hope you are doing well today.
I just have some feedback regarding the article methodology itself:
1. For the 1st 15 color PNG with transparency, it would be better to use the lossless mode of JXL, as it performs much better in this kind of image than the normal lossy varDCT mode.
In fact, for any type of image with simple colors, shapes and graphics, it is better to always use CJXL in lossless mode as it performs better in the types of images we use PNG for anyway(lossless is activated by using -d 0.0)
2. The animation itself presents an interesting scenario in itself: AVIF will of course perform better since it can use its video coding tools to work its magic, as expected, and WebP lossless/APNG lossless have special modes which have good animation efficiency(lossy WebP isn’t very good for these types of animations, and lossless is usually better). JXL lossy performing poorly is also expected, with lossless performing well, but not much better than the GIF one due to its subtractive nature(JXL can do some sort of inter-coding, but its toolset hasn’t been activated yet).
3. One of the defining features of JXL is that lossless transcoding of JPEGs can be done, which means for any JPEG source, using that mode is an excellent idea to get more efficiency from storing JPEGs and as such, is the main mode I’d use for already well compressed JPEG encoded images(lossless transcoding of JPEGs is activated by default).
Hey, thanks for the feedback on this.
for issue number 1. It sounds like I need to run comparisons with PNGs similar to how I treat PNG<->WEBP conversion then. Cool! It looks like Bintu-Logo.png compresses down to 10.6kb like what Fabulous Monkey was doing with that -j 0.0 flag! Thank you very much! I’ll re-run the script tonight throughout my site to perform size comparisons between my old cjxl and new with lossless. Thanks so much on this! I’ll be sure to revise this article!
For scenario number 2. I’d like to try to run a comparison on the same level as what i do with AVIF . If the cjxl command supported y2m video like what I’m doing in the script (realistically I’m doing doing that because AVIFENC cannot support GIF encoding out the gate.) I would be happy to pass it through that to give it the same advantage that AVIF is getting.
Now for issue number 3. You are right, quality remains perfect with lossless jxl. but the size of the file is 111kb. Which granted! It’s smaller then the original JPG! But it did get a lot bigger then the 36kb lossy -q 85 one.
Anyhow, thank you for checking out my blog! I will re-run my compression for my site tonight!
Bintu logo Jxl is just 10kb tbh.
I was not able to open the 7z.. having some problems with it. But looking at the descriptions I’m guessing you’re running cjxl lossless then?
Hello Fabulous Monkey,
It looks like another commenter filled me in on using the -d 0.0 lossless for indexed palette PNG files. Which is perfect! It produced the same size you were getting. I’ll re-run the script tonight by doing a size comparison between -d 85 and -d 0.0 in an attempt to get the best of both worlds.