Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TiffImagePlugin doesn't honor the ROWSPERSTRIP tag value #6607

Closed
agiudiceandrea opened this issue Sep 22, 2022 · 4 comments · Fixed by #7654
Closed

TiffImagePlugin doesn't honor the ROWSPERSTRIP tag value #6607

agiudiceandrea opened this issue Sep 22, 2022 · 4 comments · Fixed by #7654
Labels

Comments

@agiudiceandrea
Copy link

agiudiceandrea commented Sep 22, 2022

What did you do?

I tried to save a PIL.Image.Image (mode=RGBA, size=335x333, 8 bits per sample) to a TIFF file with LZW compression and 9 rows per strip.

img.save('output.tiff', compression='tiff_lzw', tiffinfo={278: 9})

What did you expect to happen?

The file to be saved as a TIFF file with LZW compression and 9 rows per strip.

What actually happened?

The file was saved as a TIFF file with LZW compression and 48 rows per strip.

What are your OS, Python and Pillow versions?

  • OS: Windows 10 64-bit
  • Python: 3.9.5
  • Pillow: 9.2.0
@radarhere radarhere added the TIFF label Sep 22, 2022
@radarhere
Copy link
Member

As context, ROWSPERSTRIP has been set by TiffImagePlugin since PIL.

If I make a change to allow ROWSPERSTRIP to be set by the user, the following test code starts failing.

def test_write_metadata(tmp_path):
"""Test metadata writing through the python code"""
with Image.open("Tests/images/hopper.tif") as img:
f = str(tmp_path / "temp.tiff")
img.save(f, tiffinfo=img.tag)

The error is

raise NotImplementedError("multistrip support not yet implemented")

@agiudiceandrea
Copy link
Author

agiudiceandrea commented Sep 24, 2022

@radarhere, thanks.
Opening an image with a certain number of rows per strip and just saving it without any manipulation and with the same tags:

sourceimg = Image.open('input.tiff')
tiffinfo = sourceimg.tag_v2
sourceimg.save('output', tiffinfo=tiffinfo)

then the saved image will have a different number of rows per strip.

Anyway, changing the TiffImagePlugin.ROWSPERSTRIP tag number to another bogus non conflicting tag number, e.g. 10, it is possible to trick the TiffImagePlugin, so it will write its calculated value of the rows per strip to such bogus tag number 10 so the tiff library will use the rows per strip provided by the tiffinfo:

sourceimg = Image.open('input.tiff')
tiffinfo = sourceimg.tag_v2
TiffImagePlugin.ROWSPERSTRIP = 10
sourceimg.save('output', tiffinfo=tiffinfo)

However, this is not a complete workaround, as the saved image will have a spurious tag number 10.

@radarhere
Copy link
Member

Changing TiffImagePlugin.ROWSPERSTRIP is an inventive idea, but I think it might break reading TIFF files afterwards.

If you're looking for a workaround, see what you think of this.

from PIL import Image, TiffImagePlugin

def setRowsPerStrip(im, rows_per_strip):
    TiffImagePlugin.WRITE_LIBTIFF = True
    
    bits = TiffImagePlugin.SAVE_INFO[im.mode][4]
    stride = len(bits) * ((im.size[0] * bits[0] + 7) // 8)
    TiffImagePlugin.STRIP_SIZE = rows_per_strip * stride

im = Image.open("Tests/images/hopper.tif")
setRowsPerStrip(im, 110)
im.save("out.tif")

@radarhere
Copy link
Member

I've created #7654 to resolve this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants