Changed
POST /upscale default backend is now realesrgan (was swin2sr). Real-ESRGAN restores plausible detail on low-res and degraded photos — the main thing people upscale — and runs in a single pass (~6s vs minutes of tiled inference). Swin2SR remains available via model=swin2sr for accuracy-sensitive work (product shots, archival): faithful sharpening, no invented detail.
/remove output params are now multipart form fields (format, quality, max_dim, width, height, despill, watermark, watermark_opacity, preset) — matching every other endpoint. They were previously query-only, so SDK-style form fields were silently ignored. If you passed these as a query string on /remove, switch to form fields.
Improved
- Alpha edge quality across all cutout endpoints:
- Non-square images are padded to a square before the model's fixed 1024px resize — aspect ratio preserved, no more squished thin edges (hair, water reflections).
- Guided-filter alpha refinement snaps the mask to true image edges.
- Compositing (
/replace-bg, /studio-shot) now blends in linear light — kills the faint dark halo on semi-transparent edges. Implemented with a 256-entry LUT: bit-identical output, 2x faster.
- Swin2SR tiling rewritten to core-crop with halo context — no seam smear on small images.
- EXIF orientation is baked in on decode — sideways phone photos are history, on every endpoint.
Added
POST /studio-shot: optional width / height output resize, plus enhance + enhance_strength (subtle brightness/saturation lift for ecommerce). Saved presets now honor width/height here too.
- Shared preset application across
/remove, /psd, /replace-bg, /studio-shot — endpoints can no longer drift on which preset keys they honor.
eval/ — reproducible quality-eval harness (test cases + runners) used to validate all of the above.
Fixed
- Demo keys can no longer upscale output past the 512px demo cap via resize params.
/psd transparency, Stripe meter dedup, and assorted hardening from this cycle's code review (five verified findings, all fixed and live).
Demo
# Restore a low-res photo (new default backend)
curl -X POST "https://useknockout--api.modal.run/upscale" \
-H "Authorization: Bearer kno_public_beta_4d7e9f1a3c5b2e8d6a9f7c1b3e5d8a2f" \
-F "file=@small.jpg" -F "scale=4" \
-o restored.png
# Faithful mode (previous default)
curl ... -F "model=swin2sr"