如何在 PIL 中缩放动画 GIF 图像并保留动画

发布于 2025-01-01 23:02:26 字数 1629 浏览 1 评论 0原文

我想知道是否可以使用 PIL 缩放动画 GIF 图像。特别是 Plone 的原型 ImageField 目前丢失了使用其缩放方法缩放的图像的动画:

def scale(self, data, w, h, default_format = 'PNG'):
    """ scale image (with material from ImageTag_Hotfix)"""
    #make sure we have valid int's
    size = int(w), int(h)

    original_file=StringIO(data)
    image = PIL.Image.open(original_file)
    # consider image mode when scaling
    # source images can be mode '1','L,','P','RGB(A)'
    # convert to greyscale or RGBA before scaling
    # preserve palletted mode (but not pallette)
    # for palletted-only image formats, e.g. GIF
    # PNG compression is OK for RGBA thumbnails
    original_mode = image.mode
    img_format = image.format and image.format or default_format
    if original_mode == '1':
        image = image.convert('L')
    elif original_mode == 'P':
        image = image.convert('RGBA')
    image.thumbnail(size, self.pil_resize_algo)
    # decided to only preserve palletted mode
    # for GIF, could also use image.format in ('GIF','PNG')
    if original_mode == 'P' and img_format == 'GIF':
        image = image.convert('P')
    thumbnail_file = StringIO()
    # quality parameter doesn't affect lossless formats
    image.save(thumbnail_file, img_format, quality=self.pil_quality)
    thumbnail_file.seek(0)
    return thumbnail_file, img_format.lower()

我知道如何识别动画 GIF:以下计算结果为 True image.format == 'GIF' 和 image.seek(image.tell ()+1)。我尝试过不转换为 RGBA 模式,但这不起作用。

背景:在我们的 Plone 实例上,我们修改了默认图像类型以设置其图像字段的original_size 属性,以强制所有图像使用适当的质量设置进行缩放。这对于 jpeg 非常有效,但意味着我们目前无法上传动画 GIF

I'm wondering if it's possible to scale an animated GIF image using PIL. In particular Plone’s archetypes ImageField currently loses the animation from images scaled using its scale method:

def scale(self, data, w, h, default_format = 'PNG'):
    """ scale image (with material from ImageTag_Hotfix)"""
    #make sure we have valid int's
    size = int(w), int(h)

    original_file=StringIO(data)
    image = PIL.Image.open(original_file)
    # consider image mode when scaling
    # source images can be mode '1','L,','P','RGB(A)'
    # convert to greyscale or RGBA before scaling
    # preserve palletted mode (but not pallette)
    # for palletted-only image formats, e.g. GIF
    # PNG compression is OK for RGBA thumbnails
    original_mode = image.mode
    img_format = image.format and image.format or default_format
    if original_mode == '1':
        image = image.convert('L')
    elif original_mode == 'P':
        image = image.convert('RGBA')
    image.thumbnail(size, self.pil_resize_algo)
    # decided to only preserve palletted mode
    # for GIF, could also use image.format in ('GIF','PNG')
    if original_mode == 'P' and img_format == 'GIF':
        image = image.convert('P')
    thumbnail_file = StringIO()
    # quality parameter doesn't affect lossless formats
    image.save(thumbnail_file, img_format, quality=self.pil_quality)
    thumbnail_file.seek(0)
    return thumbnail_file, img_format.lower()

I know how to identify a animated GIF: The following evaluates to True image.format == 'GIF' and image.seek(image.tell()+1). I’ve tried not converting to RGBA mode but that doesn't work.

Background: On our Plone instance we've modified the default image type to set the original_size attribute of its image field to force all images to scaled with an appropriate quality setting. This works great for jpegs but means we currently can't upload animated GIFs

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦行七里 2025-01-08 23:02:26

您可以使用 images2gif.py 读取 gif 并独立缩放每个帧。 images2gif 将允许您用一系列图像编写动画 gif。

我在互联网上找到的 images2gif.py 不处理透明度,所以我修复了这个问题。您可以在这里找到:
https://bitbucket.org/bench/images2gif.py

You can use images2gif.py to read gifs and than scale each frame independently. images2gif will allow you to write an animated gif with a sequence of Images.

The images2gif.py I found on the internet didn't handle transparency, so i fixed that. You can find that here:
https://bitbucket.org/bench/images2gif.py

影子的影子 2025-01-08 23:02:26

PIL 对动画 GIF 的支持有限,但正如前面所说,它是有限的,您必须在非常低的级别上工作才能处理它。

虽然可以在当前版本 (9.2) 的 PIL (Pillow) 中操作和缩放 GIF,但它相当晦涩,并且仅提供每个帧的“渲染”版本:也就是说,如果您有带有自定义调色板的 GIF 或每帧的形状,您只能访问图像查看程序中呈现的展平帧。

如果您想处理动画 gif,我建议您尝试 PIL 之外的其他缩放图像的方法。可能,最直接的方法是使用进程外 ImageMagick 和 subprocess.Popen - (即使如此,此时,我只是猜测 ImageMagick 对动画 GIF 做了“正确的事情”) -

一个选项是一个“图像处理服务器”,带有另一个 Python 脚本,除了您的 zope 安装将接收缩放图像的请求 - 可能通过 xmlrpc 调用 - 您可以将其构建为 GIMP 插件并使用用于缩放 GIF 的 GIMP。

另一种选择是保持原样,并在动画 GIF 需要出现在原始图像之外的另一个维度时使用“静止图像”,并在适合动画的地方显示原始图像。 (或者可能只是要求提交已正确尺寸的动画 gif)

PIL has got some limited support for animated GIF's but it is, as said, limited, and you have to work in very low level to deal with it.

While it is possible to manipulate and scale GIFs in PIL (Pillow) at the current version (9.2), its rather obscure, and only offer the "rendered" version of each frame: that is, if you have a GIF with custom palettes or shapes per frame, you can only get access to the flattened frames as they are presented in an image viewing program.

I'd advise trying some other method for scaling images than PIL if you want to deal with animated gif's. Possibly, the most straightforward way is to use an off-process ImageMagick, with subprocess.Popen - (and even then, at this time, I am only guessing ImageMagick "does the right thing" with animated GIF's) -

An option is to have an "image processing server", with another Python script, apart from your zope install that will receive requests to scale the images - possibly with a xmlrpc call - you could build this as a GIMP plug-in and use GIMP for scaling the GIF's.

Another option is to leave things as they are, and use "stills" for animated GIF's where they need to appear in another dimension than the original, and display the original image where the animation is appropriate. (Or maybe simply require that animated gif's be submitted already on the proper size)

小耗子 2025-01-08 23:02:26

Pillow(PIL 的分支)自版本 3.0.0PR #1384 已合并。

Pillow (PIL's fork) supports animated GIF since version 3.0.0 when PR #1384 was merged.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文