Skip to content

Loading large TIFF fails with OSError: -9 #5370

@martinleopold

Description

@martinleopold

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    AnacondaIssues with Anaconda's PillowTIFF

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions