What happens when you convert GIF to PNG
A GIF and a PNG store colour in different ways, so the conversion is never a straight copy. GIF keeps a palette of at most 256 colours and marks one palette slot as invisible. PNG stores full colour with a real alpha channel per pixel. Going from GIF to PNG widens the container without adding anything back, and the interesting decisions all sit in what happens to animation frames on the way through.
The first frame problem
Animated GIFs rarely store whole pictures. After frame one, a well compressed GIF writes only the rectangle that changed. A mouth moving in a 400 by 300 cartoon might be a 60 by 40 patch with an offset. Every frame carries a disposal flag saying what to do with the previous frame before drawing the next one.
A converter built on <img> and a canvas never sees any of that. The browser hands over one rendered still, and everything after it is out of reach. Converters that offer a frame slider on top of that model are moving a control connected to nothing. This page reads the file itself, replays the disposal rules in order, and stores each frame as a finished full size image. That is why the frame strip below the preview shows complete pictures instead of floating patches.
Disposal methods, and why frames look broken without them
| Flag | Name | What the decoder does | Skipping it produces |
|---|---|---|---|
| 0 | Unspecified | Leave the canvas alone and draw the next patch over it | Usually fine, since most encoders mean "keep" |
| 1 | Do not dispose | Keep every pixel already drawn | Nothing visible. This is the common case |
| 2 | Restore to background | Clear the frame rectangle to transparent before the next frame | Trails and smearing, as old pixels never get erased |
| 3 | Restore to previous | Roll the canvas back to the state before this frame | Overlays and flashes that stick around permanently |
Flag 2 is where naive extraction falls apart most visibly. Text overlays and cursor animations lean on it heavily, and a decoder ignoring the flag turns a clean animation into a pile of stacked ghosts. The frame thumbnails on this page are the composited result, so what you see in the strip is what lands in the PNG.
Transparency crosses over, but it does not improve
GIF transparency is one bit. A palette index is either invisible or fully opaque, with nothing in between. PNG gives each pixel 256 levels of alpha. The conversion moves the invisible pixels across as alpha zero and everything else as alpha 255, which is correct and also the ceiling.
The practical result: jagged edges in the GIF stay jagged in the PNG. GIF encoders normally hide this by matting artwork against the background colour it will sit on, so a logo cut for a white page carries a faint white fringe baked into its edge pixels. Convert that to PNG, drop it on a dark panel, and the fringe shows. Nothing in a converter fixes it, because the softer edge was thrown away when the GIF was first written. Re-export from the original artwork when edge quality matters.
Expect the PNG to be larger than the GIF. The browser encoder writes 32-bit RGBA PNG with no palette, so a 256 colour image gets stored at four bytes per pixel before compression. A 40KB animated GIF often expands into 60KB of PNG per frame. Converting is about getting a lossless still into a pipeline, never about saving bytes. Run the results through an optimiser afterwards if size matters.
Sprite sheets, and when to pick one
The sheet mode tiles every decoded frame into a single PNG on a fixed grid, left to right and top to bottom. Each cell is the full logical size of the GIF, so cells line up exactly and a CSS background-position step or an engine spritesheet importer reads them without hand measuring. The column slider shows the finished pixel dimensions before you commit, which matters because a 40 frame GIF at one column produces a very tall texture that some GPUs refuse to sample.
Choose the sheet when the destination animates by shifting a viewport across one image: CSS steps animations, Unity or Godot sprite imports, or a shader sampling a flipbook. Choose the ZIP when frames are edited individually, fed to a video encoder, or reviewed one at a time. Choose a single frame when a still is all anyone wanted, which is most of the time a poster image is being pulled out of a screen recording.
Frame timing does not survive the trip
Each GIF frame carries its own delay, in hundredths of a second. The source panel reports the total loop length and each thumbnail shows its own hold time on hover, since uneven timing is common and worth knowing before rebuilding an animation elsewhere. PNG has nowhere to keep any of it. Once frames are exported, the pacing lives only in whatever you rebuild them with, and assuming a flat frame rate across the set will drift against the original.
Delays below 20ms are a related trap. Browsers historically clamp anything under that to 100ms, so a GIF claiming 10ms per frame plays far slower than its own header suggests. Rebuild against the real numbers rather than the playback you remember.
What the decoder reports, and why it helps
- Version, either GIF87a or GIF89a. An 87a file has no animation and no transparency by design, so a single frame is the honest answer for one.
- Global palette size. A 16 or 32 colour palette signals artwork that was quantised hard, which explains banding you might otherwise blame on the conversion.
- Frames on a local palette. Some encoders give individual frames their own colour table. Those frames often shift in tone against their neighbours, and the count tells you to expect it.
- Transparent index count. If no frame declares one, every exported PNG is fully opaque and the transparency setting changes nothing.
- Loop count. Zero means infinite, which is what the NETSCAPE application block writes for a normal looping GIF.
Limits worth knowing before relying on this
- Output is unindexed RGBA. Encoding runs through the browser, which writes truecolour PNG. A palette PNG would be smaller for this kind of artwork, and building one is out of scope here.
- No APNG output. Frames come out as separate stills or one sheet. Rebuilding a moving image needs a separate encoder.
- Comments and application blocks are dropped. GIF text extensions and authoring metadata are read for the summary and then discarded, since PNG output here carries no text chunks.
- Memory sets the real ceiling. Every frame is held as a full size RGBA buffer. A 600 by 600 GIF with 200 frames needs roughly 288MB, and a mobile browser gives up well before that. The page refuses files over 50MB or 40 megapixels rather than freezing the tab.
- Malformed GIFs stop at the damage. Decoding is strict about block structure. A truncated or hand-edited file returns the frames read up to the break, so a lower frame count than expected points at the file rather than the reader.
- Interlaced GIFs are reordered on read, which is handled, though very old files using rare extension blocks may report fewer frames than a specialist tool finds.
Everything runs in this tab. The GIF is read into memory as bytes, decoded in JavaScript on this page, and the PNG or ZIP is offered from browser memory. No request carries the image anywhere, which matters when the GIF is a screen recording of internal software.
