Skip to main content

Perceptual, policy-driven image optimization engine for modern workflows

Project description

perceptimg

perceptimg

Perceptual, policy-driven image optimization for modern workflows

PyPI Version Python Versions License CI Status Coverage

GitHub Stars GitHub Issues Buy Me a Coffee


Overview

perceptimg is a Python library for perceptual, policy-driven image optimization. Unlike traditional tools that optimize for file size or a single quality knob, perceptimg analyzes image content, interprets declarative policies, tests multiple strategies, and selects the best candidate based on perceptual quality metrics.

Key Features

Feature Description
Policy-Driven Declarative constraints for size, quality, and use case
Content-Aware Analyzes images for text, faces, and edge density
Multi-Format JPEG, PNG, WebP, AVIF, JXL, HEIF, GIF, TIFF, APNG
Perceptual Metrics SSIM, PSNR, and weighted perceptual scoring
Explainable Results Full decision trail for every optimization
Batch Processing Parallel processing with progress callbacks
Enterprise Ready Checkpointing, retry, rate limiting, Prometheus metrics
Clean Architecture Dependency inversion, modular engines, extensible

Supported Formats

Core Formats     JPEG, PNG, TIFF, GIF (always available via Pillow)
Modern Formats   WebP, AVIF, JPEG XL (JXL), HEIF/HEIC, APNG (codec-dependent)

Installation

From PyPI (Recommended)

pip install perceptimg

From Source

git clone https://github.com/seifreed/perceptimg.git
cd perceptimg
python3 -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate
pip install -e ".[dev]"

Quick Start

from perceptimg import optimize, Policy

# Define policy constraints
policy = Policy(
    max_size_kb=150,
    min_ssim=0.97,
    preserve_text=True,
    target_use_case="web"
)

# Optimize image
result = optimize("input.png", policy)

# Access results
print(f"Format: {result.report.chosen_format}")
print(f"Size: {result.report.size_before_kb:.1f}KB → {result.report.size_after_kb:.1f}KB")
print(f"SSIM: {result.report.ssim:.4f}")
print(f"Reasons: {result.report.reasons}")

Usage

Command Line Interface

# Basic optimization
perceptimg optimize input.png --policy policy.json --out output.webp

# With inline constraints
perceptimg optimize input.png --max-size-kb 100 --min-ssim 0.95 --formats webp,avif

# JSON output
perceptimg optimize input.png --policy policy.json --log-json

Available Options

Option Description
--policy Path to JSON policy file
--out Output file path
--max-size-kb Maximum output size in KB
--min-ssim Minimum SSIM threshold (0.0-1.0)
--formats Preferred formats (comma-separated)
--preserve-text Prefer text clarity
--preserve-faces Prefer face quality
--log-json Structured JSON logging
--log-level Log level (DEBUG, INFO, WARNING)

Policy Configuration

Python API

from perceptimg import Policy

policy = Policy(
    max_size_kb=120,
    min_ssim=0.98,
    preserve_text=True,
    preserve_faces=True,
    allow_lossy=True,
    preferred_formats=("webp", "avif", "jpeg"),
    target_use_case="mobile",
)

JSON Configuration

{
  "max_size_kb": 150,
  "min_ssim": 0.97,
  "preserve_text": true,
  "preserve_faces": false,
  "allow_lossy": true,
  "preferred_formats": ["webp", "avif", "jpeg"],
  "target_use_case": "web"
}

Batch Processing

Basic Batch

from perceptimg import Policy, optimize_batch

policy = Policy(max_size_kb=100, min_ssim=0.9)
images = ["img1.png", "img2.png", "img3.png"]

result = optimize_batch(images, policy)
print(f"Success: {len(result.successful)}/{result.total}")
print(f"Success rate: {result.success_rate:.1%}")

Async Processing

import asyncio
from perceptimg import Policy, optimize_batch_async

async def main():
    policy = Policy(max_size_kb=100)
    result = await optimize_batch_async(images, policy)
    print(f"Processed {result.total} images")

asyncio.run(main())

Memory-Efficient Streaming

from perceptimg import Policy, optimize_lazy

policy = Policy(max_size_kb=100)

for path, result in optimize_lazy(large_image_list, policy):
    if isinstance(result, Exception):
        print(f"Error {path}: {result}")
    else:
        print(f"OK {path}: {result.report.size_after_kb:.1f}KB")

Enterprise Features

Checkpoint/Resume

from perceptimg import Policy, optimize_batch_with_checkpoint

result = optimize_batch_with_checkpoint(
    images,
    policy,
    checkpoint_path="checkpoint.json",
    checkpoint_interval=10,  # Save every 10 images
)
# Resume after interruption by calling again with same checkpoint_path

Retry with Exponential Backoff

from perceptimg import Policy, optimize_batch_with_retry
from perceptimg.core.retry import RetryConfig

retry_config = RetryConfig(max_retries=3, base_delay_ms=100)

result = optimize_batch_with_retry(
    images,
    policy,
    retry_config=retry_config,
    continue_on_error=True,
)

Rate Limiting

from perceptimg import Policy, optimize_batch_with_rate_limit
from perceptimg.core.rate_limiter import RateLimitConfig

rate_limit = RateLimitConfig(requests_per_second=5)

result = optimize_batch_with_rate_limit(
    images,
    policy,
    rate_limit=rate_limit,
)

Prometheus Metrics

from perceptimg import Policy, optimize_batch_with_metrics
from perceptimg.core.metrics_exporter import MetricsCollector

metrics = MetricsCollector()
result, stats = optimize_batch_with_metrics(images, policy, metrics=metrics)

print(f"Average SSIM: {stats['average_ssim']:.2f}")
print(f"Compression ratio: {stats['average_compression_ratio']:.1%}")

Architecture

perceptimg/
├── adapters/           # Framework adapters (PIL)
│   └── pil_adapter.py
├── core/               # Domain logic
│   ├── interfaces.py   # Abstractions (ImageAdapter Protocol)
│   ├── analyzer.py     # Content analysis
│   ├── metrics.py      # SSIM, PSNR, perceptual scoring
│   ├── optimizer.py    # Orchestration
│   ├── policy.py       # Declarative constraints
│   ├── strategy.py     # Candidate generation
│   └── batch/          # Batch processing
├── engines/            # Format-specific encoders
│   ├── webp_engine.py
│   ├── avif_engine.py
│   └── ...
└── utils/              # IO, heuristics, logging

Clean Architecture Compliance

Layer Responsibility
Core Business logic, domain models, policies
Adapters Framework-specific implementations
Engines Format-specific encoding
Utils Infrastructure services

Extensibility

Custom Optimization Engine

from perceptimg.engines.base import OptimizationEngine, EngineResult
from perceptimg.core.optimizer import Optimizer, register_engine

class MyCustomEngine(OptimizationEngine):
    format = "custom"
    priority = 100
    
    @property
    def is_available(self) -> bool:
        return True
    
    def optimize(self, image, strategy) -> EngineResult:
        # Custom optimization logic
        return EngineResult(data=optimized_bytes, format="custom", quality=90)

# Register custom engine
optimizer = Optimizer()
register_engine(optimizer, MyCustomEngine())

Custom Analyzer

from perceptimg.core.analyzer import Analyzer

class CustomAnalyzer(Analyzer):
    def analyze(self, image):
        result = super().analyze(image)
        # Add custom heuristics
        result.custom_score = self._compute_custom(image)
        return result

API Reference

OptimizationResult

Field Type Description
image_bytes bytes Optimized image data
image PIL.Image Pillow image object
report OptimizationReport Detailed results

OptimizationReport

Field Type Description
chosen_format str Selected format
quality int Quality setting
size_before_kb float Original size
size_after_kb float Optimized size
ssim float SSIM score
psnr float PSNR score
perceptual_score float Weighted quality score
reasons list[str] Decision trail

Requirements

  • Python 3.13+
  • Pillow (PIL fork)
  • NumPy
  • scikit-image
  • See pyproject.toml for full dependencies

Quality

This project enforces:

Tool Purpose
ruff Linting
black Formatting
mypy Type checking
bandit Security analysis
pytest Testing (145 tests)
# Run all quality checks
ruff check perceptimg tests
black perceptimg tests --check
mypy perceptimg --ignore-missing-imports
bandit -r perceptimg -q --exclude perceptimg/tests
pytest tests/

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Support the Project

If you find perceptimg useful, consider supporting its development:

Buy Me A Coffee

License

This project is licensed under the MIT License - see the LICENSE file for details.

Attribution Required:


Made with dedication for the image optimization community

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

perceptimg-0.1.0.tar.gz (67.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

perceptimg-0.1.0-py3-none-any.whl (69.7 kB view details)

Uploaded Python 3

File details

Details for the file perceptimg-0.1.0.tar.gz.

File metadata

  • Download URL: perceptimg-0.1.0.tar.gz
  • Upload date:
  • Size: 67.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for perceptimg-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e4d6edc9cf4be875d677d3483717cb537f011a84133f6659237dc5188ec642fe
MD5 8cce7716aebc15f8bf8ec5083ee3e44a
BLAKE2b-256 12378aa4c4db40d650c61cab65b4399f657c077fe25659f386bd1faaa8702128

See more details on using hashes here.

File details

Details for the file perceptimg-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: perceptimg-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 69.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for perceptimg-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 091edd734be23c5345206bc2c97c5b8d18e74a6a136466398949b9645b8f6862
MD5 7c4e69591eff4a828ed5317fe098fdaf
BLAKE2b-256 d2c2ffa279629ebcdc7e6fe240aafc149d76b373b0fbf5c9ffc53731ee020903

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page