Improve image compression heuristics and algorithm used (#4158)

This commit is contained in:
Nick80835 2023-07-23 15:58:10 -04:00 committed by GitHub
parent ce010e9bfb
commit 694c78c8e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -47,7 +47,17 @@ def _resize_photo_if_needed(
if isinstance(file, bytes): if isinstance(file, bytes):
file = io.BytesIO(file) file = io.BytesIO(file)
before = file.tell() if isinstance(file, io.IOBase) else None if isinstance(file, io.IOBase):
# Pillow seeks to 0 unconditionally later anyway
old_pos = file.tell()
file.seek(0, io.SEEK_END)
before = file.tell()
elif isinstance(file, str) and os.path.exists(file):
# Check if file exists as a path and if so, get its size on disk
before = os.path.getsize(file)
else:
# Would be weird...
before = None
try: try:
# Don't use a `with` block for `image`, or `file` would be closed. # Don't use a `with` block for `image`, or `file` would be closed.
@ -58,10 +68,11 @@ def _resize_photo_if_needed(
except KeyError: except KeyError:
kwargs = {} kwargs = {}
if image.width <= width and image.height <= height: # Check if image is within acceptable bounds, if so, check if the image is at or below 10 MB, or assume it isn't if size is None or 0
if image.width <= width and image.height <= height and (before <= 10000000 if before else False):
return file return file
image.thumbnail((width, height), PIL.Image.ANTIALIAS) image.thumbnail((width, height), PIL.Image.LANCZOS)
alpha_index = image.mode.find('A') alpha_index = image.mode.find('A')
if alpha_index == -1: if alpha_index == -1:
@ -80,12 +91,12 @@ def _resize_photo_if_needed(
result.save(buffer, 'JPEG', progressive=True, **kwargs) result.save(buffer, 'JPEG', progressive=True, **kwargs)
buffer.seek(0) buffer.seek(0)
return buffer return buffer
except IOError: except IOError:
return file return file
finally: finally:
if before is not None: # The original position might matter
file.seek(before, io.SEEK_SET) if isinstance(file, io.IOBase):
file.seek(old_pos)
class UploadMethods: class UploadMethods: