PROJECT 11 // AN IMAGE IS NOT ONLY A GRID OF PIXELS
Image Surfer
A real 2D FFT and Haar wavelet playground: load an image, then manipulate its actual frequency and wavelet structure and watch a genuine inverse transform reconstruct it, live, entirely in this browser tab. Every visible effect comes from real transform coefficients, never a blur filter standing in for one.
LIVE WEB APPLICATION // LOCAL PROCESSING
Surf an Image
Real 2D FFT and Haar wavelet decomposition, running entirely in this browser tab. Load an image, then manipulate its actual frequency and wavelet structure -- every change you see comes from real transform coefficients, not a blur filter standing in for one.
YOUR IMAGE IS NOT UPLOADED
The transform is the product
Most Fourier and wavelet demonstrations show a transform, explain it, and stop. Image Surfer treats the transform as an instrument instead: mute the fine wavelet detail and the image visibly softens toward its own broad shapes; boost the low end of the spectrum and the picture leans toward structure over texture. The controls read as approachable labels, broad structure, fine detail, but underneath them every single edit is a real change to real magnitude, phase, or wavelet coefficients, run back through a genuine inverse transform.
That distinction is enforced, not just claimed. The processing facade only accepts explicit, typed operations against a stored, untouched copy of the original transform, so a screen effect that only looked like Fourier filtering, a CSS blur standing in for a low-pass, could not accidentally end up wired to a slider. If it is not a real coefficient edit, it does not exist in this codebase.
Color without paying for it three times
Running a 2D FFT independently on red, green, and blue would triple the cost of every single slider drag, measured directly in this project's own benchmark at roughly 33ms for one channel at a comfortable working resolution, which is already most of the interactive budget on its own. Image Surfer instead separates an image into luminance and chrominance: only luminance, the channel that actually carries "structure," runs through the interactive transform, while color and saturation pass through untouched and get recombined at reconstruction time.
The conversion has to be exact in both directions or the whole idea falls apart the moment a user loads an image and does nothing at all. The first attempt used two independently-published, independently-rounded constant sets for the forward and inverse directions, which round-tripped a pure red pixel to something visibly off, a real, measured error, not floating-point noise. The fix was to derive every inverse coefficient algebraically from the same three forward coefficients, so the two directions are exact matrix inverses of each other by construction instead of by two decimal roundings happening to agree.
Prove the math before building anything that touches it
Nothing resembling an interface existed before both transforms had a deterministic test suite: forward and inverse round trips against synthetic fixtures, a horizontal edge that had to concentrate its energy in the wavelet band actually named "horizontal," a sinusoid whose FFT had to show a peak at exactly the frequency that generated it. That discipline caught a real defect in the wavelet inverse transform, one that would have silently produced a garbled image the first time anyone tried a multi-level wavelet edit, and a second real defect in the test fixtures themselves, before either could hide behind a plausible-looking screenshot.
This project's own transferable lesson is not really about Fourier transforms. A visual, interactive feature is exactly the kind of code where "it looks right" is the most dangerous form of passing, because a human glancing at a picture will forgive a surprising amount of actual wrongness. Numeric fixtures with a known correct answer do not forgive it, which is why they ran first, not last.