A high-performance CLI tool for stripping JPEG metadata and optimizing image size, written in Rust.
Think of it as a simplified, self-hosted alternative to tinyjpg.com.
- Blazing fast - Concurrent processing with configurable parallelism
- Download & optimize - Process both local files and remote URLs
- Flexible configuration - Configure via file, environment variables, or CLI args
- Detailed logging - Track performance with execution time logs
- Quality control - Adjustable JPEG quality (1-100)
Input Files
↓
┌─────────────────┐
│ Parse & Classify│
└────────┬────────┘
↓
┌────┴────┐
↓ ↓
┌────────┐ ┌─────────┐
│ URLs │ │ Locals │
│ Vec │ │ Vec │
└───┬────┘ └────┬────┘
↓ ↓
┌────────┐ (skip download)
│Download│ ↓
│ Bytes │ ┌──────────────┐
└───┬────┘ │ Optimize & │
↓ │ Save (CPU) │
└────→ │ - Decode │
│ - Strip meta │
│ - Re-encode │
└──────────────┘
↓
Output Directory
Key Design:
- Input is split into two vectors:
VecLinks(URLs) andVecLocal(local files) - Either vector can be empty
- URLs are downloaded first (I/O-bound), then optimized
- Local files go directly to optimization (CPU-bound)
- Both processes run in parallel using tokio + semaphore for concurrency control
# Clone the repository
git clone https://github.com/yourusername/strip-jpeg.git
cd strip-jpeg
# Build release version
cargo build --release
# Binary will be at ./target/release/strip-jpeg# Optimize local images
strip-jpeg image1.jpg image2.jpg
# Download and optimize from URLs
strip-jpeg https://example.com/photo.jpg
# Mix local and remote
strip-jpeg photo.jpg https://example.com/image.jpg
# Read from stdin
echo "image1.jpg" | strip-jpeg
# Custom output directory and quality
strip-jpeg -o ./optimized -q 85 *.jpgstrip-jpeg [OPTIONS] [INPUTS]...
Arguments:
[INPUTS]... Input JPEG files or URLs
Options:
-c, --config <FILE> Path to configuration file
-o, --output-dir <DIR> Output directory [default: ./out]
-q, --quality <0-100> JPEG quality [default: 80]
-j, --jobs <N> Parallel jobs [default: CPU cores]
-i, --input-file <FILE> Read inputs from file
-h, --help Print help
-V, --version Print versionConfiguration priority (highest to lowest):
- CLI arguments
- Environment variables
- Configuration file
- Defaults
Create config.toml:
output_dir = "./optimized"
quality = 85
jobs = 4Use it:
strip-jpeg -c config.toml image.jpgexport STRIP_JPEG_OUTPUT_DIR="./output"
export STRIP_JPEG_QUALITY=90
export STRIP_JPEG_JOBS=8
strip-jpeg image.jpgControl log verbosity with RUST_LOG:
# Show all debug logs
RUST_LOG=debug strip-jpeg image.jpg
# Only info and above
RUST_LOG=info strip-jpeg image.jpg
# Module-specific logging
RUST_LOG=strip_jpeg=debug,tokio=info strip-jpeg image.jpg# Optimize with default settings (quality 80)
strip-jpeg photo.jpg
# Set custom quality
strip-jpeg -q 90 photo.jpg
# Process multiple files
strip-jpeg *.jpg# Single URL
strip-jpeg https://example.com/image.jpg
# Multiple URLs
strip-jpeg \
https://example.com/photo1.jpg \
https://example.com/photo2.jpg# From file list
cat images.txt
image1.jpg
image2.jpg
https://example.com/photo.jpg
strip-jpeg -i images.txt
# Or via stdin
find . -name "*.jpg" | strip-jpeg -o ./optimized# Limit concurrent processing to 4 jobs
strip-jpeg -j 4 *.jpg
# Maximize parallelism (use all CPU cores)
strip-jpeg -j $(nproc) *.jpg
# With detailed timing logs
RUST_LOG=info strip-jpeg *.jpgSample output with timing logs:
INFO Strip-JPEG v1.0 started
INFO Found 2 URLs and 3 local files
INFO Processing 3 local files
INFO Optimized: "./out/photo1.jpg" in 45.23ms
INFO Optimized: "./out/photo2.jpg" in 52.11ms
INFO Optimized: "./out/photo3.jpg" in 48.77ms
INFO Processed 3 images: 3 successful, 0 failed
INFO Downloading 2 URLs
INFO Downloaded 245678 bytes in 123.45ms
INFO Processed 2 images: 2 successful, 0 failed
INFO Completed in 0.89s
- tokio - Async runtime
- clap - CLI argument parsing
- image - Image processing
- reqwest - HTTP client for downloads
- config - Hierarchical configuration
- tracing - Structured logging
- anyhow - Error handling