fix: is_uniform_animated_webp

This commit is contained in:
xz-dev 2024-09-15 22:49:17 +08:00
parent 86cb2edcfa
commit ca296b41c6
No known key found for this signature in database
GPG Key ID: A20912F811313E36
1 changed files with 52 additions and 51 deletions

View File

@ -148,29 +148,30 @@ 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:
img = Image.open(BytesIO(data)) with Image.open(BytesIO(data)) as img:
if img.n_frames <= 1: if img.n_frames <= 1:
return False return True
first_frame = np.array(img) img_iter = ImageSequence.Iterator(img)
for frame_number in range(1, img.n_frames): first_frame = np.array(img_iter[0].convert("RGBA"))
img.seek(frame_number)
current_frame = np.array(img) for frame in img_iter:
if not np.array_equal(first_frame, current_frame): current_frame = np.array(frame.convert("RGBA"))
return False if not np.array_equal(first_frame, current_frame):
return False
return True return True
def webp_to_gif_or_png(data: bytes) -> bytes: def webp_to_gif_or_png(data: bytes) -> bytes:
# check if the webp is animated with Image.open(BytesIO(data)) as image:
image: Image.Image = Image.open(BytesIO(data)) # check if the webp is animated
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:
@ -187,40 +188,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):
image: Image.Image = Image.open(BytesIO(data)) with Image.open(BytesIO(data)) as image:
new_file = BytesIO() with BytesIO() as new_file:
# 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):