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
π‘οΈ 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
- π PSNR Analysis - Calculate Peak Signal-to-Noise Ratio between original and compressed images
- π§ 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