metalgrow
AI-powered image upscaler accelerated on Apple Metal (MPS).
metalgrow runs super-resolution on Apple Silicon GPUs through PyTorch's MPS
backend, with graceful fallbacks to CUDA and CPU. It ships with a bicubic
baseline so the pipeline is runnable end-to-end, and exposes a clean seam for
plugging in a learned backbone (Real-ESRGAN, SwinIR, etc.).
Table of contents
Features
- 🍎 Apple Metal first — PyTorch MPS backend, zero config on Apple Silicon
- 🔁 Portable — automatic fallback to CUDA / CPU when MPS isn't available
- 🧩 Pluggable backbones — bicubic, Real-ESRGAN (x2/x4), SwinIR (x2/x4)
- 🧱 Tiled inference — process arbitrarily large images with feathered overlap blending
- 📂 Batch mode — upscale whole directories or globs with a progress bar
- 📦 Model registry —
metalgrow modelsmanages cached weights with sha256 verification - 🧪 Tested — pytest suite covering the CPU baseline, tiling, batch mode, and registry
Requirements
- Python 3.11+
- macOS with Apple Silicon for MPS acceleration (optional — CPU/CUDA also work)
Install
git clone https://github.com/joaodotwork/metalgrow.git
cd metalgrow
uv venv && source .venv/bin/activate
uv pip install -e .
Or with plain pip:
python -m venv .venv && source .venv/bin/activate
pip install -e .
Usage
CLI
Single file:
metalgrow info
metalgrow upscale input.jpg out.png --scale 2
metalgrow upscale input.jpg out.png --scale 4 --device mps --backbone realesrgan-x4
Whole directory or glob (writes to a target directory, mirroring filenames):
metalgrow upscale ./photos ./photos-upscaled --scale 2 --backbone realesrgan-x2
metalgrow upscale "./photos/*.png" ./out --scale 2 --skip-existing
| Flag | Default | Description |
|---|---|---|
--scale, -s |
2.0 |
Upscale factor (1.01–8.0) |
--device, -d |
auto |
auto | mps | cuda | cpu |
--backbone, -b |
bicubic |
bicubic | realesrgan-x{2,4} | swinir-x{2,4} |
--dtype |
fp32 |
fp32 | fp16 (fp16 is MPS-only and noisier) |
--tile |
backbone hint | Tile size in input px for tiled inference (0 disables) |
--tile-pad |
backbone hint | Context padding per tile edge (covers backbone receptive field) |
--skip-existing |
off | Batch mode: skip outputs that already exist |
--workers, -j |
4 |
Batch mode: parallel I/O workers (inference stays serial) |
Manage cached model weights
metalgrow models list
metalgrow models download realesrgan-x4
metalgrow models rm realesrgan-x4
Weights cache to ~/.cache/metalgrow/ by default; override with the
METALGROW_CACHE_DIR env var. Every download is sha256-verified.
See docs/models.md for a quality / speed / memory
comparison (with benchmark numbers) and guidance on which backbone to pick,
or docs/usage.md for the full CLI / library reference.
Library
from PIL import Image
from metalgrow import Upscaler
upscaler = Upscaler(backbone="realesrgan-x2", device="auto") # auto | mps | cuda | cpu
result = upscaler.upscale(
Image.open("input.jpg").convert("RGB"),
scale=2.0,
tile=256, # optional — backbone has sensible defaults
tile_pad=16,
)
result.save("out.png")
Project layout
src/metalgrow/
device.py # device auto-selection (MPS → CUDA → CPU)
upscaler.py # Upscaler class + tiled inference with overlap blending
batch.py # directory / glob batch mode
weights.py # weight registry, sha256 verification, cache management
cli.py # typer CLI (upscale, info, models)
backbones/ # bicubic, realesrgan, swinir; plugin registry
tests/
docs/
usage.md # CLI recipes, library API, env vars, pitfalls
models.md # backbone comparison, benchmark snapshot, tiling
benchmarks.md # full (device × backbone × scale) tables
architecture.md # module layout, data flow, extension points
Roadmap
- Integrate a learned SR backbone (Real-ESRGAN default)
- Tiled inference for large images
- Batch / directory mode
- Model registry + weight download
- Second backbone family (SwinIR)
- GitHub Actions CI (lint + test on macOS + Linux)
- Benchmarks: MPS vs CPU (CUDA pending GPU runner)
- v0.1.0 release
Contributing
Issues and PRs are welcome. Please run ruff and pytest before opening a PR.
License
MIT — see LICENSE.
Made with 🔩 on Apple Silicon.
Release files for metalgrow 0.1.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 | |
|---|---|---|---|
| metalgrow-0.1.1.tar.gz | 90.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| metalgrow-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 109.1 kB
Release files / metalgrow-0.1.1.tar.gz
| Download URL | metalgrow-0.1.1.tar.gz |
|---|---|
| Size | 90.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d7fc3a7b0ce84259db3c9dda4ba0d29da1122b01075b4ecd42c9a7331f89b641
|
|
BLAKE2b-256 checksum How to use checksums |
d917355145d15dac921cd02ba339aa51d8f302d562d87101e5504aeef9a93156
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 13, 2026.
Transparency logRelease files / metalgrow-0.1.1-py3-none-any.whl
| Download URL | metalgrow-0.1.1-py3-none-any.whl |
|---|---|
| Size | 18.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bc30ab4e69401c791b636d33a89c2d594ee48dda02faca0cd49d97ba949f0cf2
|
|
BLAKE2b-256 checksum How to use checksums |
5be2be0f2f46954ca8ed2ba4fb89025401138a13d6c0887146cc02078925098c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 13, 2026.
Transparency log