strukturag / libheif

libheif is an HEIF and AVIF file format decoder and encoder.
Other
1.77k stars 306 forks source link

Unsupported color conversion for large AVIF image since v1.19.0 #1389

Closed kleisauke closed 5 days ago

kleisauke commented 6 days ago

With this test image: https://github.com/libvips/libvips/blob/master/test/test-suite/images/17000x17000.avif

v1.19.0 and v1.19.3 - decoding fails with the following error:

$ heif-dec 17000x17000.avif x.png
File contains 1 image
Could not decode image: Unsupported feature: Unsupported color conversion

v1.18.2 - decoding succeeds:

$ heif-dec 17000x17000.avif x.png
File contains 1 image
Written to x.png
$ file x.png
x.png: PNG image data, 17000 x 17000, 8-bit/color RGB, non-interlaced

Interestingly, the AVIF image decodes correctly when outputting to a JPEG image on both versions, suggesting that this issue might be related to the following change in the v1.19.0 release notes:

  • decoding is faster, especially if you let libheif decide on the best colorspace to work in by passing heif_colorspace_unknown and heif_chroma_unknown to heif_decode_image(). It will then use the input colorspace and avoid unnecessary conversions.

Let me know if I should perform a git bisect.

farindk commented 6 days ago

I identified that the reason for this is the security limit on the maximum memory allocation size when allocating the output image memory: https://github.com/strukturag/libheif/blob/e18c15e1365eeee83e7ee1da8376f33a88e176b6/libheif/pixelimage.cc#L260-L262

The individual Y,Cb,Cr planes of the input are below the allocation limit, but the combined, interleaved RGB image exceeds the limit in the color conversion. Because of this, the error only happens when exporting to an RGB format, but exporting to JPEG works.

The error message is misleading and I'll improve that.

Unfortunately, the security check uses the global limits and adding the command line option --disable-limits does not work in this case. I'll work on that.

farindk commented 6 days ago

Now, it returns this error instead: Could not decode image: Memory allocation error: Security limit exceeded: Allocating 867136015 exceeds the security limit of 536870912 bytes

farindk commented 6 days ago

And now it decodes with --disable-limits.

kleisauke commented 5 days ago

Thanks! I confirm that it decodes correctly with --disable-limits and would otherwise give a proper error message without that flag now.

Note to self: libvips should align the unlimited load flag to libheif's --disable-limits flag. https://github.com/strukturag/libheif/blob/8a139a67ad3ceaaa236ae3c62d32f652e4e5f600/examples/heif_dec.cc#L800-L802

See e.g. commit https://github.com/kleisauke/libvips/commit/5bf7cc60b080d397ef62d37840b664a0bafbc76b. However, this should likely be done after the loader/saver is revised to a tile-based one.

farindk commented 5 days ago

Thanks for the test file and the confirmation.