Algorithm & UI/UX
Canvasによる「エモさ」の自動生成:比率制御と端末内完結処理の工夫
本ツールは、ユーザーのプライバシーを最優先しながら、写真の「エモさ」を最大限に引き出すために、Canvas APIを用いた高度な画像制御とブラウザ内完結の最適化を組み合わせています。その実装の裏側を少しだけ公開します。
1. 高速レスポンスを実現する「スケールファクタ制御」
リッチな画像加工ツールにおいて、高解像度の画像をそのまま編集Canvasに描画し続けると、メモリ不足や描画遅延が発生し、特にモバイル端末での操作性が著しく低下します。
この問題に対し、本実装では「プレビュー」と「最終書き出し」で共通のロジックを用いつつ、内部的にscale値を動的に切り替える手法を採用しました。編集画面では低解像度で高速に再描画を行い、保存時のみフル解像度でレンダリングすることで、サクサクとした操作感と高品質な出力を両立させています。
// 描画ロジックの核心部分(コンセプト)
function drawFrame(isPreview) {
const config = frameConfig[selectedRatio];
const targetCanvas = isPreview ? previewCanvas : fullCanvas;
// プレビュー時は描画負荷を下げるためのスケールを適用
const scale = isPreview ? // プレビュー用のチューニング係数 : 1;
targetCanvas.width = config.width * scale;
targetCanvas.height = config.height * scale;
// ...ここからCanvasコンテキストを使用した複雑な描画処理
}
2. アスペクト比を問わない「インテリジェント・クロップ」
チェキ風フレームの魅力は、特有の縦長・正方形比率にあります。しかし、ユーザーがアップロードする写真は千差万別です。
単に画像をリサイズして配置するのではなく、Math.maxを用いた「Cover(外接)」アルゴリズムをCanvas上で実装することで、どのようなアスペクト比の写真でも、フレームの指定範囲を隙間なく埋めつつ、中央部分を自動的に切り出す制御を行っています。
// 画像をフレーム中央に配置する座標計算
const imgW = originalImageObj.width;
const imgH = originalImageObj.height;
// フレームのアスペクト比に合わせてクロップ率を算出
const coverScale = Math.max(pW / imgW, pH / imgH);
// 描画座標の算出
const renderW = imgW * coverScale;
const renderH = imgH * coverScale;
const renderX = pX + (pW - renderW) / // 左右中央寄せの計算係数;
const renderY = pY + (pH - renderH) / // 上下中央寄せの計算係数;
ctx.drawImage(originalImageObj, renderX, renderY, renderW, renderH);
3. プライバシーを守る「端末内HEIC変換・リサイズ」
最新のiPhoneで撮影されるHEIC形式は、ブラウザのCanvas APIで直接扱うことができません。通常はサーバー側で変換を行いますが、本ツールは「安全性のためにサーバーへ写真を送らない」というポリシーを掲げています。
そこで、heic2anyライブラリをブラウザ上で動的にインポートし、クライアントサイドのみでJPEGへ変換、さらにその後の処理負荷を抑えるために、一定以上の解像度を持つ画像は自動的に最適化(独自のしきい値によるリサイズ)を行うパイプラインを構築しました。
async function handleFile(file) {
// 1. HEIC形式の場合はブラウザ内でJPEG変換を実行(サーバー通信なし)
if (file.type === 'image/heic') {
const convertedBlob = await // クライアントサイド変換ロジック;
}
// 2. ブラウザのメモリ制限を超えないよう、独自のしきい値で事前リサイズ
const MAX_LIMIT = // 安定動作のための最大サイズ制限値;
if (img.width > MAX_LIMIT || img.height > MAX_LIMIT) {
// ここでCanvasを用いてダウンサンプリング処理を行う
}
}
Developer's Note
このツールを開発する上で最もこだわったのは、**「エモい手書き感」と「徹底したプライバシー保護」の共存**です。
画像加工はサーバーで処理した方が実装は遥かに楽ですが、ユーザーの「推しの写真」や「プライベートな写真」を一時的にでもサーバーに置くことは避けたかった。そのため、すべての計算をブラウザで行う道を選びました。
また、Canvasでのテキスト描画はフォントの読み込みタイミングに依存しやすく、初期は文字が反映されないバグに悩まされましたが、document.fonts.loadを用いた非同期制御により、Webフォント(よもぎフォント)が確実に描画される仕組みを整えています。