mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 17:36:18 +03:00
Added get_ifd method to access embedded IFDs
This commit is contained in:
parent
d5db62be7b
commit
3caec4344e
|
@ -284,7 +284,7 @@ class TestPyDecoder(PillowTestCase):
|
|||
@unittest.skipIf(not HAVE_WEBP or not _webp.HAVE_WEBPANIM,
|
||||
"WebP support not installed with animation")
|
||||
def test_exif_webp(self):
|
||||
im = Image.open("Tests/images/hopper.webp") # WebP
|
||||
im = Image.open("Tests/images/hopper.webp")
|
||||
exif = im.getexif()
|
||||
self.assertEqual(exif, {})
|
||||
|
||||
|
@ -321,5 +321,15 @@ class TestPyDecoder(PillowTestCase):
|
|||
self.assertEqual(reloaded_exif, {
|
||||
258: 8,
|
||||
40963: 455,
|
||||
305: 'Pillow test'
|
||||
305: 'Pillow test',
|
||||
})
|
||||
|
||||
def test_exif_interop(self):
|
||||
im = Image.open("Tests/images/flower.jpg")
|
||||
exif = im.getexif()
|
||||
self.assertEqual(exif.get_ifd(0xa005), {
|
||||
1: 'R98',
|
||||
2: b'0100',
|
||||
4097: 2272,
|
||||
4098: 1704,
|
||||
})
|
||||
|
|
|
@ -689,6 +689,7 @@ class PyDecoder(object):
|
|||
|
||||
class Exif(MutableMapping):
|
||||
_data = {}
|
||||
_ifds = {}
|
||||
endian = "<"
|
||||
|
||||
def _fixup_dict(self, src_dict):
|
||||
|
@ -704,6 +705,19 @@ class Exif(MutableMapping):
|
|||
|
||||
return {k: _fixup(v) for k, v in src_dict.items()}
|
||||
|
||||
def _get_ifd_dict(self, fp, head, tag):
|
||||
try:
|
||||
# an offset pointer to the location of the nested embedded ifd.
|
||||
# It should be a long, but may be corrupted.
|
||||
fp.seek(self._data[tag])
|
||||
except (KeyError, TypeError):
|
||||
pass
|
||||
else:
|
||||
from . import TiffImagePlugin
|
||||
info = TiffImagePlugin.ImageFileDirectory_v1(head)
|
||||
info.load(fp)
|
||||
return self._fixup_dict(info)
|
||||
|
||||
def load(self, data):
|
||||
# Extract EXIF information. This is highly experimental,
|
||||
# and is likely to be replaced with something better in a future
|
||||
|
@ -720,30 +734,25 @@ class Exif(MutableMapping):
|
|||
fp.seek(info.next)
|
||||
info.load(fp)
|
||||
self._data = dict(self._fixup_dict(info))
|
||||
|
||||
# get exif extension
|
||||
try:
|
||||
# exif field 0x8769 is an offset pointer to the location
|
||||
# of the nested embedded exif ifd.
|
||||
# It should be a long, but may be corrupted.
|
||||
fp.seek(self._data[0x8769])
|
||||
except (KeyError, TypeError):
|
||||
pass
|
||||
else:
|
||||
info = TiffImagePlugin.ImageFileDirectory_v1(head)
|
||||
info.load(fp)
|
||||
self._data.update(self._fixup_dict(info))
|
||||
ifd = self._get_ifd_dict(fp, head, 0x8769)
|
||||
if ifd:
|
||||
self._data.update(ifd)
|
||||
self._ifds[0x8769] = ifd
|
||||
|
||||
# get gpsinfo extension
|
||||
try:
|
||||
# exif field 0x8825 is an offset pointer to the location
|
||||
# of the nested embedded gps exif ifd.
|
||||
# It should be a long, but may be corrupted.
|
||||
fp.seek(self._data[0x8825])
|
||||
except (KeyError, TypeError):
|
||||
pass
|
||||
else:
|
||||
info = TiffImagePlugin.ImageFileDirectory_v1(head)
|
||||
info.load(fp)
|
||||
self._data[0x8825] = self._fixup_dict(info)
|
||||
ifd = self._get_ifd_dict(fp, head, 0x8825)
|
||||
if ifd:
|
||||
self._data[0x8825] = ifd
|
||||
self._ifds[0x8825] = ifd
|
||||
|
||||
for tag in [
|
||||
0xa005, # interop
|
||||
]:
|
||||
ifd = self._get_ifd_dict(fp, head, tag)
|
||||
if ifd:
|
||||
self._ifds[tag] = ifd
|
||||
|
||||
def toBytes(self, offset=0):
|
||||
from . import TiffImagePlugin
|
||||
|
@ -756,6 +765,9 @@ class Exif(MutableMapping):
|
|||
ifd[tag] = value
|
||||
return b"Exif\x00\x00"+head+ifd.toBytes(offset)
|
||||
|
||||
def get_ifd(self, tag):
|
||||
return self._ifds.get(tag, {})
|
||||
|
||||
def __str__(self):
|
||||
return str(self._data)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user