Fix image orientation when generating thumbnail (#5039)
This commit is contained in:
parent
07cff7b121
commit
f89f688a55
|
@ -0,0 +1 @@
|
||||||
|
Fix image orientation when generating thumbnails (needs pillow>=4.3.0). Contributed by Pau Rodriguez-Estivill.
|
|
@ -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):
|
||||||
)
|
)
|
||||||
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):
|
||||||
)
|
)
|
||||||
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
|
||||||
|
|
||||||
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):
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue