Thumbnails: Support animated GIFs (#2686)

Co-authored-by: Richard Schreiber <wiffbi@gmail.com>
This commit is contained in:
Raphael Michel
2022-06-15 18:21:43 +02:00
committed by GitHub
parent 8eaa8999e5
commit 54a4631e22

View File

@@ -25,7 +25,7 @@ from io import BytesIO
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.core.files.storage import default_storage from django.core.files.storage import default_storage
from PIL import Image, ImageOps from PIL import Image, ImageOps, ImageSequence
from PIL.Image import Resampling from PIL.Image import Resampling
from pretix.helpers.models import Thumbnail from pretix.helpers.models import Thumbnail
@@ -171,12 +171,23 @@ def create_thumbnail(sourcename, size):
except: except:
raise ThumbnailError('Could not load image') raise ThumbnailError('Could not load image')
image = resize_image(image, size) frames = [resize_image(frame, size) for frame in ImageSequence.Iterator(image)]
image_out = frames[0]
save_kwargs = {}
if source.name.lower().endswith('.jpg') or source.name.lower().endswith('.jpeg'): if source.name.lower().endswith('.jpg') or source.name.lower().endswith('.jpeg'):
# Yields better file sizes for photos # Yields better file sizes for photos
target_ext = 'jpeg' target_ext = 'jpeg'
quality = 95 quality = 95
elif source.name.lower().endswith('.gif') or source.name.lower().endswith('.png'):
target_ext = source.name.lower()[-3:]
quality = None
image_out.info = image.info
save_kwargs = {
'append_images': frames[1:],
'loop': image.info.get('loop', 0),
'save_all': True,
}
else: else:
target_ext = 'png' target_ext = 'png'
quality = None quality = None
@@ -184,11 +195,11 @@ def create_thumbnail(sourcename, size):
checksum = hashlib.md5(image.tobytes()).hexdigest() checksum = hashlib.md5(image.tobytes()).hexdigest()
name = checksum + '.' + size.replace('^', 'c') + '.' + target_ext name = checksum + '.' + size.replace('^', 'c') + '.' + target_ext
buffer = BytesIO() buffer = BytesIO()
if image.mode == "P" and source.name.lower().endswith('.png'): if image_out.mode == "P" and source.name.lower().endswith('.png'):
image = image.convert('RGBA') image_out = image_out.convert('RGBA')
if image.mode not in ("1", "L", "RGB", "RGBA"): if image_out.mode not in ("1", "L", "RGB", "RGBA"):
image = image.convert('RGB') image_out = image_out.convert('RGB')
image.save(fp=buffer, format=target_ext.upper(), quality=quality) image_out.save(fp=buffer, format=target_ext.upper(), quality=quality, **save_kwargs)
imgfile = ContentFile(buffer.getvalue()) imgfile = ContentFile(buffer.getvalue())
t = Thumbnail.objects.create(source=sourcename, size=size) t = Thumbnail.objects.create(source=sourcename, size=size)