Skip to content

Commit

Permalink
Merge 26e7169 into daa8b51
Browse files Browse the repository at this point in the history
  • Loading branch information
Glandos committed Feb 18, 2019
2 parents daa8b51 + 26e7169 commit 9dd52e2
Showing 1 changed file with 65 additions and 20 deletions.
85 changes: 65 additions & 20 deletions src/PIL/JpegImagePlugin.py
Expand Up @@ -436,18 +436,64 @@ def _getmp(self):
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 not isinstance(value, dict):
return value[0]
except Exception:
pass
return value

return {k: _fixup(v) for k, v in src_dict.items()}
def _fixup(value):
try:
if len(value) == 1 and not isinstance(value, dict):
return value[0]
except Exception:
pass
return value


class ExifImageFileDirectory(TiffImagePlugin.ImageFileDirectory_v1):
'''
Specialization for parsing EXIF data:
- Remove support for v2 to avoid useless computations
- custom __setitem__ to supports IFD values
- values are "fixed up" so that 1-size tuples are expanded
- custom update() to avoid iterating and expanding non parsed data
The goal is to use the lazyness of ImageFileDirectory_v1 in _getexif().
'''

def to_v2(self):
raise NotImplementedError()

def _setitem(self, tag, value, legacy_api):
TiffImagePlugin.ImageFileDirectory_v1._setitem(self, tag, value, legacy_api)
if legacy_api:
val = self._tags_v1[tag]
if not isinstance(val, (tuple, bytes)):
val = val,
self._tags_v1[tag] = _fixup(val)

def __setitem__(self, tag, value):
if isinstance(value, TiffImagePlugin.ImageFileDirectory_v2):
self._tags_v1[tag] = value
else:
TiffImagePlugin.ImageFileDirectory_v1.__setitem__(self, tag, value)

def __getitem__(self, tag):
if tag not in self._tags_v1: # unpack on the fly
data = self._tagdata[tag]
typ = self.tagtype[tag]
size, handler = self._load_dispatch[typ]
# We don't support v2
self._setitem(tag, handler(self, data, True), True)
val = self._tags_v1[tag]
# Don't try to convert as tuple, it is done in _setitem
return val

def update(self, *args, **kwds):
if args and isinstance(args[0], TiffImagePlugin.ImageFileDirectory_v2):
other = args[0]
# custom update
self._tags_v1.update(other._tags_v1)
self._tags_v2.update(other._tags_v2)
self._tagdata.update(other._tagdata)
self.tagtype.update(other.tagtype)
else:
TiffImagePlugin.ImageFileDirectory_v1.update(self, *args, **kwds)


def _getexif(self):
Expand All @@ -464,10 +510,9 @@ def _getexif(self):
fp = io.BytesIO(data[6:])
head = fp.read(8)
# process dictionary
info = TiffImagePlugin.ImageFileDirectory_v1(head)
fp.seek(info.next)
info.load(fp)
exif = dict(_fixup_dict(info))
exif = ExifImageFileDirectory(head)
fp.seek(exif.next)
exif.load(fp)
# get exif extension
try:
# exif field 0x8769 is an offset pointer to the location
Expand All @@ -477,9 +522,9 @@ def _getexif(self):
except (KeyError, TypeError):
pass
else:
info = TiffImagePlugin.ImageFileDirectory_v1(head)
info = ExifImageFileDirectory(head)
info.load(fp)
exif.update(_fixup_dict(info))
exif.update(info)
# get gpsinfo extension
try:
# exif field 0x8825 is an offset pointer to the location
Expand All @@ -489,9 +534,9 @@ def _getexif(self):
except (KeyError, TypeError):
pass
else:
info = TiffImagePlugin.ImageFileDirectory_v1(head)
info = ExifImageFileDirectory(head)
info.load(fp)
exif[0x8825] = _fixup_dict(info)
exif[0x8825] = info

return exif

Expand Down

0 comments on commit 9dd52e2

Please sign in to comment.