{"action":"created","issue":{"url":"https://api.github.com/repos/un1t/django-resized/issues/14","labels_url":"https://api.github.com/repos/un1t/django-resized/issues/14/labels{/name}","comments_url":"https://api.github.com/repos/un1t/django-resized/issues/14/comments","events_url":"https://api.github.com/repos/un1t/django-resized/issues/14/events","html_url":"https://github.com/un1t/django-resized/pull/14","id":115605434,"number":14,"title":"Normalize orientation from meta data","user":{"login":"mverleg","id":6442863,"avatar_url":"https://avatars.githubusercontent.com/u/6442863?v=3","gravatar_id":"","url":"https://api.github.com/users/mverleg","html_url":"https://github.com/mverleg","followers_url":"https://api.github.com/users/mverleg/followers","following_url":"https://api.github.com/users/mverleg/following{/other_user}","gists_url":"https://api.github.com/users/mverleg/gists{/gist_id}","starred_url":"https://api.github.com/users/mverleg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mverleg/subscriptions","organizations_url":"https://api.github.com/users/mverleg/orgs","repos_url":"https://api.github.com/users/mverleg/repos","events_url":"https://api.github.com/users/mverleg/events{/privacy}","received_events_url":"https://api.github.com/users/mverleg/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-11-06T22:42:26Z","updated_at":"2015-11-06T22:43:14Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/un1t/django-resized/pulls/14","html_url":"https://github.com/un1t/django-resized/pull/14","diff_url":"https://github.com/un1t/django-resized/pull/14.diff","patch_url":"https://github.com/un1t/django-resized/pull/14.patch"},"body":"I've been having trouble with uploaded jpg pictures having the wrong orientation (in Firefox). This is due to some cameras storing orientation in exif tags, which isn't handled correctly by PIL. As an example, with the attached image:\r\n\r\n    from PIL import Image, ExifTags\r\n    \r\n    def normalize_rotation(image):\r\n        \"\"\"\r\n        Find orientation header and rotate the actual data instead.\r\n        Adapted from http://stackoverflow.com/a/6218425/723090\r\n        \"\"\"\r\n        try:\r\n            image._getexif()\r\n        except AttributeError:\r\n            \"\"\" No exit data; this image is not a jpg and can be skipped. \"\"\"\r\n            return image\r\n        for orientation in ExifTags.TAGS.keys():\r\n            \"\"\" Look for orientation header, stop when found. \"\"\"\r\n            if ExifTags.TAGS[orientation] == 'Orientation':\r\n                break\r\n        else:\r\n            \"\"\" No orientation header found, do nothing. \"\"\"\r\n            return image\r\n        \"\"\" Apply the different possible orientations to the data; preserve format. \"\"\"\r\n        format = image.format\r\n        action_nr = image._getexif()[orientation]\r\n        if action_nr == 3:\r\n            image = image.rotate(180, expand=True)\r\n        elif action_nr == 6:\r\n            image = image.rotate(270, expand=True)\r\n        elif action_nr == 8:\r\n            image = image.rotate(90, expand=True)\r\n        image.format = format\r\n        return image\r\n    \r\n    img = Image.open('cny.jpg')\r\n    img2 = normalize_rotation(img)\r\n    \r\n    img.save('cny_nofix.jpg')\r\n    img2.save('cny_fix.jpg')\r\n    \r\nMultiple programs (all?) show cny_fix.jpg with the correct orientation but cny_nofix.jpg as being rotated 90 degrees (counter-clockwise) as compared to the input file. Not desirable.\r\n\r\nThe solution is to find the rotation header that PIL ignored, and manually apply the rotation to the actual data. This is what `normalize_rotation` does (and some handling of special cases, making it look more complicated than it is).\r\n\r\nI've tested it on Python 2.7 and 3.4 with jpg and png images (png images don't have this problem, but just to be sure it doesn't crash).\r\n\r\n![cny](https://cloud.githubusercontent.com/assets/6442863/11010564/f890940a-84df-11e5-9173-0c6c5470fd23.jpg)\r\n"},"comment":{"url":"https://api.github.com/repos/un1t/django-resized/issues/comments/154565981","html_url":"https://github.com/un1t/django-resized/pull/14#issuecomment-154565981","issue_url":"https://api.github.com/repos/un1t/django-resized/issues/14","id":154565981,"user":{"login":"mverleg","id":6442863,"avatar_url":"https://avatars.githubusercontent.com/u/6442863?v=3","gravatar_id":"","url":"https://api.github.com/users/mverleg","html_url":"https://github.com/mverleg","followers_url":"https://api.github.com/users/mverleg/followers","following_url":"https://api.github.com/users/mverleg/following{/other_user}","gists_url":"https://api.github.com/users/mverleg/gists{/gist_id}","starred_url":"https://api.github.com/users/mverleg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mverleg/subscriptions","organizations_url":"https://api.github.com/users/mverleg/orgs","repos_url":"https://api.github.com/users/mverleg/repos","events_url":"https://api.github.com/users/mverleg/events{/privacy}","received_events_url":"https://api.github.com/users/mverleg/received_events","type":"User","site_admin":false},"created_at":"2015-11-06T22:43:14Z","updated_at":"2015-11-06T22:43:14Z","body":"Ironically, github seems to suffer from a similar problem, the attached image has been rotated too... I'll host an original copy somewhere, one minute."}}