junevm/splathash

16 bytes fixed size image placeholder, an alternative to blurhash and thumbhash

Go

208

26 commits

updated Feb 28, 2026

See the code

README

SplatHash

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.

Visual comparison of SplatHash, ThumbHash, and BlurHash reconstructions

Columns: original · SplatHash 32×32 · ThumbHash · BlurHash. Regenerate: mise run compare.

Install

LanguagePackageDocs
Gogo get github.com/junevm/splathash/src/gosrc/go/README.md
TypeScript / JSnpm install splathash-tssrc/ts/README.md
Pythonpip install splathash-pysrc/py/README.md

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).

SplatHashThumbHashBlurHash
Decode0.067 ms0.50 ms6.55 ms
Encode3.53 ms0.86 ms445 ms
Decode allocs71,1685
Bytes16 fixed25–3720–25
String22 chars34–50 chars27–30 chars

Decode runs on every page load for every user. Encode runs once at upload. Optimize for decode.

Raw output
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

FeatureSplatHashThumbHashBlurHash
Fixed output sizeYes (16 bytes)NoNo
Storable as 128-bit integerYesNoNo
Perceptual color space (Oklab)YesNoNo
Spatially localized basisYes (Gaussians)NoNo
Global weight optimizationYes (Ridge)NoNo
Alpha channel supportYesYesNo
Bit-exact cross-language parityYesNoNo
Configurable quality vs. sizeNoNoYes

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 LICENSE.

blurhash
golang
image-processing
placeholder-image
python
thumbhash
typescript

Contributors

junevm

17 commits

junevm/splathash

16 bytes fixed size image placeholder, an alternative to blurhash and thumbhash

Go

208

26 commits

updated Feb 28, 2026

See the code

README

SplatHash

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.

Visual comparison of SplatHash, ThumbHash, and BlurHash reconstructions

Columns: original · SplatHash 32×32 · ThumbHash · BlurHash. Regenerate: mise run compare.

Install

LanguagePackageDocs
Gogo get github.com/junevm/splathash/src/gosrc/go/README.md
TypeScript / JSnpm install splathash-tssrc/ts/README.md
Pythonpip install splathash-pysrc/py/README.md

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).

SplatHashThumbHashBlurHash
Decode0.067 ms0.50 ms6.55 ms
Encode3.53 ms0.86 ms445 ms
Decode allocs71,1685
Bytes16 fixed25–3720–25
String22 chars34–50 chars27–30 chars

Decode runs on every page load for every user. Encode runs once at upload. Optimize for decode.

Raw output
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

FeatureSplatHashThumbHashBlurHash
Fixed output sizeYes (16 bytes)NoNo
Storable as 128-bit integerYesNoNo
Perceptual color space (Oklab)YesNoNo
Spatially localized basisYes (Gaussians)NoNo
Global weight optimizationYes (Ridge)NoNo
Alpha channel supportYesYesNo
Bit-exact cross-language parityYesNoNo
Configurable quality vs. sizeNoNoYes

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 LICENSE.

blurhash
golang
image-processing
placeholder-image
python
thumbhash
typescript

Contributors

junevm

17 commits

Languages

Go

42.5%

Python

29.2%

TypeScript

28.3%