From 815ef03860b4340235d23fa847bef5b36ba640b9 Mon Sep 17 00:00:00 2001 From: Skia Date: Sun, 20 Nov 2016 13:39:04 +0100 Subject: [PATCH] Better handle rotations --- core/templates/core/user_pictures.jinja | 2 +- core/utils.py | 15 ++++++++++++++- locale/fr/LC_MESSAGES/django.po | 2 +- sas/models.py | 13 +++++++++++++ sas/templates/sas/picture.jinja | 12 +++++++++--- sas/views.py | 21 +++++++++++++++++---- 6 files changed, 55 insertions(+), 10 deletions(-) diff --git a/core/templates/core/user_pictures.jinja b/core/templates/core/user_pictures.jinja index e4cf9055..268edaed 100644 --- a/core/templates/core/user_pictures.jinja +++ b/core/templates/core/user_pictures.jinja @@ -12,7 +12,7 @@ {% for r in user.pictures.exclude(picture=None).filter(picture__parent=album) %}
- {{ r.picture.get_display_name() }} + {{ r.picture.get_display_name() }}
{% endfor %} diff --git a/core/utils.py b/core/utils.py index 087cafa2..423c42b6 100644 --- a/core/utils.py +++ b/core/utils.py @@ -1,7 +1,7 @@ # Image utils from io import BytesIO -from PIL import Image +from PIL import Image, ExifTags # from exceptions import IOError import PIL from django.core.files.base import ContentFile @@ -25,3 +25,16 @@ def resize_image(im, edge, format): im.save(fp=content, format=format.upper(), quality=90, optimize=True, progressive=True) return ContentFile(content.getvalue()) +def exif_auto_rotate(image): + for orientation in ExifTags.TAGS.keys() : + if ExifTags.TAGS[orientation]=='Orientation' : break + exif=dict(image._getexif().items()) + + if exif[orientation] == 3 : + image=image.rotate(180, expand=True) + elif exif[orientation] == 6 : + image=image.rotate(270, expand=True) + elif exif[orientation] == 8 : + image=image.rotate(90, expand=True) + + return image diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 9cb2df31..a407eda2 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -1950,7 +1950,7 @@ msgstr "Erreur de création du dossier %(folder_name)s : %(msg)s" #: sas/views.py:41 #, python-format msgid "Error uploading file %(file_name)s: %(msg)s" -msgstr "Erreur d'envoie du fichier %(file_name)s : %(msg)s" +msgstr "Erreur d'envoi du fichier %(file_name)s : %(msg)s" #: core/views/forms.py:59 core/views/forms.py:62 msgid "Choose file" diff --git a/sas/models.py b/sas/models.py index b8a9ee2f..e3f96318 100644 --- a/sas/models.py +++ b/sas/models.py @@ -30,6 +30,19 @@ class Picture(SithFile): def get_download_thumb_url(self): return reverse('sas:download_thumb', kwargs={'picture_id': self.id}) + def rotate(self, degree): + from PIL import Image + from io import BytesIO + from django.core.files.base import ContentFile + for attr in ['file', 'compressed', 'thumbnail']: + if self.__getattribute__(attr): + im = Image.open(BytesIO(self.__getattribute__(attr).read())) + new_image = BytesIO() + im = im.rotate(degree, expand=True) + im.save(fp=new_image, format=self.mime_type.split('/')[-1].upper(), quality=90, optimize=True, progressive=True) + self.__getattribute__(attr).save(self.name, ContentFile(new_image.getvalue())) + self.save() + def get_next(self): return self.parent.children.exclude(is_moderated=False, asked_for_removal=True).filter(id__gt=self.id).order_by('id').first() diff --git a/sas/templates/sas/picture.jinja b/sas/templates/sas/picture.jinja index b46b61bd..dc17a829 100644 --- a/sas/templates/sas/picture.jinja +++ b/sas/templates/sas/picture.jinja @@ -34,8 +34,12 @@ {% block content %} {{ print_path(picture.parent) }} {{ picture.get_display_name() }}

{{ picture.get_display_name() }}

-
- {{ picture.get_display_name() }} +
+ {% if is_vertical %} + {{ picture.get_display_name() }} + {% else %} + {{ picture.get_display_name() }} + {% endif %}
@@ -77,7 +81,9 @@ {% trans %}HD version{% endtrans %}

- {% trans %}Ask for removal{% endtrans %} + {% trans %}Rotate left{% endtrans %}
+ {% trans %}Rotate right{% endtrans %}
+ {% trans %}Ask for removal{% endtrans %}

{% endblock %} diff --git a/sas/views.py b/sas/views.py index 8f77b348..7b5e40c2 100644 --- a/sas/views.py +++ b/sas/views.py @@ -10,12 +10,16 @@ from django.core.exceptions import PermissionDenied from ajax_select import make_ajax_form, make_ajax_field +from io import BytesIO +from PIL import Image + from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, CanCreateMixin, TabedViewMixin from core.views.forms import SelectUser, LoginForm, SelectDate, SelectDateTime from core.views.files import send_file from core.models import SithFile, User from sas.models import Picture, Album, PeoplePictureRelation +from core.utils import resize_image, exif_auto_rotate class SASForm(forms.Form): album_name = forms.CharField(label=_("Add a new album"), max_length=30, required=False) @@ -23,9 +27,6 @@ class SASForm(forms.Form): required=False) def process(self, parent, owner, files, automodere=False): - from core.utils import resize_image - from io import BytesIO - from PIL import Image try: if self.cleaned_data['album_name'] != "": album = Album(parent=parent, name=self.cleaned_data['album_name'], owner=owner, is_moderated=automodere) @@ -40,14 +41,19 @@ class SASForm(forms.Form): try: new_file.clean() im = Image.open(BytesIO(f.read())) + try: + im = exif_auto_rotate(im) + except: pass + file = resize_image(im, max(im.size), f.content_type.split('/')[-1]) thumb = resize_image(im, 200, f.content_type.split('/')[-1]) compressed = resize_image(im, 600, f.content_type.split('/')[-1]) + new_file.file = file + new_file.file.name = new_file.name new_file.thumbnail = thumb new_file.thumbnail.name = new_file.name new_file.compressed = compressed new_file.compressed.name = new_file.name new_file.save() - print(new_file.compressed) except Exception as e: self.add_error(None, _("Error uploading file %(file_name)s: %(msg)s") % {'file_name': f, 'msg': repr(e)}) @@ -94,6 +100,10 @@ class PictureView(CanViewMixin, DetailView, FormMixin): def get(self, request, *args, **kwargs): self.object = self.get_object() self.form = self.get_form() + if 'rotate_right' in request.GET.keys(): + self.object.rotate(270) + if 'rotate_left' in request.GET.keys(): + self.object.rotate(90) if 'remove_user' in request.GET.keys(): try: user = User.objects.filter(id=int(request.GET['remove_user'])).first() @@ -122,6 +132,9 @@ class PictureView(CanViewMixin, DetailView, FormMixin): def get_context_data(self, **kwargs): kwargs = super(PictureView, self).get_context_data(**kwargs) kwargs['form'] = self.form + im = Image.open(BytesIO(self.object.file.read())) + (w, h) = im.size + kwargs['is_vertical'] = (w / h) < 1 return kwargs def get_success_url(self):