From b9aafa3441719be5116a684cb0eb02a6a21d6bdf Mon Sep 17 00:00:00 2001 From: Nick80835 <24271245+Nick80835@users.noreply.github.com> Date: Sun, 12 Jan 2025 18:11:46 -0500 Subject: [PATCH] Fix IOError with some image modes in photo resize This fixes image compression with mode "P" (potentially others) which is necessary as the server has erroneous alpha color with some types of images (mode "P" for example). This also properly applies the background argument that may be passed to _resize_photo_if_needed by always compressing images with alpha regardless of whether the server will compress the image for us. --- telethon/client/uploads.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/telethon/client/uploads.py b/telethon/client/uploads.py index c8b8d951..091e8d15 100644 --- a/telethon/client/uploads.py +++ b/telethon/client/uploads.py @@ -67,24 +67,31 @@ def _resize_photo_if_needed( except KeyError: kwargs = {} - # 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 + if image.mode == 'RGB': + # 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 - image.thumbnail((width, height), PIL.Image.LANCZOS) - - alpha_index = image.mode.find('A') - if alpha_index == -1: - # If the image mode doesn't have alpha - # channel then don't bother masking it away. + # If the image is already RGB, don't convert it + # certain modes such as 'P' have no alpha index but can't be saved as JPEG directly + image.thumbnail((width, height), PIL.Image.LANCZOS) result = image else: # We could save the resized image with the original format, but # JPEG often compresses better -> smaller size -> faster upload # We need to mask away the alpha channel ([3]), since otherwise # IOError is raised when trying to save alpha channels in JPEG. + image.thumbnail((width, height), PIL.Image.LANCZOS) result = PIL.Image.new('RGB', image.size, background) - result.paste(image, mask=image.split()[alpha_index]) + mask = None + + if image.has_transparency_data: + if image.mode == 'RGBA': + mask = image.getchannel('A') + else: + mask = image.convert('RGBA').getchannel('A') + + result.paste(image, mask=mask) buffer = io.BytesIO() result.save(buffer, 'JPEG', progressive=True, **kwargs)