Interactive, browser-native image compression using Singular Value Decomposition
Built entirely in Vanilla JS — no backend, no libraries, no build step.
Upload any image and compress it in real time using rank-k matrix approximation via SVD. Drag the slider to choose how many singular values to keep — from aggressive compression (k=5) to near-lossless (k=max). The entire SVD pipeline runs in your browser, including:
- Per-channel Jacobi eigendecomposition on AᵀA
- Live reconstruction as you drag the slider
- PSNR quality metric and compression ratio
- Error map visualisation (normalised difference heatmap)
- Lossless PNG download at exact selected quality
Any image channel (m×n matrix) can be factored via SVD:
Keeping only the top-k singular values gives the best rank-k approximation (Eckart–Young theorem):
Compression ratio:
Quality metric (PSNR):
A PSNR above ~30 dB is considered perceptually good quality.
The browser has no numpy.linalg.svd. This app implements the full pipeline:
1. Extract R, G, B channel matrices (Float64Array)
2. For each channel:
a. Compute AᵀA (n×n symmetric)
b. Jacobi iterations → orthogonal V, eigenvalues λᵢ
c. Singular values σᵢ = √λᵢ, sort descending
d. Recover U columns: uᵢ = A·vᵢ / σᵢ
3. For slider value k:
reconstruct = Σ(i=0..k-1) σᵢ · uᵢ · vᵢᵀ
4. Clamp to [0,255], write to ImageData
The same pipeline in NumPy (for reference):
import numpy as np
from PIL import Image
img = np.array(Image.open("photo.jpg").convert("RGB"), dtype=np.float64)
def svd_compress(channel, k):
U, S, Vt = np.linalg.svd(channel, full_matrices=False)
return np.clip(U[:, :k] @ np.diag(S[:k]) @ Vt[:k, :], 0, 255)
k = 30
compressed = np.stack([svd_compress(img[:,:,c], k) for c in range(3)], axis=2)
# Quality metrics
mse = np.mean((img - compressed) ** 2)
psnr = 20 * np.log10(255.0 / np.sqrt(mse))
ratio = (img.shape[0]*img.shape[1]) / (k*(1+img.shape[0]+img.shape[1]))
print(f"PSNR: {psnr:.1f} dB | Compression: {ratio:.1f}×")| Feature | Detail |
|---|---|
| 📤 Image Upload | PNG, JPG, WEBP — drag & drop or click, up to 800×800 |
| 🎚️ Rank-k Slider | Real-time reconstruction as you drag — full range k=1 to min(W,H) |
| 📊 4 Live Metrics | Compression ratio, PSNR (dB), energy retained %, bytes saved |
| 📉 SV Spectrum | Singular value bar chart — see which components are kept/discarded |
| 📈 PSNR Curve | Quality vs k chart with live position marker |
| 🔍 Error Map | Normalised blue→red heatmap of reconstruction error |
| 🎨 RGB & Grayscale | SVD applied per-channel (RGB) or on luminance (grayscale) |
| ⬇️ HQ Download | Lossless PNG, fresh full-resolution reconstruction at exact k value |
| 🖼️ Demo Images | Three synthetic test images (portrait, landscape, texture) |
| 📱 Mobile-friendly | Responsive layout, touch-optimised slider, high-quality scaling |
SVD-COMPRESSION/
├── index.html ← Entire app — all CSS, JS, SVD math inline (no build)
├── README.md ← This file
├── notebook.ipynb ← Python/NumPy equivalent implementation
├── report.pdf ← Full mathematical writeup
├── requirements.txt ← Python deps for notebook
└── results/ ← Sample compression outputs
├── error_maps.png
├── psnr_vs_k_curves.png
├── singular_value_spectrum.png
└── *_compression_grid.png
No install needed — just open the file:
git clone https://github.com/aryan24cse109-dev/SVD-COMPRESSION
cd SVD-COMPRESSION
# Option 1 — direct open
open index.html # macOS
start index.html # Windows
xdg-open index.html # Linux
# Option 2 — local server (recommended)
python -m http.server 8000
# → http://localhost:8000For the Python notebook:
pip install -r requirements.txt
jupyter notebook notebook.ipynb| Layer | Detail |
|---|---|
| Language | Vanilla JavaScript (ES6+, no framework) |
| Math | Custom Jacobi SVD — zero libraries |
| Rendering | HTML5 Canvas API + ImageData |
| Styling | CSS3, CSS custom properties, responsive grid |
| Fonts | Space Mono + Syne (Google Fonts) |
| Deployment | GitHub Pages (auto-deploy from main) |
- Singular Value Decomposition — matrix factorisation, U·Σ·Vᵀ
- Low-rank approximation — Eckart–Young–Mirsky theorem
- Jacobi eigendecomposition — iterative algorithm for symmetric matrices
- Information compaction — energy in the singular value spectrum
- PSNR / MSE — standard image quality metrics
- HTML5 Canvas API — pixel-level image manipulation in the browser
- Golub, G. H., & Van Loan, C. F. (2013). Matrix Computations (4th ed.). Johns Hopkins University Press.
- Eckart, C., & Young, G. (1936). The approximation of one matrix by another of lower rank. Psychometrika, 1(3), 211–218.
- NumPy linalg.svd
- Wikipedia: Singular Value Decomposition
Aryan Agarwal · GitHub