Skip to content
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

whish for 2016: matplotlib can use only Pillow 3.0+ to create animated GIF #5750

Closed
stonebig opened this issue Dec 26, 2015 · 20 comments
Closed
Milestone

Comments

@stonebig
Copy link
Contributor

Imagemagick is a problem on windows, and the animated gif functionality of Pillow seems to work for some well-known situations since 3.0.0.

(would spare 40 Mo of Imagemagick downloads on Windows 64bit, and installation tricks, a huge win)

@tacaswell tacaswell added this to the proposed next point release (2.1) milestone Dec 26, 2015
@tacaswell
Copy link
Member

Someone just needs to write a pillow-based writer. This should be pretty simple once #5454 gets merged.

@WarrenWeckesser
Copy link
Contributor

the animated gif functionality of Pillow seems to work for some well-known situations since 3.0.0.

Do you have an up-to-date example that demonstrates this? This would be a good use-case for #5454. A working script that uses Pillow to programmatically create an animated GIF from a sequence of individual images (either Pillow Image instances or numpy arrays) would be a great help. I did a little googling, but it is hard to tell what would be the best practice when using Pillow 3 (e.g. the file gifmaker.py doesn't actually contain much code these days; it has been moved to the gif plugin).

@stonebig
Copy link
Contributor Author

I did the little googling earlier, with same lack of example of writing.
For reading, this one example worked (with the patch suggested by @radarhere) :

python-pillow/Pillow#1525

import PIL
import PIL.Image
i = PIL.Image.open('index.gif')
i.show() # correct image displays on left
i.seek(i.tell() + 1)
i.show() # image is incorrect on right

index
gif_patch

@WarrenWeckesser
Copy link
Contributor

Cool, but that starts with an animated GIF. We'll need to be able to create one "from scratch".

I took a look at the Pillow unit tests for the gif plugin, and based on that, here's what I have so far. The GIF should be a yellow rectangle that fades to black:

import numpy as np
from PIL import Image, GifImagePlugin


width = 80
height = 50
num_frames = 10
data = np.zeros((num_frames, height, width, 3), dtype=np.uint8)
for k, val in enumerate(np.linspace(255, 0, num_frames)):
    data[k, :, :, 0:2] = int(val)

im = Image.new('RGB', (height, width))
im = im.convert('P', palette=Image.WEB)
#im = im.convert('P', palette=Image.ADAPTIVE, colors=256)

with open('foo.gif', 'wb') as f:
    for s in GifImagePlugin.getheader(im)[0]:
        f.write(s)
    for a in data:
        imdata = Image.fromarray(a)
        imdata = imdata.convert('P', palette=Image.WEB)
        #imdata = imdata.convert('P', palette=Image.ADAPTIVE, colors=256)
        d = GifImagePlugin.getdata(imdata, duration=250)
        for s in d:
            f.write(s)
    f.write(b';')
    f.close()

Using palette=Image.ADAPTIVE doesn't work as expected. I don't know why, but I just started experimenting with this. palette=Image.WEB limits the colors pretty severely.

@stonebig
Copy link
Contributor Author

promising, but works only when I attach foo.gif, and not after... curious, missing a loop ?

foo

like:

        d = GifImagePlugin.getdata(imdata, duration=250 , loop=22)

foo

better but still all black after a 22*while

... loop=0 !

        d = GifImagePlugin.getdata(imdata, duration=250 , loop=0) # infinite = 0

foo

@WarrenWeckesser
Copy link
Contributor

I put a "proof of concept" animated GIF writer class in a gist: https://gist.github.com/WarrenWeckesser/7c8423d3935cad422774

Here's an example of its use:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
from animated_gif_writer import AnimatedGifWriter


def update_line(num, data, line):
    line.set_data(data[:, :num+1])
    return line,

fig = plt.figure(figsize=(4.1, 4.0))
ax = fig.add_subplot(111, xlim=(-1, 1), ylim=(-1, 1),
                     autoscale_on=False,  aspect='equal',
                     title="Matplotlib Animation")

num_frames = 8

theta = np.linspace(0, num_frames*np.pi, num_frames)
data = np.exp(1j*theta).view(np.float64).reshape(-1, 2).T

lineplot, = ax.plot([], [], 'b-', linewidth=1.5)
# Reduce the number of colors by turning off antialiasing.
lineplot.set_antialiased(False)

ani = animation.FuncAnimation(fig, update_line, frames=num_frames,
                              init_func=lambda: None,
                              fargs=(data, lineplot))
ani.save('mpl_example.gif', dpi=60, fps=2, writer='pillow-gif')
# Or...
#   writer = AnimatedGifWriter(fps=2)
#   ani.save('mpl_example.gif', dpi=60, writer=writer)

It creates:

mpl_example

@stonebig
Copy link
Contributor Author

cool !

@WarrenWeckesser
Copy link
Contributor

@stonebig You might also be interested in animated PNG files. If so, check out numpngw: https://pypi.python.org/pypi/numpngw

@stonebig
Copy link
Contributor Author

Even Greater, animated png are much more powerfull ! How to pack that so that these two awesome bleeding edge leaders can easily switch away from writer='imagemagick' ?

@WarrenWeckesser
Copy link
Contributor

Jake's notebook generates an animated GIF with:

anim = animation.FuncAnimation(fig, animate_as_gif,
                               frames=2 * Nframes + 30, interval=50)
anim.save('MagicTriangle.gif', writer='imagemagick')

You can generate an animated PNG by adding the import from numpngw import AnimatedPNGWriter, and changing anim.save('MagicTriangle.gif', writer='imagemagick') to

writer = AnimatedPNGWriter(fps=1000.0/anim._interval)
anim.save('MagicTriangle.png', dpi=72, writer=writer)

magictriangle

@WeatherGod
Copy link
Member

Weird, in gmail, that animated PNG was not animated when embedded in the
email, but worked fine when clicked and viewed separately... Animated GIFs
work fine no matter what.

On Tue, Dec 29, 2015 at 6:00 PM, Warren Weckesser notifications@github.com
wrote:

Jake's notebook generates an animated GIF with:

anim = animation.FuncAnimation(fig, animate_as_gif,
frames=2 * Nframes + 30, interval=50)
anim.save('MagicTriangle.gif', writer='imagemagick')

You can generate an animated PNG by adding the import from numpngw import
AnimatedPNGWriter, and changing anim.save('MagicTriangle.gif',
writer='imagemagick') to

writer = AnimatedPNGWriter(fps=1000.0/anim._interval)
anim.save('MagicTriangle.png', dpi=72, writer=writer)

[image: magictriangle]
https://cloud.githubusercontent.com/assets/321463/12043744/f177441c-ae55-11e5-921b-3d59f4eecc0f.png


Reply to this email directly or view it on GitHub
#5750 (comment)
.

@stonebig
Copy link
Contributor Author

hum, gmail is maybe not showing the real image, like blackberry servers tends to do, until you download it ? .. Indeed, the image in gmail is 6.72 K instead of 349.7 K

(maybe it's a gmail bug and you just earned 10.000 $ ?)

@stonebig
Copy link
Contributor Author

Wheater test (to check for discriminatory practice from google):
magictriangle

@WeatherGod
Copy link
Member

That one works.

On Tue, Dec 29, 2015 at 6:31 PM, stonebig notifications@github.com wrote:

Wheater test (to check for discriminatory practice from google):
[image: magictriangle]
https://cloud.githubusercontent.com/assets/4312421/12044128/b22d0cc4-ae8c-11e5-974d-02f833336ab3.gif


Reply to this email directly or view it on GitHub
#5750 (comment)
.

@stonebig
Copy link
Contributor Author

Why Google truncates the smaller-than-gif "png" is a mystery. On a side note, the "animated png" doesn't work on Windows Phone "8.1" default and unique browser.

@WarrenWeckesser
Copy link
Contributor

@stonebig: Animated PNG also doesn't work in Safari. It works in Firefox, and I've learned that it can work in Chrome and Opera with an appropriate extension installed. I don't know the status of animated PNG in any Windows browsers (other than what you just reported).

@WeatherGod
Copy link
Member

Would also be nice to find out how well it works in PowerPoint. Codec
issues are hell at conferences.
On Dec 30, 2015 5:04 PM, "Warren Weckesser" notifications@github.com
wrote:

@stonebig https://github.com/stonebig: Animated PNG also doesn't work
in Safari. It works in Firefox, and I've learned that it can work in Chrome
and Opera with an appropriate extension installed. I don't know the status
of animated PNG in any Windows browsers (other than what you just reported).


Reply to this email directly or view it on GitHub
#5750 (comment)
.

@WarrenWeckesser
Copy link
Contributor

Earlier I wrote:

Animated PNG also doesn't work in Safari.

I just saw this at http://animatedpngs.com/:

Safari is the default browser for Macs. WebKit, Safari's rendering engine, powers all browsers on iOS, meaning iPhones, iPads, and iPods with iOS 8+ now support APNGs.

I have Safari 9.0.2 on my laptop, which doesn't show the animation when displaying an animated PNG, but perhaps newer versions of Safari support it.

@stonebig
Copy link
Contributor Author

Reading the Wikipedia entry about "animated png" (https://en.wikipedia.org/wiki/APNG), I see:

  • the consensus has never been reached between "APNG" and "MNG", because of "whatever",
  • the situation is blocked since 2007 when the PNG group officially rejected APNG as an official extension, and remains not rosy.

Is there some movement to resolve this around a third format that would avoid anyone loosing face ? (it's not clear to me, reading the internet; GIFV, AWEBP, BPG, ...)

Is there a secondary step transforming apng in something everybody accepts to read ?

@tacaswell tacaswell modified the milestones: 2.1 (next point release), 2.2 (next next feature release) Oct 3, 2017
@QuLogic
Copy link
Member

QuLogic commented Feb 10, 2018

Animated GIF with Pillow is implemented in #10240.

@QuLogic QuLogic closed this as completed Feb 10, 2018
@QuLogic QuLogic modified the milestones: needs sorting, v2.2.0 Feb 12, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants