From 3473eb8e7f225e6d2fc3709b0565289d64ff9cec Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 26 Nov 2022 15:44:03 +1100 Subject: [PATCH] Added Exif hide_offsets() --- Tests/test_image.py | 25 +++++++++++++++++++++++++ src/PIL/Image.py | 19 ++++++++++++++++--- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/Tests/test_image.py b/Tests/test_image.py index e579034904d..45fedbe4ddb 100644 --- a/Tests/test_image.py +++ b/Tests/test_image.py @@ -838,6 +838,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) diff --git a/src/PIL/Image.py b/src/PIL/Image.py index 7faf0c2481b..10ca3a65e82 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -3503,6 +3503,7 @@ class Exif(MutableMapping): def __init__(self): self._data = {} + self._hidden_data = {} self._ifds = {} self._info = None self._loaded_exif = None @@ -3556,6 +3557,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:] @@ -3576,6 +3578,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 @@ -3631,8 +3634,9 @@ def get_ifd(self, tag): if tag not in self._ifds: if tag in [0x8769, 0x8825]: # exif, 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 [0xA005, 0x927C]: # interop, makernote if 0x8769 not in self._ifds: @@ -3717,7 +3721,16 @@ 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 == 0x8769 and self._hidden_data: + ifd = {k: v for (k, v) in ifd.items() if k not in (0xA005, 0x927C)} + return ifd + + def hide_offsets(self): + for tag in (0x8769, 0x8825): + if tag in self: + self._hidden_data[tag] = self[tag] + del self[tag] def __str__(self): if self._info is not None: