From c803d7abbb168862fb6fc0f1df0176827f2cd4ce Mon Sep 17 00:00:00 2001 From: SDE Date: Sat, 2 Dec 2023 16:26:53 +0300 Subject: [PATCH] 0.8.23 fix png black bg --- BaseModels/PIL/pillow_backend.py | 70 ++++++++++++++++++++++++++++++++ TWB/settings.py | 3 +- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 BaseModels/PIL/pillow_backend.py diff --git a/BaseModels/PIL/pillow_backend.py b/BaseModels/PIL/pillow_backend.py new file mode 100644 index 0000000..5baed96 --- /dev/null +++ b/BaseModels/PIL/pillow_backend.py @@ -0,0 +1,70 @@ +import os +from io import BytesIO + +from django.conf import settings +from django.utils.functional import cached_property +from PIL import Image + +from ckeditor_uploader import utils + + +THUMBNAIL_SIZE = getattr(settings, "CKEDITOR_THUMBNAIL_SIZE", (75, 75)) + + +class PillowBackend: + def __init__(self, storage_engine, file_object): + self.file_object = file_object + self.storage_engine = storage_engine + + @cached_property + def is_image(self): + try: + Image.open( + BytesIO(self.file_object.read()) + ).verify() # verify closes the file + return True + except OSError: + return False + finally: + self.file_object.seek(0) + + def _compress_image(self, image): + quality = getattr(settings, "CKEDITOR_IMAGE_QUALITY", 75) + image = image.resize(image.size, Image.ANTIALIAS).convert("RGB") + image_tmp = BytesIO() + image.save(image_tmp, format="JPEG", quality=quality, optimize=True) + return image_tmp + + def save_as(self, filepath): + if not self.is_image: + saved_path = self.storage_engine.save(filepath, self.file_object) + return saved_path + + image = Image.open(self.file_object) + + should_compress = getattr(settings, "CKEDITOR_FORCE_JPEG_COMPRESSION", False) + is_animated = hasattr(image, "is_animated") and image.is_animated + if should_compress and not is_animated: + file_object = self._compress_image(image) + filepath = f"{os.path.splitext(filepath)[0]}.jpg" + saved_path = self.storage_engine.save(filepath, file_object) + else: + file_object = self.file_object + saved_path = self.storage_engine.save(filepath, self.file_object) + + if not is_animated: + self.create_thumbnail(file_object, saved_path) + return saved_path + + def create_thumbnail(self, file_object, file_path): + thumbnail_filename = utils.get_thumb_filename(file_path) + thumbnail_io = BytesIO() + # File object after saving e.g. to S3 can be closed. + try: + image = Image.open(file_object).convert("RGBA") + except ValueError: + file_object = self.storage_engine.open(file_path) + image = Image.open(file_object).convert("RGBA") + image.thumbnail(THUMBNAIL_SIZE, Image.ANTIALIAS) + image.save(thumbnail_io, format="PNG", optimize=True) + return self.storage_engine.save(thumbnail_filename, thumbnail_io) diff --git a/TWB/settings.py b/TWB/settings.py index 96b5650..a3f8576 100644 --- a/TWB/settings.py +++ b/TWB/settings.py @@ -217,7 +217,8 @@ CKEDITOR_RESTRICT_BY_USER = True CKEDITOR_BROWSE_SHOW_DIRS = True # CKEDITOR_IMAGE_BACKEND = 'ckeditor_uploader.backends.PillowBackend' -CKEDITOR_IMAGE_BACKEND = 'pillow' +# CKEDITOR_IMAGE_BACKEND = 'pillow' +CKEDITOR_IMAGE_BACKEND = "BaseModels.PIL.pillow_backend.PillowBackend" # CKEDITOR_BROWSE_SHOW_DIRS = True