Notes › Resources › Splitting a GIF into individual images: frame-by-frame extraction

Splitting a GIF into individual images: frame-by-frame extraction

In my third year of making course videos, I was always the person on the team who produced the cover last. Last month I had a bad miss: a colleague sent a GIF preview over WeChat at 480x270 with 48 frames, and I needed to pick one frame as the 1280x720 cover. I dragged the scrub bar back and forth in the player, and six out of eight stops landed on the frame where a hand was covering the logo. Twenty-odd minutes were gone just like that. Only afterwards did I work out where the problem was: the player gives me time, but what I need is a frame index, and GIF frames do not all last the same length, so guessing a frame number from a timestamp was never going to work.

1. Why dragging the scrub bar cannot land on the frame you want

GIF stores frames one by one, and each frame carries its own delay: fast motion might run at 60ms per frame, while setup and still passages can reach 1000ms. So playback at 1.2 seconds and frame 12 are not the same thing at all. A single second might hold seven or eight frames with the image shifted dozens of pixels, or two seconds might sit on the same pose. To freeze an animation at an exact point, the only reliable method is to list the frames by index and pick one, rather than dragging a timeline.

When I parsed this GIF, it came out as 48 frames, about 6.6 seconds in total, 480x270. The first 6 frames last 400ms each, the still setup before the cursor enters the frame; the remaining 42 run at about 100ms each, and all the action is in those. In other words, the range I actually had to choose from was only the second half.

2. When splitting frames is actually worth it

  • Picking a cover: the animation itself looks good, but the platform's cover slot only accepts a still image.
  • Checking frame by frame: a subtitle, logo or watermark that leaks out on a single frame is invisible during playback.
  • Handing off stills: the other side's tool cannot read an animation and needs a set of frames.
  • Splitting to edit: replace a few frames, drop redundant still frames, reset the delays and rebuild.
  • Building a frame comparison: put a few key frames side by side to explain the motion in a tutorial.

3. The order I actually work in

  1. Drop the GIF into GIF Frame Extractor and look first at the three numbers it reports: frame count, total duration, dimensions. Those three decide every later judgment; a 480x270 source is that big, so I cannot enlarge the cover much.
  2. The frame preview is a grid of thumbnails, most of it visible on one screen. I scan the whole thing, pick three candidates, then download only those frames instead of pulling all 48 at once.
  3. To see how long each frame actually holds, read the delay next to its index. In that cursor-crosses-the-menu GIF, the first six frames at 400ms were all still setup; removing them cut the total from 6.6 seconds to 4.2 seconds while the file size barely moved, because a still frame is identical to the one before it and delta storage costs almost nothing. What I actually saved was the reader's patience.
  4. When I need the whole sequence, for a motion breakdown comparison for example, download every frame as one archive instead of clicking 48 times.
  5. With the candidate frames in hand, open them at 400% in my image editor and check three lines: the fingers, the logo and the subtitle. Only when the frame is clean does it become the cover.

4. Four criteria I use to choose a cover from dozens of frames

Once the frames are laid out, the real difficulty becomes which frame can serve as the cover. My four criteria are in priority order:

  1. Take the frame before the peak of the action, not the peak itself. The peak frame often has motion blur or a hand sitting right on a key element; the frame before it shows the intent most clearly.
  2. Key elements must not be covered: if any one of the logo, the button label or the cursor is hidden, the frame is out.
  3. Weight the composition to the left: a landscape cover needs room on the right for the headline, and a centered composition plus text feels cramped.
  4. Skip pure still frames: they look clean, but as a cover they read like a screenshot and carry none of the information an animation has.

Splitting those 48 frames into ranges gives a direct answer:

Frame rangeDelay per frameWhat is on screenMy conclusion
1-6about 400msCursor outside the frame, interface stillSkip all, pure setup
7-14about 100msCursor moving toward the menuCandidate, but the elements are not open yet
15-28about 100msMenu open, submenu item highlightedThe cover comes from this range, frame 24 in the end
29-44about 100msClick, then the panel switchesFrame 36 used for the second process shot
45-48about 100msWind-down, the image barely movesKept as the final frame of the loop

With only a player, I could never have arrived at frame 24. I would have kept dragging around the four-second mark, and every stop would have been the wrong cell.

5. Things to watch after splitting

SymptomCauseWhat I do
A frame blurs when enlarged to 1280x720The source GIF is only 480x270; splitting frames cannot invent detailSplitting is only for choosing the image; once the index is fixed, ask the colleague to export a high resolution still from the project file
Two neighboring frames do not match in colorGIF has only a 256 color palette; the color was already fixed in the source fileColor-correct the extracted images together, and do not expect frame-to-frame color continuity
One extracted frame is larger than the whole GIFGIF stores the delta between frames, while a still is a complete frameCompress before posting to the group or submitting; Image Compressor usually takes about half off a PNG
The only format I get out is PNGPNG is lossless, which keeps the full information of the frameIf I need JPG or WebP, I save a copy in my image editor; conversion is not part of splitting

6. Two things worth doing while you are there

First, save the chosen frame together with the one before and after it, so if the cover has an obstruction I can try a neighbor. Second, if the frames have to go back to a colleague to cut the final video, edit them and rebuild with Images to GIF in the new order and with new delays. That is much faster than picking through an animation editor frame by frame, and it avoids the palette being recalculated over and over.

7. Common questions

Q: Does splitting reduce image quality?

Splitting exports the frames as they are, with no extra loss. The ceiling is set by the source GIF: its 256 colors, original width and height, and the dithering from encoding are already in the file.

Q: Can I take just one frame and discard the rest?

Yes, and that is how I use it now. Click the frame I need in the preview and download it alone; the rest does not matter. The archive is only for the whole sequence.

Q: Why does the total duration not match frame count times delay?

I have seen a few tenths of a second of drift, usually because some frames had their delay written as the minimum value. When picking a cover, going by index is more reliable than working back from time.

Q: Can APNG or animated WebP be split the same way?

For those formats I still ask the person who made the animation for still frames directly. I have not run them through the splitting flow, so I will not claim it works.

Q: Is my GIF uploaded to a server?

No, parsing and export both run locally in the browser. Unreleased material a colleague sends does not need to go through external approval first.

After this I changed how our team hands off work: every animation preview now comes with a still sequence, and picking a frame went from dragging a player and hoping to reading an index. The cover for that video took me three minutes from start to finish.

📎 Related articles

SOS is 9 tones, the full alphabet is 104: how Morse timing is calculated 2026-10-21 What does a weight of 30 mean on a spinner? Sector angles and draws with or without replacement 2026-10-21 Why white text on gradients is hard to read: checking WCAG contrast at every stop 2026-10-21 Enlarging old photos without blur: how much detail enhancement can recover 2026-10-15 Barcodes for inventory labels: choosing between CODE128 and EAN-13 2026-10-15