From 5c46b74c69a542ffe55d6228b21521c5c2178f12 Mon Sep 17 00:00:00 2001 From: Goffi Date: Thu, 13 Aug 2020 23:46:18 +0200 Subject: [PATCH] plugin XEP-0264: fix orientation of thumbnails: Rotation of thumbnailis is now modified according to EXIF orientation data. Original image is not modified as user may want to keep it, and orientation transformation can modify encoding parameters. Update `pillow` minimum version to the first one with `exif_transpose` implementation. --- sat/plugins/plugin_xep_0264.py | 18 +++++++++++++----- setup.py | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/sat/plugins/plugin_xep_0264.py b/sat/plugins/plugin_xep_0264.py index 2f4ad8e0..119ec763 100644 --- a/sat/plugins/plugin_xep_0264.py +++ b/sat/plugins/plugin_xep_0264.py @@ -34,7 +34,7 @@ from sat.core import exceptions import hashlib try: - from PIL import Image + from PIL import Image, ImageOps except: raise exceptions.MissingModule( "Missing module pillow, please download/install it from https://python-pillow.github.io" @@ -138,7 +138,9 @@ class XEP_0264(object): """ return hashlib.sha256(repr((image_uid, size)).encode()).hexdigest() - def _blockingGenThumb(self, source_path, size=None, max_age=None, image_uid=None): + def _blockingGenThumb( + self, source_path, size=None, max_age=None, image_uid=None, + fix_orientation=True): """Generate a thumbnail for image This is a blocking method and must be executed in a thread @@ -152,16 +154,21 @@ class XEP_0264(object): return Failure(exceptions.DataError("Can't open image")) img.thumbnail(size) + if fix_orientation: + img = ImageOps.exif_transpose(img) + uid = self.getThumbId(image_uid or source_path, size) with self.host.common_cache.cacheData( PLUGIN_INFO[C.PI_IMPORT_NAME], uid, MIME_TYPE, max_age ) as f: img.save(f, SAVE_FORMAT) + log.debug(f"fixed orientation for {f.name}") return img.size, uid - def generateThumbnail(self, source_path, size=None, max_age=None, image_uid=None): + def generateThumbnail( + self, source_path, size=None, max_age=None, image_uid=None, fix_orientation=True): """Generate a thumbnail of image @param source_path(unicode): absolute path to source image @@ -172,13 +179,14 @@ class XEP_0264(object): @param image_uid(unicode, None): unique ID to identify the image use hash whenever possible if None, source_path will be used + @param fix_orientation(bool): if True, fix orientation using EXIF data @return D(tuple[tuple[int,int], unicode]): tuple with: - size of the thumbnail - unique Id of the thumbnail """ - d = threads.deferToThread( - self._blockingGenThumb, source_path, size, max_age, image_uid=image_uid + self._blockingGenThumb, source_path, size, max_age, image_uid=image_uid, + fix_orientation=fix_orientation ) d.addErrback( lambda failure_: log.error("thumbnail generation error: {}".format(failure_)) diff --git a/setup.py b/setup.py index 1f7868bd..70b3d4e9 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ install_requires = [ 'miniupnpc', 'mutagen', 'netifaces', - 'pillow', + 'pillow >= 6.0.0', 'progressbar2', 'cryptography', 'pygments',