Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Support for animated GIF images #217

wants to merge 6 commits into


None yet
5 participants

anvio commented Apr 4, 2013

Hi Chris,

After a long long night I finally managed to add support for animated GIF images to easy-thumbnails.

It uses images2gif.py to extract all frames as PIL images. These frame images get processed by the thumbnail processors like every other still image. After they have been processed they get merged into one animated GIF (see Thumbnailer.generate_thumbnail).

Some animated GIFs react very badly to "resample=Image.ANTIALIAS" when resized. Therefore, I had to add a new "resample" kwarg to the default scale_and_crop processor (see easy_thumbnails/processors.py:158). This kwarg can be used to override the default behavior of Image.ANTIALIAS to Image.NEAREST. The NEAREST resample mode gets set explicitly when a GIF is getting processed (see easy_thumbnails/files.py:301). The downside is that resized GIFs do not have the best quality but the compatibility is improved. Maybe this is something that the user can specify in the Django settings (quality or compatibility)?

I thought this feature would be nice to have in the official version of easy-thumbnails. So feel free to add it! If you have any questions, do not hesitate to contact me!


anvio commented Apr 4, 2013

Oh, btw ... you have to set
in the settings file to make sure the image keeps the .gif extension.

anvio commented Apr 4, 2013

Please consider this pull request as work in progress. I just noticed some problems:

  • Some animations run at a faster speed than the original
  • Some animations get displayed in the wrong color space
  • There might be a memory leak. Just had a situation where my Gunicorn instances got unreachable.

Pascal Beyeler added some commits Apr 4, 2013

anvio commented Apr 5, 2013

I was able to solve a few problems:

  • Animations do not run at a faster speed than the original anymore
  • There are no more color space problems
  • The "resample" kwarg in the default scale_and_crop processor is no longer needed and was removed

Further improvements:

  • images2gif.py is no longer required to read the GIF images -> switched to default PIL functions

Still existing issues:

  • Resizing the animations needs a lot of memory but I guess this is a general problem that comes with GIF processing. If someone has some ideas to reduce the memory footprint, feel free to contribute a patch

Natim commented Apr 12, 2013

Nice feature to have :)


SmileyChris commented Apr 12, 2013

This is great work, @pascal.beyeler

I wonder if this could be implemented as a source generator. I think it'd need some abstraction of the engine code too, but that would be a good thing.

The abstraction i was thinking of: making source processors smarter so they are used for saving the thumbs too (cycle through the classes, stopping at the first one that returns True from it's save method if it has one).


siovene commented Sep 30, 2013

Hi, is there any chance of seeing this merged any time soon? I can't do without this feature.


SmileyChris commented Sep 30, 2013

In it's current state, no. But with an abstraction of the engine code to allow source generators to save thumbs, and the base of this code added as a source generator, sure.

anvio commented Oct 28, 2013

Hi Chris, please could you add the abstraction you are looking for? Afterwards, I will add the animated GIF support to the new structure.

Hi all, how usable is this PR as-is today? I have a project that requires this functionality. Is there anything I can do to help it along? Documentation updates, perhaps?

anvio commented Jan 14, 2014

Hi Martin, you could do some testing. This PR hasn't been used in production. I wouldn't start documenting this feature yet as it is not final. @SmileyChris seems to be a bit busy at the moment. So we may have to wait a bit longer until this PR finds its way into the master branch.


SmileyChris commented Jan 14, 2014

Yeah, sorry that I've been a bit negligent of the project recently. Trying to catch up at the moment.

I really would like this to be abstracted rather than an integral part of the code. Maybe that will have to wait until my rewrite though - this has been an interesting bit to consider during my architecture of it. Currently my thinking is that images will have a wrapper that abstract both image processing and the save method. So there can be a separate source reader that finds an animated gif and returns an AnimatedGifWrapper that encapsulates any unique processing / saving logic.


SmileyChris commented Jan 30, 2014

Ok, I put some more thought into this... so here's what needs to be done for this to be mergable.

There should be a separate source processor that checks if the image is an animated gif (otherwise it can just return and let the standard source processor do the work).

Instead of returning a PIL Image, it returns a wrapper class that contains all of the logic to split out the image to separate frames. Use a __getattr__ that passes PIL methods through to each frame and returns a new wrapper class with the altered frames (or if the method doesn't return an Image class, just return the first result [e.g. .size]). Override the save method to do the right thing.

Then you don't need to change much inside of easy-thumbnails core.

The trickiest part of this is that easy-thumbnails relies on the extension to find the image in cache rather than regenerating it (either thumbnail_extension or thumbnail_transparency_extention). My thoughts are at the moment that we should just save it using the thumbnail_transparency_extension (PNG by default) even though it's a gif. The browser should figure it out no matter what the extension anyway.


SmileyChris commented Feb 24, 2014

There's a lot to change here. Reopen or create a new pull request when you're ready to resubmit.

@anvio is this something you're still working on?

anvio commented Apr 17, 2014

@mkoistinen Sorry, I am no longer working on this. We will soon move to a non-Python thumbnailing solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment