Colorful GIF Creator
Create animated GIF images frame-by-frame with drawing tools, color palettes, onion skinning, and real LZW encoding - entirely in your browser.
About
GIF89a remains the only universally supported animated image format with no playback dependency on JavaScript or video codecs. This tool implements the full GIF89a binary specification client-side: median-cut color quantization reduces each frame to a 256-color palette, then Lempel-Ziv-Welch (LZW) compression encodes pixel indices into variable-length codes. A malformed global color table or incorrect sub-block chunking produces corrupted files that fail silently in browsers. The encoder handles disposal methods, frame delays in 10ms increments, and transparent color indices. This tool approximates professional output assuming input frames share a similar color distribution; wildly divergent palettes across frames may produce banding artifacts despite Floyd-Steinberg dithering.
Pro tip: GIF frame delays below 20ms are clamped to 100ms by most browsers. Target 50 - 100ms per frame for reliable cross-platform playback. Canvas dimensions above 512×512 with many frames will increase encoding time and file size substantially.
Formulas
GIF uses LZW compression to encode indexed pixel streams. The initial code size is derived from the palette bit depth:
The LZW encoder emits variable-length codes starting at minCodeSize + 1 bits, growing up to 12 bits. A Clear Code (2minCodeSize) resets the dictionary when the code table reaches 4096 entries. The End-of-Information code is Clear Code + 1.
eoiCode = clearCode + 1
Color quantization uses median-cut partitioning. The RGB color space is recursively bisected along its longest axis. For n target colors, the algorithm performs log2(n) splits, then maps each original pixel to the nearest centroid via Euclidean distance:
Frame delay in the Graphic Control Extension is stored as a 16-bit unsigned little-endian integer representing hundredths of a second:
Where r, g, b are RGB channel values, d is color distance, paletteSize is the number of quantized colors, and ms is the desired frame delay in milliseconds.
Reference Data
| Parameter | GIF89a Specification | Practical Notes |
|---|---|---|
| Max Colors per Frame | 256 (indexed palette) | Use dithering for photographic content |
| Color Table Size | 21 to 28 entries | Smaller tables reduce file size |
| Frame Delay Unit | 10ms increments | Delay = 0 treated as ~100ms by browsers |
| Min Reliable Delay | 20ms (50fps) | Chrome/Firefox clamp lower values |
| Recommended Delay | 50 - 100ms | 10 - 20fps is standard |
| LZW Min Code Size | 2 - 8 bits | Derived from color table size |
| LZW Max Code Size | 12 bits (4096 entries) | Table resets via Clear Code |
| Max Image Dimension | 65535×65535px | Practical limit ~1024px for web |
| Transparency | 1 color index per frame | Binary transparency only (no alpha) |
| Disposal Method 0 | No disposal specified | Renderer decides behavior |
| Disposal Method 1 | Do not dispose | Frame persists under next frame |
| Disposal Method 2 | Restore to background | Clears frame area before next |
| Disposal Method 3 | Restore to previous | Rarely supported correctly |
| Looping | Netscape Application Extension | 0 = infinite loop |
| Sub-block Size | Max 255 bytes per sub-block | Data split into chunks |
| File Signature | GIF89a (6 bytes) | GIF87a lacks animation support |
| Typical Web GIF Size | 64 - 320px | Emoji/reaction GIF sweet spot |
| Compression Ratio | ~40 - 60% | Flat colors compress best |
| Max Practical Frames | No spec limit | 50 - 100 frames for reasonable file size |
| Interlacing | 4-pass Adam7-like scheme | Rarely used for animated GIFs |