diff --git a/PIL/JpegImagePlugin.py b/PIL/JpegImagePlugin.py index 61a6af633..beda4f7a0 100644 --- a/PIL/JpegImagePlugin.py +++ b/PIL/JpegImagePlugin.py @@ -394,6 +394,19 @@ class JpegImageFile(ImageFile.ImageFile): return _getmp(self) +def _fixup_dict(src_dict): + # Helper function for _getexif() + # returns a dict with any single item tuples/lists as individual values + def _fixup(value): + try: + if len(value) == 1 and type(value) != type({}): + return value[0] + except: pass + return value + + return dict([(k, _fixup(v)) for k, v in src_dict.items()]) + + def _getexif(self): # Extract EXIF information. This method is highly experimental, # and is likely to be replaced with something better in a future @@ -408,9 +421,9 @@ def _getexif(self): file = io.BytesIO(data[6:]) head = file.read(8) # process dictionary - info = TiffImagePlugin.ImageFileDirectory_v2(head) + info = TiffImagePlugin.ImageFileDirectory_v1(head) info.load(file) - exif = dict(info) + exif = dict(_fixup_dict(info)) # get exif extension try: # exif field 0x8769 is an offset pointer to the location @@ -420,9 +433,9 @@ def _getexif(self): except (KeyError, TypeError): pass else: - info = TiffImagePlugin.ImageFileDirectory_v2(head) + info = TiffImagePlugin.ImageFileDirectory_v1(head) info.load(file) - exif.update(info) + exif.update(_fixup_dict(info)) # get gpsinfo extension try: # exif field 0x8825 is an offset pointer to the location @@ -434,7 +447,8 @@ def _getexif(self): else: info = TiffImagePlugin.ImageFileDirectory_v1(head) info.load(file) - exif[0x8825] = dict([(k, v[0]) if len(v) == 1 else (k, v) for k, v in info.items()]) + exif[0x8825] = _fixup_dict(info) + return exif diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index 6f144bfea..c54d08713 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -188,6 +188,38 @@ class TestFileJpeg(PillowTestCase): # Assert self.assertEqual(exif[gps_index], expected_exif_gps) + def test_exif_rollback(self): + # rolling back exif support in 3.1 to pre-3.0 formatting. + # expected from 2.9, with b/u qualifiers switched for 3.2 compatibility + # this test passes on 2.9 and 3.1, but not 3.0 + expected_exif = {34867: 4294967295, + 258: (24, 24, 24), + 36867: '2099:09:29 10:10:10', + 34853: {0: b'\x00\x00\x00\x01', + 2: (4294967295, 1), + 5: b'\x01', + 30: 65535, + 29: '1999:99:99 99:99:99'}, + 296: 65535, + 34665: 185, + 41994: 65535, + 514: 4294967295, + 271: 'Make', + 272: 'XXX-XXX', + 305: 'PIL', + 42034: ((1, 1), (1, 1), (1, 1), (1, 1)), + 42035: 'LensMake', + 34856: b'\xaa\xaa\xaa\xaa\xaa\xaa', + 282: (4294967295, 1), + 33434: (4294967295, 1)} + + im = Image.open('Tests/images/exif_gps.jpg') + exif = im._getexif() + + for tag, value in expected_exif.items(): + self.assertEqual(value, exif[tag]) + + def test_exif_gps_typeerror(self): im = Image.open('Tests/images/exif_gps_typeerror.jpg')