symbols_pangaea
symbols_pangaea

Reputation: 25

Wrong order of frames creating GIF animation from PNG files

I'm saving a GIF file from multiple PNG files I create inside a loop. I'm not able to save the PNG's with the right name, because when translated to GIF I get the wrong order of the frames. The following code is exactly what I need but with the order of the frames messed up. Thanks a lot, I'm new to python.

# basic animated mod 39 wheel in python
import glob
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np 
plt.close()
plt.rcParams.update({
    "lines.color": "white",
    "patch.edgecolor": "white",
    "text.color": "lightgray",
    "axes.facecolor": "black",
    "axes.edgecolor": "lightgray",
    "axes.labelcolor": "white",
    "xtick.color": "white",
    "ytick.color": "white",
    "grid.color": "lightgray",
    "figure.facecolor": "black",
    "figure.edgecolor": "black",
    "savefig.facecolor": "black",
    "savefig.edgecolor": "black"})
plt.xlabel('real axis')
plt.ylabel('imaginary axis')
plt.title('events constellation')
plt.xlim(-4, 4)
plt.ylim(-4, 4)
plt.gca().set_aspect('equal', adjustable='box')
#for fullscreen plt.draw just reinforces de rendering?
#plt.draw()
#mng = plt.get_current_fig_manager()
#mng.full_screen_toggle()

for n in range(1,40):

    cnums = 3 * np.exp(1j * 2 * np.pi * (1/39) * n)
    x = cnums.real 
    y = cnums.imag 
    plt.scatter(x, y , label="event", marker="o", color="blue", s=250)
    #plt.pause(1)
    plt.savefig(f'/outpng/img{n}.png',dpi=100)



# filepaths
fp_in = "/outpng/*.png"
fp_out = "/outpng/image.gif"

# https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#gif
img, *imgs = [Image.open(f) for f in sorted(glob.glob(fp_in))]
img.save(fp=fp_out, format='GIF', append_images=imgs,
         save_all=True, duration=600, loop=0)

Upvotes: 0

Views: 516

Answers (1)

Nathan
Nathan

Reputation: 3648

If I understand correctly, you have:

lst_files = glob.glob(fp_in)
>>> ['/outpng/img28.png', '/outpng/img4.png', '/outpng/img20.png', '/outpng/img32.png', '/outpng/img36.png', '/outpng/img11.png', '/outpng/img1.png', '/outpng/img9.png', '/outpng/img24.png', '/outpng/img35.png', '/outpng/img7.png', '/outpng/img12.png',]

And you want to have the files 'in order' (presumable the number is the order of the images). You can do this using:

import re

def get_number(file_name):
    m = re.findall('img([0-9]*)\.', file_name)[0]
    return int(m)

lst_files = ['/outpng/img28.png', '/outpng/img4.png', '/outpng/img20.png', '/outpng/img32.png', '/outpng/img36.png', '/outpng/img11.png', '/outpng/img1.png', '/outpng/img9.png', '/outpng/img24.png', '/outpng/img35.png', '/outpng/img7.png', '/outpng/img12.png']
lst_numbers = [get_number(i) for i in lst_files]

lst_number_files = sorted(list(zip(lst_numbers, lst_files)))
lst_files_sorted = [i[1] for i in lst_number_files]

How this works:

  1. you find the number in the string (using re.findall) which fits 'imgX.' where X is your number
  2. you match the numbers to the file names
  3. you sort the files based on the number
  4. you flatten the list to only contain the file names

Now you can use this list to make your GIF:

img, *imgs = [Image.open(f) for f in lst_files_sorted]

Upvotes: 1

Related Questions