-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pillow animated gifs #76
base: main
Are you sure you want to change the base?
Conversation
e1c648b
to
63ee7c0
Compare
63ee7c0
to
7ad41b7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good, but I have few questions.
Also would be great to test it on a real project: I don't have a chance to do it.
@Image.converter_to(RGBAImageBuffer, cost=200) | ||
def to_buffer_rgba(self): | ||
if self.has_animation(): | ||
pass # TODO: Raise warning |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to clarify: are you planning to fix these todos separately or in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, forgot I had these. I'll have another look in this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If Willow is forced to decide which frame to use when saving the image, I think this should raise a warning. I know it's common to just pick the first frame but I think it's better to require them to explicitly state this as they might be calling .save_as_png
without considering what to do with animated GIFs.
It also never makes sense to attempt to do face detection on an animated image. So if this happens there must be a missing check and a warning should help surface this issue.
We probably should have an operation available on all image classes to allow selecting individual frames in the image. This way, users can always explicitly choose the first frame if they want to remove animation (and this would have no effect on non-animated images).
Something like:
myimage.frame(0).save_as_png()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Choosing a frame sounds like a good idea. Should probably be a separate PR to keep this focussed.
willow/plugins/pillow.py
Outdated
} | ||
|
||
if 'transparency' in image.info: | ||
params['transparency'] = image.info['transparency'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could not find any reference of variability in frames transparency, but if it turns out to be true, this is another place to consider. also why not user has_alpha()
as in the image operation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only information I could find on this is in the GIF spec
Section 23 says that the fields which define transparency are assigned per graphics block, so it's possible that these settings can change per-frame but even on different areas of a single frame as well.
To check if Pillow supports multiple GIF palettes, I tried opening an image with multiple palettes and saving it again.
(Image source https://en.wikipedia.org/wiki/GIF#/media/File:SmallFullColourGIF.gif)
I think the answer to that is clear! And looking at the Pillow source code, looks like only one palette gets used in the _save
function so it's not possible for it to have different palettes for each block: https://github.com/python-pillow/Pillow/blob/master/src/PIL/GifImagePlugin.py#L507
Thinking about it, this is probably a really hard problem. Whenever we save a GIF image, we can't assume the colour palette of the original image is still valid as resizing would generate many more colour variations than there were in the original image, and it's also possible that the image could've been modified in another way that could add more colours as well.
This would mean that we would have to programmatically re split each frame of the image back into blocks and generate a new colour pallete for each one. It would need to balance between having enough blocks in the image to represent as many colours as possible yet not having too many so the image file isn't too big.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To demonstrate a tool that can actually do this image blocking/pallette generation automatically, I generated a new GIF using the following website: https://ezgif.com/
This clearly has lower quality than the original, but also it's 6x larger! (315KB up from 54KB)
Trying out other formats, this APNG is 79KB and looks much better:
I can't show them here, but a high quality WEBP comes out at 115KB and a 70% quality WEBP (which looks roughly the same as the GIF above) is 40KB
All modern browsers except IE11 supports at least one of these formats (apng, webp). So I think it would be worth adding support for these into Willow.
What's the status of this PR? |
@danihodovic it's awaiting review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A great improvement, @kaedroho!
Found two issues with RGBA animated gifs which I documented in separate comments.
Ran a few quick and dirty memory tests:
- the linked image (5.5MB) takes about 35MB on the image edit page (using the
max-800x600
rendition) - the same image but in higher resolution (17.2MB) took 79MB
Code looks good to me. One thing I'm not clear on, though: given that |
Good point! I've merged the two classes together now |
My plan for this is to implement both animated GIF and animated WEBP support in Willow, then add logic into Wagtail so that it always transcodes animated GIFs into animated WEBP files. This fixes issues with having to save a GIF that contains more than 256 colours (which will be inevitable if we've resized the image). See discussion in #76 (comment) |
Hey @coredumperror I'm getting similar results with a different image here I think this is just a Pillow limitation. It must be difficult saving GIF images like this which have a limit of 256 colours. I think the best solution would be for us to add support for animated webp/apng so images can be saved in those formats instead. |
Yes, please! Animated GIF is soooo 1990s. Hell, mosts sites that let you share GIFs just convert to mp4 video with no audio track. I wonder if that would be possible? |
Hadn't thought of that before! I think we could view MP4 w/o audio as just another animated image format, so could support that if Pillow/wand does (but can always add an ffmpeg plugin if not!) |
Relevant blog post: https://paulbakaus.com/2020/01/17/gifs-must-die/ |
I am exceedingly glad to hear this. :) |
We're still very interested in Wagtail properly supporting animated whatevers (GIF, webp, mp4, etc.). |
Incidentally @thenewguy makes the case for animated GIFs to be treated as "media" (i.e. no resizing and other Willlow filters) - torchbox/wagtailmedia#127 |
I like that idea! In many cases, GIFs would be both smaller and better quality if we don't try to process them. Wagtailmedia may also be able to provide the processing code required to convert them into videos as well. |
This PR adds support for animated GIFs in the Pillow backend