Architecture & Performance
複数Canvas合成と疑似ぼかし
アルゴリズムの最適化手法
ブラウザ上での画像加工は、解像度が増すほど計算負荷が指数関数的に増大します。ユーザー体験を損なわず、かつ滑らかなペン操作を実現するための「レイヤー合成」と「疑似フィルタ」のハックを紐解きます。
1. destination-in モードを用いた非破壊レイヤー合成
このツールの核心は、元の画像を直接書き換えるのではなく、5枚のCanvas(元画像、モザイク用、ぼかし用、マスク用、合成一時用)をレイヤーとして管理している点にあります。ユーザーがなぞった軌跡を「マスク」として保持し、globalCompositeOperation = 'destination-in' を使用してエフェクト層を型抜きしています。
メリット: 消しゴム機能の実装が「マスク層を透明にするだけ」で完結します。また、モザイクとぼかしを切り替える際も、既に描いたマスクを流用できるため、再描画のコストが最小限で済みます。
// マスクを用いた合成プロセスの概要
function renderComposite() {
// 1. 一時キャンバスにエフェクト層(モザイク等)を描画
tempCtx.drawImage(effectLayer, 0, 0);
// 2. 「型抜き」モードに切り替え
tempCtx.globalCompositeOperation = 'destination-in';
// 3. ユーザーがなぞった軌跡(マスク)を重ねる
tempCtx.drawImage(maskCanvas, 0, 0);
// 4. 元画像の上に、型抜かれたエフェクトだけを上書き
mainCtx.drawImage(originalImg, 0, 0);
mainCtx.drawImage(tempCanvas, 0, 0);
} 2. 縮小・拡大による低コストな「疑似ぼかし」ハック
ブラウザ標準の filter: blur() は、動的に変化する描画に対しては計算負荷が非常に高く、スマホではカクつきの原因になります。本ツールでは、画像を一度極小サイズに縮小し、imageSmoothingEnabled = true(滑らかな補完)を有効にした状態で元のサイズに拡大し直すことで「疑似ぼかし」を生成しています。
メリット: ピクセルごとの重い畳み込み演算を回避し、GPUのテクスチャ補完機能を利用するため、4K近い画像でも一瞬でぼかし済みレイヤーを用意できます。
// 疑似ぼかしレイヤーの生成ロジック
function createPseudoBlur(source) {
const scale = // 独自のチューニング値;
const smW = source.width * scale;
const smH = source.height * scale;
// 一旦小さく描画(情報を間引く)
smallCanvasCtx.drawImage(source, 0, 0, smW, smH);
// 滑らかな補完を有効にして元のサイズへ戻す
blurCtx.imageSmoothingEnabled = true;
blurCtx.drawImage(smallCanvas, 0, 0, smW, smH, 0, 0, source.width, source.height);
} 3. requestAnimationFrame による描画頻度の制御
高頻度で発生する touchmove イベントごとに Canvas の合成処理を走らせると、ブラウザの描画パイプラインが飽和します。本ツールでは、イベント発生時は「フラグを立てる」だけにとどめ、ディスプレイの更新タイミング(requestAnimationFrame)に合わせて描画を統合しています。
メリット: 入力イベントと描画更新を分離することで、ペンの追従性を最大限に高めつつ、バッテリー消費や発熱を抑えることができます。
// レンダリング・ループの最適化
let isPending = false;
function onMove() {
updateMaskData(); // マスクの座標更新は即時
if (!isPending) {
isPending = true;
requestAnimationFrame(() => {
renderComposite(); // 重い合成処理をフレーム同期
isPending = false;
});
}
} Developer's Note
このツールの開発において、最もこだわったのは「iPhoneユーザーへの配慮」です。
iOSの標準カメラで採用されている HEIC 形式は、そのままではブラウザで扱えません。これを解決するために、heic2any ライブラリを動的に読み込む仕組みを導入しました。また、iOS Safari はメモリ制限が厳しいため、1500pxを超える巨大な画像は、アスペクト比を保ったまま安全なサイズへ自動リサイズするガードレールを設けています。
「アナログな『なぞる』という動作を、デジタルでいかにストレスなく再現するか」。そのために、高度なAIではなく、泥臭いCanvasの最適化を積み上げたのがこのツールです。