猫の手ツール

Algorithm & UI/UX

Canvasで実現する「エモい」質感。
モバイル向け最適化と独自ブラー

「水滴レンズ風ジェネレーター」は、一見シンプルな画像加工ツールですが、ブラウザ(特にモバイル環境)での動作を安定させるために、Canvas APIの性能を限界まで引き出す工夫が凝らされています。本稿ではその中核となるロジックを紐解きます。

このツールの入力から出力まで

現行コードの確認日:

入力
写真と雨粒の量・サイズ、背景のぼかしを指定します。
処理
写真の色調とぼかしを変え、円や光点で最大500個の水滴を描きます。
出力
入力は長辺 2000px 以下、出力は 1000×1000px の JPEG(品質指定 0.85)です。

まず確認する点:水滴の中で背景が屈折する光学計算は行いません。粒を0にしても残る色調加工を、元写真と比べます。

仕上がりの例

写真に水滴レンズ風の効果を重ねた例です。

加工前・加工後
左は愛猫2匹が並ぶ写真。右はぼかした写真に多数の丸い水滴を加えた画像。

加工前・加工後

左は愛猫2匹が並ぶ写真。右はぼかした写真に多数の丸い水滴を加えた画像。

掲載画像はサイトにある既存の公開作例です。保存済みの資料では運営者の愛猫の写真を使用しています。今回の確認日が、この作例を実行した日を表すわけではありません。

保存済み検証記録の条件を見る

資料の種類は「ツールの出力画像を保存した記録」です。公開作例と保存済み記録で素材や色などが異なる場合があるため、下の数値は保存済み検証記録の条件として読んでください。

記録の入力画像
800×667px (JPEG)
記録の出力画像
1000×1000px (JPEG)
保存済み記録の主な操作・出力条件
画面の項目記録の値現行コードの初期値・範囲
記録で選択されていた項目普通—
水滴の量60初期値 60 / 範囲 0〜100
背景のぼかし8初期値 8 / 範囲 0〜20
写真のズーム100初期値 100 / 範囲 50〜300

記録では「エモい画像を生成!」から完成表示へ進んでいます。初期値と記録値を比べてから、効果を1項目ずつ変えると作用を確認しやすくなります。

資料ファイルの作成日は実行日として扱っていません。個別端末の処理速度や、ほかの写真に対する検出・加工の精度を測定した資料でもありません。

実装の確認箇所:src/pages/image/water-droplets/index.astro。以下のコード抜粋と出力条件は、この本番実装に基づいて説明します。

仕組みを読み進めるときは、Canvas APIと画像処理(画像寸法、drawImage、画素と透明度の扱い)、メモリ管理と画像処理(画素バッファ、縮小と容量予算)が参考になります。

1. モバイルSafariを考慮した「疑似ブラー」の実装

Canvasの filter は利用できるブラウザに差があります。このツールは縮小・拡大と重ね描きでぼかし風の画像を作ります。

当ツールではこの問題を回避するため、オフスクリーンキャンバスを利用した「多重縮小転送方式」による疑似ブラーを採用しています。

写真部分の彩度と明るさの計算を1画素にした例です。水滴の円はこの処理の後に描きます。

function dropletTone(r, g, b) {
  const y = r * 0.299 + g * 0.587 + b * 0.114;
  return new Uint8ClampedArray([r, g, b].map(v => (v * 1.1 - y * 0.1) * 0.9));
}

この手法のメリットは、画像の拡大・縮小と重ね描きでぼかし風の見た目を作れる点にあります。これにより、ぼかし用の畳み込み処理を実装せずに輪郭を広げます。端末によっては再描画に時間がかかる場合があります。

2. ピクセル操作による「エモい」カラーグレーディング

単に水滴を描画するだけでは、写真と合成した際に質感が浮いてしまいます。当ツールでは、描画された写真のピクセルに対して彩度と明るさの調整を行っています。

特にこだわったのは、Luma(輝度)ベースの彩度・明るさ調整です。CSSフィルタの saturate や brightness を使わず、あえて getImageData で直接ピクセルを弄ることで、ノスタルジックな質感を演出しています。

この独自実装により、単なる色の強調ではなく、暗部が少し沈み、光のボケが引き立つような「記憶の中の景色」に近い色合いを生み出しています。

3. 描画負荷を軽減する「水滴キャッシュシステム」

「水滴の量」スライダーを動かした際、毎回ランダムに水滴を生成すると、水滴の位置がパラパラと動いてしまい、不自然な見え方になります。これを防ぎ、かつ計算量を減らすために、あらかじめ大量の水滴データをメモリ上にキャッシュしています。

このように「描画すべき情報の決定」と「実際の描画」を分離することで、複雑なベクター描画を伴う水滴の追加処理でも既存の水滴の位置を保てます。

出力の仕様と確認する点

入力は長辺 2000px 以下、出力は 1000×1000px の JPEG(品質指定 0.85)です。写真の位置とズームを変えて正方形内の構図を調整します。

水滴は最大 500 個の円、輪郭の光沢、小さな光点です。サイズは小 0.5 倍・標準 1 倍・大 1.6 倍。水滴の中で背景を拡大・反転する光の屈折は計算しません。

ぼかし 1〜20 では縮小率 1 / (値×0.2+1) の画像を5回ずらして重ねます。水滴 0・ぼかし 0 でも彩度と明るさの調整は残るため、元写真と同じ色にはなりません。