faster image resizing and smaller results

This commit is contained in:
thomas girod 2024-10-02 23:15:37 +02:00
parent 655d72a2b1
commit d0f17bd41a
2 changed files with 32 additions and 21 deletions

View File

@ -82,40 +82,47 @@ def get_semester_code(d: Optional[date] = None) -> str:
return "P" + str(start.year)[-2:]
def resize_image(im: Image, edge: int, img_format: str):
"""Resize an image to fit the given edge length and format."""
def resize_image(
im: Image, edge: int, img_format: str, *, optimize: bool = True
) -> ContentFile:
"""Resize an image to fit the given edge length and format.
Args:
im: the image to resize
edge: the length that the greater side of the resized image should have
img_format: the target format of the image ("JPEG", "PNG", "WEBP"...)
optimize: Should the resized image be optimized ?
"""
(w, h) = im.size
ratio = edge / max(w, h)
(width, height) = int(w * ratio), int(h * ratio)
return resize_image_explicit(im, (width, height), img_format)
return resize_image_explicit(im, (width, height), img_format, optimize=optimize)
def resize_image_explicit(im: Image, size: tuple[int, int], img_format: str):
"""Resize an image to the given size and format."""
def resize_image_explicit(
im: Image, size: tuple[int, int], img_format: str, *, optimize: bool = True
) -> ContentFile:
"""Resize an image to the given size and format.
Args:
im: the image to resize
size: the target dimension, as a [width, height] tuple
img_format: the target format of the image ("JPEG", "PNG", "WEBP"...)
optimize: Should the resized image be optimized ?
"""
img_format = img_format.upper()
content = BytesIO()
# use the lanczos filter for antialiasing and discard the alpha channel
im = im.resize((size[0], size[1]), Resampling.LANCZOS)
if size != im.size:
im = im.resize((size[0], size[1]), Resampling.LANCZOS)
if img_format == "JPEG":
# converting an image with an alpha channel to jpeg would cause a crash
im = im.convert("RGB")
try:
im.save(
fp=content,
format=img_format,
quality=90,
optimize=True,
progressive=True,
)
im.save(fp=content, format=img_format, optimize=optimize)
except IOError:
PIL.ImageFile.MAXBLOCK = im.size[0] * im.size[1]
im.save(
fp=content,
format=img_format,
quality=90,
optimize=True,
progressive=True,
)
im.save(fp=content, format=img_format, optimize=optimize)
return ContentFile(content.getvalue())

View File

@ -117,7 +117,11 @@ class Picture(SasFile):
# 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)
# the HD version of the image doesn't need to be optimized, because :
# - it isn't frequently queried
# - optimizing large images takes a lot time, which greatly hinders the UX
# - photographers usually already optimize their images
file = resize_image(im, max(im.size), extension, optimize=False)
thumb = resize_image(im, 200, "webp")
compressed = resize_image(im, 1200, "webp")
if overwrite: