AOMediaCodec / libavif

libavif - Library for encoding and decoding .avif files
Other
1.53k stars 195 forks source link

Lossless avif worse than a bmp in a zip file #2434

Open uriesk opened 2 days ago

uriesk commented 2 days ago

I noticed that lossless libavif gets beaten by PNGs and regularly even by BMPs inside a zip file.

Like here is a screenshot of this repository, once as BMP in a ZIP file, and once as AVIF. Everything with default settings, only the lossless switch on avifenc. The zipped BMP has 406 kB, the AVIF has 412 kB. libavif.bmp.zip libavif.avif.zip

(Note that the only reason why i zipped the AVIF as well, is because github doesn't allow AVIF upload. You have to extract it.)

Meanwhile both WEBP and JXL get the file down to below 250 kB in lossless mode. So i don't think that this is intentional.

vrabaud commented 2 days ago

Hi, thx for the report. AVIF lossless is lossy with not quantization which makes it work great for photos but not for artificial content, where other algorithms perform better. Still, using the default arguments with libaom as an encoder, I get:

avifenc -q 100 /tmp/test.png /tmp/tmp
Successfully loaded: /tmp/test.png
Quality set to 100, assuming --lossless to enable warnings on potential lossless issues.
WARNING: [--lossless] Input data was RGB and matrixCoefficients isn't set to identity (--cicp x/x/0); Output might not be lossless.
AVIF to be written: (Lossy)
 * Resolution     : 1363x1512
 * Bit Depth      : 8
 * Format         : YUV444
 * Alpha          : Not premultiplied
 * Range          : Full
 * Color Primaries: 1
 * Transfer Char. : 2
 * Matrix Coeffs. : 6
 * ICC Profile    : Absent
 * XMP Metadata   : Absent
 * Exif Metadata  : Absent
 * Transformations: None
 * Progressive    : Unavailable
Encoding with codec 'aom' speed [6], color quality [100 (Lossless)], alpha quality [100 (Lossless)], tileRowsLog2 [0], tileColsLog2 [0], 72 worker thread(s), please wait...

Encoded successfully.
 * Color total size: 335309 bytes
 * Alpha total size: 0 bytes
Wrote AVIF: /tmp/tmp

335kB is not the 412kB you mention. Which command line did you use? You can also change the speed: ./avifenc -q 100 -s 0 /tmp/test.png /tmp/tmp does give 250kB like the other codecs. I did not use -l, which is invalid. Even -s 0 only gives 308 kB

You can also push WebP to get an even lower size:

cwebp -lossless -m 6 -q 100 /tmp/test.png
File:      /tmp/test.png
Dimension: 1363 x 1512
Output:    204782 bytes (0.79 bpp)
Lossless-ARGB compressed size: 204782 bytes
  * Header size: 1996 bytes, image data size: 202760
  * Lossless features used: SUBTRACT-GREEN
  * Precision Bits: histogram=5 cache=10
uriesk commented 2 days ago

Hello, i used avifenc --lossless input.png output.avif and avifenc --version gives me

Version: 1.0.4 (dav1d [dec]:1.4.3, aom [enc/dec]:v3.9.0, rav1e [enc]:0.7.1 (UNKNOWN), svt [enc]:v2.1.0)
libyuv : unavailable

What i noticed is that the larger the image is, the more likely lossless avif is to beat zipped bmp files. This one has 1363x1512, which is on the larger end already. I made a screenshot of your reply and tested it with that.

time { magick post.png post.bmp; zip post.bmp.zip post.bmp; } takes 0.141s and produces a post.bmp.zip with 235 kB

time avifenc --lossless post.png post.avif takes 8.527s and produces a post.avif with 291 kB

time avifenc -q 100 -s 0 post.png post.avif takes 1m18.503s and produces a post.avif with 202 kB

While it is nice that the -s 0 produces a smaller output than a bitmap in a zip file, over 1 min of encoding is quite a lot. In comparison:

time cjxl -q 100 post.png post.jxl takes 0m4,305s and produces a post.jxl with 177 kB, so it's even beating the -s 0 avif by over 14% while encoding 16 times faster.

I attached all the files here: aviftest.zip

uriesk commented 2 days ago

which makes it work great for photos but not for artificial content

To test this one, i downloaded the current bing.com wallpaper and converted it to png, which outputed a 3.8 MB PNG file. I converted it to a zipped bmp file and it has 4.8 MB. I converted it to a lossless AVIF and it has 4.4 MB.

While lossless avif is 10% more effective than zipping a bmp file in this case, it is also 16% larger than the PNG file. There seems to be something wrong with lossless avif. If that is by design, then this is a bit sad, since webp has a great lossless mode.

Here the files of this test: aviftest2.zip

vrabaud commented 2 days ago

You are right, in a way, it is by design because there is no specific path for lossless. E.g., WebP lossless is totally different from lossy.

At least, the last photo you sent can be compressed to 2.9 M using -s 0, which is closer to the 2.6M from WebP.

y-guyon commented 1 day ago

@uriesk May I know why -q 100 is necessary? Could -q 90 or another high quality value be enough visually for your use case?

uriesk commented 1 day ago

@y-guyon Generational loss. Most images on the web are PNGs. If we would want them to be lossy, we wouldn't use PNG. https://w3techs.com/technologies/overview/image_format