Skip to content
Snippets Groups Projects
Commit f89f688a authored by PauRE's avatar PauRE Committed by Richard van der Hoff
Browse files

Fix image orientation when generating thumbnail (#5039)

parent 07cff7b1
Branches
Tags
No related merge requests found
Fix image orientation when generating thumbnails (needs pillow>=4.3.0). Contributed by Pau Rodriguez-Estivill.
...@@ -53,7 +53,7 @@ REQUIREMENTS = [ ...@@ -53,7 +53,7 @@ REQUIREMENTS = [
"pyasn1-modules>=0.0.7", "pyasn1-modules>=0.0.7",
"daemonize>=2.3.1", "daemonize>=2.3.1",
"bcrypt>=3.1.0", "bcrypt>=3.1.0",
"pillow>=3.1.2", "pillow>=4.3.0",
"sortedcontainers>=1.4.4", "sortedcontainers>=1.4.4",
"psutil>=2.0.0", "psutil>=2.0.0",
"pymacaroons>=0.13.0", "pymacaroons>=0.13.0",
......
...@@ -444,6 +444,9 @@ class MediaRepository(object): ...@@ -444,6 +444,9 @@ class MediaRepository(object):
) )
return return
if thumbnailer.transpose_method is not None:
m_width, m_height = thumbnailer.transpose()
if t_method == "crop": if t_method == "crop":
t_byte_source = thumbnailer.crop(t_width, t_height, t_type) t_byte_source = thumbnailer.crop(t_width, t_height, t_type)
elif t_method == "scale": elif t_method == "scale":
...@@ -578,6 +581,12 @@ class MediaRepository(object): ...@@ -578,6 +581,12 @@ class MediaRepository(object):
) )
return return
if thumbnailer.transpose_method is not None:
m_width, m_height = yield logcontext.defer_to_thread(
self.hs.get_reactor(),
thumbnailer.transpose
)
# We deduplicate the thumbnail sizes by ignoring the cropped versions if # We deduplicate the thumbnail sizes by ignoring the cropped versions if
# they have the same dimensions of a scaled one. # they have the same dimensions of a scaled one.
thumbnails = {} thumbnails = {}
......
...@@ -20,6 +20,17 @@ import PIL.Image as Image ...@@ -20,6 +20,17 @@ import PIL.Image as Image
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
EXIF_ORIENTATION_TAG = 0x0112
EXIF_TRANSPOSE_MAPPINGS = {
2: Image.FLIP_LEFT_RIGHT,
3: Image.ROTATE_180,
4: Image.FLIP_TOP_BOTTOM,
5: Image.TRANSPOSE,
6: Image.ROTATE_270,
7: Image.TRANSVERSE,
8: Image.ROTATE_90
}
class Thumbnailer(object): class Thumbnailer(object):
...@@ -31,6 +42,30 @@ class Thumbnailer(object): ...@@ -31,6 +42,30 @@ class Thumbnailer(object):
def __init__(self, input_path): def __init__(self, input_path):
self.image = Image.open(input_path) self.image = Image.open(input_path)
self.width, self.height = self.image.size self.width, self.height = self.image.size
self.transpose_method = None
try:
# We don't use ImageOps.exif_transpose since it crashes with big EXIF
image_exif = self.image._getexif()
if image_exif is not None:
image_orientation = image_exif.get(EXIF_ORIENTATION_TAG)
self.transpose_method = EXIF_TRANSPOSE_MAPPINGS.get(image_orientation)
except Exception as e:
# A lot of parsing errors can happen when parsing EXIF
logger.info("Error parsing image EXIF information: %s", e)
def transpose(self):
"""Transpose the image using its EXIF Orientation tag
Returns:
Tuple[int, int]: (width, height) containing the new image size in pixels.
"""
if self.transpose_method is not None:
self.image = self.image.transpose(self.transpose_method)
self.width, self.height = self.image.size
self.transpose_method = None
# We don't need EXIF any more
self.image.info["exif"] = None
return self.image.size
def aspect(self, max_width, max_height): def aspect(self, max_width, max_height):
"""Calculate the largest size that preserves aspect ratio which """Calculate the largest size that preserves aspect ratio which
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment