AI Image Upscaler
Upscale images 2x using neural network inference in the browser.
AI Image Upscaler runs neural-network inference in the browser to double image resolution — "Upscale images using neural network inference in the browser." Drop one photo, pick "Scale Factor" (2x or 4x toggle, default 2x), and click "Upscale {scale}". Live statuses track every phase: "Preparing image...", "Loading AI model...", "Downloading AI model (~20MB, cached after first load)..." with byte progress, "Creating inference session...", "Running AI upscaler...", then side-by-side "Original" vs "Upscaled ({scale})" panels with dimensions and sizes.
**Critical third-party disclosure:** inference is local, but two network fetches happen — (1) onnxruntime-web's WASM runtime loads from the jsDelivr CDN (cdn.jsdelivr.net/npm/onnxruntime-web@1.30.0/dist/), and (2) a **~20MB ONNX model** (2x_AnimeInterpretersV2) streams once from HuggingFace and is stored in the browser's Cache API under bucket ai-upscaler-models. The UI hint says it plainly: "AI model (~20MB) downloads once and is cached in your browser." Your image never uploads. If the model fails, a canvas fallback runs with "AI model unavailable, using smart upscale..." / "Done (canvas upscale)".
How it works
lib/imageAiUpscaler.ts dynamically imports onnxruntime-web and sets ort.env.wasm.wasmPaths = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.30.0/dist/' so the WASM binaries load from jsDelivr. The model URL (https://huggingface.co/smartywu/anime-interpreters-v2-onnx/resolve/main/2x_AnimeInterpretersV2.onnx) is fetched with streaming progress, then stored in Cache API bucket ai-upscaler-models for instant repeat loads.
Inference converts RGBA ImageData to a float32 tensor [1,3,H,W], runs a session with executionProviders ['webgl','wasm'] (WebGL preferred, WASM fallback), and renders the output float32 back to a uint8 canvas as PNG. On any failure the catch path falls back to a canvas imageSmoothingQuality:'high' ×2 upscale. Code-grounded quirk: output size is always ×2 in both paths (even the 4x branch multiplies by 2, and the dimension hint always shows ×2).
How to use
- Drop one image — dimensions load for the "Original: {w}×{h} → Output: …" hint line.
- First run: accept the ~20MB model download (hint + status "Downloading AI model..."); later runs hit the Cache API cache.
- Choose "Scale Factor": 2x (default) or 4x.
- Click "Upscale {scale}" and watch the skeleton statuses through preparation, session creation, and inference.
- Review side-by-side "Original" vs "Upscaled ({scale})" panels with "{w}×{h} · {size}" captions.
- Click "Download" (PNG) or "Start Over".
- If AI failed, confirm the fallback ran (status "Done (canvas upscale)").
Tips
- The model is AnimeInterpretersV2 ONNX (2x) from HuggingFace — results favor anime/illustration content.
- WebGL is the preferred execution provider with WASM fallback — both need the jsDelivr onnxruntime WASM files.
- Cache name ai-upscaler-models persists across visits until browser storage is cleared.
- Despite the 4x button, the current code multiplies by 2 only — plan for 2× output dimensions.
AI Image Upscaler FAQ
Does it upload my image?
No — inference runs in-browser. Only the ONNX model (~20MB, from HuggingFace) and the onnxruntime-web WASM (from jsDelivr CDN) are downloaded; your image never leaves the device.
How big is the download?
The UI says ~20MB, cached after first load via Cache API bucket ai-upscaler-models — plus the onnxruntime WASM runtime from jsDelivr.
Does 4x really give 4× dimensions?
Not in the current code — both branches use multiplier 2 and the hint always shows ×2 output.
What if the model fails to load?
A canvas fallback upscale runs with status "AI model unavailable, using smart upscale..." finishing as "Done (canvas upscale)".
Which execution providers are used?
onnxruntime-web sessions run with executionProviders ['webgl', 'wasm'] — WebGL first, WASM as fallback.
Credits
- onnxruntime-web — ONNX inference runtime; WASM assets loaded from jsDelivr CDN
- 2x_AnimeInterpretersV2 (HuggingFace) — Upscaler model fetched once and cached via Cache API