猫の手ツール

Rendering Architecture

Canvas合成モードと静的キャッシュによるレトロ質感の再現

セピア色の「深み」と、時間の経過を感じさせる「傷やノイズ」の質感を、ブラウザのメインスレッドを止めずに描画するための工夫を紐解きます。

1. 「Color」と「Multiply」による多段セピア変換

セピア調の画像を作る際、単一の半透明レイヤーを重ねるだけでは、ハイライト部分のディテールが失われ、不自然な「塗りつぶし感」が出てしまいます。本ツールでは、globalCompositeOperation を活用し、2段階の合成を行っています。

メリット: まず color モードで輝度を維持したまま色相だけをアンティーク調に変更し、次に multiply(乗算)で深みのある影を付与しています。これにより、元の写真が持つ質感を殺さずに、重厚なセピア色を実現しています。

// 二段階の合成モードによる色調補正
ctx.save();

// 1. 色相の置換(輝度はそのまま)
ctx.globalCompositeOperation = 'color';
ctx.globalAlpha = // 独自のチューニング値;
ctx.fillStyle = '#704214'; // 特製のアンティークカラー
ctx.fillRect(drawX, drawY, dw, dh);

// 2. 質感の深度化(乗算による影の強調)
ctx.globalCompositeOperation = 'multiply';
ctx.globalAlpha = // 独自のチューニング値;
ctx.fillStyle = '#5a3a22'; // 深みのある影色
ctx.fillRect(drawX, drawY, dw, dh);

ctx.restore();

2. ノイズパターンとスクラッチの「事前生成・キャッシュ化」

アンティーク写真に欠かせない「激しいノイズ」や「無数の傷(スクラッチ)」は、描画のたびに乱数計算を行うと非常に重くなります。特にスライダーで調整を行う際、リアルタイムに数千本の線を再計算するのは現実的ではありません。

メリット: 小さなノイズタイル(Pattern)をオフスクリーンCanvasに事前に描き、メインCanvasには createPattern で敷き詰めることで負荷を劇的に軽減しています。また、傷の座標も配列としてキャッシュし、スライダー操作時はその配列を走査するだけにすることで、滑らかなプレビューを実現しました。

// ノイズパターンのキャッシュ生成
const noiseCanvas = document.createElement('canvas');
// ここにピクセル単位のノイズ生成ロジックが入ります(初期化時のみ実行)

// 描画時の適用
const pattern = ctx.createPattern(noiseCanvas, 'repeat');
ctx.fillStyle = pattern;
ctx.globalAlpha = // スライダーによる変動値;
ctx.fillRect(0, 0, CW, CH);

// 傷(スクラッチ)のキャッシュ利用
// 座標や角度をあらかじめ計算済みの配列から呼び出し
cachedScratches.slice(0, numLines).forEach(scratch => {
    // 描画処理のみを実行
    ctx.moveTo(scratch.x, scratch.y);
    ctx.lineTo(scratch.x + scratch.len * scratch.angle, scratch.y + scratch.len);
});

3. ブラウザクラッシュを防ぐ「MAX_SIZE」ガードレール

現代のスマホ写真は4000pxを超えることも珍しくありませんが、そのような巨大なImageDataをCanvasでピクセル操作しようとすると、メモリ不足でブラウザがクラッシュ(タブのクラッシュ)を引き起こします。

メリット: 画像読み込み時に、アスペクト比を維持したまま、処理可能な上限値(ガードレール)へリサイズするパイプラインを構築しています。これにより、低スペックなデバイスでも安定して加工を楽しめる堅牢性を確保しています。

// 巨大画像に対する動的リサイズ処理
const MAX_DIMENSION = // 独自の制限値;
if (img.width > MAX_DIMENSION || img.height > MAX_DIMENSION) {
    const scale = Math.min(MAX_DIMENSION / img.width, MAX_DIMENSION / img.height);
    
    // 一時Canvasを作成し、縮小描画
    // この縮小済み画像をソースとして以降の加工を行う
    // ここにリサイズ実行処理が入ります
}

Developer's Note

「エモさ」とは、情報の欠損から生まれる想像力だと考えています。

このツールでは、単にセピアにするだけでなく、いかに「綺麗に汚すか」に心血を注ぎました。傷(スクラッチ)も、ただの黒い線ではなく、時折「白い傷」を混ぜることで、印画紙の物理的な剥がれを表現しています。

また、iPhone独自のHEIC形式をブラウザ内でJPEGへ動的変換する仕組みは、当サイトの「外部サーバーへ一切送信しない」というポリシーを貫くために不可欠な実装でした。あなたのプライベートな記憶を、あなたの端末の中だけで、100年前の物語に変える。その魔法を支えるのは、泥臭いCanvasの最適化技術です。