ongteckwu/pyjamaz
High-Performance Image Optimizer for Python, Nodejs, Zig, CLI
refsBlazing-fast CLI tool for optimizing images with perceptual quality guarantees. Built with Zig using Tiger Style methodology.
| Metric | Result |
|---|---|
| Test Coverage | 73/73 unit tests (100%), 196/211 conformance (93%) |
| Memory Safety | 0 leaks detected (verified with testing.allocator) |
| Performance | 50-100ms per image (5x better than 500ms target) |
| Parallel Speedup | 1.2-1.4x faster with 4 cores |
| Compression | 87.4% average size reduction (12.6% of original) |
| Regressions | 0% - original file baseline prevents size increases |
| Formats | 4 (JPEG, PNG, WebP, AVIF) |
| Metrics | 2 perceptual (DSSIM, SSIMULACRA2) + size constraints |
From Homebrew (coming soon):
brew install pyjamaz
From Source:
# Install dependencies (macOS)
brew install vips jpeg-turbo dssim
# Build
git clone https://github.com/yourusername/pyjamaz.git
cd pyjamaz
zig build
# Run
./zig-out/bin/pyjamaz input.jpg -o output.jpg --max-bytes 100000
# Optimize single image with size constraint
pyjamaz input.jpg -o output.jpg --max-bytes 100000
# Optimize with quality constraint (SSIMULACRA2)
pyjamaz input.png -o output.webp --max-diff 0.002 --metric ssimulacra2
# Batch optimize directory
pyjamaz src/ -o optimized/ --max-bytes 50000
# Generate JSON manifest
pyjamaz input.jpg --manifest results.jsonl
# Use caching for 15-20x speedup
pyjamaz input.jpg --max-bytes 100000
# Second run: instant cache hit! โก
# Custom cache settings
pyjamaz input.jpg --cache-dir /tmp/cache --cache-max-size 2147483648
Pyjamaz can also be used as a Python library for programmatic image optimization:
import pyjamaz
# Optimize with size constraint
result = pyjamaz.optimize_image(
'input.jpg',
max_bytes=100_000, # 100KB max
)
if result.passed:
result.save('output.jpg')
print(f"Optimized to {result.size:,} bytes")
Features:
Installation:
# Install from PyPI
uv pip install pyjamaz-optimizer
# Or install from source
cd bindings/python
uv pip install -e .
# Run examples
uv run python examples/basic.py
uv run python examples/batch.py
Complete documentation: See Python API Reference for detailed usage, examples, and integration guides.
Pyjamaz can also be used from Node.js with full TypeScript support:
import * as pyjamaz from "@pyjamaz/nodejs";
// Optimize with size constraint
const result = await pyjamaz.optimizeImage("input.jpg", {
maxBytes: 100_000,
});
if (result.passed) {
await result.save("output.jpg");
console.log(`Optimized to ${result.size} bytes`);
}
Features:
Installation:
# Install Node.js bindings
cd bindings/nodejs
npm install
npm run build
# Run examples
npm run build && node dist/examples/basic.js
npx ts-node examples/basic.ts
Complete documentation: See Node.js API Reference for detailed usage, examples, and integration guides.
Python: Production-ready bindings with automatic memory management
Node.js: TypeScript-first bindings with full type safety
Note: TIFF format is not supported. Pyjamaz focuses exclusively on web image formats. To optimize TIFF files, convert them to PNG first using ImageMagick or similar tools.
--metric none)15-20x speedup on repeated optimizations with content-addressed caching:
Cache location:
~/.cache/pyjamaz/ or $XDG_CACHE_HOME/pyjamaz/%LOCALAPPDATA%\pyjamaz\cache\Cache management:
# View cache size
du -sh ~/.cache/pyjamaz
# Clear cache manually
rm -rf ~/.cache/pyjamaz
# Cache will auto-evict oldest entries when limit reached
--sharpen auto)--flatten #FFFFFF)-v, -vv, -vvv)Platform: Apple M1 Pro, macOS 15.0, libvips 8.17.0
| Image Size | Sequential | Parallel (4 cores) | Speedup | With Cache |
|---|---|---|---|---|
| 100KB PNG | 80ms | 67ms | 1.2x | 5ms |
| 500KB JPEG | 120ms | 100ms | 1.2x | 7ms |
| 2MB PNG | 200ms | 143ms | 1.4x | 10ms |
Result: 5x faster than MVP target (500ms) โ
Conformance Test Results (211 images):
| Test Suite | Pass Rate | Avg Compression | Notes |
|---|---|---|---|
| Kodak | 24/24 (100%) | 9.3% of original | Photographic images |
| PNGSuite | 162/176 (92%) | High reduction | 14 intentionally corrupt files |
| WebP Gallery | 5/5 (100%) | No regression | Already optimal |
| TestImages | 2/3 (67%) | 15.5% of original | 1 TIFF skipped (not supported) |
| Overall | 196/211 (93%) | 12.6% of original (87.4% reduction) | 15 correctly skipped |
testing.allocatorโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 1. Decode & Normalize (libvips) โ
โ โข Load from disk or memory buffer โ
โ โข Auto-rotate via EXIF metadata โ
โ โข Convert to sRGB color space โ
โ โข Format detection from magic numbers โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 2. Cache Lookup (Blake3 hash) โ
โ โข Compute key from (input + options) โ
โ โข Check cache for existing result โ
โ โข Return if cache hit (15-20x faster!) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 3. Generate Candidates (Parallel) โ
โ Thread 1: AVIF encoding โโ โ
โ Thread 2: WebP encoding โโผโโโ Candidate Pool โ
โ Thread 3: JPEG encoding โโค โ
โ Thread 4: PNG encoding โโ โ
โ PLUS: Original file (baseline) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 4. Score Candidates (Perceptual Metrics) โ
โ โข Calculate DSSIM or SSIMULACRA2 diff โ
โ โข Filter: diff_score โค max_diff โ
โ โข Filter: file_size โค max_bytes โ
โ โข Keep only candidates passing all constraints โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 5. Select Best Candidate โ
โ โข Pick smallest passing candidate โ
โ โข Tiebreak by format preference โ
โ โข Cache result for future use โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 6. Output โ
โ โข Write optimized file โ
โ โข Generate JSONL manifest (optional) โ
โ โข Return result with timing metrics โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
pyjamaz/
โโโ src/
โ โโโ optimizer.zig # Core optimization pipeline
โ โโโ cache.zig # Content-addressed caching (680 LOC)
โ โโโ vips.zig # libvips FFI bindings
โ โโโ codecs.zig # Multi-format encoding
โ โโโ image_ops.zig # Image operations
โ โโโ search.zig # Binary search for quality
โ โโโ metrics.zig # Perceptual quality metrics
โ โ โโโ dssim.zig # DSSIM FFI bindings
โ โ โโโ ssimulacra2.zig # SSIMULACRA2 native impl
โ โโโ cli.zig # Command-line interface
โ โโโ test/ # Test suites
โ โโโ unit/ # 73 unit tests
โ โโโ integration/ # Integration tests
โ โโโ benchmark/ # Performance benchmarks
โโโ testdata/ # 211 conformance test images
โโโ docs/ # Comprehensive documentation
| Category | Count | Pass Rate | Status |
|---|---|---|---|
| Unit Tests | 73 | 100% (73/73) | โ All passing |
| Conformance Tests | 211 | 93% (196/211) | โ Excellent |
| Memory Leak Tests | All | 0 leaks | โ Clean |
| Integration Tests | 8 | 100% (8/8) | โ All passing |
Skipped Tests:
# All unit tests
zig build test
# Conformance tests (211 images)
zig build conformance # Fast mode (~3s, size checks only)
zig build conformance -Denable-dssim # With DSSIM quality checks (~15-20s)
# Integration tests
zig build test-integration
# Memory tests (CI/CD recommended)
zig build memory-test # Zig memory tests (~1 min)
zig build memory-test-zig # Same as above
# Benchmarks
zig build benchmark
# Specific module
zig build test -Dtest-filter=optimizer
Fast Mode (default, ~3s):
zig build conformance
DSSIM Mode (thorough, ~15-20s):
zig build conformance -Denable-dssim
Why 15 Tests are Skipped:
xc*: Invalid color typexd*: Invalid bit depthxs*: Invalid PNG signaturexh*: Invalid headerxlf*: Invalid chunk lengthThese files are correctly skipped - attempting to optimize corrupt/unsupported files would be an error.
The Node.js and Python memory tests are available but require manual setup:
Node.js Memory Tests:
# Prerequisites
zig build # Build library first
cd bindings/nodejs
npm install # If not done already
# Run tests
node --expose-gc tests/memory/gc_verification_test.js
node tests/memory/ffi_memory_test.js
node tests/memory/error_recovery_test.js
node tests/memory/buffer_memory_test.js
Python Memory Tests:
# Prerequisites
zig build # Build library first
uv pip install psutil # Optional: for better memory tracking
# Run tests
cd bindings/python
uv run python tests/memory/gc_verification_test.py
uv run python tests/memory/ctypes_memory_test.py
uv run python tests/memory/error_recovery_test.py
uv run python tests/memory/buffer_memory_test.py
Expected Results:
Note: If tests fail with module not found errors, set the library path:
export PYJAMAZ_LIB_PATH=/path/to/pyjamaz/zig-out/lib/libpyjamaz.dylib
See docs/MEMORY_TESTS.md for detailed troubleshooting.
---
## ๐ Documentation
### Guides
- **[TODO Roadmap](docs/TODO.md)** - Development roadmap and milestones
- **[Contributing Guide](docs/CONTRIBUTING.md)** - How to contribute
- **[Tiger Style Guide](docs/TIGER_STYLE_APPLICATION.md)** - Coding standards
- **[Quick Start](docs/QUICKSTART.md)** - Getting started guide
### API Documentation
- **[Python API Reference](docs/PYTHON_API.md)** - Complete Python bindings documentation
- Installation and setup
- API reference with all parameters
- Usage examples (basic, batch, Flask, FastAPI)
- Performance tips and troubleshooting
- **[Node.js API Reference](docs/NODEJS_API.md)** - Complete Node.js/TypeScript bindings documentation
- Installation and setup
- TypeScript-first API with full type definitions
- Usage examples (async/sync, batch, Express, Fastify)
- Integration guides and troubleshooting
### Implementation Details
- **[Performance Optimizations](docs/OPTIMIZATIONS.md)** - Complete optimization guide
- **[Perceptual Metrics Design](docs/PERCEPTUAL_METRICS_DESIGN.md)** - DSSIM & SSIMULACRA2
- **[Parallel Optimization](docs/PARALLEL_OPTIMIZATION.md)** - Thread pool design
- **[Test Suites](docs/TEST_SUITES.md)** - Conformance test tracking
- **[RFC Documents](docs/RFC.md)** - Design decisions
---
## ๐ฏ Tiger Style Methodology
Pyjamaz follows [Tiger Style](https://github.com/tigerbeetle/tigerbeetle/blob/main/docs/TIGER_STYLE.md) for safety and predictability:
### 1. Safety First โ
```zig
pub fn optimizeImage(allocator: Allocator, job: OptimizationJob) !OptimizationResult {
// Pre-conditions (4 assertions)
std.debug.assert(job.formats.len > 0);
std.debug.assert(job.concurrency > 0);
std.debug.assert(job.input_path.len > 0);
std.debug.assert(job.output_path.len > 0);
// ... rest of function
}
```
- **2+ assertions per function**: Validate inputs, outputs, invariants
- **Bounded loops**: No `while(true)`, explicit MAX constants
- **Explicit error handling**: `try` or explicit `catch`, never silent failures
### 2. Predictable Performance โ
```zig
const MAX_ITERATIONS: u8 = 7; // log2(100 quality levels) โ 6.6
while (iteration < MAX_ITERATIONS and q_min <= q_max) : (iteration += 1) {
// Binary search converges in โค7 iterations guaranteed
}
std.debug.assert(iteration <= MAX_ITERATIONS);
```
- **Bounded operations**: All loops and allocations have explicit limits
- **Back-of-envelope calculations**: Performance claims documented
- **Static allocation**: Prefer stack over heap where possible
### 3. Developer Experience โ
- **Functions โค70 lines**: Easy to understand and review
- **Clear naming**: `binarySearchQuality` not `binSearch`
- **Documentation**: Explain WHY, not WHAT
### 4. Minimal Dependencies โ
- **Only Zig stdlib + system libraries**: libvips, libjpeg-turbo, libdssim
- **Pure Zig implementation**: Except for codec/metric system libraries
- **Justification**: System libraries are battle-tested and industry-standard
---
## ๐ค Contributing
Contributions welcome! Pyjamaz is built to be contributor-friendly.
### Quick Start
1. **Find a task**: Check [docs/TODO.md](docs/TODO.md)
2. **Follow Tiger Style**: See [docs/TIGER_STYLE_APPLICATION.md](docs/TIGER_STYLE_APPLICATION.md)
3. **Write tests**: >80% coverage, use `testing.allocator`
4. **Format & test**: `zig fmt src/` then `zig build test`
### Development Workflow
```bash
# Fork and clone
git clone https://github.com/yourusername/pyjamaz.git
cd pyjamaz
# Create feature branch
git checkout -b feature/my-feature
# Make changes (follow Tiger Style)
# - 2+ assertions per function
# - Functions โค70 lines
# - Bounded loops with MAX constants
# Write tests
# src/test/unit/my_module_test.zig
# Run checks
zig build test
zig build conformance
zig fmt src/
# Commit and push
git commit -m "feat: Add awesome feature
- Implemented X with Y approach
- Added Z tests
- Performance: <100ms"
git push origin feature/my-feature
```
See [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) for detailed guidelines.
---
## ๐ Roadmap
See [docs/TODO.md](docs/TODO.md) for the complete development roadmap.
**Current Focus** (v1.0.0):
- โ
Core engine stable (73/73 tests passing)
- โ
Caching layer (15-20x speedup)
- โ
Python bindings complete (automatic memory management, comprehensive tests)
- โ
Node.js bindings complete (TypeScript-first, sync/async APIs, 30+ tests)
- ๐ Replace libvips with native decoders (2-5x performance improvement)
- โณ Homebrew distribution (`brew install pyjamaz`)
- โณ Production polish (fuzzing, security audit)
**Future** (v1.1.0+):
- Watch mode (re-optimize on file changes)
- JSON output mode (machine-readable)
- Progress bars for batch operations
- Config file support (`.pyjamazrc`)
---
## ๐ Acknowledgments
- **[Zig Language](https://ziglang.org/)** - Safe, fast systems programming
- **[TigerBeetle](https://github.com/tigerbeetle/tigerbeetle)** - Tiger Style inspiration
- **[libvips](https://www.libvips.org/)** - Fast image processing library
- **[PNGSuite](http://www.schaik.com/pngsuite/)** - Comprehensive PNG test images
- **[fssimu2](https://github.com/rust-av/ssimulacra2)** - SSIMULACRA2 implementation
---
## ๐ License
MIT License - see [LICENSE](./LICENSE) for details.
---
## ๐ Star History
If Pyjamaz helps you, please consider giving it a star! โญ
---
## ๐ฌ Contact
- **Issues**: [GitHub Issues](https://github.com/yourusername/pyjamaz/issues)
- **Discussions**: [GitHub Discussions](https://github.com/yourusername/pyjamaz/discussions)
---
**Last Updated**: 2025-10-31 (Python & Node.js bindings complete!)
**Current Version**: 1.0.0-dev (CLI + Python + Node.js bindings)
**Status**: Pre-1.0 (core stable, bindings ready, optimizing performance)
๐ **Happy optimizing!**