pixopt
A powerful, easy-to-use Python library and CLI tool for optimizing images for web and storage.
📖 Documentation • 📦 PyPI • 🏷️ Releases
Table of Contents
- Overview
- Features
- Installation
- Quick Start
- CLI Usage
- Library Usage
- API Reference
- Development
- Contributing
- Changelog
- Acknowledgements
- License
Overview
pixopt is a fast Python image optimizer designed for modern web workflows. It provides both a rich command-line interface (CLI) and a clean Python API to resize, compress, convert formats, generate responsive assets, extract lazy-loading placeholders, and detect the optimal format automatically.
Whether you are a developer automating image pipelines, a designer preparing assets, or a DevOps engineer optimizing static sites, pixopt handles the heavy lifting so you don't have to.
Features
- 🖼️ Format conversion — JPEG, PNG, WEBP, AVIF, GIF, HEIC/HEIF, SVG
- 🎞️ Animated GIF → WEBP — convert animated GIFs to much lighter animated WEBP
- 🧹 SVG minification — pure-Python SVG cleanup (no Node.js tools needed)
- 📱 HEIC/HEIF import — open iPhone photos directly via
pillow-heif - 🎯 Lossless mode — lossless PNG/WEBP compression for UI assets that need pixel-perfect fidelity
- 🔍 Adaptive quality — binary-search quality to hit a target file size automatically
- 📊 Visual comparison — generate interactive HTML before/after sliders
- 📐 Responsive srcset — generate multiple width variants and HTML
<img srcset="...">snippets - 🎨 Lazy-loading placeholders — extract dominant color, generate LQIP data URIs, or blurhash strings
- 🧠 Smart format detection — auto-detect the most efficient format (photo → WEBP, graphic → PNG, transparent → WEBP)
- 💾 Backup originals — copy originals to a backup directory before processing
- ⚡ Batch processing — optimize single files, directories, or multiple files at once
- �️ Watermarking — add text or image watermarks with position, opacity and tiling
- 🧩 Sprite sheets & contact sheets — pack images into CSS sprites or visual contact sheets
- 📦 Asset bundles — generate ready-to-deploy asset packages for the web
- 📄 PDF import/export — extract pages as images or bundle images into PDFs
- 🚀 Next-gen formats — produce JXL and AVIF outputs
- 🔎 Duplicate detection — find visually or exactly similar images
- 📁 Directory scanning — scan folders and produce reports with size savings
- 🥊 Format benchmark — compare size/quality across JPEG, PNG, WEBP, AVIF, JXL
- 🎨 Color palette — extract dominant color swatches from images
- 🌊 Async API — async versions of all major operations
- 🔡 Base64 & bytes I/O — optimize in-memory images for APIs and web services
- 🔐 Safety hardening — path validation, input limits, and resource leak protection
- �💻 Beautiful CLI — built with Typer for an intuitive command-line experience
Installation
Requirements
- Python: 3.10, 3.11, 3.12, 3.13, or 3.14
- Core dependencies: Pillow (>=12.3.0), pillow-heif, typer, rich, piexif, numpy
- Optional: PyMuPDF for PDF import/export (
pip install pixopt[pdf])
From PyPI
pip install pixopt
With HEIC/HEIF support
pillow-heif is included as a core dependency, so HEIC/HEIF support is available out of the box.
pip install pixopt
With PDF support
pip install "pixopt[pdf]"
From source
git clone https://github.com/MathiasPaulenko/pixopt.git
cd pixopt
pip install -e ".[dev,docs]"
Verify installation
pixopt --help
Quick Start
CLI
pip install pixopt
pixopt optimize photo.jpg --quality 80 --width 1200
Library
from pixopt import optimize_image
from pixopt.models import OutputFormat
result = optimize_image(
"photo.jpg",
"photo_optimized.webp",
max_width=1200,
quality=80,
output_format=OutputFormat.WEBP,
)
print(f"Saved {result.savings_percent:.1f}%")
CLI Usage
The CLI is built with Typer and provides an intuitive interface for all optimization features.
Commands
optimize
Optimize a single image or all images in a directory.
pixopt optimize photo.jpg photo_optimized.jpg --quality 80 --width 1200
pixopt optimize ./images ./optimized --recursive --quality 85 --format webp
batch
Optimize multiple specific files at once.
pixopt batch photo1.jpg photo2.png photo3.bmp -o ./optimized --width 800
convert
Convert an image to a different format or extension.
pixopt convert photo.png photo.webp -f webp
pixopt convert ./images ./webp_images -r -f webp
favicon
Convert an image to a multi-resolution ICO favicon.
pixopt favicon logo.png favicon.ico
pixopt favicon logo.png favicon.ico --size 16 --size 32 --size 48
info
Inspect image metadata without optimizing.
pixopt info photo.jpg
compare
Generate an interactive HTML before/after slider.
pixopt compare photo.jpg comparison.html --open
srcset
Generate responsive image variants and an HTML srcset snippet.
pixopt srcset hero.jpg --sizes 320,640,1024,1920 --output-dir ./responsive/
pixopt srcset hero.jpg --sizes 320,640,1024,1920 -f webp --html snippet.html
placeholder
Extract a placeholder for lazy loading (color, LQIP, or blurhash).
pixopt placeholder photo.jpg --type color
pixopt placeholder photo.jpg --type lqip
pixopt placeholder photo.jpg --type blurhash -o blurhash.txt
watermark
Add text or image watermarks.
pixopt watermark photo.jpg watermarked.jpg --text "© 2026"
pixopt watermark photo.jpg watermarked.jpg --watermark-image logo.png --position bottom-right --opacity 0.5
sprite
Pack images into a sprite or contact sheet.
pixopt sprite sprite.png icon1.png icon2.png icon3.png
pixopt sprite contact.jpg ./thumbnails/* --contact-sheet
bundle
Generate a ready-to-deploy asset bundle from a source image.
pixopt bundle photo.jpg -o ./bundle
pdf
Import PDF pages as images or export images as a PDF.
pixopt pdf document.pdf -o ./pages
pixopt pdf output.pdf --from-images page1.jpg,page2.jpg
nextgen
Convert images to next-generation JXL or WebP2.
pixopt nextgen detect
pixopt nextgen convert photo.jpg -o photo.jxl -f jxl
duplicates
Find duplicate or visually similar images.
pixopt duplicates ./images --threshold 95
scan
Scan a directory and report optimization potential.
pixopt scan ./images --recursive
benchmark
Compare size/quality across formats.
pixopt benchmark photo.jpg --format JPEG --format WEBP --format AVIF
palette
Extract a color palette from an image.
pixopt palette photo.jpg --count 5
metrics
Compute PSNR/SSIM quality metrics between two images.
pixopt metrics original.jpg optimized.jpg
Global Options
| Option | Short | Description | Default |
|---|---|---|---|
--quality |
-q |
JPEG/WEBP quality (1-100) | 85 |
--width |
-w |
Maximum width in pixels | — |
--height |
-h |
Maximum height in pixels | — |
--format |
-f |
Output format: auto, jpeg, png, webp, avif, original | auto |
--strip |
-s |
Remove metadata | True |
--progressive |
— | Progressive JPEG encoding | True |
--recursive |
-r |
Process directories recursively | False |
--overwrite |
— | Overwrite source files | False |
--lossless |
— | Lossless PNG/WEBP compression | False |
--target-size |
— | Target file size in KB (adaptive quality) | — |
--smart-format |
— | Auto-detect the most efficient output format | False |
--backup |
— | Backup originals to this directory | — |
--min-size |
— | Skip files already smaller than this threshold (KB) | — |
Use-Case Recipes
Lossless PNG/WEBP for UI assets
pixopt convert icon.png icon.webp --lossless -f webp
Target a specific file size
pixopt optimize photo.jpg --target-size 50
Auto-detect the output format
pixopt optimize photo.jpg photo_optimized.jpg --smart-format
pixopt convert graphic.png output.webp --smart-format
Backup originals before processing
pixopt optimize ./images --backup ./originals --recursive
Skip already-optimized files
pixopt optimize ./images --min-size 10 --recursive
Animated GIF to animated WEBP
pixopt convert animation.gif animation.webp -f webp
Convert HEIC (iPhone) to JPEG
pixopt convert photo.heic photo.jpg
Optimize SVG
pixopt convert icon.svg icon.min.svg
Library Usage
pixopt can be used as a Python library for custom workflows and integrations.
Basic optimization
from pixopt import optimize_image
from pixopt.models import OutputFormat
result = optimize_image(
"photo.jpg",
"photo_optimized.webp",
max_width=1200,
quality=80,
strip_metadata=True,
output_format=OutputFormat.WEBP,
)
print(f"Saved {result.savings_percent:.1f}% ({result.human_savings})")
print(f"Output: {result.output_path}")
Batch processing
from pixopt import optimize_directory
from pixopt.models import OutputFormat
results = optimize_directory(
"./images",
"./optimized",
recursive=True,
max_width=800,
quality=75,
output_format=OutputFormat.WEBP,
)
for r in results:
if r.success:
print(f"{r.source_path.name}: {r.savings_percent:.1f}% saved")
else:
print(f"{r.source_path.name}: failed — {r.error}")
Format conversion
from pixopt import optimize_image
from pixopt.models import OutputFormat
result = optimize_image(
"icon.png",
"icon.webp",
output_format=OutputFormat.WEBP,
lossless=True,
)
Lossless compression
from pixopt import optimize_image
from pixopt.models import OutputFormat
result = optimize_image(
"ui_asset.png",
"ui_asset.webp",
output_format=OutputFormat.WEBP,
lossless=True,
)
Adaptive quality
from PIL import Image
from pixopt import optimize_image
from pixopt.adaptive_quality import find_quality_for_target_size
from pixopt.models import OutputFormat
with Image.open("photo.jpg") as img:
img.load()
quality = find_quality_for_target_size(img, "JPEG", target_size=50 * 1024)
result = optimize_image(
"photo.jpg",
"photo_optimized.jpg",
output_format=OutputFormat.JPEG,
quality=quality,
)
print(f"Use quality {quality}")
Placeholders
from pixopt.placeholder import generate_placeholder
# Dominant color
color = generate_placeholder("photo.jpg", placeholder_type="color")
# → "#3f7a8c"
# Low-quality image placeholder (base64 data URI)
lqip = generate_placeholder("photo.jpg", placeholder_type="lqip")
# → "data:image/jpeg;base64,/9j/4AAQ..."
# Blurhash
blurhash = generate_placeholder("photo.jpg", placeholder_type="blurhash")
# → "LEHV6nWB2yk8pyo0adR*.7kCMdnj"
Smart format detection
from pixopt.smart_format import detect_optimal_format
fmt = detect_optimal_format("photo.jpg")
# Returns OutputFormat.WEBP for photos, PNG for graphics, WEBP for transparent images
Responsive srcset
from pixopt.srcset_generator import generate_srcset_images
variants = generate_srcset_images(
"hero.jpg",
"./responsive",
widths=[320, 640, 1024, 1920],
output_format="WEBP",
quality=80,
)
for v in variants:
print(f"{v.width}px -> {v.size_bytes} bytes")
Backup and min-size filter
from pixopt import optimize_image
result = optimize_image(
"photo.jpg",
"photo_optimized.jpg",
quality=75,
backup_dir="./backups",
min_size_bytes=10240, # Skip files below 10 KB
)
Favicon generation
from pixopt.optimizer import convert_to_favicon
result = convert_to_favicon(
"logo.png",
"favicon.ico",
sizes=[16, 32, 48],
)
Watermarking
from pixopt import add_text_watermark, add_image_watermark
add_text_watermark(
"photo.jpg",
"watermarked.jpg",
"© 2026",
position="bottom-right",
)
add_image_watermark(
"photo.jpg",
"watermarked.jpg",
watermark="logo.png",
position="bottom-right",
opacity=0.5,
)
Sprite sheets
from pixopt.sprite import create_sprite
result = create_sprite(
["icon1.png", "icon2.png", "icon3.png"],
"sprite.png",
layout="grid",
fmt="PNG",
)
Asset bundles
from pixopt.bundle import generate_asset_bundle
bundle = generate_asset_bundle("photo.jpg", "./bundle")
print(bundle.dominant_color)
PDF export
from pixopt.pdf_io import images_to_pdf
pdf = images_to_pdf(
["page1.jpg", "page2.jpg"],
"output.pdf",
)
Next-gen formats
from pixopt.nextgen import convert_to_nextgen
convert_to_nextgen("photo.jpg", "photo.jxl", fmt="jxl")
Base64 and bytes I/O
import base64
from pixopt import optimize_base64, base64_to_image
with open("photo.jpg", "rb") as f:
b64 = base64.b64encode(f.read()).decode("ascii")
result = optimize_base64(b64, output_format="WEBP", quality=80)
print(result.base64) # optimized base64 string
API Reference
For the complete auto-generated API documentation, visit the official docs.
Key modules:
pixopt.optimizer— Core optimization functions (optimize_image,optimize_directory,convert_to_favicon)pixopt.models— Data models (OptimizationResult,OutputFormat)pixopt.placeholder— Placeholder generation (generate_placeholder,extract_dominant_color,generate_lqip_datauri,generate_blurhash)pixopt.smart_format— Smart format detection (detect_optimal_format)pixopt.srcset_generator— Responsive image generation (generate_srcset_images,SrcsetImage)pixopt.adaptive_quality— Adaptive quality (find_quality_for_target_size)pixopt.html_comparison— Visual comparison (generate_comparison_html)pixopt.watermark— Watermarking (add_text_watermark,add_image_watermark)pixopt.sprite— Sprite sheets and contact sheets (create_sprite,create_contact_sheet)pixopt.bundle— Asset bundles (generate_asset_bundle)pixopt.pdf_io— PDF import/export (images_to_pdf,pdf_to_images)pixopt.nextgen— Next-gen formats (convert_to_nextgen)pixopt.duplicates— Duplicate detection (find_duplicates,compute_hash)pixopt.inventory— Directory scanning and reporting (scan_directory,ScanReport)pixopt.benchmark— Format benchmarking (benchmark_formats)pixopt.palette— Color palette extraction (extract_palette)pixopt.io_bytes— Base64 and bytes I/O (optimize_base64,base64_to_image)pixopt.async_api— Async operations (async_optimize_image,async_batch_optimize)pixopt.pipeline— Fluent optimization pipeline (Pipeline)pixopt.presets— Built-in and custom presets (BUILTIN_PRESETS,apply_preset)
Development
Install in development mode:
git clone https://github.com/MathiasPaulenko/pixopt.git
cd pixopt
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
Run tests:
pytest tests/ -v
Run linters, type checkers, format check, and security checks:
ruff check .
ruff format . --check
mypy pixopt
python -m pyright
python -m bandit -r pixopt
python -m pip_audit .
Build documentation locally:
pip install -e ".[docs]"
mkdocs serve
Contributing
We welcome contributions! Please read our Contributing Guide for details on code style, testing, and the pull request workflow.
Quick setup:
git clone https://github.com/MathiasPaulenko/pixopt.git
cd pixopt
pip install -e ".[dev]"
pytest
Changelog
See CHANGELOG.md for the full history of changes.
Acknowledgements
pixopt is built on top of the excellent Python imaging and CLI ecosystem, especially Pillow, pillow-heif, Typer, Rich, piexif, and NumPy.
License
MIT License — © 2026 pixopt contributors
Release files for pixopt 1.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pixopt-1.2.1.tar.gz | 161.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pixopt-1.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 277.9 kB
Release files / pixopt-1.2.1.tar.gz
| Download URL | pixopt-1.2.1.tar.gz |
|---|---|
| Size | 161.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
21468ac2b71650b6ddea98e674cbafb690d9582361493a6b4de0a2883b582bcc
|
|
BLAKE2b-256 checksum How to use checksums |
a354d246e4206cdc01278174537ba43337948b47cff0a5141986d6ca09b3f5b2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / pixopt-1.2.1-py3-none-any.whl
| Download URL | pixopt-1.2.1-py3-none-any.whl |
|---|---|
| Size | 116.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8e1efab68c3ad6c2d8d959439984093480191f4c77d3a130332e478097980fcd
|
|
BLAKE2b-256 checksum How to use checksums |
923f9368471477f38852d76ac780a66534d44cd663563b71076cb2640b79d5fb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|