Algorithm & UI/UX
光の回折をブラウザで再現する:
キラキラ・クロス加工の裏側
夜景やジュエリーを輝かせる「クロスフィルター」の効果を、数式とCanvas描画だけで再現。サーバーを介さない高速な輝度検知と、動的なベクター描画の仕組みを紐解きます。
1. 適応的サンプリングによる高速輝度検知
写真の中から「輝いている場所」を自動で見つけ出すため、ピクセルごとの輝度を解析しています。しかし、数百万画素におよぶ高解像度画像をすべて走査すると、特にモバイル端末では大きな遅延が発生します。
本ツールでは、画像の解像度に応じて解析間隔を動的に調整する「サンプリング・ステップ」を導入しました。これにより、精度を維持しながら解析時間を劇的に短縮しています。
// 高速解析のためのサンプリングロジック概要
const step = // 解像度に応じたサンプリング間隔を算出;
for (let y = 0; y < h; y += step) {
for (let x = 0; x < w; x += step) {
const i = (y * w + x) * 4;
// RGB値を元に輝度を算出
const brightness = // 独自の輝度計算ロジック;
if (brightness > sparkleSettings.threshold) {
// ハイライト箇所として座標を記録
points.push({x, y});
}
}
} 2. 座標変換とベクターグラデーションによる「光の筋」の生成
キラキラの描写には静止画画像を使用せず、Canvasの描画命令のみで構成されています。これにより、大きさを変えても画質が劣化せず、さらに「虹色(プリズム)」のような複雑な色変化も、数式ベースのグラデーションでリアルタイムに生成可能です。
指定された本数(4本、6本、8本)に合わせて ctx.rotate を用いながら座標系を回転させ、中心から外側へ減衰する光の軌跡を描いています。
// 回転座標系を利用したマルチアーム描画
ctx.translate(x, y); // 輝点に中心を移動
const arms = // 設定された光の数;
const rotation = (Math.PI * 2) / arms;
for (let i = 0; i < arms; i++) {
ctx.save();
ctx.rotate(i * rotation);
// 中心から外側へ消えていく線形グラデーション
const grad = ctx.createLinearGradient(0, 0, size, 0);
// ここにカラー設定に応じたaddColorStop処理が入ります
ctx.fillStyle = grad;
// 光の鋭さを表現するパスを描画
// ここに三角形(光の筋)の描画ロジックが入ります
ctx.fill();
ctx.restore();
} Developer's Note
実装において最もこだわったのは「タップによる手動追加」と「自動検知」の融合です。アルゴリズムが完璧にハイライトを見つけられなくても、ユーザーが「ここを光らせたい!」と思った場所を自由に装飾できるUXを目指しました。
また、Canvasの globalCompositeOperation = 'screen' を活用することで、光が重なった部分が白飛びする「現実の光学現象に近い合成」をブラウザ上で再現しています。サーバーへの画像アップロードが一切発生しないため、プライベートな写真も安心して加工できる、今の時代に合った設計を貫いています。