gizmobench

GIF Frame Extractor

Most GIF frame extractors hand back what the file stores, and a GIF stores each frame as the rectangle that changed since the last one, so the PNGs come out as fragments floating on nothing. This tool decodes the GIF in this browser tab, draws every frame onto a running canvas in order with its transparency and its disposal rule applied, and writes out the picture a player would actually have shown at that moment. Every PNG keeps its own frame number, so frame 6 is frame-06.png whether it came out with the rest or on its own, and the names are padded so a folder sorts into playing order. Take all of the frames, every Nth frame, or one frame every so many milliseconds: the timings never move, and each frame keeps the moment it appears in the animation. Download a single frame from the list, or take all of them in a zip that also holds frames.csv, one row per frame with its number, its start time and the delay the file itself stores. Nothing is uploaded and there is no account.

source.gifnothing open

Drop a GIF here, or choose one below.

no GIF open yet
framesnothing yet

Every frame is decoded and composited in this tab, then written out as a PNG.

· or drop one anywhere on the stage

Never uploadedNo accountWhole frames, not patchesUp to 300 frames
Frames
Size
open a GIF
Total
open a GIF
Export
open a GIF

No GIF open yet. Choose one, or drop it on the stage.

Every frame is composited before it is written, including the ones a selection skips, because a GIF frame is usually only the rectangle that changed and the frames after it are drawn on top. The zip holds the PNGs and frames.csv, a row a frame with its number, the moment it appears and the delay the file stores. The ceilings are 300 frames, 25 million pixels in a single frame and 120 million across the whole animation, because every frame is unpacked to full size in the memory of this tab.

Whole frames, with their timings. Each PNG is the frame as it is actually displayed, composited with everything under it and with the disposal rules applied, not the raw patch stored in the file. Timings come from the file and are listed in the manifest. Up to 300 frames, decoded in your browser.

Common questions

How do I extract the frames from a GIF?
Open the GIF, or drop it on the stage, and the frames appear in the list on the right as they are written. Each row is a PNG with the moment it appears in the animation beside it, so choosing a row saves that one frame. The button under the stage saves all of them in a zip. The first screen takes every frame; the segmented control beside it switches to every Nth frame or to one frame every so many milliseconds.
Are these whole frames, or the patches the file stores?
Whole frames. A GIF usually stores only the rectangle that changed since the previous frame, and each frame carries a disposal rule saying what happens to that rectangle afterwards: leave it, clear it back to the background, or put back what was underneath. This tool composites every frame onto a running canvas in order and applies those rules, so each PNG is the full picture at the size of the GIF's own canvas. That is checked in this tool's tests with a disposal 3 fixture, where the frame after a restore-to-previous frame has to be built on the picture that came before it rather than on the one that asked to be undone.
Can I take only some of the frames?
Yes, in two ways. Every Nth frame takes frame 1, then every Nth after it, so every 5th frame of a 48 frame GIF gives 10 PNGs. By time samples the animation at a fixed interval and takes whichever frame is on screen at each moment, which is what you want when the delays are uneven. A frame that several samples land on comes out once rather than as copies of the same picture, and every frame that comes out keeps its own number and its own start time. Frames the selection skips are still composited, because the frames after them are drawn on top of them.
What is inside the zip?
One PNG per extracted frame, plus frames.csv, which has a header and then a row per frame with the file name, the frame number, the moment it appears in milliseconds and the delay the GIF itself stores for it. The delay column of a full extraction adds up to the animation's whole running time. The same manifest can be copied as text from the row under the stage, alongside the list of times and the list of delays.
Why are the frames numbered the way they are?
The number is the frame's own place in the animation, not its place in the export, so a frame taken on its own still says which one it was. The number is padded to the width of the whole frame count and never to fewer than two digits, which is what makes a folder sort into playing order instead of 1, 10, 100, 2. A 48 frame GIF gives frame-01.png to frame-48.png; a 120 frame GIF gives frame-001.png to frame-120.png.
Are the delays exact?
They are the numbers the file stores, carried through without rounding or averaging, and the start time beside each frame is simply the delays before it added up. A GIF holds each delay in hundredths of a second, so they arrive here as multiples of 10 milliseconds. There is one substitution and it belongs to the decoder: a frame that stores a delay of zero is read as 100 milliseconds, which is the tenth of a second most players show such a frame for. Everything else in the manifest is the file's own timing, in the order the frames play.
Is my GIF uploaded anywhere?
No. The file is read by a JavaScript GIF decoder running in this tab, composited by this page's own code, drawn to a canvas here and packed into the zip here. There is no upload, no queue, no account and no request of any kind: no byte of the animation leaves this browser. The only thing kept between visits is the selection you chose, stored in this browser, and the Start over button on this page forgets it.
What are the limits, and why does a local tool have any?
300 frames, 25 million pixels in a single frame and 120 million pixels across the whole animation. Every frame is unpacked to the full canvas at four bytes a pixel while the work runs, so past that point a phone stops responding instead of finishing. A file over a limit is refused with the number it actually reached and what to do about it, rather than having frames quietly dropped, and a long run has a Cancel button that really stops it because the work yields between frames.

Each PNG is the frame as it is actually displayed, composited with everything under it and with the disposal rules applied, not the raw patch stored in the file. Timings come from the file and are listed in the manifest. Up to 300 frames, decoded in your browser.