zengif
Server-side GIF codec with zero-trust design, memory bounds, streaming, and full animation transparency support.
Why zengif?
zengif combines streaming GIF codec capabilities with server-side production features:
| Feature | gif + gif-dispose | zengif |
|---|---|---|
| Streaming decode | ✅ | ✅ |
| Disposal + transparency | ✅ | ✅ |
| Memory limits | ✅ | ✅ |
| Cooperative cancellation | ❌ | ✅ |
| Error tracing (file:line) | ❌ | ✅ |
| Round-trip metadata | ❌ | ✅ |
| High-quality encode | ❌ | ✅ |
The gif crate provides excellent low-level GIF parsing with memory limits. gif-dispose adds disposal method handling. zengif wraps these and adds: cancellation support, error tracing with file:line info, and a unified API for encode/decode with metadata preservation.
Features
- Streaming decode/encode - Process GIFs without loading entire file into memory
- Complete animation support - All disposal methods (Keep, Background, Previous) + transparency working together
- Memory bounded - Configurable limits, reject oversized inputs before allocating
- Production ready - Error tracing via
whereat, cancellation viaenough - Zero-trust design - Validate headers, bounds-check frames, limit decompression ratio
- Round-trip fidelity - Frame timing, loop count, palette, and disposal methods preserved
- High-quality encoding - Optional imagequant integration for small file sizes
Quick Start
Decoding
use ;
use Unstoppable;
let limits = default
.max_dimensions
.max_frame_count;
let stats = new;
let cursor = new;
let mut decoder = new?;
while let Some = decoder.next_frame?
println!;
Encoding
use ;
use Unstoppable;
let config = new.repeat;
let limits = default;
let mut output = Vecnew;
let mut encoder = new?;
for frame in source_frames
encoder.finish?;
Round-Trip with Metadata
use ;
use Unstoppable;
let stats = new;
let mut decoder = new?;
let metadata = decoder.metadata.clone;
let mut encoder = from_metadata?;
while let Some = decoder.next_frame?
encoder.finish?;
With Cancellation
use Stopper;
use ;
let stop = new;
let stop_clone = stop.clone;
// In another thread/task:
stop_clone.cancel;
// Decoder will return GifError::Cancelled
let stats = new;
let decoder = new?;
Memory Limits
Protect against malicious inputs:
use Limits;
let limits = default
.max_dimensions // Max canvas size
.max_total_pixels // Max 64M pixels per frame
.max_frame_count // Max frames
.max_file_size // 500 MB
.max_memory; // 1 GB peak memory
Error Handling
Errors include location and context for debugging:
Error: InvalidFrameBounds { frame_left: 0, frame_top: 0, frame_width: 5000,
frame_height: 5000, canvas_width: 100, canvas_height: 100 }
at src/decode/frame.rs:142:9
╰─ validating frame 3
at src/decode/mod.rs:89:5
╰─ in decode_frame
Feature Flags
| Feature | Default | Description |
|---|---|---|
std |
✅ | Enable std library (disable for no_std+alloc) |
simd |
❌ | SIMD acceleration via wide/multiversed |
rgb-interop |
❌ | Interop with the rgb crate |
imgref-interop |
❌ | Interop with the imgref crate |
no_std / WASM Support
zengif supports no_std environments with alloc. Disable the default std feature:
[]
= { = "0.3", = false }
With std (default): Full codec - decoder, encoder, quantizers, heuristics.
Without std: Core types only - GifError, Limits, Stats, Rgba, Palette, ComposedFrame, Screen, Disposal. Useful for WASM or embedded where you process frames but use a different codec.
Verified targets: wasm32-unknown-unknown (144KB release build with decoder).
Color Quantization Backends
Choose one or more quantization backends for high-quality GIF encoding:
| Feature | License | Quality | Speed | Notes |
|---|---|---|---|---|
imagequant |
AGPL-3.0 | Best | Medium | Recommended - best quality AND smallest files (LZW-aware dithering), commercial license |
quantizr |
MIT | Good | Fast | Best MIT-licensed option |
color_quant |
MIT | Good | Fastest | High-throughput servers |
exoquant-deprecated |
MIT | Good | Slow | Deprecated - use quantizr instead |
Without any quantization feature, zengif is purely MIT/Apache-2.0 licensed.
Performance
Benchmarks on AMD Ryzen 9 5900X:
| Operation | Throughput |
|---|---|
| Decode (composited) | ~150 MB/s |
| Encode (quantized) | ~40 MB/s |
| Encode (pre-indexed) | ~200 MB/s |
AI-Generated Code Notice
Developed with Claude (Anthropic). Not all code manually reviewed. Review critical paths before production use.
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Dependency Licensing: imagequant (AGPL)
The optional imagequant feature uses libimagequant by Kornel Lesiński, which is licensed under AGPL-3.0. For closed-source projects, please purchase a commercial license — it's reasonably priced and supports continued development of excellent image optimization tools.
Alternative MIT-licensed quantizers: quantizr or color_quant for fully permissive licensing (slightly lower quality).
Without any quantization feature (the default), zengif has no AGPL dependencies and is purely MIT/Apache-2.0 licensed.