Ran a snippet of code, see below.
The script to complete without error.
Stack trace, see below.
Pillow==3.4.2
(also fails with Pillow==3.5.0.dev0)
Python 3.5.2
Please include code that reproduces the issue and whenever possible, an image that demonstrates the issue. The best reproductions are self-contained scripts with minimal dependencies. If you are using a framework such as plone, django, or buildout, try to replicate the issue just using Pillow.
from io import BytesIO
from contextlib import closing
from PIL import Image
image = Image.open('phototest.tif')
print(image)
with closing(BytesIO()) as f:
image.save(f, image.format or 'JPEG')
value = f.getvalue()
Where the image can be found here, or download it with this command:
curl "https://github.com/tesseract-ocr/tesseract/blob/master/testing/phototest.tif?raw=true" > phototest.tif
The output is:
<PIL.TiffImagePlugin.TiffImageFile image mode=1 size=640x480 at 0x7F37D8546E10>
Traceback (most recent call last):
File "try.py", line 9, in <module>
image.save(f, image.format or 'JPEG')
File "/usr/local/lib/python3.5/dist-packages/PIL/Image.py", line 1698, in save
save_handler(self, fp, filename)
File "/usr/local/lib/python3.5/dist-packages/PIL/TiffImagePlugin.py", line 1487, in _save
offset = ifd.save(fp)
File "/usr/local/lib/python3.5/dist-packages/PIL/TiffImagePlugin.py", line 758, in save
entries.append((tag, typ, count, data.ljust(4, b"\0"), b""))
AttributeError: 'tuple' object has no attribute 'ljust'
Minimal repro is:
from PIL import Image
im = Image.open('phototest.tif')
im.save('tmp.tif')
It's 3.x only, this works in 2.7. It succeeded before the great metadata rewrite of Pillow 3.0.
Error is in a metadata entry:
Tag 34377, Type: 1, Value: ("8BIM\x03\xed\x00\x00\x00\x00\x00\x10\x00\xc8\x00\x00\x00\x01\x00\x01\x00\xc8\x00\x00\x00\x01\x00\x018BIM\x03\xf3\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x008BIM'\x10\x00\x00\x00\x00\x00\n\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02",)
save: PhotoshopInfo (34377) - type: byte (1) - value: <table: 70 bytes>
and in 3.5:
Tag 34377, Type: 1, Value: ((b"8BIM\x03\xed\x00\x00\x00\x00\x00\x10\x00\xc8\x00\x00\x00\x01\x00\x01\x00\xc8\x00\x00\x00\x01\x00\x018BIM\x03\xf3\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x008BIM'\x10\x00\x00\x00\x00\x00\n\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02",),)
save: PhotoshopInfo (34377) - type: byte (1) - value: ((b"8BIM\x03\xed\x00\x00\x00\x00\x00\x10\x00\xc8\x00\x00\x00\x01\x00\x01\x00\xc8\x00\x00\x00\x01\x00\x018BIM\x03\xf3\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x008BIM'\x10\x00\x00\x00\x00\x00\n\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02",),)
Any updates on this ?
Was affected by this issue today (pillow 4.2.1).
This is still broken for me. Pillow 7.0.0
>>> im.save('/tmp/WhiteRim.tiff', compression='raw')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.6/dist-packages/PIL/Image.py", line 2102, in save
save_handler(self, fp, filename)
File "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py", line 1629, in _save
offset = ifd.save(fp)
File "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py", line 865, in save
result = self.tobytes(offset)
File "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py", line 828, in tobytes
entries.append((tag, typ, count, data.ljust(4, b"\0"), b""))
AttributeError: 'tuple' object has no attribute 'ljust'
I'm having this same issue with Pillow 7.0.0. But oddly the same code works fine on my Mac, but not on my AWS lambda instance.
Traceback (most recent call last):
File "/var/task/lambda_function.py", line 121, in lambda_handler
img.save(local_compressed, extension, quality=IMAGE_COMPRESSION_QUALITY)
File "/var/task/PIL/Image.py", line 2102, in save
save_handler(self, fp, filename)
File "/var/task/PIL/TiffImagePlugin.py", line 1629, in _save
offset = ifd.save(fp)
File "/var/task/PIL/TiffImagePlugin.py", line 865, in save
result = self.tobytes(offset)
File "/var/task/PIL/TiffImagePlugin.py", line 828, in tobytes
entries.append((tag, typ, count, data.ljust(4, b"\0"), b""))
AttributeError: 'tuple' object has no attribute 'ljust'
'tuple' object has no attribute 'ljust'
@aaronmeierx @TheJKFever What Linux version are you using? Can you reproduce it with the image from the PR [1]? If not, please can you attach your problem image? Which Python version are you using? Does it work for you with Pillow 4.3.0? How about intermediate versions?
[1] https://github.com/python-pillow/Pillow/blob/master/Tests/images/issue_2278.tif
I cannot reproduce with Alpine and Pillow 7.0.0 and that image:
[email protected]:/var/www/html $ cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.11.3
PRETTY_NAME="Alpine Linux v3.11"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"
[email protected]:/var/www/html $ python3
Python 3.8.1 (default, Dec 30 2019, 15:43:37)
[GCC 9.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from PIL import Image
>>> Image.__version__
'7.0.0'
>>> im = Image.open("issue_2278.tif")
>>> im
<PIL.TiffImagePlugin.TiffImageFile image mode=1 size=640x480 at 0x7F9BA46C6130>
>>> im.save("temp.tif")
For the record, the original image appears to have moved to https://github.com/tesseract-ocr/test/blob/master/testing/phototest.tif?raw=true
Closing, as we don't have the images to reproduce the re-opened form of this. If they can be supplied, this can be re-opened.
I'll probably submit a PR later (I think I have another issue I need to look into and if it's related, I'll roll them both together), but for now, for anyone who's stuck on this, I spent a LOT of time tracking it down today. My monkeypatch fix is:
from PIL.TiffImagePlugin import ImageFileDirectory_v2, TiffTags
def _monkey_write_undefined(_, value):
if isinstance(value, tuple) and len(value) == 1:
return value[0]
else:
return value
ImageFileDirectory_v2._write_dispatch[TiffTags.UNDEFINED] = _monkey_write_undefined
This is because the call to ImageFileDirectory_v2.tobytes(…) tries to:
values = value if isinstance(value, tuple) else (value,)
data = self._write_dispatch[typ](self, *values)
When typ=7, this goes to write_undefined which returns the value; but the data.ljust() call below expectes a bytes object.
It doesn't happen with the linked test image, above. I have it happening with several images that I can't share (client images), but here's some data from one of these images in case it helps:
❯ nix-shell -p imagemagick --run 'identify broken.tif'
broken.tif TIFF 4800x6000 4800x6000+0+0 8-bit sRGB 82.4212MiB 0.000u 0:00.005
identify: Incompatible type for "RichTIFFIPTC"; tag ignored. `TIFFFetchNormalTag' @ warning/tiff.c/TIFFWarnings/976.
❯ file broken.tif
broken.tif: TIFF image data, big-endian, direntries=22, height=6000, bps=0, compression=none, PhotometricIntepretation=RGB, orientation=upper-left, width=4800
Photoshop 2020 reports that this image is from Adobe Photoshop CC 2018 (Macintosh).
FWIW, I think this issue should be reopened, but I understand the difficulty of doing so without a test image/file.
Most helpful comment
This is still broken for me. Pillow 7.0.0