From 8d3014b8bf94ee6d07276b227dfac4d6f7f5a859 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 15 Apr 2023 21:03:59 +1000 Subject: [PATCH 1/5] Added inPlace argument to exif_transpose() --- Tests/images/orientation_rectangle.jpg | Bin 0 -> 669 bytes Tests/test_imageops.py | 12 ++++++ src/PIL/ImageOps.py | 53 +++++++++++++++---------- 3 files changed, 43 insertions(+), 22 deletions(-) create mode 100644 Tests/images/orientation_rectangle.jpg diff --git a/Tests/images/orientation_rectangle.jpg b/Tests/images/orientation_rectangle.jpg new file mode 100644 index 0000000000000000000000000000000000000000..85cfbd0a813a1b36d64318ead4f0fe5a3258a51f GIT binary patch literal 669 zcmex=wh=DOELf4NWZ*Q!{f5ODks= zS2uSLPp{yR(6I1`$f)F$)U@=B%&g*)(z5c3%Btp;*0%PJ&aO$5r%atTea6gLixw|g zx@`H1m8&*w-m-Pu_8mKS9XfpE=&|D`PM*4S`O4L6*Kgds_3+W-Cr_U}fAR9w$4{TX zeEs(Q$Io9Ne=#yJL%anfAwEO%mmttzOe`$SEbJhEF*22dJTAz>s%Xe2([0-9])", ): - transposed_image.info["XML:com.adobe.xmp"] = re.sub( - pattern, "", transposed_image.info["XML:com.adobe.xmp"] + exif_image.info["XML:com.adobe.xmp"] = re.sub( + pattern, "", exif_image.info["XML:com.adobe.xmp"] ) + if inPlace: + return return transposed_image + if inPlace: + return return image.copy() From bcb8dfc2fa9011c99d6332d5b0aa00c82e1c6cdf Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 15 Apr 2023 22:30:18 +1000 Subject: [PATCH 2/5] Rearranged code --- src/PIL/ImageOps.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/PIL/ImageOps.py b/src/PIL/ImageOps.py index 460a21ce2b8..5dc34f4424c 100644 --- a/src/PIL/ImageOps.py +++ b/src/PIL/ImageOps.py @@ -622,9 +622,7 @@ def exif_transpose(image, inPlace=False): exif_image.info["XML:com.adobe.xmp"] = re.sub( pattern, "", exif_image.info["XML:com.adobe.xmp"] ) - if inPlace: - return - return transposed_image - if inPlace: - return - return image.copy() + if not inPlace: + return transposed_image + elif not inPlace: + return image.copy() From fe8599c5d64b2932b430a0178f17009855397fe6 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 16 Apr 2023 14:04:39 +1000 Subject: [PATCH 3/5] Use ExifTags --- src/PIL/Image.py | 4 ++-- src/PIL/ImageOps.py | 8 ++++---- src/PIL/TiffImagePlugin.py | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/PIL/Image.py b/src/PIL/Image.py index 5a43f6c4a43..34b8bbcbd71 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -1418,12 +1418,12 @@ def getexif(self): self._exif.load(exif_info) # XMP tags - if 0x0112 not in self._exif: + if ExifTags.Base.Orientation not in self._exif: xmp_tags = self.info.get("XML:com.adobe.xmp") if xmp_tags: match = re.search(r'tiff:Orientation(="|>)([0-9])', xmp_tags) if match: - self._exif[0x0112] = int(match[2]) + self._exif[ExifTags.Base.Orientation] = int(match[2]) return self._exif diff --git a/src/PIL/ImageOps.py b/src/PIL/ImageOps.py index 5dc34f4424c..facc30ba0ee 100644 --- a/src/PIL/ImageOps.py +++ b/src/PIL/ImageOps.py @@ -21,7 +21,7 @@ import operator import re -from . import Image, ImagePalette +from . import ExifTags, Image, ImagePalette # # helpers @@ -589,7 +589,7 @@ def exif_transpose(image, inPlace=False): image will be returned. """ image_exif = image.getexif() - orientation = image_exif.get(0x0112) + orientation = image_exif.get(ExifTags.Base.Orientation) method = { 2: Image.Transpose.FLIP_LEFT_RIGHT, 3: Image.Transpose.ROTATE_180, @@ -608,8 +608,8 @@ def exif_transpose(image, inPlace=False): exif_image = image if inPlace else transposed_image exif = exif_image.getexif() - if 0x0112 in exif: - del exif[0x0112] + if ExifTags.Base.Orientation in exif: + del exif[ExifTags.Base.Orientation] if "exif" in exif_image.info: exif_image.info["exif"] = exif.tobytes() elif "Raw profile type exif" in exif_image.info: diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index 3d4d0910abd..7f8449ea673 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -49,7 +49,7 @@ from fractions import Fraction from numbers import Number, Rational -from . import Image, ImageFile, ImageOps, ImagePalette, TiffTags +from . import ExifTags, Image, ImageFile, ImageOps, ImagePalette, TiffTags from ._binary import i16be as i16 from ._binary import i32be as i32 from ._binary import o8 @@ -1183,7 +1183,7 @@ def get_photoshop_blocks(self): :returns: Photoshop "Image Resource Blocks" in a dictionary. """ blocks = {} - val = self.tag_v2.get(0x8649) + val = self.tag_v2.get(ExifTags.Base.ImageResources) if val: while val[:4] == b"8BIM": id = i16(val[4:6]) @@ -1548,7 +1548,7 @@ def _setup(self): palette = [o8(b // 256) for b in self.tag_v2[COLORMAP]] self.palette = ImagePalette.raw("RGB;L", b"".join(palette)) - self._tile_orientation = self.tag_v2.get(0x0112) + self._tile_orientation = self.tag_v2.get(ExifTags.Base.Orientation) # From f338f35657baad30295b45353d699cace83d3699 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 14 Jun 2023 10:01:36 +1000 Subject: [PATCH 4/5] Changed inPlace to be keyword-only argument --- src/PIL/ImageOps.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PIL/ImageOps.py b/src/PIL/ImageOps.py index facc30ba0ee..752d132a320 100644 --- a/src/PIL/ImageOps.py +++ b/src/PIL/ImageOps.py @@ -576,13 +576,13 @@ def solarize(image, threshold=128): return _lut(image, lut) -def exif_transpose(image, inPlace=False): +def exif_transpose(image, *, inPlace=False): """ If an image has an EXIF Orientation tag, other than 1, transpose the image accordingly, and remove the orientation data. :param image: The image to transpose. - :param inPlace: Boolean. + :param inPlace: Boolean. Keyword-only argument. If ``True``, the original image is modified in-place, and ``None`` is returned. If ``False`` (default), a new :py:class:`~PIL.Image.Image` object is returned with the transposition applied. If there is no transposition, a copy of the From 7d97fa8b86a9f61069579fbedb2cc09fb437b12f Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 14 Jun 2023 16:12:47 +1000 Subject: [PATCH 5/5] Use snake case --- Tests/test_imageops.py | 4 ++-- src/PIL/ImageOps.py | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Tests/test_imageops.py b/Tests/test_imageops.py index e7d04cceb3b..b05785be0ec 100644 --- a/Tests/test_imageops.py +++ b/Tests/test_imageops.py @@ -404,13 +404,13 @@ def check(orientation_im): assert 0x0112 not in transposed_im.getexif() -def test_exif_transpose_inplace(): +def test_exif_transpose_in_place(): with Image.open("Tests/images/orientation_rectangle.jpg") as im: assert im.size == (2, 1) assert im.getexif()[0x0112] == 8 expected = im.rotate(90, expand=True) - ImageOps.exif_transpose(im, inPlace=True) + ImageOps.exif_transpose(im, in_place=True) assert im.size == (1, 2) assert 0x0112 not in im.getexif() assert_image_equal(im, expected) diff --git a/src/PIL/ImageOps.py b/src/PIL/ImageOps.py index 752d132a320..17702778c13 100644 --- a/src/PIL/ImageOps.py +++ b/src/PIL/ImageOps.py @@ -576,13 +576,13 @@ def solarize(image, threshold=128): return _lut(image, lut) -def exif_transpose(image, *, inPlace=False): +def exif_transpose(image, *, in_place=False): """ If an image has an EXIF Orientation tag, other than 1, transpose the image accordingly, and remove the orientation data. :param image: The image to transpose. - :param inPlace: Boolean. Keyword-only argument. + :param in_place: Boolean. Keyword-only argument. If ``True``, the original image is modified in-place, and ``None`` is returned. If ``False`` (default), a new :py:class:`~PIL.Image.Image` object is returned with the transposition applied. If there is no transposition, a copy of the @@ -601,11 +601,11 @@ def exif_transpose(image, *, inPlace=False): }.get(orientation) if method is not None: transposed_image = image.transpose(method) - if inPlace: + if in_place: image.im = transposed_image.im image.pyaccess = None image._size = transposed_image._size - exif_image = image if inPlace else transposed_image + exif_image = image if in_place else transposed_image exif = exif_image.getexif() if ExifTags.Base.Orientation in exif: @@ -622,7 +622,7 @@ def exif_transpose(image, *, inPlace=False): exif_image.info["XML:com.adobe.xmp"] = re.sub( pattern, "", exif_image.info["XML:com.adobe.xmp"] ) - if not inPlace: + if not in_place: return transposed_image - elif not inPlace: + elif not in_place: return image.copy()