Skip to content

Commit

Permalink
Merge pull request #5575 from radarhere/tiff_exif
Browse files Browse the repository at this point in the history
 Added "exif" keyword argument to TIFF saving
  • Loading branch information
hugovk committed Sep 6, 2021
2 parents ecf3a34 + 3f38280 commit ba7502c
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 6 deletions.
24 changes: 20 additions & 4 deletions Tests/test_file_tiff.py
Expand Up @@ -403,10 +403,8 @@ def test_ifd_tag_type(self):
with Image.open("Tests/images/ifd_tag_type.tiff") as im:
assert 0x8825 in im.tag_v2

def test_exif(self):
with Image.open("Tests/images/ifd_tag_type.tiff") as im:
exif = im.getexif()

def test_exif(self, tmp_path):
def check_exif(exif):
assert sorted(exif.keys()) == [
256,
257,
Expand Down Expand Up @@ -439,6 +437,24 @@ def test_exif(self):
assert gps[0] == b"\x03\x02\x00\x00"
assert gps[18] == "WGS-84"

outfile = str(tmp_path / "temp.tif")
with Image.open("Tests/images/ifd_tag_type.tiff") as im:
exif = im.getexif()
check_exif(exif)

im.save(outfile, exif=exif)

outfile2 = str(tmp_path / "temp2.tif")
with Image.open(outfile) as im:
exif = im.getexif()
check_exif(exif)

im.save(outfile2, exif=exif.tobytes())

with Image.open(outfile2) as im:
exif = im.getexif()
check_exif(exif)

def test_exif_frames(self):
# Test that EXIF data can change across frames
with Image.open("Tests/images/g4-multi.tiff") as im:
Expand Down
5 changes: 5 additions & 0 deletions docs/handbook/image-file-formats.rst
Expand Up @@ -903,6 +903,11 @@ The :py:meth:`~PIL.Image.Image.save` method can take the following keyword argum
require a matching type in
:py:attr:`~PIL.TiffImagePlugin.ImageFileDirectory_v2.tagtype` tagtype.

**exif**
Alternate keyword to "tiffinfo", for consistency with other formats.

.. versionadded:: 8.4.0

**compression**
A string containing the desired compression method for the
file. (valid only with libtiff installed) Valid compression
Expand Down
27 changes: 25 additions & 2 deletions src/PIL/TiffImagePlugin.py
Expand Up @@ -1143,6 +1143,17 @@ def load_end(self):
if not self.is_animated:
self._close_exclusive_fp_after_loading = True

# reset buffered io handle in case fp
# was passed to libtiff, invalidating the buffer
self.fp.tell()

# load IFD data from fp before it is closed
exif = self.getexif()
for key in TiffTags.TAGS_V2_GROUPS.keys():
if key not in exif:
continue
exif.get_ifd(key)

def _load_libtiff(self):
"""Overload method triggered when we detect a compressed tiff
Calls out to libtiff"""
Expand Down Expand Up @@ -1507,12 +1518,24 @@ def _save(im, fp, filename):
ifd[IMAGELENGTH] = im.size[1]

# write any arbitrary tags passed in as an ImageFileDirectory
info = encoderinfo.get("tiffinfo", {})
if "tiffinfo" in encoderinfo:
info = encoderinfo["tiffinfo"]
elif "exif" in encoderinfo:
info = encoderinfo["exif"]
if isinstance(info, bytes):
exif = Image.Exif()
exif.load(info)
info = exif
else:
info = {}
logger.debug("Tiffinfo Keys: %s" % list(info))
if isinstance(info, ImageFileDirectory_v1):
info = info.to_v2()
for key in info:
ifd[key] = info.get(key)
if isinstance(info, Image.Exif) and key in TiffTags.TAGS_V2_GROUPS.keys():
ifd[key] = info.get_ifd(key)
else:
ifd[key] = info.get(key)
try:
ifd.tagtype[key] = info.tagtype[key]
except Exception:
Expand Down

0 comments on commit ba7502c

Please sign in to comment.