GIF Maker — turn images into an animated GIF
Stitch JPG, PNG, WebP, AVIF, or GIF frames into a single animated .gif file in your browser. Set the frame delay, loop count, and output dimensions — files never leave your device, no signup, sources cited below.
How it works
The GIF format hasn't changed since CompuServe published the GIF89a specification in July 1990. A GIF is a sequence of palette- indexed bitmaps wrapped in three layers of metadata: the file header, an optional Global Colour Table, and one Graphic Control Extension + Image Descriptor per frame. The pixel data of each frame is compressed with LZW (Welch, 1984) — the same algorithm UNIX compress used to ship inside .tar.Z archives a year before GIF was published. Loop counts above one are encoded via the Netscape 2.0 Application Extension, a de-facto standard added by Netscape Navigator 2.0 in 1996 and supported by every browser and image viewer since.
The encoding pipeline this tool runs has five deterministic steps per frame, then one finalisation step at the end:
- Decode. Load each source through
createImageBitmap(or, on browsers without it, the<img>element) so the browser's native decoder reads JPG, PNG, WebP, AVIF, GIF, and BMP without any JavaScript decoder. - Cover-fit. Every frame in a GIF must share one rectangle. The tool picks the median width × height across the queue, applies the chosen longest-side cap, and cover-fits each frame onto that rectangle (scale uniformly to fill, centre-crop the overflow).
- Quantise. Each frame's 24-bit RGBA pixels are reduced to a palette of up to 256 colours using PnnQuant — a port of the Pairwise Nearest Neighbour algorithm (McNeill, 2018). Photo content tolerates 256 colours invisibly; flat-colour cartoons can drop to 64 with no perceptible loss.
- Index. Map every pixel to its nearest palette entry, producing a flat
Uint8Arraywith one byte per pixel. This is the input the LZW compressor actually sees. - Compress & write. LZW compresses the indexed bitmap, the encoder writes a Graphic Control Extension (delay + transparent index) and an Image Descriptor, then the compressed pixel data. On the first frame the encoder also writes the GIF header, the Logical Screen Descriptor, the Global Colour Table, and — when the loop count isn't -1 — the Netscape 2.0 application extension.
File-size estimation uses an empirical bytes-per-pixel band fitted against gifenc output on representative content:
bytes_per_frame = pixels × density + 18 (GCE + ImgDesc) density(flat) = 0.40 density(midtone) = 0.55 density(photo) = 0.70 header = 14 + 19 (Netscape) + 3 × paletteSize (Global Colour Table) total = header + frames × bytes_per_frame
The estimator is cross-checked against a discrete content-band lookup; the two land within ±5% on every input. The per-pixel density is the LZW dictionary's reward for finding long runs of repeated colour: cartoons with large flat regions compress to about 0.4 bytes per pixel, photographs with smooth gradients pay closer to 0.7. Real output may differ ±15% on textured frames — the figure on the calculator is a best estimate, not a measurement.
Worked examples
Frame delay and frame rate at a glance
GIF delays are stored as hundredths of a second (a 16-bit unsigned integer). The tool exposes the value in milliseconds because that's the unit web tools speak; the table below shows what each common delay translates to.
| Delay | Frame rate | Reads as | Best for |
|---|---|---|---|
| 40 ms | 25.0 fps | Fast | Smooth animation, video-like |
| 80 ms | 12.5 fps | Fast | Reaction GIFs, screen recordings |
| 100 ms | 10.0 fps | Brisk | Animated emoji, micro-interactions |
| 200 ms | 5.0 fps | Brisk | Slideshow, step-by-step instructions |
| 500 ms | 2.0 fps | Steady | Photo carousel, slow montage |
| 1000 ms | 1.0 fps | Slow | Manual-paced reveal, presentation |
Most browsers floor the effective delay at 20 ms and quietly bump 0–10 ms delays to 100 ms for compatibility with very old GIF89a players. Stay above 20 ms to keep playback consistent across Chrome, Firefox, Safari, and Edge.
Frequently asked questions
Sources & references
- CompuServe Inc. — GIF89a Specification (31 July 1990)
- Welch, T.A. — A Technique for High-Performance Data Compression (LZW, IEEE Computer 17, 1984)
- Netscape 2.0 Application Extension (de-facto loop-count standard, 1996)
- gifenc — Mattt DesLauriers's pure-JS GIF encoder (the encoder this tool wraps)
- MDN — CanvasRenderingContext2D.getImageData (the pixel pipeline behind the encoder)
- McNeill, M. — PnnQuant.js (Pairwise Nearest Neighbour colour quantiser, the algorithm gifenc uses)
The GIF89a byte structure, the Netscape extension layout, and the encoder behaviour described above were last cross-checked against the cited sources on 2026-05-11. The page is reviewed when gifenc ships a major release or when a browser changes the canvas pixel-data contract in a way that affects sampling.
Related tools
Comments & feedback
Spotted a bug or want an improvement? Tell us — our team reviews every comment, and good ideas get built. Comments are public and anonymous.
Found a bug, edge case, or want to suggest an improvement?
Email me at [email protected] — most fixes ship within 24 hours.