よくある質問
BlurHash は誰が作り、なぜ作られたのですか?
BlurHash は 2018 年に **Dag Ågren** によって公開されました。彼は **Wolt**(フードデリバリー、後に DoorDash が買収)のフィンランドのエンジニアです。Wolt のモバイルアプリはリストスクロール中の画像プレースホルダーが必要でした — 遅いモバイル回線でレストランのメニューを閲覧するとき、写真が読み込まれる空のグレーボックスは違和感を与えました。単色の平均色ブロック(単純すぎる)、小さなプリデコードサムネイル(JSON ペイロードで大きすぎる)、SQIP / Polished スタイルの SVG 近似(脆すぎる)を試した後、BlurHash は中間を取りました: 認識できるぼかしにデコードされる ~30 バイト。リファレンス実装は C で、TypeScript、Swift、Kotlin、Python、Go、Rust への移植があります。アルゴリズム自体は base83 にパックされた小さな離散コサイン変換です。**MIT ライセンス** なので商用アプリでも自由に出荷できます。
BlurHash はどうやって画像を 30 バイトまで圧縮するのですか?
**JPEG** の中核と同じ数学である **離散コサイン変換**(DCT)です。ただし高周波係数を積極的に切り捨てます。エンコーダは入力画像を縮小し、小さな画像の DCT を計算し、各 RGB チャンネルの components_x × components_y の最も低周波の係数のみを保持し、値を base83 ASCII にパックします。デコードはその逆です: 係数を読み、IDCT、キャンバスに描画。圧縮比は DCT 係数の約 99% を捨てることから来ます — 結果は数本のなめらかなカラーグラデーション以上のディテールは持ちませんが、それらのグラデーションは小サイズにおける画像の「雰囲気」を運ぶものです。エンコーダは内部で線形光 sRGB を使い色のブレンドを自然に見せ、デコーダはレンダリング前に sRGB に戻します。
BlurHash 対 LQIP / SQIP / ThumbHash — どれを使うべきですか?
**LQIP**(Low-Quality Image Placeholder)はただの縮小 JPEG(品質 5〜10%、通常長辺 16〜32 px)です。data URI でインライン化すると 200〜500 バイト — BlurHash より大きいですが、JavaScript なしでレンダリングでき、Next.js の `placeholder="blur"` でネイティブサポートされます。**SQIP** は画像を近似する SVG プリミティブを生成します。視覚的に独特ですが 1〜3 KB でエンコードも遅いです。**ThumbHash**(2023 年、Figma の Evan Wallace 作)は BlurHash の現代的競合です — ~25 バイト、わずかに視覚品質が良く、透明度に対応し、デコードが速いです。エコシステムサポートが最大限必要なら **BlurHash**(主要全言語にポートあり、Unsplash 統合)。今日始める新規プロジェクトには **ThumbHash**(同じ考え方、わずかに良いトレードオフ、ただしエコシステムは若い)。レンダリングパスで JavaScript を実行しない、または CDN が既に画像を最適化しているなら **LQIP**。
Next.js や React で BlurHash を使うには?
React では **`react-blurhash`** パッケージが最も簡単です: `<Blurhash hash={hash} width={400} height={300} />` がクライアント側で canvas を描画します。サーバレンダリング React の場合、ハッシュをサーバ側で RGBA ピクセルにデコードして base64 データ URL を出力し、それを `<img src=...>` または CSS `background-image` として使います — Next.js の `placeholder="blur"` が静的画像で内部的に行っていることです。Next.js Image に BlurHash を組み込むには、ページの `getStaticProps` / Server Component fetch でハッシュをデータ URL にデコードし、`blurDataURL` として渡し、`placeholder="blur"` を設定します。注意: Next.js の組み込み blur は BlurHash 文字列ではなく base64 JPEG/PNG データ URL を期待します — 先にデコードする必要があります。Vue、Svelte、Solid もそれぞれ類似パッケージがあります: `vue-blurhash`、`svelte-blurhash`、`solid-blurhash`。素の HTML でも動作します: `blurhash` npm パッケージを読み込み、ImageData にデコードし、canvas に描画。
BlurHash をブラウザではなくサーバでエンコードできますか?
はい、本番環境では普通そうします。Node.js の `blurhash` パッケージは本ツールと同じライブラリでブラウザ外で動作するだけです。任意の画像形式をデコードしエンコード前に縮小するには `sharp` と組み合わせます。Python: `blurhash-python`。Go: `github.com/buckket/go-blurhash`。Rust: `blurhash` クレート。典型的なパイプライン: 画像アップロード → `sharp({raw}).resize(64).raw().toBuffer()` → `encode(buffer, 64, 64*h/w, 4, 3)` → DB の画像 URL の隣にハッシュを保存。ここのブラウザツールはアドホックなワンオフエンコード、コンポーネント数の設計検証、または画像アップロードパイプラインを制御できない場合のためのものです。サーバ側エンコードは類似性クエリ用にハッシュをインデックス化できるという利点もあります — DC 成分だけで「支配色が類似する画像を見つける」用の小さなパーセプチュアルハッシュとして機能します。
デコードプレビューが元画像より彩度が高く見えるのはなぜですか?
BlurHash は線形 sRGB 色空間でエンコードされます — アルゴリズムはガンマカーブを除去した *後で* 色を平均化し DCT 変換するので、知覚的に正しい色のブレンドが得られます。デコーダに `punch` 値を 1 より大きく指定すると(`react-blurhash` の既定は 1.0 ですが、一部の統合は 1.5 を既定にします)、AC 成分が増幅され色が元画像より鮮やかになります。忠実な再現には `punch: 1.0` でデコード。実画像が届く前にプレースホルダーを「生き生き」とさせたいときだけ高い punch を使い、スワップ時に短い色シフトが起こることを受け入れます。一部の BlurHash 統合は線形光補正を欠いて代わりに色あせた出力を出すこともあります — 色が変なら参照実装と比較してください。
関連する概念
BlurHash は **プレースホルダー画像** または **プログレッシブ画像ロード** と呼ばれるカテゴリに位置し、その系譜はインターレース GIF / JPEG プログレッシブデコード(1986 年の CompuServe 向け Marc Adler の研究、1994 年の JFIF プログレッシブベースライン)にさかのぼります。共通の目標: 視聴者に *何か* を即座に表示してページが何もロードしていないように見えないようにし、ディテールは時間をかけて到着させる。現代の Web は 2014 年頃にこのアイデアを再訪しました — **Medium** が、小さな埋め込みサムネイルで CSS blur フィルターを駆動する有名なブログ記事を公開しました — これが現在 **LQIP** と呼ばれているものです。そこから: Cloudinary の **ベクトル化 SVG** プレースホルダー(2016)、Tobias Baldauf の **SQIP**(2017)、Wolt の **BlurHash**(2018)、Figma エンジニア Evan Wallace の **ThumbHash**(2023)。各反復はバイト数と知覚品質、エコシステム成熟度のトレードオフを変えました。2024 年以降の世代には **AVIF / WebP プログレッシブロード** が含まれ、これによりブラウザはフル画像が到着する前に同じファイルの低ディテール版をレンダリングできます。
下層の数学は 1974 年に Nasir Ahmed が導入した **離散コサイン変換**(DCT)で、これは JPEG、MP3、MPEG、H.264 ビデオを支える同じ変換です。DCT は空間周波数を分離します: 低周波成分は広いグラデーションと色の遷移を捉え、高周波成分は鋭いエッジや細かいテクスチャを捉えます。高周波を捨てると画像は緩やかに劣化します — 人間は低周波内容のほうをはるかに強く知覚するためです。BlurHash はこれを論理的極限まで進め、RGB チャンネルあたり 9〜81 個の DCT 係数だけを保持して密にパックします。JPEG は数千個保持します。同じ洞察は逆画像検索エンジンで使われるサムネイル生成と画像ハッシュ技術(pHash や dHash といった知覚ハッシュは同様に DCT 係数を切り詰めます)の基礎にもあります。
隣接する 3 つの関心事が BlurHash と交差します。**累積レイアウトシフト**(CLS)は、コンテンツがロードされる際に要素が動くページを罰する Core Web Vitals メトリクスです — 画像プレースホルダーは正確なピクセル空間を予約することで CLS を防ぎます。プレースホルダーが最終画像と同じ幅 × 高さを占めるため、BlurHash はここで有効です。**アクセシビリティ**: BlurHash プレースホルダー自体には alt テキストや意味的コンテンツがありません — `<img alt="...">` とペアにし、スクリーンリーダーが canvas ではなく alt を読むようにしてください。**コンテンツセキュリティポリシー**: BlurHash デコードは `<canvas>` とインライン base64 データ URI を使用し、どちらも厳格な CSP の `script-src` や `img-src` ルールで制限される可能性があります — デコード済み BlurHash サムネイルをデータ URL として配信する場合は、`default-src` が `data:` URI を許可することを確認してください。いずれも BlurHash 採用の障害ではなく、統合時に検証すべき運用上のディテールです。