Commit 815ef038 authored by Skia's avatar Skia

Better handle rotations

parent 869634d6
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
{% for r in user.pictures.exclude(picture=None).filter(picture__parent=album) %} {% for r in user.pictures.exclude(picture=None).filter(picture__parent=album) %}
<div style="display: inline-block; border: solid 1px black; width: 9%; margin: 0.1%"> <div style="display: inline-block; border: solid 1px black; width: 9%; margin: 0.1%">
<a href="{{ url("sas:picture", picture_id=r.picture.id) }}#pict"> <a href="{{ url("sas:picture", picture_id=r.picture.id) }}#pict">
<img src="{{ r.picture.as_picture.get_download_url() }}" alt="{{ r.picture.get_display_name() }}" style="max-width: 100%"/> <img src="{{ r.picture.as_picture.get_download_thumb_url() }}" alt="{{ r.picture.get_display_name() }}" style="max-width: 100%"/>
</a> </a>
</div> </div>
{% endfor %} {% endfor %}
......
# Image utils # Image utils
from io import BytesIO from io import BytesIO
from PIL import Image from PIL import Image, ExifTags
# from exceptions import IOError # from exceptions import IOError
import PIL import PIL
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
...@@ -25,3 +25,16 @@ def resize_image(im, edge, format): ...@@ -25,3 +25,16 @@ def resize_image(im, edge, format):
im.save(fp=content, format=format.upper(), quality=90, optimize=True, progressive=True) im.save(fp=content, format=format.upper(), quality=90, optimize=True, progressive=True)
return ContentFile(content.getvalue()) 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
...@@ -1950,7 +1950,7 @@ msgstr "Erreur de création du dossier %(folder_name)s : %(msg)s" ...@@ -1950,7 +1950,7 @@ msgstr "Erreur de création du dossier %(folder_name)s : %(msg)s"
#: sas/views.py:41 #: sas/views.py:41
#, python-format #, python-format
msgid "Error uploading file %(file_name)s: %(msg)s" 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 #: core/views/forms.py:59 core/views/forms.py:62
msgid "Choose file" msgid "Choose file"
......
...@@ -30,6 +30,19 @@ class Picture(SithFile): ...@@ -30,6 +30,19 @@ class Picture(SithFile):
def get_download_thumb_url(self): def get_download_thumb_url(self):
return reverse('sas:download_thumb', kwargs={'picture_id': self.id}) 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): 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() return self.parent.children.exclude(is_moderated=False, asked_for_removal=True).filter(id__gt=self.id).order_by('id').first()
......
...@@ -34,8 +34,12 @@ ...@@ -34,8 +34,12 @@
{% block content %} {% block content %}
{{ print_path(picture.parent) }} {{ picture.get_display_name() }} {{ print_path(picture.parent) }} {{ picture.get_display_name() }}
<h3>{{ picture.get_display_name() }}</h3> <h3>{{ picture.get_display_name() }}</h3>
<div style="display: inline-block; width: 89%; background: #333;" id="pict"> <div style="display: inline-block; width: 89%; background: #333; border: solid #333 2px;" id="pict">
<img src="{{ picture.get_download_compressed_url() }}" alt="{{ picture.get_display_name() }}" style="width: 90%; display: block; margin: auto"/> {% if is_vertical %}
<img src="{{ picture.get_download_compressed_url() }}" alt="{{ picture.get_display_name() }}" style="width: 60%; display: block; margin: auto"/>
{% else %}
<img src="{{ picture.get_download_compressed_url() }}" alt="{{ picture.get_display_name() }}" style="width: 100%; display: block; margin: auto"/>
{% endif %}
</div> </div>
<div style="display: inline-block; width: 10%; vertical-align: top;"> <div style="display: inline-block; width: 10%; vertical-align: top;">
<div> <div>
...@@ -77,7 +81,9 @@ ...@@ -77,7 +81,9 @@
<a href="{{ picture.get_download_url() }}">{% trans %}HD version{% endtrans %}</a> <a href="{{ picture.get_download_url() }}">{% trans %}HD version{% endtrans %}</a>
</p> </p>
<p style="font-size: smaller;"> <p style="font-size: smaller;">
<a href="?ask_removal">{% trans %}Ask for removal{% endtrans %}</a> <a href="?rotate_left">{% trans %}Rotate left{% endtrans %}</a><br>
<a href="?rotate_right">{% trans %}Rotate right{% endtrans %}</a><br>
<a href="?ask_removal">{% trans %}Ask for removal{% endtrans %}</a><br>
</p> </p>
</div> </div>
{% endblock %} {% endblock %}
......
...@@ -10,12 +10,16 @@ from django.core.exceptions import PermissionDenied ...@@ -10,12 +10,16 @@ from django.core.exceptions import PermissionDenied
from ajax_select import make_ajax_form, make_ajax_field 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 import CanViewMixin, CanEditMixin, CanEditPropMixin, CanCreateMixin, TabedViewMixin
from core.views.forms import SelectUser, LoginForm, SelectDate, SelectDateTime from core.views.forms import SelectUser, LoginForm, SelectDate, SelectDateTime
from core.views.files import send_file from core.views.files import send_file
from core.models import SithFile, User from core.models import SithFile, User
from sas.models import Picture, Album, PeoplePictureRelation from sas.models import Picture, Album, PeoplePictureRelation
from core.utils import resize_image, exif_auto_rotate
class SASForm(forms.Form): class SASForm(forms.Form):
album_name = forms.CharField(label=_("Add a new album"), max_length=30, required=False) album_name = forms.CharField(label=_("Add a new album"), max_length=30, required=False)
...@@ -23,9 +27,6 @@ class SASForm(forms.Form): ...@@ -23,9 +27,6 @@ class SASForm(forms.Form):
required=False) required=False)
def process(self, parent, owner, files, automodere=False): def process(self, parent, owner, files, automodere=False):
from core.utils import resize_image
from io import BytesIO
from PIL import Image
try: try:
if self.cleaned_data['album_name'] != "": if self.cleaned_data['album_name'] != "":
album = Album(parent=parent, name=self.cleaned_data['album_name'], owner=owner, is_moderated=automodere) album = Album(parent=parent, name=self.cleaned_data['album_name'], owner=owner, is_moderated=automodere)
...@@ -40,14 +41,19 @@ class SASForm(forms.Form): ...@@ -40,14 +41,19 @@ class SASForm(forms.Form):
try: try:
new_file.clean() new_file.clean()
im = Image.open(BytesIO(f.read())) 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]) thumb = resize_image(im, 200, f.content_type.split('/')[-1])
compressed = resize_image(im, 600, 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 = thumb
new_file.thumbnail.name = new_file.name new_file.thumbnail.name = new_file.name
new_file.compressed = compressed new_file.compressed = compressed
new_file.compressed.name = new_file.name new_file.compressed.name = new_file.name
new_file.save() new_file.save()
print(new_file.compressed)
except Exception as e: except Exception as e:
self.add_error(None, _("Error uploading file %(file_name)s: %(msg)s") % {'file_name': f, 'msg': repr(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): ...@@ -94,6 +100,10 @@ class PictureView(CanViewMixin, DetailView, FormMixin):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
self.object = self.get_object() self.object = self.get_object()
self.form = self.get_form() 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(): if 'remove_user' in request.GET.keys():
try: try:
user = User.objects.filter(id=int(request.GET['remove_user'])).first() user = User.objects.filter(id=int(request.GET['remove_user'])).first()
...@@ -122,6 +132,9 @@ class PictureView(CanViewMixin, DetailView, FormMixin): ...@@ -122,6 +132,9 @@ class PictureView(CanViewMixin, DetailView, FormMixin):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(PictureView, self).get_context_data(**kwargs) kwargs = super(PictureView, self).get_context_data(**kwargs)
kwargs['form'] = self.form kwargs['form'] = self.form
im = Image.open(BytesIO(self.object.file.read()))
(w, h) = im.size
kwargs['is_vertical'] = (w / h) < 1
return kwargs return kwargs
def get_success_url(self): def get_success_url(self):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment