Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get frames per second of a gif in python?

In python, im loading in a gif with PIL. I extract the first frame, modify it, and put it back. I save the modified gif with the following code

imgs[0].save('C:\\etc\\test.gif',
           save_all=True,
           append_images=imgs[1:],
           duration=10,
           loop=0)

Where imgs is an array of images that makes up the gif, and duration is the delay between frames in milliseconds. I'd like to make the duration value the same as the original gif, but im unsure how to extract either the total duration of a gif or the frames displayed per second.

As far as im aware, the header file of gifs does not provide any fps information.

Does anyone know how i could get the correct value for duration?

Thanks in advance

Edit: Example of gif as requested:

enter image description here

Retrived from here.

like image 689
Thomas B. Avatar asked Jan 27 '23 03:01

Thomas B.


1 Answers

In GIF files, each frame has its own duration. So there is no general fps for a GIF file. The way PIL supports this is by providing an info dict that gives the duration of the current frame. You could use seek and tell to iterate through the frames and calculate the total duration.

Here is an example program that calculates the average frames per second for a GIF file.

import os
from PIL import Image

FILENAME = os.path.join(os.path.dirname(__file__),
                        'Rotating_earth_(large).gif')

def get_avg_fps(PIL_Image_object):
    """ Returns the average framerate of a PIL Image object """
    PIL_Image_object.seek(0)
    frames = duration = 0
    while True:
        try:
            frames += 1
            duration += PIL_Image_object.info['duration']
            PIL_Image_object.seek(PIL_Image_object.tell() + 1)
        except EOFError:
            return frames / duration * 1000
    return None

def main():
    img_obj = Image.open(FILENAME)
    print(f"Average fps: {get_avg_fps(img_obj)}")

if __name__ == '__main__':
    main()

If you assume that the duration is equal for all frames, you can just do:

print(1000 / Image.open(FILENAME).info['duration'])
like image 78
agtoever Avatar answered Feb 02 '23 01:02

agtoever