Algorithm & UI/UX
Canvasで描く「叙情的な雨」と
軽量ブラーのハック
本ツールでは、雨や窓枠の描画に外部画像を使用せず、ブラウザ標準のCanvas APIのみで「雨粒越しの視界」を演出しています。モバイル端末でのパフォーマンスを維持しつつ、切なさを最大化するための独自の画像処理アルゴリズムについて解説します。
このツールの入力から出力まで
現行コードの確認日:
- 入力
- 写真を選び、雨粒と背景のぼかしを調整します。
- 処理
- ぼかした写真に雨粒の図形や輪郭を重ね、窓越しに見える静止画を合成します。
- 出力
- 長辺 1500px 以下の入力を使い、1000×1000px の JPEG(品質指定 0.85)を保存します。
まず確認する点:ぼかしと粒の量は独立した効果です。雨粒の下で写真の細部がどう見えるか、文字や顔の残り方を確認します。
仕上がりの例
写真に雨粒と窓枠を重ね、雨の車窓風にした例です。
掲載画像はサイトにある既存の公開作例です。保存済みの資料では運営者の愛猫の写真を使用しています。今回の確認日が、この作例を実行した日を表すわけではありません。
保存済み検証記録の条件を見る
資料の種類は「ツールの出力画像を保存した記録」です。公開作例と保存済み記録で素材や色などが異なる場合があるため、下の数値は保存済み検証記録の条件として読んでください。
- 記録の入力画像
- 800×667px (JPEG)
- 記録の出力画像
- 1000×1000px (JPEG)
| 画面の項目 | 記録の値 | 現行コードの初期値・範囲 |
|---|---|---|
| 記録で選択されていた項目 | モダン | — |
| 雨粒の量 | 60 | 初期値 60 / 範囲 0〜100 |
| 背景のぼかし | 8 | 初期値 8 / 範囲 0〜20 |
| 写真のズーム | 100 | 初期値 100 / 範囲 50〜300 |
記録では「エモい画像を生成!」から完成表示へ進んでいます。初期値と記録値を比べてから、効果を1項目ずつ変えると作用を確認しやすくなります。
資料ファイルの作成日は実行日として扱っていません。個別端末の処理速度や、ほかの写真に対する検出・加工の精度を測定した資料でもありません。
実装の確認箇所:src/pages/image/rainy-window/index.astro。以下のコード抜粋と出力条件は、この本番実装に基づいて説明します。
仕組みを読み進めるときは、Canvas APIと画像処理(画像寸法、drawImage、画素と透明度の扱い)、メモリ管理と画像処理(画素バッファ、縮小と容量予算)が参考になります。
1. 縮小画像を重ねる疑似ぼかしの実装
Canvasの filter = "blur(px)" は利用できるブラウザに差があります。このツールは縮小・拡大と重ね描きで輪郭を広げる方法を使います。
そこで本ツールでは、「オフスクリーンCanvasへの縮小描画」と「多重描画」を組み合わせた疑似ブラーハックを採用しました。まず画像を設定に応じて最大 1/5 まで縮小してピクセルを潰し、それを元のサイズに引き伸ばしながら、わずかに座標をずらして透明度を重ねて描画します。これにより、輪郭を複数方向へ広げます。ガウスぼかしとは計算方法が異なり、端末ごとの速度も保証しません。
雨量から描画する雨粒の数を求める例です。キャッシュの先頭からこの個数を取り出します。
function dropCount(density) {
return Math.floor(Math.max(0, Math.min(100, density)) / 100 * 500);
} 2. ピクセル操作による「叙情的な色彩」の調整
「エモさ」の正体は、彩度を落としつつコントラストを微調整した独特のトーンにあります。CSSフィルタを使わず、CanvasのgetImageDataから取得した生ピクセルデータ(RGBA配列)を直接操作することで、各ピクセルの輝度に基づいた高度な色調補正を行っています。
具体的には、各ピクセルのRGB値からLuma(輝度)を算出し、その輝度値に寄せることで彩度を制御し、最後に独自の係数を掛けて全体的なトーンを落ち着かせています。
3. 雨粒のランダム生成とキャッシュ戦略
雨粒はellipse関数を用いて描画していますが、スライダーを動かすたびに全ての雨粒の位置をランダム生成すると、雨粒が画面上で「踊って」しまい、リアリティが損なわれます。
これを防ぐため、アプリ起動時に500 個の雨粒の座標、サイズ、透明度、および「伸び率(縦長具合)」を事前に計算して配列にキャッシュしています。ユーザーが密度スライダーを動かした際は、その配列の「参照するインデックス範囲」を増減させるだけでよいため、同じ編集中は既存の雨粒の位置が変わりません。
出力の仕様と確認する点
長辺 1500px 以下の入力を使い、1000×1000px の JPEG(品質指定 0.85)を保存します。雨は固定の楕円とハイライトで、滴が流れる動画や屈折の計算ではありません。
ぼかしは 0〜20。正の値では縮小した写真を透明度 0.2 で5回重ねます。雨量 0 でも彩度・明るさの調整と周辺減光は残るため、元写真と同一にはなりません。
窓の種類は外枠のみ・中央の縦桟・十字の桟などを切り替えます。枠なしに相当する選択でも外周の線は描かれる実装です。ズームや移動で画像のない領域ができていないか保存前に確認します。
