Pure Zig JPEG encoder/decoder. Zero dependencies.
zig build -Doptimize=ReleaseFast
zig build run -- encode input.ppm output.jpg --quality 85
zig build run -- encode input.ppm output.jpg --preset web
zig build run -- decode input.jpg output.ppm
Input/output uses PPM (P6) format. Convert with ImageMagick or ffmpeg:
convert photo.png photo.ppm # ImageMagick
ffmpeg -i photo.png photo.ppm # ffmpeg
const kiyo = @import("kiyo");
const jpeg = try kiyo.encodeJPEG(allocator, &image_data, .{
.quality = 75,
.fast_mode = false,
});
defer jpeg.deinit(allocator);
const image = try kiyo.decodeJPEG(allocator, jpeg.buffer, .{});
defer image.deinit(allocator);src/
root.zig public API
main.zig CLI entry point
types.zig pixel and block types
encoder.zig JPEG encoder
decoder.zig JPEG decoder
io.zig file I/O
presets.zig quality presets
core/
color_space.zig RGB <-> YCbCr
block_processor.zig 8x8 block splitting
dct.zig DCT / IDCT / fast DCT
quantization.zig quantize / dequantize
zigzag.zig zigzag reorder + RLE
encoding/
bitstream.zig bit-level writer
huffman.zig Huffman tables + encode
jpeg_writer.zig JPEG marker assembly
integration_tests.zig 227 tests
test/
benchmark.zig benchmarks
bench_pro.zig advanced benchmarks
verify.zig end-to-end validation
fuzz_encoder.zig encoder fuzz testing
fuzz_decoder.zig decoder fuzz testing
RGBA pixels
|
v
+--------------+
| RGB to YCbCr | 256-entry LUT, no f64 math
+--------------+
|
v
+--------------+
| Block Split | image into 8x8 blocks
+--------------+
|
v
+--------------+
| DCT | standard or fast (17x)
+--------------+
|
v
+--------------+
| Quantize | multiply by 1/q (no division)
+--------------+
|
v
+--------------+
| Zigzag + RLE | i16 path (no f64)
+--------------+
|
v
+--------------+
| Huffman | precomputed tables
+--------------+
|
v
+--------------+
| JPEG Write | markers + stuffed data
+--------------+
|
v
.jpg file
.jpg file
|
v
+--------------+
| Parse Header | SOI, DQT, SOF0, DHT, SOS
+--------------+
|
v
+--------------+
| Huffman Dec | bit reader + lookup
+--------------+
|
v
+--------------+
| Dequantize | scale back
+--------------+
|
v
+--------------+
| IDCT | frequency to spatial
+--------------+
|
v
+--------------+
| YCbCr to RGB | color reconversion
+--------------+
|
v
RGBA pixels
4:4:4 4:2:0
+------+------+------+------+ +------+------+------+------+
| Y | Y | Y | Y | | Y | Y | Y | Y |
+------+------+------+------+ | Y | Y | Y | Y |
| Y | Y | Y | Y | +------+------+------+------+
+------+------+------+------+ | Y | Y | Y | Y |
| Y | Y | Y | Y | | Y | Y | Y | Y |
+------+------+------+------+ +------+------+------+------+
Cb = 1 block per Y block Cb = 1 block per 4 Y blocks
Cr = 1 block per Y block Cr = 1 block per 4 Y blocks
DCT standard 2.8 us/block
DCT fast 0.2 us/block 17.2x faster
Quantize 0.1 us/block
Color convert 1.5 ms / 256x256
Full encode 19 ms / 256x256 3.3 Mpixels/s
name quality fast
---------------------------
thumbnail 30 yes
web 60 no
balanced 75 no
high 90 no
maximum 100 no
zig build test unit tests
zig build bench benchmarks
zig build verify end-to-end validation
zig build build CLI
zig build run -- help CLI usage
MIT