The Alliance for Open Media has come up with the image format AVIF, that got a lot of praise from Netflix. It’s based on the AV1 video codec. It promises to fit high quality images in even smaller file sizes than WebP or JPEG.
Support for AVIF has recently landed in Chrome and Cloudflare is actively marketing them featuring it as well.
As I have recently experimented a little with image processing services, I came up with a test setup to compare the different formats.
In case the AVIF images in this article dont’ show up correctly, please use a browser supporting AVIF today (e.g. Chrome).
In my test setup I am using the following libraries in the specified versions:
h2non/bimgwith some of my own patches to support AVIF as noted in https://github.com/h2non/bimg/pull/356 as a wrapper around libvips.
libvips 8.10.2: All calls to libjpeg, libwebp or libheif (rav1e for AVIF encoding) will go through libvips.
libheif 1.9.1(Passes AVIF calls to
Setting the “
quality” or “
compression” to a fixed value in libwebp, libjpeg or rav1e for AVIF encoding will create fairly differently sized images and results that are not really comparable.
I am aiming to produce image files in the different formats that have comparable file sizes, so we can visually inspect the perceived quality from the same amount of image data.
This is an image taken by me on a sunny day closeby Fallbodensee in Switzerland. It features sharp edges around the mountains as well as soft areas on the lake and the sky.
Uncompressed at 1400x933px it is 820kb in size. This is a bit too much data for my taste to feature this image on a website.
I’m aiming to reduce the image size to just 10% of the original image (80kb). After some experimentation this has also proven to be a size where artifacts become visible.
JPEG (81kb) at 37% quality, generated in 191ms.
WebP (82kb) at 52% quality, generated in 303ms.
AVIF (81kb) at 44% quality, generated in 1417ms
Apart from the visual differences in my tests with the aforementioned stack is that generating AVIF images takes a higher amount of time longer than generating JPEG or WebP images.
When I started out my tests a single AVIF image could take around 6 seconds to be generated.
libvips (as of 8.10.2) support passing a speed parameter, that will change how much CPU effort goes into generating the image. Think of it like the compression value of a gzip. More effort = better compression.
Since I want to compare the image formats with a target use-case being the web, I have opted to go with the fastest speed
8 as any introduced latency isn’t desirable for the web.
Even if the results can be cached, the first response should execute in a timely fashion. Via the
speed setting I got my response times down from the initial 6 seconds to 1.5 seconds, which I’d consider reasonable for the web.
Processing speed is something that is actively worked on for the
rav1e encoder and the
0.4.0-alpha already made a near 100% improvement in that area. Since it’s an alpha and not yet integrated in libvips I am not using it for this comparison just yet. Going from 1.5s to 750ms would arguably be great for any request-response scenario.
To check how much on an impact the “
speed” setting has, I generated the same image at the slowest speed
AVIF (80kb) at 51% quality, generated in 3 minutes
Yes, you read that right - 3 minutes to process the image into AVIF at slowest speed for best compression on the same machine that processes the JPEG in 120ms.
Interestingly I was able to up the quality by 7%, compared to the fastest
speed setting - certainly the setting has a direct effect on the compression.
With this performance the best compression and slowest speed setting of the AVIF encoder is not a setting I’d turn on in a request-response scenario.
You can already visibly see the sky and lake colours visibly losing quality and showing artifacts on the JPEG compared to WebP or AVIF.
Here’s a section of the water. From first to last: Original, JPEG, fast AVIF, slow AVIF, WebP.
What we see is some surface detail staying in the JPEG and causing badly looking artifacts, whilst WebP and AVIF have a little lower detail and very low artifacts on the water surface.
This is similar to the situation in the sky parts of the image, where JPEG adds some sharp edges.
Impressively there’s quite a bit of a difference in how washed out the fastly generated AVIF is compared to the slowly generated AVIF that maintains some more detail.
In any of the compressed image formats, there is a lot of detail lost on the side of the mountain.
The grainy artifacts of the JPEG are visually quite okay in this edge case - but the overall image quality has lost out to its competitor formats already due to the visible artifacts in the more smooth areas, like the sky and the water.
AVIF and WebP look to be on par here. The AVIF format with the highest CPU effort again retaining a little more detail.
Visually AVIF definitely blows JPEGs out of the water at high compression rates and in certain scenarios is more visually pleasing than WebP.
At the scale of Netflix it’s an absolutely sane choice - it’s a great image and video format!
If you want your server to deliver AVIF images currently you may still be looking at a lot of patches across the stack as the file type may not correctly be detected by your webserver or application etc.
To compress images into AVIF you are also still looking at setting up a number of libraries from source.
With only 1 browser supporting AVIF currently, it certainly is not ready for prime time.
WebP has seen a very slow going (10 years) gradual adoption and is only now considered a format that can be used widely - the needed libraries and file type support should by now be part of any linux distribution you want to use.
If your main business is delivering images or video and you may also be in a space where you control the client (think e.g. instagram/Netflix) AVIF is certainly an option to save bandwidth whilst maintaining image quality.
This is certainly what it’s meant for. Until the libraries are more widely adopted I’d hesitate to make the investment to support AVIF just yet as a “regular” company or software developer.
Only 25% of browsers support AVIF and about 85% support WebP globally.
They all have one thing in common: They will announce in the request header that they do so:
On the backend side its up to you to read out this information and serve the most optimal image format.
In case you don’t control the backend, the
<picture> html tag is available in 96% of browsers globally and it allows us to specify the best image format for any given client.
<picture> <source type="image/avif" srcset="image/foo.avif"> <source type="image/webp" srcset="image/foo.webp"> <source type="image/png" srcset="image/foo.png"> </picture>
The picture tag also allows providing different resolutions for different picture sizes (e.g. for different devices). This is a great way to save bandwidth and making sure we’ll always use the optimal image format for the client. ⭐️
More and more CDNs (like aforementioned Cloudflare), image processing services and OSS projects like imgproxy may support AVIF without you going through the hoops of fixing webservers and compiling the necessary libraries.
In light of more and more companies going “serviceful” I’d argue that is the right path if you want AVIF support right now, as alternatively you are looking at a fairly large amount of work.
The rate of adoption of AVIF is unknown at this stage, but I’d certainly expect that over time it’ll become as simple and fast to convert to AVIF as it is today to convert to WebP. The amount of work to support AVIF will decline eventually and thus my recommendation may change over time.
I am currently working on an open-source release of the image processing server I used for this article. This may help you to have an option to produce AVIF images without compiling libraries and patching webservers etc.
Stay tuned for more and please ask away in the comment section below!
Special shoutout to all the maintainers behind the libraries I was using for this!