maxhumber / gif Goto Github PK
View Code? Open in Web Editor NEWThe matplotlib Animation Extension
License: MIT License
The matplotlib Animation Extension
License: MIT License
Different gif.save()
parameters seem to have no effect.
Code to reproduce (gif.save()
call on line 118): https://gist.github.com/ddejohn/fa67039541bdb7e387c403fe32a65eb9
Here's an album of gifs produced with four different sets of parameters:
duration=100, unit="ms", between="frames"
duration=5, unit="ms", between="frames"
duration=1, unit="s", between="startend"
duration=10, unit="s", between="startend"
The only apparent difference is file size:
Good day. Very useful this library!
I do not know how it works internally, however I would like to know if there is a way to use it (and if possible, in what way) with the plotly.py library
Thank you, have a nice day.
Hi, using gif-22.5.0 for the first time...
macOS 12.4
python 3.9.12
Running example at Usage point in https://pypi.org/project/gif/
(.pepito) jose@MacBook-Air-2 keynote % python3 gif.py
Traceback (most recent call last):
File "/Users/jose/Web/keynote/gif.py", line 3, in <module>
import gif
File "/Users/jose/Web/keynote/gif.py", line 9, in <module>
gif.options.matplotlib["dpi"] = 300
AttributeError: partially initialized module 'gif' has no attribute 'options' (most likely due to a circular import)
I want to show a bar plot where bar for the next unit on x-axis appear one after the other and then stop once the last point is reached.
I managed to successfully create my bar plot and save the the gif, however the gif loops which I do not want.
Is there a way to repeat loops?
In trying to plot an audio signal stored in the array piano
as a function of time t
, in increments of 1000 elements, with various parts of the signal highlighted as the animation goes on with axvspan
, I created the function:
@gif.frame
def plot_progression(T):
#f, ax = plt.subplots(figsize=(6,4), dpi=100)
plt.plot(t[:(T+1)*1000], piano[0][:(T+1)*1000], c="k", alpha=0.7)
plt.xlabel("Time (seconds)")
plt.ylabel("Amplitude (?)")
plt.xlim([0,20])
plt.ylim([-0.4, 0.4])
if 1.8 < t[T] < 4.5:
plt.axvspan(1.8, t[T], facecolor="Red", ls="--", lw=2.0, label=r"$C_{3}$", alpha=0.2)
elif t[T] > 4.5:
plt.axvspan(1.8, 4.5, facecolor="Red", ls="--", lw=2.0, label=r"$C_{3}$", alpha=0.2)
plt.legend(fontsize="small")
elif 5.5 < t[T] < 7.8:
plt.axvspan(5.5, t[T], facecolor="Orange", ls="--", lw=2.0, label=r"$E_{3}$", alpha=0.2)
elif t[T] > 7.8:
plt.axvspan(5.5, 7.8, facecolor="Orange", ls="--", lw=2.0, label=r"$E_{3}$", alpha=0.2)
elif 8.9 < t[T] < 11.2:
plt.axvspan(8.9, t[T], facecolor="Green", ls="--", lw=2.0, label=r"$G_{3}$", alpha=0.2)
elif t[T] > 11.2:
plt.axvspan(8.9, 11.2, facecolor="Green", ls="--", lw=2.0, label=r"$G_{3}$", alpha=0.2)
elif 12.2 < t[T] < 15.3:
plt.axvspan(12.2, t[T], facecolor="Purple", ls="--", lw=2.0, label=r"$C_{maj}$", alpha=0.2)
elif t[T] > 15.3:
plt.axvspan(12.2, 15.3, facecolor="Purple", ls="--", lw=2.0, label=r"$C_{maj}$", alpha=0.2)
with the gif creation loop:
frames = []
for T in range(382):
frame = plot_progression(T)
frames.append(frame)
del frame
gif.save(frames, "./audio_progression.gif", duration=45.4)
Problem is, none of the conditionals ever get triggered. All I get is the audio signal, no vspans
or inclusion of the legend elements:
Also, is there any way to have the gif not loop? I know in gif.py
the setting have loop=0
what do we set that to to get it to not loop? Can this be added as an argument to gif.save()
?
Since the code uses indexes [0] and [1:] to take the first and then the rest of the elements of the list, I understand generators won't work here.
You could say the solution would be just converting the generator into a list, but for my use case (2500k frames @ 150 dpi) it takes a lot of memory to allocate the list. Actually, it might work the other way around.
I'd suggest something like:
def save(frames, path, duration=100):
# iter() works for either lists and other iterators (such as generators)
frames = iter(frames)
firstframe = next(frames)
firstframe.save(
path,
save_all=True,
append_images=frames, # The first one was already read by next()
optimize=True,
duration=duration,
loop=0,
)
Any thoughts?
Hi! I have an idea about optimizing gif size:
from PIL import Image
from pathlib import Path
import numpy as np
# read list of pngs
paths = sorted(Path('.').glob('out*.png'))
# open pngs as numpy arrays
images = [np.array(Image.open(path)) for path in paths]
# stack the arrays into a single image
mega_img = Image.fromarray(np.hstack(images))
# reduce number of colors to 255, allowing for 0 to be transparent
mega_img = mega_img.quantize(colors=256 - 1, dither=0)
# append transparent color to the palette
palette = b'\xff\x00\xff' + mega_img.palette.getdata()[1]
# split arrays back
arrays = np.hsplit(np.array(mega_img), len(paths))
for array in arrays:
# account for transparent color
array += 1
prev_array = arrays[0]
for array in arrays[1:]:
mask = array == prev_array
prev_array = array.copy()
# set unchanged pixels to transparent color
array[mask] = 0
path = 'out.gif'
duration_ms = 200
images = [Image.fromarray(array) for array in arrays]
images[0].save( # type: ignore
path,
save_all=True,
append_images=images[1:],
palette=palette,
optimize=True,
duration=duration_ms,
disposal=0,
loop=0,
transparency=0,
version='GIF89a',
)
With this code my image sequence produced 176KiB gif instead of 3400KiB gif. The downside is that it is reasonably slower and uses at least 2x memory. Is there a place for this optimization technique in this library?
I would love some help with some more cool examples/
If you contribute one, I'll mail you a sticker ๐
Currently things happend in the global namespace. I think it would be very nice to be able to have separate objects for separate gifs, something like this:
my_gif = GifObj()
@my_gif.frame
def frame(i):
...
my_gif.save_img("my_gif.gif", frames=range(100))
I can try to draft a PR if you want.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.