Zlib & Deflate
Zlib and Deflate are closely related formats based on the DEFLATE algorithm. They’re used extensively in PNG images, ZIP files, HTTP, and many other contexts.
Format Comparison
Section titled “Format Comparison”| Format | Description | Checksum | Auto-detect |
|---|---|---|---|
| Deflate | Raw DEFLATE stream | None | No |
| Zlib | DEFLATE + zlib header/trailer | Adler-32 | Yes |
| Gzip | DEFLATE + gzip header/trailer | CRC32 | Yes |
All three use the same compression algorithm but different wrappers.
Performance
Section titled “Performance”| Format | Compress | Decompress | Ratio |
|---|---|---|---|
| Deflate | 2.4 GB/s | 2.4 GB/s | 99.2% |
| Zlib | 2.4 GB/s | 2.4 GB/s | 99.2% |
When to Use Which
Section titled “When to Use Which”| Use Case | Format |
|---|---|
| PNG images | Zlib |
| ZIP files | Deflate (raw) |
| HTTP Content-Encoding | Gzip |
| Custom protocol | Deflate (minimal overhead) |
| Data integrity needed | Zlib (Adler-32) |
| General file compression | Gzip |
Zlib wraps DEFLATE with a small header and Adler-32 checksum.
Basic Usage
Section titled “Basic Usage”const cz = @import("compressionz");
// Compressconst compressed = try cz.compress(.zlib, data, allocator);defer allocator.free(compressed);
// Decompressconst decompressed = try cz.decompress(.zlib, compressed, allocator);defer allocator.free(decompressed);With Options
Section titled “With Options”// Compression levelconst best = try cz.compressWithOptions(.zlib, data, allocator, .{ .level = .best,});
// With dictionaryconst dict = try cz.compressWithOptions(.zlib, data, allocator, .{ .dictionary = my_dictionary,});Format Structure
Section titled “Format Structure”┌─────────────────────────────────────────────────────┐│ Zlib Header (2 bytes) ││ - CMF: compression method and flags ││ - FLG: flags (check bits, preset dict, level) ││ - [Dictionary ID] (4 bytes, if FDICT set) │├─────────────────────────────────────────────────────┤│ Compressed Data (DEFLATE) │├─────────────────────────────────────────────────────┤│ Adler-32 Checksum (4 bytes) │└─────────────────────────────────────────────────────┘Magic Bytes
Section titled “Magic Bytes”// Zlib detection (CMF * 256 + FLG must be divisible by 31)fn isZlib(data: []const u8) bool { if (data.len < 2) return false; const cmf = data[0]; const flg = data[1]; return (cmf & 0x0F) == 8 and // DEFLATE method (@as(u16, cmf) * 256 + flg) % 31 == 0;}Deflate
Section titled “Deflate”Raw DEFLATE stream without any wrapper.
Basic Usage
Section titled “Basic Usage”const cz = @import("compressionz");
// Compressconst compressed = try cz.compress(.deflate, data, allocator);defer allocator.free(compressed);
// Decompressconst decompressed = try cz.decompress(.deflate, compressed, allocator);defer allocator.free(decompressed);With Dictionary
Section titled “With Dictionary”Both Zlib and Deflate support dictionary compression:
const dictionary = "common patterns in your data...";
// Compress with dictionaryconst compressed = try cz.compressWithOptions(.deflate, data, allocator, .{ .dictionary = dictionary,});defer allocator.free(compressed);
// Decompress with same dictionaryconst decompressed = try cz.decompressWithOptions(.deflate, compressed, allocator, .{ .dictionary = dictionary,});defer allocator.free(decompressed);Format Structure
Section titled “Format Structure”┌─────────────────────────────────────────────────────┐│ DEFLATE Blocks ││ ││ Block Header (3 bits) ││ - BFINAL: 1 if last block ││ - BTYPE: block type (00=stored, 01=fixed, 10=dyn) ││ ││ Block Data ││ - Huffman-coded literals and length/distance pairs ││ ││ ... more blocks ... ││ ││ Final block (BFINAL=1) │└─────────────────────────────────────────────────────┘Dictionary Compression
Section titled “Dictionary Compression”Zlib and Deflate are the only codecs in compressionz (besides Zstd) that support dictionary compression.
How It Works
Section titled “How It Works”The dictionary provides a “seed” of common patterns that the compressor can reference:
// Without dictionary: compressor builds patterns from scratch// With dictionary: compressor starts with known patterns
const json_dict = \\{"id":,"name":,"email":,"created_at":,"updated_at": \\,"status":"active","status":"inactive","status":"pending" \\,"type":"user","type":"admin","type":"guest";
// Small JSON objects compress much better with dictionaryconst compressed = try cz.compressWithOptions(.zlib, json_data, allocator, .{ .dictionary = json_dict,});Dictionary Benefits
Section titled “Dictionary Benefits”| Data Size | Without Dict | With Dict | Improvement |
|---|---|---|---|
| 100 bytes | 95 bytes | 45 bytes | 53% smaller |
| 500 bytes | 380 bytes | 210 bytes | 45% smaller |
| 1 KB | 720 bytes | 520 bytes | 28% smaller |
| 10 KB | 6.5 KB | 5.8 KB | 11% smaller |
Dictionary compression is most effective for small data with predictable patterns.
Streaming
Section titled “Streaming”Both formats support streaming:
const cz = @import("compressionz");const std = @import("std");
// Streaming compressionpub fn compressStream(allocator: std.mem.Allocator, input: anytype, output: anytype) !void { var comp = try cz.compressor(.zlib, allocator, output, .{}); defer comp.deinit();
var buf: [65536]u8 = undefined; while (true) { const n = try input.read(&buf); if (n == 0) break; try comp.writer().writeAll(buf[0..n]); } try comp.finish();}
// Streaming decompressionpub fn decompressStream(allocator: std.mem.Allocator, input: anytype) ![]u8 { var decomp = try cz.decompressor(.zlib, allocator, input); defer decomp.deinit(); return decomp.reader().readAllAlloc(allocator, 1024 * 1024 * 1024);}Direct API Access
Section titled “Direct API Access”const cz = @import("compressionz");
// Zlibconst zlib_compressed = try cz.zlib_codec.compress(data, allocator, .default, .zlib);const zlib_decompressed = try cz.zlib_codec.decompress(compressed, allocator, .zlib);
// Deflateconst deflate_compressed = try cz.zlib_codec.compress(data, allocator, .default, .deflate);const deflate_decompressed = try cz.zlib_codec.decompress(compressed, allocator, .deflate);
// With dictionaryconst dict_compressed = try cz.zlib_codec.compressWithDict( data, allocator, .default, .zlib, dictionary);const dict_decompressed = try cz.zlib_codec.decompressWithDict( compressed, allocator, .zlib, max_size, dictionary);Algorithm Details
Section titled “Algorithm Details”DEFLATE Algorithm
Section titled “DEFLATE Algorithm”DEFLATE combines two compression techniques:
- LZ77 — Replace repeated sequences with (length, distance) pairs
- Huffman Coding — Use shorter codes for more frequent symbols
Input: "ABRACADABRA"
LZ77 output: A B R A C A D [match: length=4, distance=7] A (The "ABRA" at the end matches "ABRA" from 7 positions back)
Huffman coding: Assign short bit sequences to common symbols A=0, B=10, R=110, C=1110, D=11110, etc.Block Types
Section titled “Block Types”| Type | Name | Use Case |
|---|---|---|
| 00 | Stored | Incompressible data (passed through) |
| 01 | Fixed | Pre-defined Huffman codes |
| 10 | Dynamic | Custom Huffman codes per block |
Use Cases
Section titled “Use Cases”PNG Images
Section titled “PNG Images”PNG uses Zlib internally:
// PNG file structure (simplified)// IHDR chunk (image header)// IDAT chunk (zlib-compressed image data) <-- Zlib here// IEND chunk (end marker)ZIP Files
Section titled “ZIP Files”ZIP uses raw Deflate:
// ZIP local file header// Deflate-compressed file data <-- Raw Deflate here// Data descriptor (optional)Custom Protocols
Section titled “Custom Protocols”For minimal overhead, use raw Deflate:
fn sendCompressed(socket: *Socket, data: []const u8, allocator: Allocator) !void { // 4-byte size prefix + deflate data (no zlib overhead) const compressed = try cz.compress(.deflate, data, allocator); defer allocator.free(compressed);
var header: [4]u8 = undefined; std.mem.writeInt(u32, &header, @intCast(compressed.len), .little);
try socket.writeAll(&header); try socket.writeAll(compressed);}Comparison
Section titled “Comparison”| Aspect | Deflate | Zlib | Gzip |
|---|---|---|---|
| Overhead | 0 bytes | 6 bytes | 18+ bytes |
| Checksum | None | Adler-32 | CRC32 |
| Dictionary | ✅ | ✅ | ❌ |
| Auto-detect | ❌ | ✅ | ✅ |
| Use case | Embedding | Libraries | Files |