Repository: stephenmcd/mezzanine

Issue:
Thumbnails of rotated images appear on their side
Hi,

Scaling an image which contains a rotation, for example: 
http://roominreturn.test.go2people.nl/media/uploads/rooms/photo.jpg ,
results in a rotated image which is cut to the wrong dimensions and rotated sideways.

The thumbnail image is cut to height in stead of width and width in stead of height. In addition, it is shown sideways. For an example, see the image of the first room at:
http://roominreturn.test.go2people.nl/en/rooms/

The thumbnail shows correctly in my browser (Chrome on Mac), although still the size of width and height are exchanged: 
http://roominreturn.test.go2people.nl/media/uploads/rooms/.thumbnails/photo.jpg/photo-768x595.jpg

The code I am using in my template is:
`<img src="{{ MEDIA_URL }}{% thumbnail room.image_set.all.0.image 768 595 padding="True" %}" alt="{{ room }}" title="{{ room }}" />
`

(By the way, sorl.thumbnail works a bit better for me, see: http://roominreturn.test.go2people.nl/en/rooms/test_room/ )



Discussion:
The software versions I am using are:
$ pip freeze 
Django==1.8.12
Mezzanine==4.0.1
Pillow==3.2.0
PyJWT==1.4.0
Unidecode==0.04.18
argparse==1.2.1
beautifulsoup4==4.4.1
bleach==1.4.2
chardet==2.3.0
distribute==0.6.24
django-appconf==1.0.1
django-compressor==1.4
django-contrib-comments==1.6.1
django-crispy-forms==1.4.0
django-debug-toolbar==1.3.0
django-easy-maps==0.9
django-extensions==1.5.3
django-facebook==6.0.3
django-file-resubmit==0.4.2
django-filter==0.9.2
django-modeltranslation==0.9.1
-e git://github.com/peeb/django-mollie-ideal.git@d7da9c4a40f734101cb41c4405e35b92053a2d6a#egg=django_mollie_ideal-dev
django-registration-redux==1.2
django-rosetta==0.7.6
easy-thumbnails==2.3
filebrowser-safe==0.4.0
future==0.15.2
geopy==1.10.0
gevent==1.0.1
grappelli-safe==0.4.1
greenlet==0.4.5
gunicorn==19.3.0
html5lib==1.0b8
mailsnake==1.6.3
-e git://github.com/wimfeijen/mezzanine-blocks.git@532764dde0481473a451242184a6721ab229c5f1#egg=mezzanine_blocks-dev
microsofttranslator==0.5
-e git://github.com/mollie/mollie-api-python@7768a4afc54c2958047c6e1340ca0e62cf12d891#egg=mollie_api_python-dev
oauthlib==1.0.3
polib==1.0.6
psycopg2==2.6
python-dateutil==2.4.2
python-memcached==1.54
python-openid==2.2.5
python-social-auth==0.2.12
pytz==2015.6
requests==2.8.1
requests-oauthlib==0.5.0
simplejson==3.7.3
six==1.10.0
sorl-thumbnail==12.4a1
sqlparse==0.1.14
tzlocal==1.2
wsgiref==0.1.2

Hi @wimfeijen,

[This Stack Overflow post](http://stackoverflow.com/questions/4228530/pil-thumbnail-is-rotating-my-image) discusses this problem. It seems Pillow is a bit naive when it comes to the rotation flags, and doesn't preserve them through operations like "fit".

There's a bit of sample code there, and [here's the relevant code in Mezzanine](https://github.com/stephenmcd/mezzanine/blob/82441cbb7ce7f3188a80fce3d4ec66e0b589dfd6/mezzanine/core/templatetags/mezzanine_tags.py#L394). I won't get to this for a while but if you'd like to have a crack at a patch that would be the place to start.

Thanks for the report!

Thanks Alex for looking into this. 

A patch is in progress! :)

Great!

On Tue, 17 May 2016 at 15:30 Wim Feijen notifications@github.com wrote:

> Thanks Alex for looking into this.
> 
> A patch is in progress! :)
> 
> —
> You are receiving this because you commented.
> 
> Reply to this email directly or view it on GitHub
> https://github.com/stephenmcd/mezzanine/issues/1587#issuecomment-219640443


Resolving patch:
diff --git a/mezzanine/core/templatetags/mezzanine_tags.py b/mezzanine/core/templatetags/mezzanine_tags.py
--- a/mezzanine/core/templatetags/mezzanine_tags.py
+++ b/mezzanine/core/templatetags/mezzanine_tags.py
@@ -345,6 +345,29 @@ def thumbnail(image_url, width, height, upscale=True, quality=95, left=.5,
         return image_url
 
     image_info = image.info
+
+    # Transpose to align the image to its orientation if necessary.
+    # If the image is transposed, delete the exif information as
+    # not all browsers support the CSS image-orientation:
+    # - http://caniuse.com/#feat=css-image-orientation
+    try:
+        orientation = image._getexif().get(0x0112)
+    except:
+        orientation = None
+    if orientation:
+        methods = {
+           2: (Image.FLIP_LEFT_RIGHT,),
+           3: (Image.ROTATE_180,),
+           4: (Image.FLIP_TOP_BOTTOM,),
+           5: (Image.FLIP_LEFT_RIGHT, Image.ROTATE_90),
+           6: (Image.ROTATE_270,),
+           7: (Image.FLIP_LEFT_RIGHT, Image.ROTATE_270),
+           8: (Image.ROTATE_90,)}.get(orientation, ())
+        if methods:
+            image_info.pop('exif', None)
+            for method in methods:
+                image = image.transpose(method)
+
     to_width = int(width)
     to_height = int(height)
     from_width = image.size[0]


Test patch: