mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-11-14 05:36:48 +03:00
Partial fix for #1597
Haven't excercized all of the metadata that we're allowing yet, and there's clearly still something up with Arrays, as one of them is still crashing and making it impossible to save a palette with a libtiff image.
This commit is contained in:
parent
80ab12bdc0
commit
9fa6634f4d
|
@ -1400,8 +1400,7 @@ def _save(im, fp, filename):
|
||||||
|
|
||||||
# STRIPOFFSETS and STRIPBYTECOUNTS are added by the library
|
# STRIPOFFSETS and STRIPBYTECOUNTS are added by the library
|
||||||
# based on the data in the strip.
|
# based on the data in the strip.
|
||||||
# ICCPROFILE crashes.
|
blocklist = [STRIPOFFSETS, STRIPBYTECOUNTS]
|
||||||
blocklist = [STRIPOFFSETS, STRIPBYTECOUNTS, ICCPROFILE]
|
|
||||||
atts = {}
|
atts = {}
|
||||||
# bits per sample is a single short in the tiff directory, not a list.
|
# bits per sample is a single short in the tiff directory, not a list.
|
||||||
atts[BITSPERSAMPLE] = bits[0]
|
atts[BITSPERSAMPLE] = bits[0]
|
||||||
|
@ -1411,16 +1410,22 @@ def _save(im, fp, filename):
|
||||||
legacy_ifd = {}
|
legacy_ifd = {}
|
||||||
if hasattr(im, 'tag'):
|
if hasattr(im, 'tag'):
|
||||||
legacy_ifd = im.tag.to_v2()
|
legacy_ifd = im.tag.to_v2()
|
||||||
for k, v in itertools.chain(ifd.items(),
|
for tag, value in itertools.chain(ifd.items(),
|
||||||
getattr(im, 'tag_v2', {}).items(),
|
getattr(im, 'tag_v2', {}).items(),
|
||||||
legacy_ifd.items()):
|
legacy_ifd.items()):
|
||||||
if k not in atts and k not in blocklist:
|
# Libtiff can only process certain core items without adding
|
||||||
if isinstance(v, unicode if bytes is str else str):
|
# them to the custom dictionary. It will segfault if it attempts
|
||||||
atts[k] = v.encode('ascii', 'replace') + b"\0"
|
# to add a custom tag without the dictionary entry
|
||||||
elif isinstance(v, IFDRational):
|
#
|
||||||
atts[k] = float(v)
|
# UNDONE -- add code for the custom dictionary
|
||||||
|
if tag not in TiffTags.LIBTIFF_CORE: continue
|
||||||
|
if tag not in atts and tag not in blocklist:
|
||||||
|
if isinstance(value, unicode if bytes is str else str):
|
||||||
|
atts[tag] = value.encode('ascii', 'replace') + b"\0"
|
||||||
|
elif isinstance(value, IFDRational):
|
||||||
|
atts[tag] = float(value)
|
||||||
else:
|
else:
|
||||||
atts[k] = v
|
atts[tag] = value
|
||||||
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
print("Converted items: %s" % sorted(atts.items()))
|
print("Converted items: %s" % sorted(atts.items()))
|
||||||
|
|
|
@ -331,3 +331,59 @@ TYPES = {}
|
||||||
# 11: "float",
|
# 11: "float",
|
||||||
# 12: "double",
|
# 12: "double",
|
||||||
# }
|
# }
|
||||||
|
|
||||||
|
#
|
||||||
|
# These tags are handled by default in libtiff, without
|
||||||
|
# adding to the custom dictionary. From tif_dir.c, searching for
|
||||||
|
# case TIFFTAG in the _TIFFVSetField function:
|
||||||
|
# Line: item.
|
||||||
|
# 148: case TIFFTAG_SUBFILETYPE:
|
||||||
|
# 151: case TIFFTAG_IMAGEWIDTH:
|
||||||
|
# 154: case TIFFTAG_IMAGELENGTH:
|
||||||
|
# 157: case TIFFTAG_BITSPERSAMPLE:
|
||||||
|
# 181: case TIFFTAG_COMPRESSION:
|
||||||
|
# 202: case TIFFTAG_PHOTOMETRIC:
|
||||||
|
# 205: case TIFFTAG_THRESHHOLDING:
|
||||||
|
# 208: case TIFFTAG_FILLORDER:
|
||||||
|
# 214: case TIFFTAG_ORIENTATION:
|
||||||
|
# 221: case TIFFTAG_SAMPLESPERPIXEL:
|
||||||
|
# 228: case TIFFTAG_ROWSPERSTRIP:
|
||||||
|
# 238: case TIFFTAG_MINSAMPLEVALUE:
|
||||||
|
# 241: case TIFFTAG_MAXSAMPLEVALUE:
|
||||||
|
# 244: case TIFFTAG_SMINSAMPLEVALUE:
|
||||||
|
# 247: case TIFFTAG_SMAXSAMPLEVALUE:
|
||||||
|
# 250: case TIFFTAG_XRESOLUTION:
|
||||||
|
# 256: case TIFFTAG_YRESOLUTION:
|
||||||
|
# 262: case TIFFTAG_PLANARCONFIG:
|
||||||
|
# 268: case TIFFTAG_XPOSITION:
|
||||||
|
# 271: case TIFFTAG_YPOSITION:
|
||||||
|
# 274: case TIFFTAG_RESOLUTIONUNIT:
|
||||||
|
# 280: case TIFFTAG_PAGENUMBER:
|
||||||
|
# 284: case TIFFTAG_HALFTONEHINTS:
|
||||||
|
# 288: case TIFFTAG_COLORMAP:
|
||||||
|
# 294: case TIFFTAG_EXTRASAMPLES:
|
||||||
|
# 298: case TIFFTAG_MATTEING:
|
||||||
|
# 305: case TIFFTAG_TILEWIDTH:
|
||||||
|
# 316: case TIFFTAG_TILELENGTH:
|
||||||
|
# 327: case TIFFTAG_TILEDEPTH:
|
||||||
|
# 333: case TIFFTAG_DATATYPE:
|
||||||
|
# 344: case TIFFTAG_SAMPLEFORMAT:
|
||||||
|
# 361: case TIFFTAG_IMAGEDEPTH:
|
||||||
|
# 364: case TIFFTAG_SUBIFD:
|
||||||
|
# 376: case TIFFTAG_YCBCRPOSITIONING:
|
||||||
|
# 379: case TIFFTAG_YCBCRSUBSAMPLING:
|
||||||
|
# 383: case TIFFTAG_TRANSFERFUNCTION:
|
||||||
|
# 389: case TIFFTAG_REFERENCEBLACKWHITE:
|
||||||
|
# 393: case TIFFTAG_INKNAMES:
|
||||||
|
|
||||||
|
# some of these are not in our TAGS_V2 dict and were included from tiff.h
|
||||||
|
|
||||||
|
LIBTIFF_CORE = set ([255, 256, 257, 258, 259, 262, 263, 266, 274, 277,
|
||||||
|
278, 280, 281, 340, 341, 282, 283, 284, 286, 287,
|
||||||
|
296, 297, 321, 320, 338, 32995, 322, 323, 32998,
|
||||||
|
32996, 339, 32997, 330, 531, 530, 301, 532, 333,
|
||||||
|
# as above
|
||||||
|
269 # this has been in our tests forever, and works
|
||||||
|
])
|
||||||
|
|
||||||
|
LIBTIFF_CORE.remove(320) # Arrays error?
|
||||||
|
|
BIN
Tests/images/rdf.tif
Normal file
BIN
Tests/images/rdf.tif
Normal file
Binary file not shown.
|
@ -395,6 +395,17 @@ class TestFileLibTiff(LibTiffTestCase):
|
||||||
TiffImagePlugin.WRITE_LIBTIFF = False
|
TiffImagePlugin.WRITE_LIBTIFF = False
|
||||||
TiffImagePlugin.READ_LIBTIFF = False
|
TiffImagePlugin.READ_LIBTIFF = False
|
||||||
|
|
||||||
|
def test_crashing_metadata(self):
|
||||||
|
# issue 1597
|
||||||
|
im = Image.open('Tests/images/rdf.tif')
|
||||||
|
out = self.tempfile('temp.tif')
|
||||||
|
|
||||||
|
TiffImagePlugin.WRITE_LIBTIFF = True
|
||||||
|
# this shouldn't crash
|
||||||
|
im.save(out, format='TIFF')
|
||||||
|
TiffImagePlugin.WRITE_LIBTIFF = False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user