fdintino / pillow-avif-plugin

A pillow plugin that adds avif support via libavif
BSD 2-Clause "Simplified" License
77 stars 12 forks source link

Fail to save large AVIF image #8

Open vinlyx opened 2 years ago

vinlyx commented 2 years ago

https://github.com/fdintino/pillow-avif-plugin/blob/ac4789d9e2d1774dff2a90894cbda2d06c9d92c8/src/pillow_avif/_avif.c#L483

Hi @fdintino, I am trying to use avif plugin to convert a large TIFF image to AVIF format. Unfortunately, I got a RuntimeError: File "/xxx/Python-3.9.4/lib/python3.9/site-packages/pillow_avif/AvifImagePlugin.py", line 240, in _save enc.add( RuntimeError: rgb data is incorrect size: 119151 * 49716 (1628743820) != 5923711116

The raw TIFF image is 39717 x 49716 in RGB mode. I have tried to debug the error and find out it may due to an uint32 overflow issue. The width and height of avifRGBImage are defined as uint32_t. In this case 39717 x 49716 is larage than 4,294,967,295, so it generate a overflowed result (1628743820).

if (rgb.rowBytes * rgb.height != size) { Convert rgb.rowBytes or rgb.height uint64_t during this operation may fix the issue, but I am not sure whether it will cause any issue in the following step.

Hope this analysis will help to fix this error. Thanks!

fdintino commented 2 years ago

rgb.rowBytes and rgb.height are uint32_t in libavif, and I believe the width and height themselves have limits well below 232. But we can cast them to Py_ssize_t in that multiplication expression to fix this specific overflow.

fdintino commented 2 years ago

So...I can fix the issue in this plugin. But it appears that libavif has a limit of 16384x16384 (228 pixels). So although encoding your image would no longer fail with this particular error, you still would not be able to encode the image as AVIF.

cdgriffith commented 2 years ago

Just adding a detail that the specifications don't allow for huge images with AV1.

NOTE: Following [AV1] level definitions, coded image items compliant to the AVIF Advanced profile may not have a number of pixels greater than 35651584, a width greater than 16384 or a height greater than 8704. It is still possible to use the Advanced profile to create larger images using grid derivation.

I do not see further reference to how to achieve a "grid derivation" AVIF image.

fdintino commented 2 years ago

libavif supports image grids...I had been meaning to look into exposing that in the codec. I'll see what I can do.

vinlyx commented 2 years ago

libavif supports image grids...I had been meaning to look into exposing that in the codec. I'll see what I can do.

That would be amazing~! But I know little about image grids feature. Is there any documentation or example about that? Thanks!