Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PrivaScale — Local, Privacy-First AI Image Upscaler

PrivaScale social preview

100% on-device. Zero uploads. WebGPU + ONNX, or CPU Lanczos. Your images never leave the browser.

PrivaScale is a mobile-first PWA that upscales images entirely in the browser. No server, no tracking, no cloud. It starts immediately with the bundled AI model — no setup screens.

License Privacy WebGPU

How it works

  1. Open the app — it auto-starts: WebGPU → bundled Real-ESRGAN, no WebGPU → CPU-only mode (Lanczos, AI options disabled).
  2. Add a photo (drop, paste, or Choose photo — on mobile the OS offers gallery, camera or files).
  3. Pick scale 2× / 4×, tap Upscale.
  4. Compare before/after with the slider, or switch to zoom mode (pinch, double-tap, +/−, mouse wheel) to inspect details up to 8×.
  5. Download (PNG / JPG / WEBP). Back (↩) returns to the pre-upscale state to retry with other settings — no re-upload needed.

Optional: Settings → Face restore rebuilds faces (skin/detail) after upscale via YuNet detection + GPEN enhancement (~37 MB, downloaded once on first use).

Optional: Settings → 4x-UltraSharp for photos (~32 MB, downloaded once on selection).

Features

  • Fully local — pixels never leave the device
  • Zero-setup start — no model gate; bundled AI on WebGPU, CPU fallback otherwise
  • Models: Real-ESRGAN x4v3 (shipped), 4x-UltraSharp (optional download), Lanczos 3 (CPU, no neural net)
  • Face restore (opt-in): YuNet face detection + GPEN-BFR enhancement blended into the upscaled image
  • Tiled inference for large images
  • Mobile-first UI — single-row dock, compare slider, zoom mode (pinch / double-tap), settings sheet
  • Mobile hardening — screen wake lock during processing, 16 MP output cap on phones, adaptive tiling (256 px desktop / 128 px mobile)
  • Privacy wipe — remove photo vs clear everything (including cached models)
  • Preferences persist — model, scale, format and face-restore choices are saved on-device (localStorage, no image data) and restored on next launch
  • PWA — installable; works offline after models are on disk

Models and licenses

App code is MIT. Weights are not. See src/models/LICENSE.md.

Model In git? Size Best for License
Real-ESRGAN x4v3 Yes ~5 MB General photos (default) BSD 3-Clause — redistributable
4x-UltraSharp No ~32 MB Photos, texture CC BY-NC-SA 4.0 — non-commercial, not redistributed
YuNet 640 (face detect) No ~0.3 MB Face restore pass Via Viso Master collection — non-commercial
GPEN-BFR-256 fp16 (face enhance) No ~36 MB Face restore pass Research / non-commercial, not redistributed
Lanczos 3 Built-in — CPU-only upsample App MIT

Non-bundled weights are gitignored. Get them locally:

npm run fetch:models        # UltraSharp + YuNet + GPEN (~73 MB) + Real-ESRGAN

Or let the app download them on demand (model selection / face-restore toggle). Files land in src/models/ and the browser cache — after that, everything works offline.

For a commercial product, use Real-ESRGAN + Lanczos only, or replace the NC models with weights you have rights to.

Quick start

Browser: Chrome / Edge 113+ (WebGPU). Without WebGPU the app runs CPU-only (Lanczos 3).
Tooling: Node.js 18+ or Python 3.8+. Serve over HTTP, not file://.

git clone https://github.com/orfeomorello/privascale.git
cd privascale
npm install                 # also copies ONNX Runtime into src/vendor/ort
npm run fetch:models        # optional: UltraSharp + face models (~73 MB)
npm test                    # unit tests (node:test)
npx serve src               # → http://localhost:3000

Other servers:

python -m http.server --directory src 8000

Privacy check in DevTools: await PrivacyAudit.verifyNoDataLeak().

Deploy (static hosting)

The app is fully static — src/ is the site root and all paths are relative, so it works under any domain or subpath.

npm run package                         # → privascale-static.zip (Pages-safe)
npm run package -- --include-models     # also bundle ALL *.onnx (~140 MB, fully offline)

Cloudflare Pages (pages.dev) — recommended:

npx wrangler pages deploy src --project-name privascale

or connect the git repo in the Cloudflare dashboard (build command: none, output directory: src).

⚠️ Pages enforces a 25 MB per-file limit. These files exceed it and are handled as follows:

File Size Handling
4x-UltraSharp.onnx, GPEN-BFR-256.fp16.onnx 32–38 MB Excluded from the zip by default; downloaded from Hugging Face on first use and cached
ort-wasm-simd-threaded.jsep.wasm (+ asyncify) ~26–28 MB Needed for WebGPU inference — workarounds below

Workarounds for the ORT wasm files on Pages:

  • R2 object storage (keeps WebGPU): upload the two .wasm files to an R2 bucket with a custom domain, then point the runtime at it — e.g. ort.env.wasm.wasmPaths = 'https://cdn.example.com/ort/' in model-loader.js / face-restore.js (R2 serves arbitrary sizes, enable CORS).
  • Another static host without per-file limits (Netlify, Vercel, GitHub Pages, any VPS) — deploy the zip as-is with --include-models for a fully offline bundle.
  • CPU-only on Pages: not recommended — it would require forcing the plain ORT build and dropping WebGPU.

Usage

Desktop: drop / paste (Ctrl+V) / Choose photo → Upscale → drag the compare handle, or switch to zoom (mouse wheel, drag to pan, +/− buttons).
Mobile: Choose photo (gallery, camera or files) → Upscale → drag to compare, pinch or double-tap to zoom. Download on iOS may open a tab; use Share → Save Image.

After upscale: Download the result, ↩ Back to change model/scale and upscale again without re-uploading, 🗑️ to remove the photo.

Settings (top right): model (Real-ESRGAN included / UltraSharp download / Lanczos CPU), scale, face-restore toggle, model storage (update / clear everything).

Privacy

  • CSP: default-src 'self'; Hugging Face is allowed only to fetch optional non-commercial models
  • Images stay in memory / optional Cache Storage; never uploaded
  • Preferences (model, scale, format, face restore) are stored in a single localStorage key — no image data, declared in PrivacyAudit
  • Secure wipe: overwrite + drop references; Clear everything also drops cached models

Project structure

src/
├── index.html
├── css/styles.css
├── js/                    # pipeline, UI, ONNX loader, Lanczos CPU, face restore, settings store
├── vendor/ort/            # ONNX Runtime (npm run vendor:ort)
├── models/
│   ├── model-config.json
│   ├── LICENSE.md
│   ├── realesr-general-x4v3.onnx   # in git (BSD)
│   ├── 4x-UltraSharp.onnx          # gitignored — fetch or auto-download
│   ├── yunet_n_640_640.onnx        # gitignored — face detection
│   └── GPEN-BFR-256.fp16.onnx      # gitignored — face enhancement
├── assets/icons/          # PWA icons (generated)
└── service-worker.js
scripts/                   # fetch-models, vendor-ort, package (zip for static hosting)
test/                      # unit tests (`npm test`)
.github/                   # repo social preview image

Troubleshooting

Issue Fix
Blank page on file:// Serve over HTTP (npx serve src)
Stuck in CPU mode Use Chrome/Edge with WebGPU; AI models require it
4x-UltraSharp missing Select it in Settings — it downloads automatically
Face restore finds no faces Works on visible, front-facing faces; tiny/background faces are skipped
Face restore slow Runs on WebGPU if available, else WASM — prefer desktop or smaller images
Image too large Try 2× or a smaller crop
iOS download Long-press → Share → Save Image
HEIC iPhone camera: Most Compatible (JPEG), or convert first
Port in use npx serve src -l 3001

Restore optional weights anytime: npm run fetch:models.

License

  • Code: MIT — LICENSE
  • Real-ESRGAN weights: BSD 3-Clause (bundled)
  • UltraSharp: CC BY-NC-SA 4.0 — not in this repository; downloaded by you
  • YuNet / GPEN: research / non-commercial — not in this repository; downloaded by you

Acknowledgments


PrivaScale — upscale locally, stay private.

About

PrivaScale is a mobile-first PWA that upscales images entirely in the browser. No server, no tracking, no cloud. It starts immediately with the bundled AI model — no setup screens.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages