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

7

我想知道是否可以使用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' and image.seek(image.tell()+1)。我尝试过不将其转换为RGBA模式,但这并不起作用。
背景:在我们的Plone实例中,我们修改了默认图像类型以设置其图像字段的original_size属性,以强制所有图像使用适当的质量设置进行缩放。这对于JPEG图像非常有效,但意味着我们目前无法上传动画GIF。

缩放调色板图像可能会导致不可接受的图像质量。 - Mark Ransom
3个回答

8
您可以使用images2gif.py读取gif,然后独立缩放每个帧。 images2gif将允许您使用一系列图像编写动画gif。
我在互联网上找到的images2gif.py没有处理透明度,所以我进行了修复。您可以在此处找到修复后的版本: https://bitbucket.org/bench/images2gif.py

5
PIL(Pillow)对动态GIF图像有一些有限的支持,但是它的功能非常有限,而且您必须在非常低的级别上工作才能处理它。
虽然在当前版本(9.2)的PIL(Pillow)中有可能操作和缩放GIF,但它相当隐晦,并且只提供每帧的“渲染”版本:也就是说,如果您有一个GIF,每帧都有自定义调色板或形状,您只能访问以图像查看程序呈现的压平帧。
如果您想处理动画gif,则建议尝试使用其他方法来缩放图像,而不是使用PIL。可能最简单的方法是使用一个独立的进程ImageMagick,并与subprocess.Popen配合使用(即使到目前为止,我仅猜测ImageMagick可以正确处理动画GIF)。
另一种选择是使用“图像处理服务器”,并使用另一个Python脚本,除了zope安装外,该服务器将接收用于缩放图像的请求-可能是通过xmlrpc调用实现的-您可以构建此功能作为GIMP插件,并使用GIMP缩放GIF。
另一种选择是保持原样,并在需要出现在其他维度中的动画GIF中使用“静止”图像,并在适当的情况下显示原始图像。(或者可能只需要求以正确的大小提交动画gif)

2
谢谢。我已经调整了代码,使其在源图像不大于比例时不尝试缩放动画GIF图像。请参见http://dev.plone.org/ticket/12488。 - scarba05
1
我进一步查看了PIL - 它确实支持读取多帧gif,但完全不支持创建或写入它们。 - jsbueno

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接