--- title: Image Processor Pro emoji: πŸ–ΌοΈ colorFrom: indigo colorTo: purple sdk: docker app_port: 7860 pinned: false --- # Image Processor Pro A command-line tool that downloads images from URLs, converts them to JPEG, optimizes them, and saves them locally with date-bucketed output. A local web UI (`webapp.py`) is also included, and the repo ships a `Dockerfile` for one-click deploy to [Hugging Face Spaces](https://huggingface.co/docs/hub/spaces-sdks-docker). > The YAML block above is **only used by Hugging Face Spaces** to configure the container (Docker SDK, port 7860). It is ignored everywhere else. ## Features - Concurrent multi-threaded downloads with retry & backoff - Supports AVIF, JPG, JPEG, PNG, WEBP inputs - Converts everything to optimized progressive JPEG - Transparency flattened over a configurable background (default white) - Optional resize (max-width / max-height) preserving aspect ratio - Strips metadata by default for smaller files - Date-bucketed output: `output/YYYY-MM-DD/` - Separate success/failure log files plus rich console output - Unique filenames derived from the original image ID - Progress bar for batch runs, summary table at the end - Clean OOP design, type-hinted throughout ## Project Structure ``` image_processor/ β”œβ”€β”€ main.py # CLI entrypoint β”œβ”€β”€ downloader.py # Downloader (retries, MIME validation) β”œβ”€β”€ converter.py # Decode + RGB normalization (AVIF, PNG, WEBP, ...) β”œβ”€β”€ optimizer.py # Resize + JPEG encode/strip β”œβ”€β”€ pipeline.py # Orchestrates the downloadβ†’convertβ†’optimize flow β”œβ”€β”€ config.py # Config dataclass and supported formats β”œβ”€β”€ utils.py # Logging, URL parsing, naming helpers β”œβ”€β”€ requirements.txt β”œβ”€β”€ config.sample.json β”œβ”€β”€ urls.example.txt β”œβ”€β”€ output/ # Created at runtime: output/YYYY-MM-DD/*.jpg └── logs/ # success.log, failure.log ``` ## Installation Requires Python 3.12+. ```bash cd image_processor python -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` ## Usage ### Single image ```bash python main.py --url "https://images.meesho.com/images/products/195946861/25gkh_512.avif?width=512" ``` ### Batch from file ```bash python main.py --file urls.example.txt ``` ### Tune JPEG quality (1–95) ```bash python main.py --file urls.txt --quality 90 ``` ### Resize (cap width) ```bash python main.py --url "$URL" --max-width 1200 ``` ### Full example ```bash python main.py \ --file urls.txt \ --quality 88 \ --max-width 1600 \ --workers 16 \ --timeout 45 \ --retries 5 \ --output output \ --logs logs \ --verbose ``` ### Use a config file ```bash python main.py --file urls.txt --config config.sample.json ``` CLI flags override values from `--config`. ## CLI Options | Flag | Description | | --- | --- | | `--url URL` | Single image URL | | `--file PATH` | Text file with one URL per line (# comments allowed) | | `--config PATH` | JSON config file (see `config.sample.json`) | | `--output PATH` | Output root (default `output`) | | `--logs PATH` | Logs directory (default `logs`) | | `--quality N` | JPEG quality 1–95 (default 85) | | `--max-width N` | Resize so width ≀ N | | `--max-height N` | Resize so height ≀ N | | `--workers N` | Concurrent download workers (default 8) | | `--timeout N` | Per-request timeout seconds (default 30) | | `--retries N` | Max retries per URL (default 3) | | `--keep-metadata` | Preserve EXIF metadata | | `-v / --verbose` | Verbose logging | ## Output Layout ``` output/ └── 2026-06-18/ β”œβ”€β”€ 25gkh_512.jpg └── 25gkh_512-1.jpg # duplicate-safe naming logs/ β”œβ”€β”€ success.log └── failure.log ``` ## Error Handling The pipeline categorizes and logs each failure separately. Handled cases: - Invalid / malformed URL - Network timeout / connection error (retried with backoff) - Unsupported MIME type returned by server - Corrupted or undecodable image - Permission errors when writing output - HTTP non-2xx responses A failed item never aborts the batch β€” it's recorded in `logs/failure.log` and in the final summary table. ## Programmatic Use ```python from config import Config from pipeline import ImagePipeline config = Config(jpeg_quality=90, max_width=1200, max_workers=16) with ImagePipeline(config) as p: results = p.process_many(["https://example.com/a.png", "https://example.com/b.avif"]) for r in results: print(r.url, r.success, r.output_path) ``` ## Performance Notes - Tested architecture scales to 1000+ URLs by tuning `--workers` (I/O bound). - Downloads stream into memory in 16 KB chunks; large files are handled without spilling to temp disk. - A single `requests.Session` with a pooled HTTPAdapter is reused across workers.