pngtoolskit.org
PNG and image utilities, in the browser
Say hi →

PNG to GIF

animated GIF89a · shared palette · Floyd–Steinberg dither · nothing uploaded

Build an animated GIF from a folder of frames without installing anything or handing your images to a server. The encoder runs in this page: it samples every frame to build one shared palette, quantises with optional error-diffusion dithering, and writes a standard looping GIF89a that plays anywhere.

Drop your frames here

Drag the rows to reorder — the list order is the play order

    no files
    Ready.

    How to make a GIF from PNG frames

    1. Drop the frames. Zero-padded names like frame-001.png sort correctly; otherwise drag the rows into order.
    2. Set the frame rate. 10 fps is the usual choice for a screen recording; 24 for smooth motion; 2–4 for a slideshow.
    3. Choose the colour count. 128 is a good default. Fewer colours means a much smaller file and visible banding; 256 is the format's hard ceiling.
    4. Set an output width if the source is large. This is the single most effective way to shrink a GIF.
    5. Build and download. The status line reports the frame count, dimensions, palette size and final file size.

    The 256-colour ceiling, and what to do about it

    GIF stores each pixel as an index into a palette of at most 256 colours. This encoder samples across every frame and builds one shared palette by median cut, which is what keeps colours stable from frame to frame — a per-frame palette makes flat backgrounds shimmer as the quantisation shifts underneath them.

    Dithering trades noise for apparent colour depth. Floyd–Steinberg pushes each pixel's quantisation error into its neighbours, so a gradient that would band into visible steps becomes a fine stipple instead. It usually looks better and it usually makes the file bigger, because the added noise is harder to compress. For flat-colour content — screencasts, line art, UI motion — turn it off: the source already has few colours and dithering only adds weight.

    Transparency is one bit

    A GIF pixel is either fully opaque or fully transparent; there is nothing in between. With the option on, any pixel less than half opaque becomes fully transparent and everything else becomes fully opaque, which is why soft anti-aliased edges get a hard, jagged fringe. If your frames have semi-transparent edges and the result looks ragged, either place them on a solid background first with Background, or use APNG, which keeps the full alpha channel.

    Keeping the file small

    In order of effect: reduce the dimensions — cost scales with area, so halving the width quarters the pixel count. Drop frames — 10 fps instead of 24 is less than half the data and usually reads the same. Lower the colour count — 64 colours is often indistinguishable from 128 on screen content. Turn off dithering. And be honest about the format: for anything longer than a few seconds, a WebM or MP4 will be five to ten times smaller at better quality, and every browser plays it. GIF wins on universal pasteability, not on efficiency.

    FAQ

    Can I use JPGs as frames?

    Yes — any image format your browser decodes works, and they can be mixed. Each frame is drawn onto a common canvas before quantisation.

    Do the frames need to be the same size?

    No. Everything is scaled to the first frame's dimensions, or to the output width you set. Frames with a different aspect ratio will be stretched, so crop them to match first if that matters.

    How many frames can it handle?

    Every frame is held in memory as raw pixels while the palette is built, so a few hundred modest frames is comfortable and a thousand large ones is not. If it stalls, set an output width — that reduces the working set proportionally.

    Why is my GIF larger than the source PNGs?

    Usually dithering, which adds high-frequency noise that GIF's LZW compression handles badly. Turn it off and compare. A high colour count on photographic content has the same effect.

    Is anything uploaded?

    No. The palette, the dithering and the LZW compression all run in this page — the encoder is part of the site's JavaScript. Nothing is sent to a server and the page works offline.