はじめに
Elixir の Image モジュールで BlurHash によるぼかし画像を生成します
BlurHash の Web サイトより引用
BlurHash is a compact representation of a placeholder for an image.
和訳
BlurHashは、画像のプレースホルダーとして使われるコンパクトな表現方法です。
高画質画像の多い Web サイトを開いたとき、なかなか画像が読み込まれず、空っぽの枠だけが表示されることがあります
空っぽの状態というのがあまりカッコよくないため、低画質のサムネイルを先に読み込んでおくという手法もありますが、この場合、全画像のサムネイルをストレージに保存しなければなりません
そこで、 BlurHash では画像をぼかした低画質サムネイルを生成し、更にそれを短い文字列に変換してデータベース上に保存できるようにします
Webサイトに表示する際には文字列からサムネイルに変換して使用します
論より RUN なので、とにかく実行してみましょう
実装したノートブックはこちら
セットアップ
必要なモジュールをインストールします
Mix.install([
{:image, "~> 0.52"},
{:kino, "~> 0.13"}
])
画像の読み込み
任意の画像を読み込みます
BlurHash では不透明度(RGBA の A チャネル)を扱えないため、 RGB だけに分離します
{puppies_img, _} =
"/home/livebook/vix/puppies.png"
|> Image.open!()
|> Image.split_alpha()
puppies_img
BlurHash の文字列取得
Image.Blurhash.encode で画像を文字列化した値が取得できます
{:ok, blurhash} = Image.Blurhash.encode(puppies_img)
実行結果
{:ok, "LJGv9Eom_19J_IoNIUs=pV?Z9IoI"}
データベースにはこの文字列を保存しておきます
BlurHash の画像取得
Image.Blurhash.decode で文字列を画像に変換します
第2引数は画像の幅、第3引数は画像の高さです
{:ok, decoded} = Image.Blurhash.decode(blurhash, 400, 400)
decoded
実行結果
元画像と並べると、ぼかしていることが良くわかります
ぼかし具合の制御
Image.Blurhash.encode のオプションでぼかし具合が制御できます
- x_components: 横方向のブロック数(1 〜 9)
- y_components: 縦方向のブロック数(1 〜 9)
ブロック数が小さいほどぼかしが強くなります
ぼかし具合がどれくらい変わるのか見てみましょう
1 * 1 を指定するとエラーになるので、 2 * 2 までを指定しています
9..2//-1
|> Enum.map(fn components ->
puppies_img
|> Image.Blurhash.encode(x_components: components, y_components: components)
|> elem(1)
|> Image.Blurhash.decode(400, 400)
|> elem(1)
end)
|> then(&[puppies_img | &1])
|> Kino.Layout.grid(columns: 3)
左上は無加工の画像です
徐々にぼかしが強くなっているのが分かります
まとめ
BlurHash を使うことで、画像を短い文字列に変換し、更にぼかし画像に変換できました
EC サイトのような画像が大量に並ぶケースで使えそうです


