Skip to content

Commit

Permalink
Merge pull request #6762 from radarhere/exif_hide_offsets
Browse files Browse the repository at this point in the history
  • Loading branch information
hugovk committed Dec 23, 2022
2 parents 7a19251 + 9dfba1f commit 0934c25
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 3 deletions.
25 changes: 25 additions & 0 deletions Tests/test_image.py
Expand Up @@ -851,6 +851,31 @@ def test_exif_load_from_fp(self):
34665: 196,
}

def test_exif_hide_offsets(self):
with Image.open("Tests/images/flower.jpg") as im:
exif = im.getexif()

# Check offsets are present initially
assert 0x8769 in exif
for tag in (0xA005, 0x927C):
assert tag in exif.get_ifd(0x8769)
assert exif.get_ifd(0xA005)
loaded_exif = exif

with Image.open("Tests/images/flower.jpg") as im:
new_exif = im.getexif()

for exif in (loaded_exif, new_exif):
exif.hide_offsets()

# Assert they are hidden afterwards,
# but that the IFDs are still available
assert 0x8769 not in exif
assert exif.get_ifd(0x8769)
for tag in (0xA005, 0x927C):
assert tag not in exif.get_ifd(0x8769)
assert exif.get_ifd(0xA005)

@pytest.mark.parametrize("size", ((1, 0), (0, 1), (0, 0)))
def test_zero_tobytes(self, size):
im = Image.new("RGB", size)
Expand Down
23 changes: 20 additions & 3 deletions src/PIL/Image.py
Expand Up @@ -3551,6 +3551,7 @@ class Exif(MutableMapping):

def __init__(self):
self._data = {}
self._hidden_data = {}
self._ifds = {}
self._info = None
self._loaded_exif = None
Expand Down Expand Up @@ -3604,6 +3605,7 @@ def load(self, data):
return
self._loaded_exif = data
self._data.clear()
self._hidden_data.clear()
self._ifds.clear()
if data and data.startswith(b"Exif\x00\x00"):
data = data[6:]
Expand All @@ -3624,6 +3626,7 @@ def load(self, data):
def load_from_fp(self, fp, offset=None):
self._loaded_exif = None
self._data.clear()
self._hidden_data.clear()
self._ifds.clear()

# process dictionary
Expand Down Expand Up @@ -3686,8 +3689,9 @@ def get_ifd(self, tag):
if self._info is not None:
self._ifds[tag] = self._get_ifd_dict(self._info.next)
elif tag in [ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo]:
if tag in self:
self._ifds[tag] = self._get_ifd_dict(self[tag])
offset = self._hidden_data.get(tag, self.get(tag))
if offset is not None:
self._ifds[tag] = self._get_ifd_dict(offset)
elif tag in [ExifTags.IFD.Interop, ExifTags.IFD.Makernote]:
if ExifTags.IFD.Exif not in self._ifds:
self.get_ifd(ExifTags.IFD.Exif)
Expand Down Expand Up @@ -3770,7 +3774,20 @@ def get_ifd(self, tag):
else:
# Interop
self._ifds[tag] = self._get_ifd_dict(tag_data)
return self._ifds.get(tag, {})
ifd = self._ifds.get(tag, {})
if tag == ExifTags.IFD.Exif and self._hidden_data:
ifd = {
k: v
for (k, v) in ifd.items()
if k not in (ExifTags.IFD.Interop, ExifTags.IFD.Makernote)
}
return ifd

def hide_offsets(self):
for tag in (ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo):
if tag in self:
self._hidden_data[tag] = self[tag]
del self[tag]

def __str__(self):
if self._info is not None:
Expand Down

0 comments on commit 0934c25

Please sign in to comment.