Color Logic & Performance
Canvas合成モードによる質感表現と
解像度制御の最適化手法
「エモい写真」には、単なる半透明の色重ね以上の深みが必要です。写真のハイライトやシャドウを活かしつつトーンを統一するCanvasのブレンド技術と、巨大な画像データでも軽快に動作させるためのリサイズ戦略を解説します。
1. GlobalCompositeOperation による高度な色相ブレンド
写真に色を重ねる際、単に opacity(不透明度)を下げた色を被せるだけでは、白飛びしたり色が濁ったりしてしまいがちです。本ツールでは、Canvasの globalCompositeOperation を活用し、overlay(オーバーレイ)や soft-light(ソフトライト)などのブレンドモードを使い分けています。
メリット: オーバーレイ等を用いることで、写真の明るい部分は明るく、暗い部分は暗いまま、中間の階調にだけ色を乗せることが可能になります。これにより、写真のディテール(細部)を損なうことなく、Instagramのフィードで好まれるような洗練された「統一感」を生み出しています。
// Canvas上でのブレンド処理の核となる実装
function applyFilter(ctx, color, blendMode, opacity) {
const { width, height } = ctx.canvas;
// 写真そのものを描画した後に、合成モードを指定
ctx.save();
// 独自のブレンドモード(overlay, soft-lightなど)を適用
ctx.globalCompositeOperation = blendMode;
// 透明度を独自のチューニング値に基づき設定
ctx.globalAlpha = opacity / 100;
// 指定された色(ベージュ、ピンク等)で全面を塗りつぶす
ctx.fillStyle = color;
ctx.fillRect(0, 0, width, height);
ctx.restore();
} 2. メモリ破壊を防ぐ「二段階オフスクリーン・リサイズ」
最近のスマートフォンの写真は4Kを超えることも珍しくありませんが、そのような巨大なImageDataをCanvasでそのまま処理しようとすると、モバイルブラウザはメモリ不足で即座にクラッシュします。本ツールでは、読み込み直後にオフスクリーンCanvasを用いて、処理に最適な上限解像度(MAX_SIZE)へスケーリングしています。
メリット: 処理負荷を一定以下に抑えつつ、書き出し時にはSNS投稿に十分な高画質を維持。さらに、一度リサイズした結果を新たな Image オブジェクトとして再構成することで、プレビュー時の再描画コストを劇的に低減させています。
// 巨大画像に対する安全なガードレール実装
const MAX_DIMENSION = // 独自の制限値(例:1500px);
async function handleResolution(img) {
let w = img.width;
let h = img.height;
if (w > MAX_DIMENSION || h > MAX_DIMENSION) {
const scale = MAX_DIMENSION / Math.max(w, h);
w = Math.floor(w * scale);
h = Math.floor(h * scale);
}
// オフスクリーンCanvasで一度「焼き付け」を行う
const offscreen = document.createElement('canvas');
offscreen.width = w;
offscreen.height = h;
const ctx = offscreen.getContext('2d');
// ここで高解像度から安全なサイズへサンプリング
ctx.drawImage(img, 0, 0, w, h);
// 以降はこの「適正サイズ」の画像をソースとして使い回す
return await convertToProcessableImage(offscreen);
} 3. ブラウザ完結型の HEIC 変換パイプライン
iPhoneユーザーの標準形式である HEIC はブラウザで直接表示できないため、本ツールでは heic2any ライブラリを動的に読み込み、クライアントサイドで JPEG 変換を行っています。
メリット: 「写真を一枚も外部サーバーに送らない」という当サイトのプライバシーポリシーを貫くために、この変換工程もすべて端末内で完結させています。動的インポートを用いることで、HEIC画像を選択したユーザーだけが変換コードをロードする仕組みにし、初期読み込み速度も確保しています。
// HEIC変換のフロー(疑似コード)
if (file.name.match(/\.(heic|heif)$/i)) {
// 必要な時だけライブラリをロード
const { convert } = await import('heic-conversion-lib');
// 独自の品質パラメータでブラウザ内変換
const jpegBlob = await convert(file, {
type: "image/jpeg",
quality: // 独自の画質係数
});
// 変換後のBlobをCanvasへ流し込む
processCanvas(jpegBlob);
} Developer's Note
このツールで一番大切にしたのは、Instagramなどのフィードを「作り込む楽しさ」です。
ベージュやピンクのフィルターをただ重ねるだけなら既存のアプリでもできますが、ブラウザだけで、しかもサーバー送信なしでサクサクと何枚も加工できる体験を目指しました。特に「オーバーレイ」と「ソフトライト」の挙動は、写真の質感を一番綺麗に残せるよう、デフォルトの不透明度を微調整しています。
「大切な写真を誰にも見られず、自分好みのトーンに変える」。このシンプルな安心感を最新のフロントエンド技術で支えることが、この実装のテーマです。