Show HN: SplatHash – A lightweight alternative to BlurHash and ThumbHash
Source: Hacker News
Overview
compress any image to 16 bytes — and reconstruct it
Algorithm · Demo · Bugs · Contributing
SplatHash encodes any image into exactly 16 bytes (a 22‑char base64url string) and decodes it back to a 32×32 blurry preview in 0.067 ms. Go, TypeScript, and Python all produce bit‑for‑bit identical hashes.
Columns: original · SplatHash 32×32 · ThumbHash · BlurHash. Regenerate: mise run compare.
Install
| Language | Install command | Docs |
|---|---|---|
| Go | go get github.com/junevm/splathash/src/go | README |
| TypeScript / JS | npm install splathash-ts | README |
| Python | pip install splathash-py | README |
Go is the reference implementation. All others are verified bit‑for‑bit against it.
Benchmarks
Go benchmarks on Intel Core i5‑9300H (go test -bench=. -benchmem).
| Feature | SplatHash | ThumbHash | BlurHash |
|---|---|---|---|
| Decode time | 0.067 ms | 0.50 ms | 6.55 ms |
| Encode time | 3.53 ms | 0.86 ms | 445 ms |
| Decode allocs | 7 | 1,168 | 5 |
| Bytes | 16 fixed | 25–37 | 20–25 |
| String length | 22 chars | 34–50 chars | 27–30 chars |
Decode runs on every page load for every user. Encode runs once at upload. Optimize for decode.
BenchmarkEncodeSplatHash-8 303 3530083 ns/op 100760 B/op 29 allocs/op
BenchmarkEncodeThumbHash-8 1431 863553 ns/op 1015 B/op 6 allocs/op
BenchmarkEncodeBlurHash-8 3 445696421 ns/op 33358234 B/op 8 allocs/op
BenchmarkDecodeSplatHash-8 17182 67622 ns/op 29584 B/op 7 allocs/op
BenchmarkDecodeThumbHash-8 6559 503366 ns/op 58408 B/op 1168 allocs/op
BenchmarkDecodeBlurHash-8 171 6553100 ns/op 547552 B/op 5 allocs/op
Comparison
| Feature | SplatHash | ThumbHash | BlurHash |
|---|---|---|---|
| Fixed output size | Yes (16 bytes) | No | No |
| Storable as 128‑bit integer | Yes | No | No |
| Perceptual color space (Oklab) | Yes | No | No |
| Spatially localized basis | Yes (Gaussians) | No | No |
| Global weight optimization | Yes (Ridge) | No | No |
| Alpha channel support | Yes | Yes | No |
| Bit‑exact cross‑language parity | Yes | No | No |
| Configurable quality vs. size | No | No | Yes |
How It Works
Background color + six Gaussian blobs placed by matching pursuit, color‑optimized by Ridge Regression, all in Oklab, packed into 128 bits. Full spec: ALGORITHM.md.
Development
mise install # install Go and Node at pinned versions
mise run test # run all tests (Go + TypeScript + Python)
mise run bench # Go benchmarks
mise run compare # regenerate docs/comparison.png
License
See the LICENSE.
