Drop a JPEG/PNG here, or click to choose.
Tuned on a fast 1800 px preview — then export at native
resolution up to 16K (16,384 px per side), processed in tiles so memory stays bounded.
1 · Denoise
1b · Full-resolution export
2 · Sharpness map & crop assistant
Warm tiles are sharp, cool tiles are soft (variance of the Laplacian per tile). Drag the box over your subject — the score tells you whether the crop can hold up. Drag the bottom-right corner to resize.
3 · The story of this photograph
Prefer an AI-written story? (free — no key needed)
Click the button and a downscaled copy of your before/after is sent — only then, only for this one story — to a small relay on my own domain that adds the writing. The image is never stored or logged, and this site keeps no server-side copy of anything you load.
How it works
Noise estimation. The noise level σ is measured from the image itself with Immerkær's fast method (1996): convolve with a Laplacian-difference mask that annihilates image structure, and average what survives. Both denoisers adapt to this estimate, so the same slider position behaves consistently from ISO 800 to ISO 12800.
Non-local means (Buades, Coll & Morel, 2005) exploits self-similarity:
a feather barb or fur strand recurs many times across the frame, so each pixel is restored
as a weighted average of pixels whose neighbourhoods look alike — weights
exp(−max(‖P(i)−P(j)‖² − 2σ², 0)/h²). This implementation uses the
offset/box-filter decomposition for O(N·|search|) complexity, computes patch distances on
luminance, and applies the weights to all three channels.
Wavelet BayesShrink (Chang, Yu & Vetterli, 2000) transforms the image
into a multi-level Haar wavelet basis, where noise spreads thinly across all coefficients
but edges concentrate in a few large ones. Each detail subband is soft-thresholded at
T = σ²/σx, the Bayes-optimal threshold under a generalised-Gaussian
prior — aggressive in noisy flat sky, gentle where feather texture lives.
Two-stage oracle-guided NLM borrows the key insight of modern collaborative filtering (Dabov et al. 2007): matching noisy patches against noisy patches is unreliable, so denoise once to get a pilot estimate, then recompute patch similarities on that clean pilot — where structure and grain are already separated — and re-aggregate the original pixels with a tighter bandwidth. Verified on a step edge: the gradient across a subject's eye is preserved exactly, while flat-region noise drops a further ~20% versus single-pass NLM.
The story engine. After each rescue, the page reads the photograph back to you: light level and colour cast from the luma/chroma statistics, subject placement from the sharpness map's centre of mass, an ISO estimate from the measured σ, and what the restoration changed. You can also request an AI-written narrative — the image goes to a small relay on this domain only when you ask, and nothing you load is ever stored or logged.
The residual check. A denoiser should remove noise, not detail. The residual view shows exactly what was subtracted, amplified 4×: if it looks like uniform grain, the algorithm behaved; if you can trace an eye or wing in it, dial the strength down.
Crop scoring. The focus measure is the classic variance-of-Laplacian, computed per tile. The crop score compares the 90th-percentile sharpness inside your crop to the sharpest region of the whole frame, discounted by crop magnification — because a 1:1 crop of slightly-soft pixels reads soft, while the same pixels downsampled read fine.