PIL无法将动画文件保存为动画.webp文件。

huangapple go评论73阅读模式
英文:

PIL not saving animated files as animated .webp

问题

这是一个函数的一部分,它可以正常工作,并且会在控制台打印出'saving as animated image'。然而,保存的图像是静态的,不是动画的(尽管它是.webp格式的)。

try:
    with Image.open(avatar) as img:
        img = ImageOps.exif_transpose(img)

        if is_animated_image(img) and not permissions.Flags.enhanced_profile in user_permissions:
            response.add_errors('avatar', ["您需要增强的个人资料高级功能才能上传动画头像。"])
            response.status = status.HTTP_400_BAD_REQUEST

            return response

        width, height = img.size

        if width != height:
            print('resize_avatar')
            return resize_avatar(img, is_animated_image(img), attachment_name)

        if is_animated_image(img):
            print('saving as animated image')

            frames = []

            for frame in ImageSequence.Iterator(img):
                frames.append(frame)

            frames[0].save(
                f'{config.media_source}avatars/{attachment_name}',
                format='webp',
                save_all=True,
                append_images=frames[:1],
                loop=0,
            )
        else:
            img.save(f'{config.media_source}avatars/{attachment_name}', format='webp', save_all=True)

        response.status = status.HTTP_200_OK
        response.data = {'attachment_name' : attachment_name}

        return response

except Exception as e:
    functions.log_error("UPLOAD_AVATAR_ERROR", str(e))

    response.add_errors('avatar', ["出现了一些问题,开发人员已经收到通知。"])
    response.status = status.HTTP_400_BAD_REQUEST

    return response
英文:

This is a part of a function, it all works and 'saving as animated image' gets printed out to console. However, the saved image is a still one. It is not animated (it is .webp though).

try:
    with Image.open(avatar) as img:
        img = ImageOps.exif_transpose(img)

        if is_animated_image(img) and not permissions.Flags.enhanced_profile in user_permissions:
            response.add_errors('avatar', ["You need the enhanced profile premium feature to upload animated avatars."])
            response.status = status.HTTP_400_BAD_REQUEST

            return response

        width, height = img.size

        if width != height:
            print('resize_avatar')
            return resize_avatar(img, is_animated_image(img), attachment_name)

        if is_animated_image(img):
            print('saving as animated image')

            frames = []

            for frame in ImageSequence.Iterator(img):
                frames.append(frame)

            frames[0].save(
                f'{config.media_source}avatars/{attachment_name}',
                format='webp',
                save_all=True,
                append_images=frames[:1],
                loop=0,
            )
        else:
            img.save(f'{config.media_source}avatars/{attachment_name}', format='webp', save_all=True)

        response.status = status.HTTP_200_OK
        response.data = {'attachment_name' : attachment_name}

        return response

except Exception as e:
    functions.log_error("UPLOAD_AVATAR_ERROR", str(e))

    response.add_errors('avatar', ["Something went wrong, the developers have been notified."])
    response.status = status.HTTP_400_BAD_REQUEST

    return response

答案1

得分: 1

所以这段代码实际上有两个问题。

  1. 从某种意义上说,代码是正确的。我在抱怨我无法保存1帧的问题。但我有权抱怨,因为事实上我上传了一个gif文件,并且如第2点所解释的那样,我确信我正在处理一个动画文件。问题出在哪里?就在开头。img = ImageOps.exif_transpose(img)不支持多于1帧的图像。它可以工作,但只会对第一帧应用更改,而忽略其他帧。所以实际上,我试图存储1帧,以为我仍然拥有原始的gif文件。
  2. is_animated_image实际上计算的是1帧或多帧,而不是多于1帧。所以如果我没有如此确信这个函数只在有多于1帧时返回True,我可能早就发现了问题。

感谢@Mark Setchel让我更深入地研究我的代码。

英文:

So this code actually contained 2 issues.

  1. The code in a way was fine. I was yelling about how I couldn't save 1 frame. But I had all rights to yell because I did in fact upload a gif and as explained in point 2, I was convinced I was working with an animated file. Where did it go wrong? Right at the beginning. img = ImageOps.exif_transpose(img) does not support images with more than 1 frame. It works, but would only apply changes to the first frame and forget about the other frames. So in fact I was trying to store 1 frame thinking I still had my original gif.
  2. The is_animated_image actually counted for 1 or more and not more than 1 frames. So I could have figured out earlier there was an issue if I wasn't so convinced this function only returned True when we had more than 1 frame.

Thanks @Mark Setchel for making me deep dive more in my code.

huangapple
  • 本文由 发表于 2023年8月8日 23:46:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76861198.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定