-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Description
What did you do?
Load a large TIFF created previously with Pillow.
What did you expect to happen?
Load without error.
What actually happened?
Traceback (most recent call last):
File "large_tiff_bug.py", line 15, in <module>
img.load()
File "/Users/mlg/code/stocks-map/venv/stocks-map/lib/python3.8/site-packages/PIL/TiffImagePlugin.py", line 1088, in load
return self._load_libtiff()
File "/Users/mlg/code/stocks-map/venv/stocks-map/lib/python3.8/site-packages/PIL/TiffImagePlugin.py", line 1192, in _load_libtiff
raise OSError(err)
OSError: -9
What are your OS, Python and Pillow versions?
- OS: macOS 11.2.3
- Python: 3.8.8
- Pillow: 8.1.2
- PIL.features.version_codec('libtiff'): 4.2.0
Code:
from PIL import Image
width = 30_000
height = 35_792
print(f'creating test image: {width:,} x {height:,} = {width * height:,}; {width * height * 2:,} bytes')
img = Image.new( 'I;16', (width, height) ) # I'm using 16 bit greyscale
img.save( '_tmp.tiff', compression='tiff_adobe_deflate' ) # add zip compression, so filesize doesn't get out of hand
print()
print(f'loading test image')
Image.MAX_IMAGE_PIXELS = 1_800_000_000
img = Image.open('_tmp.tiff')
img.load()I believe we are hitting the size limit limit here, because reducing height to 35_791 in the above code makes it work.
30.000 x 35.792 x 2 bytes = 2.147.520.000 bytes -> error -9 (IMAGING_CODEC_MEMORY)
30.000 x 35.791 x 2 bytes = 2.147.460.000 bytes -> works
This leads me to believe that INT_MAX is 2.147.483.647, so it's an int32 (32 bit, signed), where it could be 64 bit (on supported platforms) and unsigned to maximize the size of loadable images.
In addition I noticed the same image CAN be loaded by pillow when re-saved in Preview.app (or Affinity Photo for that matter). It looks like Preview.app saves it in strips of a single row each, which adds some metadata but gets around the memory limit. Pillow seems to save a single strip containing all rows. So it would be cool to be able to control layout of strips when saving tiffs, as it would allow to get around the memory problem as well.
Attachment: Example TIFF + TIFF saved with Preview.app