Compare commits

..

1 Commits

Author SHA1 Message Date
xz-dev 0550c0ad3e
Merge 86cb2edcfa into 333567f481 2024-09-15 16:29:03 +08:00
1 changed files with 51 additions and 52 deletions

View File

@ -148,30 +148,29 @@ def webp_to_others(data: bytes, mimetype: str) -> bytes:
def is_uniform_animated_webp(data: bytes) -> bool: def is_uniform_animated_webp(data: bytes) -> bool:
with Image.open(BytesIO(data)) as img: img = Image.open(BytesIO(data))
if img.n_frames <= 1: if img.n_frames <= 1:
return True return False
img_iter = ImageSequence.Iterator(img) first_frame = np.array(img)
first_frame = np.array(img_iter[0].convert("RGBA")) for frame_number in range(1, img.n_frames):
img.seek(frame_number)
for frame in img_iter: current_frame = np.array(img)
current_frame = np.array(frame.convert("RGBA")) if not np.array_equal(first_frame, current_frame):
if not np.array_equal(first_frame, current_frame): return False
return False
return True return True
def webp_to_gif_or_png(data: bytes) -> bytes: def webp_to_gif_or_png(data: bytes) -> bytes:
with Image.open(BytesIO(data)) as image: # check if the webp is animated
# check if the webp is animated image: Image.Image = Image.open(BytesIO(data))
is_animated = getattr(image, "is_animated", False) is_animated = getattr(image, "is_animated", False)
if is_animated and not is_uniform_animated_webp(data): if is_animated and not is_uniform_animated_webp(data):
return webp_to_others(data, "image/gif") return webp_to_others(data, "image/gif")
else: else:
# convert to png # convert to png
return webp_to_others(data, "image/png") return webp_to_others(data, "image/png")
def opermize_gif(data: bytes) -> bytes: def opermize_gif(data: bytes) -> bytes:
@ -188,40 +187,40 @@ def opermize_gif(data: bytes) -> bytes:
def _convert_image(data: bytes, mimetype: str) -> (bytes, int, int): def _convert_image(data: bytes, mimetype: str) -> (bytes, int, int):
with Image.open(BytesIO(data)) as image: image: Image.Image = Image.open(BytesIO(data))
with BytesIO() as new_file: new_file = BytesIO()
# Determine if the image is a GIF # Determine if the image is a GIF
is_animated = getattr(image, "is_animated", False) is_animated = getattr(image, "is_animated", False)
if is_animated: if is_animated:
frames = [frame.convert("RGBA") for frame in ImageSequence.Iterator(image)] frames = [frame.convert("RGBA") for frame in ImageSequence.Iterator(image)]
# Save the new GIF # Save the new GIF
frames[0].save( frames[0].save(
new_file, new_file,
format='GIF', format='GIF',
save_all=True, save_all=True,
append_images=frames[1:], append_images=frames[1:],
loop=image.info.get('loop', 0), # Default loop to 0 if not present loop=image.info.get('loop', 0), # Default loop to 0 if not present
duration=image.info.get('duration', 100), # Set a default duration if not present duration=image.info.get('duration', 100), # Set a default duration if not present
disposal=image.info.get('disposal', 2) # Default to disposal method 2 (restore to background) disposal=image.info.get('disposal', 2) # Default to disposal method 2 (restore to background)
) )
# Get the size of the first frame to determine resizing # Get the size of the first frame to determine resizing
w, h = frames[0].size w, h = frames[0].size
else: else:
suffix = mimetypes.guess_extension(mimetype) suffix = mimetypes.guess_extension(mimetype)
if suffix: if suffix:
suffix = suffix[1:] suffix = suffix[1:]
image = image.convert("RGBA") image = image.convert("RGBA")
image.save(new_file, format=suffix) image.save(new_file, format=suffix)
w, h = image.size w, h = image.size
if w > 256 or h > 256: if w > 256 or h > 256:
# Set the width and height to lower values so clients wouldn't show them as huge images # Set the width and height to lower values so clients wouldn't show them as huge images
if w > h: if w > h:
h = int(h / (w / 256)) h = int(h / (w / 256))
w = 256 w = 256
else: else:
w = int(w / (h / 256)) w = int(w / (h / 256))
h = 256 h = 256
return new_file.getvalue(), w, h return new_file.getvalue(), w, h
def _convert_sticker(data: bytes) -> (bytes, str, int, int): def _convert_sticker(data: bytes) -> (bytes, str, int, int):