Skip to content

Commit

Permalink
Merge 3d22e52 into 1f61c4e
Browse files Browse the repository at this point in the history
  • Loading branch information
wiredfool committed Sep 14, 2017
2 parents 1f61c4e + 3d22e52 commit ba32e8a
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 11 deletions.
29 changes: 24 additions & 5 deletions PIL/TiffImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -550,11 +550,28 @@ def _setitem(self, tag, value, legacy_api):

dest = self._tags_v1 if legacy_api else self._tags_v2

if info.length == 1:
if legacy_api and self.tagtype[tag] in [5, 10]:
# Three branches:
# Spec'd length == 1, Actual length 1, store as element
# Spec'd length == 1, Actual > 1, Warn and truncate. Formerly barfed.
# No Spec, Actual length 1, Formerly (<4.2) returned a 1 element tuple.
# Don't mess with the legacy api, since it's frozen.
if ((info.length == 1) or
(info.length is None and len(values) == 1 and not legacy_api)):
# Don't mess with the legacy api, since it's frozen.
if legacy_api and self.tagtype[tag] in [5, 10]: # rationals
values = values,
dest[tag], = values
try:
dest[tag], = values
except ValueError:
# We've got a builtin tag with 1 expected entry
warnings.warn(
"Metadata Warning, tag %s had too many entries: %s, expected 1" % (
tag, len(values)))
dest[tag] = values[0]

else:
# Spec'd length > 1 or undefined
# Unspec'd, and length > 1
dest[tag] = values

def __delitem__(self, tag):
Expand Down Expand Up @@ -1011,8 +1028,10 @@ def _decoder(self, rawmode, layer, tile=None):
args = rawmode, ""
if JPEGTABLES in self.tag_v2:
# Hack to handle abbreviated JPEG headers
# FIXME This will fail with more than one value
self.tile_prefix, = self.tag_v2[JPEGTABLES]
# Definition of JPEGTABLES is that the count
# is the number of bytes in the tables datastream
# so, it should always be 1 in our tag info
self.tile_prefix = self.tag_v2[JPEGTABLES]
elif compression == "packbits":
args = rawmode
elif compression == "tiff_lzw":
Expand Down
11 changes: 8 additions & 3 deletions PIL/TiffTags.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
class TagInfo(namedtuple("_TagInfo", "value name type length enum")):
__slots__ = []

def __new__(cls, value=None, name="unknown", type=None, length=0, enum=None):
def __new__(cls, value=None, name="unknown", type=None, length=None, enum=None):
return super(TagInfo, cls).__new__(
cls, value, name, type, length, enum or {})

Expand Down Expand Up @@ -142,6 +142,8 @@ def lookup(tag):
341: ("SMaxSampleValue", DOUBLE, 0),
342: ("TransferRange", SHORT, 6),

347: ("JPEGTables", UNDEFINED, 1),

# obsolete JPEG tags
512: ("JPEGProc", SHORT, 1),
513: ("JPEGInterchangeFormat", LONG, 1),
Expand All @@ -158,7 +160,10 @@ def lookup(tag):
531: ("YCbCrPositioning", SHORT, 1),
532: ("ReferenceBlackWhite", LONG, 0),

700: ('XMP', BYTE, 1),

33432: ("Copyright", ASCII, 1),
34377: ('PhotoshopInfo', BYTE, 1),

# FIXME add more tags here
34665: ("ExifIFD", SHORT, 1),
Expand Down Expand Up @@ -188,8 +193,8 @@ def lookup(tag):

50741: ("MakerNoteSafety", SHORT, 1, {"Unsafe": 0, "Safe": 1}),
50780: ("BestQualityScale", RATIONAL, 1),
50838: ("ImageJMetaDataByteCounts", LONG, 1),
50839: ("ImageJMetaData", UNDEFINED, 1)
50838: ("ImageJMetaDataByteCounts", LONG, 0), # Can be more than one
50839: ("ImageJMetaData", UNDEFINED, 1) # see Issue #2006
}

# Legacy Tags structure
Expand Down
Binary file added Tests/images/issue_2278.tif
Binary file not shown.
24 changes: 21 additions & 3 deletions Tests/test_file_tiff_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def test_rt_metadata(self):
loaded = Image.open(f)

self.assertEqual(loaded.tag[ImageJMetaDataByteCounts], (len(bindata),))
self.assertEqual(loaded.tag_v2[ImageJMetaDataByteCounts], len(bindata))
self.assertEqual(loaded.tag_v2[ImageJMetaDataByteCounts], (len(bindata),))

self.assertEqual(loaded.tag[ImageJMetaData], bindata)
self.assertEqual(loaded.tag_v2[ImageJMetaData], bindata)
Expand All @@ -69,6 +69,16 @@ def test_rt_metadata(self):
loaded_double = loaded.tag[tag_ids['YawAngle']][0]
self.assertAlmostEqual(loaded_double, doubledata)

# check with 2 element ImageJMetaDataByteCounts, issue #2006

info[ImageJMetaDataByteCounts] = (8, len(bindata) - 8)
img.save(f, tiffinfo=info)
loaded = Image.open(f)

self.assertEqual(loaded.tag[ImageJMetaDataByteCounts], (8, len(bindata) - 8))
self.assertEqual(loaded.tag_v2[ImageJMetaDataByteCounts], (8, len(bindata) - 8))


def test_read_metadata(self):
img = Image.open('Tests/images/hopper_g4.tif')

Expand Down Expand Up @@ -202,8 +212,8 @@ def test_exif_div_zero(self):
im.save(out, tiffinfo=info, compression='raw')

reloaded = Image.open(out)
self.assertEqual(0, reloaded.tag_v2[41988][0].numerator)
self.assertEqual(0, reloaded.tag_v2[41988][0].denominator)
self.assertEqual(0, reloaded.tag_v2[41988].numerator)
self.assertEqual(0, reloaded.tag_v2[41988].denominator)

def test_expty_values(self):
data = io.BytesIO(
Expand All @@ -220,6 +230,14 @@ def test_expty_values(self):
self.fail("Should not be struct value error there.")
self.assertIn(33432, info)

def test_PhotoshopInfo(self):
im = Image.open('Tests/images/issue_2278.tif')

self.assertIsInstance(im.tag_v2[34377], bytes)
out = self.tempfile('temp.tiff')
im.save(out)
reloaded = Image.open(out)
self.assertIsInstance(reloaded.tag_v2[34377], bytes)

if __name__ == '__main__':
unittest.main()
16 changes: 16 additions & 0 deletions docs/releasenotes/4.3.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,22 @@ This release contains several performance improvements:
using a recent version of libjpeg-turbo.


TIFF Metadata Changes
=====================

* TIFF tags with unknown type/quantity now default to being bare
values if they are 1 element, where previously they would be a
single element tuple. This is only with the new api, not the legacy
api. This normalizes the handling of fields, so that the metadata
with inferred or image specified counts are handled the same as
metadata with count specified in the TIFF spec.
* The ``PhotoshopInfo``, ``XMP``, and ``JPEGTables`` tags now have a
defined type (bytes) and a count of 1.
* The ``ImageJMetaDataByteCounts`` tag now has an arbitrary number of
items, as there can be multiple items, one for UTF-8, and one for
UTF-16.


Core Image API Changes
======================

Expand Down

0 comments on commit ba32e8a

Please sign in to comment.