Only load Image once when creating all three Thumbnail sizes.

This commit is contained in:
Will Stott
2019-07-18 14:42:40 +01:00
parent cb24cebd94
commit 510966633a
10 changed files with 122 additions and 140 deletions

View File

@@ -1,12 +1,10 @@
import hashlib
import os.path
from io import BytesIO
from django.db import models
from django.core.files.uploadedfile import InMemoryUploadedFile
from django.core.urlresolvers import reverse
from django.dispatch import receiver
import PIL
try:
from importlib import import_module
@@ -67,37 +65,37 @@ class Image(models.Model):
class ThumbnailManager(models.Manager):
def get_or_create_at_size(self, image, size):
if size not in IMAGE_SIZES:
raise ValueError("Received unknown size: %s" % size)
try:
thumbnail = image.get_by_size(size)
except Thumbnail.DoesNotExist:
img = utils.scale_and_crop(image.image, **IMAGE_SIZES[size])
# save to memory
buf = BytesIO()
def get_or_create_at_sizes(self, image, sizes):
sizes_to_create = list(sizes)
sized = {}
for size in sizes:
if size not in IMAGE_SIZES:
raise ValueError("Received unknown size: %s" % size)
try:
img.save(buf, img.format, **img.info)
except IOError:
if img.info.get('progression'):
orig_MAXBLOCK = PIL.ImageFile.MAXBLOCK
temp_MAXBLOCK = 1048576
if orig_MAXBLOCK >= temp_MAXBLOCK:
raise
PIL.ImageFile.MAXBLOCK = temp_MAXBLOCK
try:
img.save(buf, img.format, **img.info)
finally:
PIL.ImageFile.MAXBLOCK = orig_MAXBLOCK
else:
raise
# and save to storage
original_dir, original_file = os.path.split(image.image.name)
thumb_file = InMemoryUploadedFile(buf, "image", original_file,
None, buf.tell(), None)
thumbnail, created = image.thumbnail_set.get_or_create(
size=size, defaults={'image': thumb_file})
return thumbnail
sized[size] = image.get_by_size(size)
except Thumbnail.DoesNotExist:
pass
else:
sizes_to_create.remove(size)
if sizes_to_create:
bufs = [
utils.write_image_in_memory(img)
for img in utils.scale_and_crop_iter(
image.image,
[IMAGE_SIZES[size] for size in sizes_to_create])
]
for size, buf in zip(sizes_to_create, bufs):
# and save to storage
original_dir, original_file = os.path.split(image.image.name)
thumb_file = InMemoryUploadedFile(buf, "image", original_file,
None, buf.tell(), None)
sized[size], created = image.thumbnail_set.get_or_create(
size=size, defaults={'image': thumb_file})
# Make sure this is in the correct order
return [sized[size] for size in sizes]
class Thumbnail(models.Model):