Some refactoring, and added a script to regenerate variants
This commit is contained in:
55
images/management/commands/regenerate_variants.py
Normal file
55
images/management/commands/regenerate_variants.py
Normal file
@@ -0,0 +1,55 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from images.models import ImageVariant
|
||||
from images.utils import get_b2_resource
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument("variants", nargs="+", type=str)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
if options["variants"] and len(options["variants"]) > 0:
|
||||
variants = options["variants"]
|
||||
else:
|
||||
variants = ImageVariant.objects.all()
|
||||
|
||||
bucket = get_b2_resource()
|
||||
|
||||
for variant_id in variants:
|
||||
print("Regenerating variant %s" % variant_id)
|
||||
|
||||
image_variant = ImageVariant.objects.filter(id=variant_id).first()
|
||||
|
||||
if image_variant.is_full_size and (
|
||||
image_variant.file_type == "jpg" or image_variant.file_type == "png"
|
||||
):
|
||||
print("Can't regenerate original image")
|
||||
continue
|
||||
|
||||
if image_variant.file_type == "webp" or image_variant.file_type == "avif":
|
||||
image_variant.regenerate = True
|
||||
image_variant.save()
|
||||
continue
|
||||
|
||||
image, file_extension = image_variant.image.create_resized_image(
|
||||
image_variant.height,
|
||||
image_variant.width,
|
||||
image_variant.gaussian_blur,
|
||||
image_variant.brightness,
|
||||
)
|
||||
|
||||
if file_extension == "jpg":
|
||||
content_type = "image/jpeg"
|
||||
elif file_extension == "png":
|
||||
content_type = "image/png"
|
||||
else:
|
||||
content_type = "binary/octet-stream"
|
||||
|
||||
image_variant.file_type = file_extension
|
||||
|
||||
bucket.upload_fileobj(
|
||||
image,
|
||||
image_variant.backblaze_filepath,
|
||||
ExtraArgs={"ContentType": content_type},
|
||||
)
|
18
images/migrations/0008_imagevariant_regenerate.py
Normal file
18
images/migrations/0008_imagevariant_regenerate.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.2 on 2025-05-03 10:57
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("images", "0007_image_version_imagevariant_available_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="imagevariant",
|
||||
name="regenerate",
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
@@ -58,18 +58,7 @@ class Image(models.Model):
|
||||
available=False,
|
||||
).save()
|
||||
|
||||
ImageVariant(
|
||||
image=variant.image,
|
||||
height=variant.height,
|
||||
width=variant.width,
|
||||
is_full_size=variant.is_full_size,
|
||||
file_type="jpegli",
|
||||
gaussian_blur=variant.gaussian_blur,
|
||||
brightness=variant.brightness,
|
||||
available=False,
|
||||
).save()
|
||||
|
||||
def create_variant(self, width, height, gaussian_blur, brightness):
|
||||
def download_original_variant(self):
|
||||
bucket = get_b2_resource()
|
||||
|
||||
original_image = BytesIO()
|
||||
@@ -85,8 +74,46 @@ class Image(models.Model):
|
||||
original_image,
|
||||
)
|
||||
original_image.seek(0)
|
||||
return original_image
|
||||
|
||||
def create_resized_image(
|
||||
self,
|
||||
height,
|
||||
width,
|
||||
gaussian_blur,
|
||||
brightness,
|
||||
):
|
||||
original_image = self.download_original_variant()
|
||||
resized_image = BytesIO()
|
||||
file_extension = "jpg"
|
||||
|
||||
with PILImage.open(original_image) as im:
|
||||
ImageOps.exif_transpose(im, in_place=True)
|
||||
im = im.filter(ImageFilter.GaussianBlur(gaussian_blur))
|
||||
enhancer = ImageEnhance.Brightness(im)
|
||||
im = enhancer.enhance(brightness)
|
||||
im.thumbnail(
|
||||
(width, height), resample=PILImage.Resampling.LANCZOS, reducing_gap=3.0
|
||||
)
|
||||
|
||||
if im.has_transparency_data:
|
||||
try:
|
||||
im.save(resized_image, "PNG", quality=90)
|
||||
file_extension = "png"
|
||||
except OSError:
|
||||
im.convert("RGB").save(resized_image, "JPEG", quality=90)
|
||||
else:
|
||||
try:
|
||||
im.save(resized_image, "JPEG", quality=90)
|
||||
except OSError:
|
||||
im.convert("RGB").save(resized_image, "JPEG", quality=90)
|
||||
|
||||
resized_image.seek(0)
|
||||
|
||||
return resized_image, file_extension
|
||||
|
||||
def create_variant(self, width, height, gaussian_blur, brightness):
|
||||
bucket = get_b2_resource()
|
||||
|
||||
image_variant = ImageVariant(
|
||||
image=self,
|
||||
@@ -99,29 +126,18 @@ class Image(models.Model):
|
||||
available=True,
|
||||
)
|
||||
|
||||
content_type = "image/jpeg"
|
||||
resized_image, file_extension = self.create_resized_image(
|
||||
height, width, gaussian_blur, brightness
|
||||
)
|
||||
|
||||
with PILImage.open(original_image) as im:
|
||||
ImageOps.exif_transpose(im, in_place=True)
|
||||
im = im.filter(ImageFilter.GaussianBlur(gaussian_blur))
|
||||
enhancer = ImageEnhance.Brightness(im)
|
||||
im = enhancer.enhance(brightness)
|
||||
im.thumbnail((width, height))
|
||||
if file_extension == "jpg":
|
||||
content_type = "image/jpeg"
|
||||
elif file_extension == "png":
|
||||
content_type = "image/png"
|
||||
else:
|
||||
content_type = "binary/octet-stream"
|
||||
|
||||
if im.has_transparency_data:
|
||||
try:
|
||||
im.save(resized_image, "PNG")
|
||||
image_variant.file_extension = "png"
|
||||
content_type = "image/png"
|
||||
except OSError:
|
||||
im.convert("RGB").save(resized_image, "JPEG")
|
||||
else:
|
||||
try:
|
||||
im.save(resized_image, "JPEG")
|
||||
except OSError:
|
||||
im.convert("RGB").save(resized_image, "JPEG")
|
||||
|
||||
resized_image.seek(0)
|
||||
image_variant.file_type = file_extension
|
||||
|
||||
bucket.upload_fileobj(
|
||||
resized_image,
|
||||
@@ -146,6 +162,7 @@ class ImageVariant(models.Model):
|
||||
is_full_size = models.BooleanField(default=False)
|
||||
file_type = models.CharField(max_length=10)
|
||||
available = models.BooleanField(default=False)
|
||||
regenerate = models.BooleanField(default=False)
|
||||
|
||||
@property
|
||||
def backblaze_filepath(self):
|
||||
|
Reference in New Issue
Block a user