mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-08-24 14:14:47 +03:00
Added ImageOps auto_transpose
This commit is contained in:
parent
929c817014
commit
aa7efbbbc9
BIN
Tests/images/g4_orientation_1.tif
Executable file
BIN
Tests/images/g4_orientation_1.tif
Executable file
Binary file not shown.
BIN
Tests/images/g4_orientation_2.tif
Executable file
BIN
Tests/images/g4_orientation_2.tif
Executable file
Binary file not shown.
BIN
Tests/images/g4_orientation_3.tif
Executable file
BIN
Tests/images/g4_orientation_3.tif
Executable file
Binary file not shown.
BIN
Tests/images/g4_orientation_4.tif
Executable file
BIN
Tests/images/g4_orientation_4.tif
Executable file
Binary file not shown.
BIN
Tests/images/g4_orientation_5.tif
Executable file
BIN
Tests/images/g4_orientation_5.tif
Executable file
Binary file not shown.
BIN
Tests/images/g4_orientation_6.tif
Executable file
BIN
Tests/images/g4_orientation_6.tif
Executable file
Binary file not shown.
BIN
Tests/images/g4_orientation_7.tif
Executable file
BIN
Tests/images/g4_orientation_7.tif
Executable file
Binary file not shown.
BIN
Tests/images/g4_orientation_8.tif
Executable file
BIN
Tests/images/g4_orientation_8.tif
Executable file
Binary file not shown.
|
@ -70,6 +70,9 @@ class TestImageOps(PillowTestCase):
|
||||||
ImageOps.exif_transpose(hopper("L"))
|
ImageOps.exif_transpose(hopper("L"))
|
||||||
ImageOps.exif_transpose(hopper("RGB"))
|
ImageOps.exif_transpose(hopper("RGB"))
|
||||||
|
|
||||||
|
ImageOps.auto_transpose(hopper("L"))
|
||||||
|
ImageOps.auto_transpose(hopper("RGB"))
|
||||||
|
|
||||||
def test_1pxfit(self):
|
def test_1pxfit(self):
|
||||||
# Division by zero in equalize if image is 1 pixel high
|
# Division by zero in equalize if image is 1 pixel high
|
||||||
newimg = ImageOps.fit(hopper("RGB").resize((1, 1)), (35, 35))
|
newimg = ImageOps.fit(hopper("RGB").resize((1, 1)), (35, 35))
|
||||||
|
@ -250,28 +253,47 @@ class TestImageOps(PillowTestCase):
|
||||||
exts = [".jpg"]
|
exts = [".jpg"]
|
||||||
if HAVE_WEBP and _webp.HAVE_WEBPANIM:
|
if HAVE_WEBP and _webp.HAVE_WEBPANIM:
|
||||||
exts.append(".webp")
|
exts.append(".webp")
|
||||||
for ext in exts:
|
for transpose in [ImageOps.exif_transpose, ImageOps.auto_transpose]:
|
||||||
base_im = Image.open("Tests/images/hopper" + ext)
|
for ext in exts:
|
||||||
|
base_im = Image.open("Tests/images/hopper" + ext)
|
||||||
|
|
||||||
orientations = [base_im]
|
orientations = [base_im]
|
||||||
for i in range(2, 9):
|
for i in range(2, 9):
|
||||||
im = Image.open("Tests/images/hopper_orientation_" + str(i) + ext)
|
im = Image.open("Tests/images/hopper_orientation_" + str(i) + ext)
|
||||||
orientations.append(im)
|
orientations.append(im)
|
||||||
for i, orientation_im in enumerate(orientations):
|
for i, orientation_im in enumerate(orientations):
|
||||||
for im in [orientation_im, orientation_im.copy()]: # ImageFile # Image
|
for im in [
|
||||||
if i == 0:
|
orientation_im,
|
||||||
self.assertNotIn("exif", im.info)
|
orientation_im.copy(),
|
||||||
else:
|
]: # ImageFile # Image
|
||||||
original_exif = im.info["exif"]
|
if i == 0:
|
||||||
transposed_im = ImageOps.exif_transpose(im)
|
self.assertNotIn("exif", im.info)
|
||||||
self.assert_image_similar(base_im, transposed_im, 17)
|
else:
|
||||||
if i == 0:
|
original_exif = im.info["exif"]
|
||||||
self.assertNotIn("exif", im.info)
|
transposed_im = transpose(im)
|
||||||
else:
|
self.assert_image_similar(base_im, transposed_im, 17)
|
||||||
self.assertNotEqual(transposed_im.info["exif"], original_exif)
|
if i == 0:
|
||||||
|
self.assertNotIn("exif", im.info)
|
||||||
|
else:
|
||||||
|
self.assertNotEqual(
|
||||||
|
transposed_im.info["exif"], original_exif
|
||||||
|
)
|
||||||
|
|
||||||
self.assertNotIn(0x0112, transposed_im.getexif())
|
self.assertNotIn(0x0112, transposed_im.getexif())
|
||||||
|
|
||||||
# Repeat the operation, to test that it does not keep transposing
|
# Repeat the operation,
|
||||||
transposed_im2 = ImageOps.exif_transpose(transposed_im)
|
# to test that it does not keep transposing
|
||||||
self.assert_image_equal(transposed_im2, transposed_im)
|
transposed_im2 = transpose(transposed_im)
|
||||||
|
self.assert_image_equal(transposed_im2, transposed_im)
|
||||||
|
|
||||||
|
def test_auto_transpose(self):
|
||||||
|
base_im = Image.open("Tests/images/g4_orientation_1.tif")
|
||||||
|
|
||||||
|
for i in range(2, 9):
|
||||||
|
im = Image.open("Tests/images/g4_orientation_" + str(i) + ".tif")
|
||||||
|
transposed_im = ImageOps.auto_transpose(im)
|
||||||
|
self.assert_image_similar(base_im, transposed_im, 0.7)
|
||||||
|
|
||||||
|
# Repeat the operation, to test that it does not keep transposing
|
||||||
|
transposed_im2 = ImageOps.auto_transpose(transposed_im)
|
||||||
|
self.assert_image_equal(transposed_im2, transposed_im)
|
||||||
|
|
|
@ -520,16 +520,7 @@ def solarize(image, threshold=128):
|
||||||
return _lut(image, lut)
|
return _lut(image, lut)
|
||||||
|
|
||||||
|
|
||||||
def exif_transpose(image):
|
def _transpose(image, orientation, exif=None):
|
||||||
"""
|
|
||||||
If an image has an EXIF Orientation tag, return a new image that is
|
|
||||||
transposed accordingly. Otherwise, return a copy of the image.
|
|
||||||
|
|
||||||
:param image: The image to transpose.
|
|
||||||
:return: An image.
|
|
||||||
"""
|
|
||||||
exif = image.getexif()
|
|
||||||
orientation = exif.get(0x0112)
|
|
||||||
method = {
|
method = {
|
||||||
2: Image.FLIP_LEFT_RIGHT,
|
2: Image.FLIP_LEFT_RIGHT,
|
||||||
3: Image.ROTATE_180,
|
3: Image.ROTATE_180,
|
||||||
|
@ -541,7 +532,40 @@ def exif_transpose(image):
|
||||||
}.get(orientation)
|
}.get(orientation)
|
||||||
if method is not None:
|
if method is not None:
|
||||||
transposed_image = image.transpose(method)
|
transposed_image = image.transpose(method)
|
||||||
del exif[0x0112]
|
if exif:
|
||||||
transposed_image.info["exif"] = exif.tobytes()
|
del exif[0x0112]
|
||||||
|
transposed_image.info["exif"] = exif.tobytes()
|
||||||
return transposed_image
|
return transposed_image
|
||||||
return image.copy()
|
return image.copy()
|
||||||
|
|
||||||
|
|
||||||
|
def exif_transpose(image):
|
||||||
|
"""
|
||||||
|
If an image has an EXIF Orientation tag, return a new image that is
|
||||||
|
transposed accordingly. Otherwise, return a copy of the image.
|
||||||
|
|
||||||
|
:param image: The image to transpose.
|
||||||
|
:return: An image.
|
||||||
|
"""
|
||||||
|
exif = image.getexif()
|
||||||
|
orientation = exif.get(0x0112)
|
||||||
|
return _transpose(image, orientation, exif)
|
||||||
|
|
||||||
|
|
||||||
|
def auto_transpose(image):
|
||||||
|
"""
|
||||||
|
If an image has an EXIF or TIFF Orientation tag, return a new image that is
|
||||||
|
transposed accordingly. Otherwise, return a copy of the image.
|
||||||
|
|
||||||
|
:param image: The image to transpose.
|
||||||
|
:return: An image.
|
||||||
|
"""
|
||||||
|
exif = image.getexif()
|
||||||
|
orientation = exif.get(0x0112)
|
||||||
|
if orientation and orientation != 1:
|
||||||
|
return _transpose(image, orientation, exif)
|
||||||
|
elif hasattr(image, "tag_v2"):
|
||||||
|
orientation = image.tag_v2.get(0x0112)
|
||||||
|
return _transpose(image, orientation)
|
||||||
|
else:
|
||||||
|
return image.copy()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user