PIL 的 tobytes() 方法后图像损坏

Image is corrupted after PIL's tobytes() method

我想将图片上传到 Google 存储桶,但是我想在上传之前减小图片的大小。当我不调用 self._resize_image 方法时,图像成功上传,没有任何问题。但是,当我调用 resize 方法时,它会一直工作到 image.tobytes() 方法。调用 image.tobytes() 方法后,无法再读取图像。

def _resize_image(self, image: bytes, base_with: int = 300) -> bytes:
    stream = BytesIO(image)
    image = Image.open(stream).convert("RGBA")
    width_percentage = base_with / float(image.size[0])
    height_size = int(float(image.size[1]) * float(width_percentage))
    image = image.resize((base_with, height_size), Image.ANTIALIAS)
    # if I do image.show() here the picture is still displayed correctly.
    return image.tobytes()  # after this line the picture is getting uploaded, but can't be read by Google anymore.

def upload_image_to_bucket(self, image: bytes, bucket_folder: str, compress: bool = True) -> str:
    if compress:
        # if I don't call this method the picture get's uploaded correctly.
        image = self._resize_image(image=image)
    file_name = f"{UUIDService().create_uuid(length=40)}.jpeg"
    bucket = self._client.storage.bucket()
    blob = bucket.blob(f"{bucket_folder}/{file_name}")
    blob.upload_from_string(data=image, content_type="image/jpeg")
    return file_name

可能是Image.ANTIALIAS函数;尝试将该字段留空。

来自Pillow's documentation on tobytes

This method returns the raw image data from the internal storage. For compressed image data (e.g. PNG, JPEG) use save(), with a BytesIO parameter for in-memory data.

所以 tobytes() 方法 returns Pillow 的图像内部表示,大概要用 frombytes() 恢复。如果要将图像保存为 JPEG,请按照文档的建议使用 the save() method

output = BytesIO()
image.save(output, format="jpeg")
... # do something with `output`

这是因为 tobytes() 函数给出了未压缩的原始字节。您可以使用 PIL 的保存功能将其保存到缓冲区中,然后再上传。

output = io.BytesIO()
img.save(output, format='JPEG')