Skip to main content

Linear Color Analysis of Modern Image Formats

It has been a standard for a long time that web image should have delivered in sRGB color profile. This was chosen mainly for compatibility reasons, because most of the browsers back then didn't have a proper color management, therefore color profiles were ignored and can be incorrectly rendered -- as without a color profile (aka. untagged) any image will be considered as sRGB. This was not a concern since most of the consumer displays at that time are barely even have full coverage of sRGB gamut.

I remebered during my college days when I still have a side job to calibrate monitors (that was way back in 2012-ish, when Spyder 4 was released), most of my customers' screen only have around 70% sRGB coverage, I even found some that went as low as 60%! Ouch! Wide gamut, or even a full sRGB coverage monitors were pipedream to most of us, we can only see them in big studios and production houses.

Anyway, I digress with my personal story.

And thus, since the advent of wide gamut displays and HDR these days, color management in browsers became an important aspect. We are no longer bounded by sRGB profile, many new wide-gamut profiles are emerged that can accomodate this shiny new display (pun intended), such as DisplayP3 and Rec.2020 profiles. Therefore, now major browsers have a proper color management to properly view those images, also to pave the road for HDR viewing support.

Well, actually in photography section we already got used to work with wide-gamut profiles such as Adobe RGB and ProPhoto RGB for a pretty long time too.


An Unideal Scenario - Lossy Compression

Now imagine this scenario, you're just a photographer working with these profiles (say for my example here, darktable's Linear ProPhoto RGB), and you just forget to convert the pictures into a web-friendly profile when deploying them. How well do these modern image codecs handle this? In my experience, wide-gamut linear profiles often hits hard for a lossy image compression... Let's investigate!

For the test image, I will be using this picture of color patches from an old XRite ColorChecker Passport. This was shot with Nikon D810 + 105mm f/2.8G VR Micro-Nikkor lens @ f/8.0 ISO 64 under Broncolor Siros lights.

Lossless 16bpc(48bpp) PNG with Linear ProPhoto RGB - 20.6 MiB

Conversion tools (all with metadata intact, minor impact though):

  • JPEG XL: cjxl 0.10.3
  • AVIF: avifenc 1.1.1
  • WebP: Krita 5.2.3 WebP export

All encoding done with default parameters, only changing the quality parameter.

For the plotting tool I'll be using is my own Color Gamut Plotter written in Qt, however I'm not suggesting that you should try it since it's still buggy and unwieldy at best xD, but feel free to try it if you insist. I also have a showcase video on YouTube. Currently it has support to only read jpg, png, tiff, and jxl as an input. Originally Qt also have webp but I disabled it since I haven't been able to upgrade it to mitigate that one big CVE-2023-4863. Therefore you'll see why AVIF and WebP test files used for plotting is a decoded image (to 16bpc PNG). As for the colorspace display, I will be using peceptual space, Oklab. For JPEG XL, this tool decodes with libjxl 0.10.2 and pulling the pixel data as 32-bit float, therefore you might see the results below that it sometimes gives more total unique colors than the RAW PNG.

RAW - Color plot
With Post-2014 ColorChecker targets
RAW - Distribution / occurrence plot
Brighter = more pixels in that specific color
note

Correct me, I'm not quite sure if "Distribution / occurrence plot" is the correct term for the second plot. I don't know what's the proper scientific term for it.

Not a perfect calibration, but some was close enough to the colorchecker targets, darktable reported at Max ~4.06dE and Avg ~1.92dE using their color calibration module. We can see how the colors are clumped pretty nicely on the distribution plot.


Comparison At ~1bpp

Color Plot

RAW ref.
JPEG XL ~1.048bpp
AVIF ~1.155bpp
WebP ~1.114bpp

Other than WebP limitation (8bpc) that shows a severe quantization errors, the color plot looks pretty similar. I don't see a discernible shift in color for both JPEG XL and AVIF. However AVIF does seems to clump colors even more, seems like smoothing out the noises? Let's dig more...

Distribution Plot

RAW ref.
JPEG XL ~1.048bpp
AVIF ~1.155bpp
WebP ~1.114bpp

We can see how 8bpp (WebP) is barely even suitable for wide-gamut and HDR, only 46,214 colors remain... Other than that, JPEG XL seems to be doing quite well at preserving the color distribution, it has a total unique color count of 4,377,184. On the other hand, AVIF is showing a smudge in color distribution, a slight quantization errors around neutral colors, and having a much smaller unique color count (1,581,283), either due to lower precision (12bpc) or it's indeed softening the colors more.

Close Up Crops & Result Images

A plot may look cool and such, but how will it differ visually? Here goes a crop to compare:

~1bpp comparison Animation
This has been converted to 8bpc sRGB for viewing compatibility

Here we can see AVIF got quite a lot of smoothing especially on dark areas, and WebP is starting to look like a blocky mess. While JPEG XL holds quite well maintaining color accuracy and textures.

And these are individual result images:

However, you may notice that these result images may look different than the crop image above that I've been converted into sRGB, since these result images are still in Linear ProPhoto RGB profile and may render differently depends on the browser. Ideally, these images should look all the same in a properly color managed browsers.


Comparison At ~0.6bpp

Few benchmarks that I saw show that AVIF works quite well in low bpp settings. Let's see how it fares in this worse scenario.

Color Plot

RAW ref.
JPEG XL ~0.600bpp
AVIF ~0.617bpp
WebP ~0.618bpp

Lowering the quality further, both JPEG XL and AVIF shows that they narrowing the color spreads even more, indicating more noise smoothing I presume? While JPEG XL mostly have proportional reductions in this perceptual Oklab space, AVIF have some colors squished unproportionally, can be seen noticeably in that green and blue patches. I'm not sure how it implies to the overall color accuracy, but the median point of those color patches on both JPEG XL and AVIF didn't seem to change significantly. And let's ignore WebP result...

Distribution Plot

RAW ref.
JPEG XL ~0.600bpp
AVIF ~0.617bpp
WebP ~0.618bpp

JPEG XL still holds quite well at 0.6bpp, clocking in at 4,373,618 total unique colors, it didn't seem to differ much from 1bpp result. AVIF shows more prominent quantization errors compared to 1bpp result and seems to 'bleed' the colors even more now, clocking at 1,246,309 total unique colors, an apparent reduction from 1bpp result.

Bonus: JPEG ~0.6bpp

JPEG ~0.605bpp
JPEG ~0.605bpp - distribution

Mmm, look at that beautiful-yet-nasty 8-bit quantization~ Even so, they still have much more color than WebP! (84,809)

Close Up Crops & Result Images

~06bpp comparison Animation
This has been converted to 8bpc sRGB for viewing compatibility

In high contrast textures, all formats still performs well to retain the details. But on the low contrast and dark areas, only JPEG XL that can retain the details well. AVIF smooth out almost everything, and most of the color patches are now almost textureless blob of color. While WebP and JPEG is a whole blocky mess now.

And these are individual result images:

However, you may notice that these result images may look different than the crop image above that I've been converted into sRGB, since these result images are still in Linear ProPhoto RGB profile and may render differently depends on the browser. Ideally, these images should look all the same in a properly color managed browsers.


Conclusion

Both JPEG XL and AVIF perform quite well on retaining color accuracy, but JPEG XL is absolutely have an edge for this scenario, barely losing any details even though it was given a wide-gamut, linear color profile. It's always a pleasure to see image codec / format with great color profile awareness!

Now, I might say that this is an 'unideal' scenario. But how long 8bpc sRGB will stand as an 'optimal' profile and bit depth? Yes, while linear TRC/gamma might not a good idea for web delivery, but as I said before that consumer HDR display is already here, with all confusing standards to choose from (PQ, HLG, etc.), it's beneficial to have an image format that can still compress wide-gamut spaces and/or various TRC/gamma efficiently. And in lossy JPEG XL case, it's even less likely to be bothered by input image's bit depth, since it already store the compressed pixel data in 32-bit float (XYB) internally.


note

Just saying this disclaimer once again, I'm just an amateur color enthusiast with quite limited scientific knowledge about color science and human visual. Therefore, this article might have some errors in both writing and testing methodology. If you found some (errors), don't hesitate to poke me!