ThumbHash
Compact, high-fidelity placeholders
5–32 byte hashes with alpha support. Store one tiny blob per image and render blurry-but-faithful previews instantly.
Rust under the hood · Python on the reins
thumbleweed unifies ThumbHash, BlurHash, ColorThief, real thumbnails (images, videos, PDFs) and mozjpeg-class compression into a single Python package — powered by a pure-Rust core. No C extensions. No NumPy. No fuss.
What's in the wheel
Every subsystem is a drop-in replacement for the library it replaces — same import names, same API shapes, just dramatically faster.
Compact, high-fidelity placeholders
5–32 byte hashes with alpha support. Store one tiny blob per image and render blurry-but-faithful previews instantly.
Smooth gradient placeholders
The classic base-83 string format, encoded and decoded entirely in Rust. Drop-in compatible with the blurhash-python API.
Dominant colour & palettes
Median-cut palette extraction from any image format — bytes, BytesIO, paths or PIL Images. Strict, validated quality range.
Real thumbnails, any source
Rasterised thumbnails for images, MP4 videos and PDFs. A pure-Rust fallback engine needs no ffmpeg and no pdfium.
mozjpeg-class re-encoding
Optional pixo-powered JPEG & PNG optimisation, auto-applied to thumbnail output. Never returns a larger file — guaranteed by a strict size guard.
— the thumbleweed warranty
Live · runs in your browser
This playground runs the actual ThumbHash and BlurHash algorithms from thumbleweed — the same pure-Rust code shipped in the Python wheel, cross-compiled to a 52 KB .wasm module. Nothing is sent to a server.
Horsepower
Mean per-call latency over the real test-fixture images (5 rounds × 100 iterations). Lower is better; bars are log-scaled. Full methodology lives in the repo README.
ThumbHash & ColorThief timings include full image decode — real end-to-end usage, not just the inner loop.
Saddle up in seconds
If you already use thumbhash, blurhash or colorthief, switching is a one-line change of the import. The higher-level helpers accept Pillow images, raw bytes, BytesIO or file paths — Pillow is only needed for PIL.Image inputs.
from PIL import Image
import thumbhash as th
img = Image.open("photo.jpg")
hash_str = th.encode_image(img) # base64, ~20-40 chars
placeholder = th.decode_image(hash_str) # RGBA preview, ≈32 px
# Raw pixel API — no Pillow needed
hash_bytes = th.encode(w, h, rgba_bytes)Pre-built wheels for every version above, built fresh in CI on each release.
Linux wheels tagged manylinux_2_28; macOS and Windows wheels are universal installs.