Skip to main content

metalgrow

AI-powered image upscaler accelerated on Apple Metal (MPS).

CI Python PyTorch Apple Silicon License: MIT Status Ruff PRs Welcome

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
  • 🖨️ Print-aware — --preserve-metadata keeps grayscale mode, the ICC profile, and a rescaled DPI tag intact
  • 📰 Descreen — --descreen removes halftone screens (moiré) from scanned print before upscaling, leaving text and linework untouched
  • 📦 Model registry — metalgrow models manages 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); learned backbones run their native factor then resample to this exact target
--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
--preserve-metadata, -p off Keep grayscale mode, embedded ICC profile, and a rescaled DPI tag (for print / preflight workflows)
--workers, -j 4 Batch mode: parallel I/O workers (inference stays serial)
--descreen off Remove halftone screens (moiré) from scanned print before the backbone runs
--descreen-strength 1.0 Notch depth, 0–1

Descreen scanned print

Newspaper and magazine scans carry the printer's halftone dot screen, which SR backbones sharpen into moiré. --descreen removes it first. Detection is local and only touches regions that actually contain a dot lattice — type, rules and blank paper come back unchanged. See ADR 0002 for how it works.

# descreen + upscale, keeping DPI / ICC / grayscale for print
metalgrow upscale scan.tif out.tif --descreen -p --scale 1.5 -b swinir-x2

# descreen only, no resize
metalgrow descreen scan.tif clean.tif -p

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
  descreen.py          # local FFT notch filter for halftone screens
  metadata.py          # ICC / DPI / grayscale capture + reapply
  weights.py           # weight registry, sha256 verification, cache management
  cli.py               # typer CLI (upscale, descreen, 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.

Metadata

Release files for metalgrow 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for metalgrow 0.2.0
File Size Uploaded
metalgrow-0.2.0.tar.gz 111.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for metalgrow 0.2.0
File Interpreter ABI Platform
metalgrow-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 140.7 kB

Release files / metalgrow-0.2.0.tar.gz

Download URL metalgrow-0.2.0.tar.gz
Size 111.5 kB
Tags Source
SHA-256 checksum
How to use checksums
44641e82e43dd86d81d3bb048f2f923664b7953f9b81e3046be9a40896e9c882
BLAKE2b-256 checksum
How to use checksums
923eb2cecb10ea450e147c99955d147b0348b2d5cd9e17e735e19de866f73501
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 2, 2026.

Transparency log

Release files / metalgrow-0.2.0-py3-none-any.whl

Download URL metalgrow-0.2.0-py3-none-any.whl
Size 29.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1a93d542affc0b00aca2da46ef502782bee70392e6851ee9824f113bf10dbd50
BLAKE2b-256 checksum
How to use checksums
695c1bbef44c1ea4aaaced1553adef3eebc0dfdc35ed49adad61d73182f88cc2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 2, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page