11

I want to compress a GIF image by extracting 15 frames from the GIF that preferably should be distinct.

I'm using Python and Pillow library and I didn't find any way to get the number of frames a GIF has in the Pillow docs. Neither did I find how to extract a specific frame from a GIF, because Pillow restricts that.

Is there any way to extract frames without iterating through each frame consequently? Is there a more advanced Python library for GIF processing?

Kirill Cherepanov
  • 927
  • 1
  • 10
  • 20
  • 1
    @Bram I'm not sure that the other question is relevant here exactly. This question is about how to jump to an arbitrary frame. – Mad Physicist Jul 28 '18 at 03:11

4 Answers4

12

Here is an extension of @radarhere's answer that divides the .gif into num_key_frames different parts and saves each part to a new image.

from PIL import Image

num_key_frames = 8

with Image.open('somegif.gif') as im:
    for i in range(num_key_frames):
        im.seek(im.n_frames // num_key_frames * i)
        im.save('{}.png'.format(i))

The result is somegif.gif broken into 8 pieces saved as 0..7.png.

Alistair Carscadden
  • 1,198
  • 5
  • 18
  • 2
    The 8 frames are probably numbered 0..7 ;-) – Mark Setchell Jul 27 '18 at 10:46
  • @MarkSetchell, yeah :--) they definitely are. – Alistair Carscadden Jul 28 '18 at 03:06
  • 1
    So the value added to the original post is how to use a for loop? – mins Mar 28 '21 at 13:15
  • @mins The value is since the question asked for "extracting 15 frames", and the answer I'm extending almost reaches that goal, my answer takes it all the way. – Alistair Carscadden Apr 05 '21 at 20:06
  • 1
    The OP didn't know how to perform a random access to a specific frame, he had to restart from frame 0 for any frame. The answer was given by @radarhere: Use `PIL.Image.seek(i)`. – mins Apr 05 '21 at 22:42
  • 1
    @mins I believe it is perfectly acceptable to extend an answer on SO to bring the answer further towards what the question is looking for. It may not be the most important detail to iterate over the frames but it is a goal stated in the question. A handful of users have obviously found this answer useful, so what exactly is your point? – Alistair Carscadden Apr 06 '21 at 03:11
9

For the number of frames, you are looking for n_frames. Take a look at here.

from PIL import Image
im = Image.open('test.gif')
print("Number of frames: "+str(im.n_frames))

For extracting a single frame -

im.seek(20)
im.save('frame20.jpg')
Scott
  • 4,974
  • 6
  • 35
  • 62
radarhere
  • 929
  • 8
  • 23
0

The real working solution to extract proper frames of any GIF file:

BigglesZX/gifextract.py

MST
  • 651
  • 1
  • 4
  • 6
0

If you have tf imported you can:

def load_gif(file_path):
    with tf.io.gfile.GFile(file_path, 'rb') as f:
        video = tf.io.decode_gif(f.read())
    return np.array(video)
man-do
  • 1
  • 1