Intelligently compress images while preserving visual quality
Compress smarter, not harder. Let AI choose the perfect quality for your images.
π¦ Installation β’ π Quick Start β’ π Documentation β’ β Why Pixiq?
π― Smart Quality Selection - Automatically finds the optimal compression quality to match your target visual quality
πΌοΈ Multiple Formats - Supports JPEG, PNG, WEBP, and AVIF with format-specific optimizations
π Intelligent Resizing - Resize images while maintaining aspect ratio and quality
π Thumbnail Generation - Create smaller versions of compressed images instantly
π¨ Alpha Channel Support - Handles transparent images correctly for each format
β‘ Performance Optimized - Fast compression with efficient memory usage
π§© Tile-Based Quality Check - PSNR analysis performed on image tiles for fast quality assessment
π‘οΈ Robust Validation - Comprehensive input validation and error handling
π Quality Metrics - Detailed compression statistics and iteration info
Using uv (fastest):
uv add pixiq
# or
uv pip install pixiqUsing pip:
pip install pixiqgit clone https://github.com/yourusername/pixiq.git
cd pixiq
# Using uv
uv sync --dev
uv pip install -e .
# Using pip
pip install -e .- Python 3.9+
- PIL (Pillow) - Image processing
- NumPy - Array operations
- pillow-avif-plugin - AVIF format support
π‘ Tip: uv is significantly faster than pip and provides better dependency management.
Try it now! Run the interactive demo:
python example.pyfrom PIL import Image
from pixiq import Pixiq
# Open your image
image = Image.open('photo.jpg')
# Compress with target quality
result = Pixiq.compress(image, perceptual_quality=0.9)
print(f"β
Compressed! Size: {result.file_size_kb:.1f} KB, Quality: {result.selected_quality}")# Compress with custom settings
result = Pixiq.compress(
input=image,
perceptual_quality=0.85, # Target visual quality (0.0-1.0)
max_size=2000, # Resize if larger than 2000px
format='WEBP', # Force WEBP format
hash_type='sha1', # Use SHA1 instead of default SHA256
output='compressed.webp' # Save to file
)
# Access compression details
print(f"π Quality: {result.selected_quality}/100")
print(f"π Dimensions: {result.dimensions}")
print(f"πΎ Size: {result.file_size_kb:.1f} KB")
print(f"π Hash ({result.hash_type}): {result.hash}")
print(f"π― Achieved quality: {result.best_iteration['perceptual_quality']:.3f}")# Create a thumbnail from compressed image
thumbnail = result.save_thumbnail(
max_size=500,
output='thumbnail.webp'
)
print(f"πΌοΈ Thumbnail: {thumbnail.dimensions}, {thumbnail.file_size_kb:.1f} KB")The main method for intelligent image compression with automatic quality selection.
| Parameter | Type | Default | Description |
|---|---|---|---|
input |
PIL Image | required | Input image to compress |
perceptual_quality |
float | 0.95 |
Target visual quality (0.0-1.0) |
tolerance |
float | 0.005 |
Quality tolerance for convergence |
max_quality |
int | None |
Maximum compression quality (1-100) |
min_quality |
int | None |
Minimum compression quality (1-100) |
max_size |
int | None |
Maximum dimension (resizes if larger) |
max_iter |
int | 5 |
Maximum binary search iterations |
format |
str | None |
Force format: 'JPEG', 'PNG', 'WEBP', 'AVIF' |
hash_type |
str | 'sha256' |
Hash algorithm: 'sha1', 'sha256', etc. |
output |
str/BytesIO | None |
Output file path or buffer |
CompressionResult - Object containing compressed image and metadata
TypeError- Invalid parameter typesValueError- Parameter values out of rangeOSError- File I/O errors
Container for compression results with convenient access methods.
| Property | Type | Description |
|---|---|---|
compressed |
PIL Image | The compressed image |
iterations_count |
int | Number of compression attempts |
iterations_info |
List[dict] | Detailed info for each iteration |
selected_quality |
int | Final compression quality (1-100) |
hash |
str | Hash of compressed image (SHA1/SHA256) |
hash_type |
str | Hash algorithm used ('sha1', 'sha256') |
file_size |
int | File size in bytes |
fmt |
str | Image format ('jpeg', 'webp', etc.) |
extra_save_args |
dict | Format-specific save parameters |
| Property | Type | Description |
|---|---|---|
file_size_kb |
float | File size in kilobytes |
dimensions |
tuple[int, int] | Image dimensions (width, height) |
best_iteration |
dict | None | Info about best quality match |
Save compressed image to file or buffer.
result.save('output.webp')
result.save(io.BytesIO())Create and save a resized version of the compressed image.
thumbnail = result.save_thumbnail(max_size=500, output='thumb.webp')Returns: New CompressionResult with resized image
| Format | Extension | Alpha Support | Optimization |
|---|---|---|---|
| JPEG | .jpg, .jpeg |
β | Progressive, optimized |
| PNG | .png |
β | Lossless compression |
| WEBP | .webp |
β | Method 6 (max compression) |
| AVIF | .avif |
β | Speed 6 (balanced) |
π‘ Tip: Pixiq automatically detects format from file extension or uses JPEG as fallback
Pixiq uses a smart binary search algorithm to find the optimal compression quality:
- π― Quality Search - Binary search over quality range (1-100) to find optimal compression
- π Tile-Based PSNR Analysis - Calculate Peak Signal-to-Noise Ratio on selected image tiles (not the entire image) for fast quality assessment. The algorithm automatically detects optimal tile size based on image type (UI vs photos) and selects tiles with the most color complexity for accurate quality measurement.
- π§ Perceptual Mapping - Convert PSNR to perceptual quality using empirical formula
- πͺ Best Match Selection - Choose quality with minimum error from target perceptual quality
- π Efficient Hashing - Generate SHA1/SHA256 hash from compressed data without re-encoding
Target Quality: 0.85
βββββββββββββββββββββββββββββββββββββββ
β Quality 1 βββββΊ Quality 100 β
β β β β β
β PSNR: 25.3 PSNR: 35.7 PSNR: 42.1 β
β Perceptual: 0.3 βββββΊ 0.8 βββββΊ 0.95 β
β β β β β
β ββββββββββββββββΌβββββββββββββββ β
β βΌ β
β β
Best Match β
β Quality: 67 β
β Error: 0.0012 β
βββββββββββββββββββββββββββββββββββββββ
Traditional image compression requires manual quality tuning:
# Old way - guesswork required
image.save('output.jpg', quality=85) # Is 85 good enough?
image.save('output.jpg', quality=75) # Too low quality?
image.save('output.jpg', quality=80) # Still guessing...Pixiq automatically finds the perfect quality for your needs:
# New way - specify what you want
result = Pixiq.compress(image, perceptual_quality=0.9)
# Automatically finds quality=67 for 90% perceptual quality!| Feature | Traditional | Pixiq |
|---|---|---|
| Quality Control | Manual guesswork | Precise target quality |
| File Size | Variable, unpredictable | Optimal for quality target |
| Time | Multiple manual attempts | Single API call |
| Consistency | Depends on user expertise | Consistent, reproducible |
| Formats | One quality per format | Optimized per format |
Original: photo.jpg (2.3 MB, 4000x3000)
Target: 85% perceptual quality
Format Quality Size Time
JPEG 78 245 KB 0.8s
WEBP 82 198 KB 0.7s
AVIF 75 156 KB 1.2s
Run the comprehensive test suite:
# Install development dependencies (using uv - recommended)
uv sync --dev
# Or using pip
pip install -e ".[dev]"
# Run tests
uv run pytest tests/
# Or using pytest directly
pytest tests/
# Or run manually
python -c "from tests.test_pixiq import *; test_basic_compression()"π‘ Tip: Using uv sync --dev is the fastest way to set up the development environment!
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
MIT License - see LICENSE file for details.
- Built with Pillow for image processing
- Uses NumPy for efficient array operations
- Powered by uv for lightning-fast package management
- Inspired by modern image optimization techniques
Made with β€οΈ for developers who care about image quality
β Star us on GitHub β’ π Report Issues β’ π¬ Join Discussions