猫の手ツール

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の最適化を積み上げたのがこのツールです。