Merge pull request #805 from ae-utbm/images-format

Better images format
This commit is contained in:
thomas girod 2024-09-01 23:33:57 +02:00 committed by GitHub
commit e0bf797876
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 43 additions and 78 deletions

View File

@ -234,10 +234,10 @@ Welcome to the wiki page!
skia_profile = SithFile( skia_profile = SithFile(
parent=profiles_root, parent=profiles_root,
name=name, name=name,
file=resize_image(Image.open(BytesIO(f.read())), 400, "JPEG"), file=resize_image(Image.open(BytesIO(f.read())), 400, "WEBP"),
owner=skia, owner=skia,
is_folder=False, is_folder=False,
mime_type="image/jpeg", mime_type="image/webp",
size=skia_profile_path.stat().st_size, size=skia_profile_path.stat().st_size,
) )
skia_profile.file.name = name skia_profile.file.name = name
@ -368,10 +368,10 @@ Welcome to the wiki page!
richard_profile = SithFile( richard_profile = SithFile(
parent=profiles_root, parent=profiles_root,
name=name, name=name,
file=resize_image(Image.open(BytesIO(f.read())), 400, "JPEG"), file=resize_image(Image.open(BytesIO(f.read())), 400, "WEBP"),
owner=richard, owner=richard,
is_folder=False, is_folder=False,
mime_type="image/jpeg", mime_type="image/webp",
size=richard_profile_path.stat().st_size, size=richard_profile_path.stat().st_size,
) )
richard_profile.file.name = name richard_profile.file.name = name
@ -853,10 +853,10 @@ Welcome to the wiki page!
sli_profile = SithFile( sli_profile = SithFile(
parent=profiles_root, parent=profiles_root,
name=name, name=name,
file=resize_image(Image.open(BytesIO(f.read())), 400, "JPEG"), file=resize_image(Image.open(BytesIO(f.read())), 400, "WEBP"),
owner=sli, owner=sli,
is_folder=False, is_folder=False,
mime_type="image/jpeg", mime_type="image/webp",
size=sli_profile_path.stat().st_size, size=sli_profile_path.stat().st_size,
) )
sli_profile.file.name = name sli_profile.file.name = name
@ -887,10 +887,10 @@ Welcome to the wiki page!
krophil_profile = SithFile( krophil_profile = SithFile(
parent=profiles_root, parent=profiles_root,
name=name, name=name,
file=resize_image(Image.open(BytesIO(f.read())), 400, "JPEG"), file=resize_image(Image.open(BytesIO(f.read())), 400, "WEBP"),
owner=krophil, owner=krophil,
is_folder=False, is_folder=False,
mime_type="image/jpeg", mime_type="image/webp",
size=krophil_profile_path.stat().st_size, size=krophil_profile_path.stat().st_size,
) )
krophil_profile.file.name = name krophil_profile.file.name = name
@ -1217,13 +1217,13 @@ Welcome to the wiki page!
parent=album, parent=album,
name=p.name, name=p.name,
file=resize_image( file=resize_image(
Image.open(BytesIO(p.read_bytes())), 1000, "JPEG" Image.open(BytesIO(p.read_bytes())), 1000, "WEBP"
), ),
owner=root, owner=root,
is_folder=False, is_folder=False,
is_in_sas=True, is_in_sas=True,
is_moderated=True, is_moderated=True,
mime_type="image/jpeg", mime_type="image/webp",
size=p.stat().st_size, size=p.stat().st_size,
) )
pict.file.name = p.name pict.file.name = p.name
@ -1252,10 +1252,10 @@ Welcome to the wiki page!
skia_profile = SithFile( skia_profile = SithFile(
parent=profiles_root, parent=profiles_root,
name=name, name=name,
file=resize_image(Image.open(BytesIO(f.read())), 400, "JPEG"), file=resize_image(Image.open(BytesIO(f.read())), 400, "WEBP"),
owner=skia, owner=skia,
is_folder=False, is_folder=False,
mime_type="image/jpeg", mime_type="image/webp",
size=skia_profile_path.stat().st_size, size=skia_profile_path.stat().st_size,
) )
skia_profile.file.name = name skia_profile.file.name = name

View File

@ -164,7 +164,7 @@
/* Stop camera */ /* Stop camera */
this.video.pause() this.video.pause()
this.video.srcObject.getTracks().forEach((track) => { this.video.srcObject.getTracks().forEach((track) => {
if (track.readyState == 'live') { if (track.readyState === 'live') {
track.stop(); track.stop();
} }
}); });
@ -172,8 +172,8 @@
canvas.toBlob((blob) => { canvas.toBlob((blob) => {
let file = new File( let file = new File(
[blob], [blob],
"{% trans %}captured{% endtrans %}.png", "{% trans %}captured{% endtrans %}.webp",
{ type: "image/jpeg" }, { type: "image/webp" },
); );
let list = new DataTransfer(); let list = new DataTransfer();

View File

@ -127,11 +127,6 @@ urlpatterns = [
UserUpdateProfileView.as_view(), UserUpdateProfileView.as_view(),
name="user_edit", name="user_edit",
), ),
path(
"user/<int:user_id>/profile_upload/",
UserUploadProfilePictView.as_view(),
name="user_profile_upload",
),
path("user/<int:user_id>/clubs/", UserClubView.as_view(), name="user_clubs"), path("user/<int:user_id>/clubs/", UserClubView.as_view(), name="user_clubs"),
path( path(
"user/<int:user_id>/prefs/", "user/<int:user_id>/prefs/",

View File

@ -102,13 +102,17 @@ def scale_dimension(width, height, long_edge):
def resize_image(im, edge, img_format): def resize_image(im, edge, img_format):
(w, h) = im.size (w, h) = im.size
(width, height) = scale_dimension(w, h, long_edge=edge) (width, height) = scale_dimension(w, h, long_edge=edge)
img_format = img_format.upper()
content = BytesIO() content = BytesIO()
# use the lanczos filter for antialiasing and discard the alpha channel # use the lanczos filter for antialiasing and discard the alpha channel
im = im.resize((width, height), Resampling.LANCZOS).convert("RGB") im = im.resize((width, height), Resampling.LANCZOS)
if img_format == "JPEG":
# converting an image with an alpha channel to jpeg would cause a crash
im = im.convert("RGB")
try: try:
im.save( im.save(
fp=content, fp=content,
format=img_format.upper(), format=img_format,
quality=90, quality=90,
optimize=True, optimize=True,
progressive=True, progressive=True,
@ -117,7 +121,7 @@ def resize_image(im, edge, img_format):
PIL.ImageFile.MAXBLOCK = im.size[0] * im.size[1] PIL.ImageFile.MAXBLOCK = im.size[0] * im.size[1]
im.save( im.save(
fp=content, fp=content,
format=img_format.upper(), format=img_format,
quality=90, quality=90,
optimize=True, optimize=True,
progressive=True, progressive=True,

View File

@ -12,6 +12,7 @@
# OR WITHIN THE LOCAL FILE "LICENSE" # OR WITHIN THE LOCAL FILE "LICENSE"
# #
# #
import mimetypes
from urllib.parse import quote, urljoin from urllib.parse import quote, urljoin
# This file contains all the views that concern the page model # This file contains all the views that concern the page model
@ -77,7 +78,7 @@ def send_file(
raise Http404 raise Http404
with open(filepath, "rb") as filename: with open(filepath, "rb") as filename:
response.content = FileWrapper(filename) response.content = FileWrapper(filename)
response["Content-Type"] = f.mime_type response["Content-Type"] = mimetypes.guess_type(filepath)[0]
response["Last-Modified"] = http_date(f.date.timestamp()) response["Last-Modified"] = http_date(f.date.timestamp())
response["Content-Length"] = filepath.stat().st_size response["Content-Length"] = filepath.stat().st_size
return response return response

View File

@ -239,10 +239,6 @@ class UserProfileForm(forms.ModelForm):
"quote": forms.Textarea, "quote": forms.Textarea,
} }
def generate_name(self, field_name, f):
field_name = field_name[:-4]
return field_name + str(self.instance.id) + "." + f.content_type.split("/")[-1]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@ -278,11 +274,11 @@ class UserProfileForm(forms.ModelForm):
im = Image.open(BytesIO(f.read())) im = Image.open(BytesIO(f.read()))
new_file = SithFile( new_file = SithFile(
parent=parent, parent=parent,
name=self.generate_name(field, f), name=f"{field.removesuffix('_pict')}_{self.instance.id}.webp",
file=resize_image(im, 400, f.content_type.split("/")[-1]), file=resize_image(im, 400, "webp"),
owner=self.instance, owner=self.instance,
is_folder=False, is_folder=False,
mime_type=f.content_type, mime_type="image/wepb",
size=f.size, size=f.size,
moderator=self.instance, moderator=self.instance,
is_moderated=True, is_moderated=True,

View File

@ -31,7 +31,7 @@ from django.conf import settings
from django.contrib.auth import login, views from django.contrib.auth import login, views
from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import PermissionDenied, ValidationError from django.core.exceptions import PermissionDenied
from django.forms import CheckboxSelectMultiple from django.forms import CheckboxSelectMultiple
from django.forms.models import modelform_factory from django.forms.models import modelform_factory
from django.http import Http404, HttpResponse from django.http import Http404, HttpResponse
@ -52,7 +52,7 @@ from django.views.generic.dates import MonthMixin, YearMixin
from django.views.generic.edit import FormView, UpdateView from django.views.generic.edit import FormView, UpdateView
from honeypot.decorators import check_honeypot from honeypot.decorators import check_honeypot
from core.models import Gift, Preferences, SithFile, User from core.models import Gift, Preferences, User
from core.views import ( from core.views import (
CanEditMixin, CanEditMixin,
CanEditPropMixin, CanEditPropMixin,
@ -561,43 +561,6 @@ class UserListView(ListView, CanEditPropMixin):
template_name = "core/user_list.jinja" template_name = "core/user_list.jinja"
class UserUploadProfilePictView(CanEditMixin, DetailView):
"""Handle the upload of the profile picture taken with webcam in navigator."""
model = User
pk_url_kwarg = "user_id"
template_name = "core/user_edit.jinja"
def post(self, request, *args, **kwargs):
from io import BytesIO
from PIL import Image
from core.utils import resize_image
self.object = self.get_object()
if self.object.profile_pict:
raise ValidationError(_("User already has a profile picture"))
f = request.FILES["new_profile_pict"]
parent = SithFile.objects.filter(parent=None, name="profiles").first()
name = str(self.object.id) + "_profile.jpg" # Webcamejs uploads JPGs
im = Image.open(BytesIO(f.read()))
new_file = SithFile(
parent=parent,
name=name,
file=resize_image(im, 400, f.content_type.split("/")[-1]),
owner=self.object,
is_folder=False,
mime_type=f.content_type,
size=f.size,
)
new_file.file.name = name
new_file.save()
self.object.profile_pict = new_file
self.object.save()
return redirect("core:user_edit", user_id=self.object.id)
class UserUpdateProfileView(UserTabsMixin, CanEditMixin, UpdateView): class UserUpdateProfileView(UserTabsMixin, CanEditMixin, UpdateView):
"""Edit a user's profile.""" """Edit a user's profile."""

View File

@ -110,19 +110,25 @@ class Picture(SasFile):
im = exif_auto_rotate(im) im = exif_auto_rotate(im)
except: except:
pass pass
file = resize_image(im, max(im.size), self.mime_type.split("/")[-1]) # convert the compressed image and the thumbnail into webp
thumb = resize_image(im, 200, self.mime_type.split("/")[-1]) # The original image keeps its original type, because it's not
compressed = resize_image(im, 1200, self.mime_type.split("/")[-1]) # meant to be shown on the website, but rather to keep the real image
# for less frequent cases (like downloading the pictures of an user)
extension = self.mime_type.split("/")[-1]
file = resize_image(im, max(im.size), extension)
thumb = resize_image(im, 200, "webp")
compressed = resize_image(im, 1200, "webp")
if overwrite: if overwrite:
self.file.delete() self.file.delete()
self.thumbnail.delete() self.thumbnail.delete()
self.compressed.delete() self.compressed.delete()
new_extension_name = self.name.removesuffix(extension) + "webp"
self.file = file self.file = file
self.file.name = self.name self.file.name = self.name
self.thumbnail = thumb self.thumbnail = thumb
self.thumbnail.name = self.name self.thumbnail.name = new_extension_name
self.compressed = compressed self.compressed = compressed
self.compressed.name = self.name self.compressed.name = new_extension_name
self.save() self.save()
def rotate(self, degree): def rotate(self, degree):
@ -224,9 +230,9 @@ class Album(SasFile):
.first() .first()
) )
if p and p.file: if p and p.file:
im = Image.open(BytesIO(p.file.read())) image = resize_image(Image.open(BytesIO(p.file.read())), 200, "webp")
self.file = resize_image(im, 200, "jpeg") self.file = image
self.file.name = self.name + "/thumb.jpg" self.file.name = f"{self.name}/thumb.webp"
self.save() self.save()