How do you scale an animated GIF image in PIL and preserve the animation
Asked Answered
G

3

7

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

Gerald answered 3/2, 2012 at 12:39 Comment(1)
Scaling a paletted image is likely to result in unacceptable image quality.Babbage
F
5

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)

Foothill answered 3/2, 2012 at 13:6 Comment(2)
Thanks. I've tweaked the code so that it doesn't attempt to scale animated GIF images if the source image is no bigger than the scale. See dev.plone.org/ticket/12488Gerald
I took a further look at PIL - it indeed has support to reading multi-frame gifś , but no support at all for creating or writing them.Foothill
H
8

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

Hirz answered 23/10, 2012 at 6:16 Comment(0)
F
5

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)

Foothill answered 3/2, 2012 at 13:6 Comment(2)
Thanks. I've tweaked the code so that it doesn't attempt to scale animated GIF images if the source image is no bigger than the scale. See dev.plone.org/ticket/12488Gerald
I took a further look at PIL - it indeed has support to reading multi-frame gifś , but no support at all for creating or writing them.Foothill
C
0

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

Crocoite answered 12/12, 2016 at 22:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.