Algorithm & UI/UX
デジカメ特有の「光のにじみ」を
Canvasで表現する
写真に日付風の文字を重ねる際、文字と光彩を分けて描くと輪郭を残したままにじみを加えられます。ここでは2回の文字描画、位置合わせ、保存される画像の仕様を説明します。
このツールの入力から出力まで
現行コードの確認日:
- 入力
- 写真を選び、年月日と文字の見た目・位置を入力します。
- 処理
- 日付文字列を組み立て、Canvasの文字描画に色や影を付けて写真へ重ねます。
- 出力
- 入力は長辺 1500px 以下、出力は JPEG(品質指定 0.95)です。
まず確認する点:入力した日付を撮影日として自動検証しません。ゼロ埋めの表記と写真の端での欠けを確認します。
仕上がりの例
写真の右上に、オレンジ色の日付を加えた例です。
日付は作例として入力した文字で、実際の撮影日時ではありません。
掲載画像はサイトにある既存の公開作例です。保存済みの資料では運営者の愛猫の写真を使用しています。今回の確認日が、この作例を実行した日を表すわけではありません。
保存済み検証記録の条件を見る
資料の種類は「ツールの出力画像を保存した記録」です。公開作例と保存済み記録で素材や色などが異なる場合があるため、下の数値は保存済み検証記録の条件として読んでください。
- 記録の入力画像
- 800×1066px (JPEG)
- 記録の出力画像
- 800×1066px (JPEG)
| 画面の項目 | 記録の値 | 現行コードの初期値・範囲 |
|---|---|---|
| 記録の日時文字 | '26 10 08 | — |
| 記録の文字サイズ | 53 | — |
| 記録の文字色 | オレンジ | — |
資料ファイルの作成日は実行日として扱っていません。個別端末の処理速度や、ほかの写真に対する検出・加工の精度を測定した資料でもありません。
実装の確認箇所:src/pages/image/date-stamp/index.astro。以下のコード抜粋と出力条件は、この本番実装に基づいて説明します。
仕組みを読み進めるときは、Canvas APIと画像処理(画像寸法、drawImage、画素と透明度の扱い)、File APIとObject URL(選んだ画像の読み込みとBlob URLの解放)が参考になります。
1. 「2層描画」によるグロー効果の再現
デジカメの日付スタンプは単なるテキストの合成ではなく、本ツールでは文字の周りに光彩を足し、日付がにじんだような表現を作ります。実際のカメラ内部の刻印方式を再現するものではありません。
Canvasの shadowBlur だけでは文字全体がボケて視認性が低下するため、本ツールでは「光彩レイヤー」と「輪郭レイヤー」を重ね合わせる手法を採用しています。
オレンジの光彩を付けてから、影を外した文字を同じ位置に描く例です。ctx の font を先に設定します。
function glowingDate(ctx, text, x, y, fontSize) {
ctx.save();
ctx.textAlign = 'right';
ctx.textBaseline = 'bottom';
ctx.fillStyle = '#ff8c00';
ctx.shadowColor = '#ff4500';
ctx.shadowBlur = fontSize * 0.15;
ctx.fillText(text, x, y);
ctx.shadowBlur = 0;
ctx.fillText(text, x, y);
ctx.restore();
} この「あえて2回書く」という実装により、デジタルのシャープさとアナログの温かみを両立させています。
2. メモリ破綻を防ぐセーフティ・スケーリング
モバイルブラウザ、特にiOS Safariでは高解像度画像をCanvasで扱うとメモリ制限によりクラッシュするリスクがあります。
本ツールでは、読み込み時にアスペクト比を維持したまま、実装で定めた長辺 1500px 以下へリサイズするロジックを組み込んでいます。
出力の仕様と確認する点
日付欄の文字を画像に焼き付ける処理です。EXIF の撮影日時を読み取って証明する機能ではなく、任意の文字列を入れられます。入力内容が撮影日と一致するかは利用者が確認します。
文字は右下を基準に配置し、文字幅を measureText で求めてドラッグ範囲を作ります。色はオレンジ・白・黒で、それぞれ影の色と強さが変わります。長い文字は画像端からはみ出すため位置とサイズを調整します。
入力は長辺 1500px 以下、出力は JPEG(品質指定 0.95)です。日付を別レイヤーとして残さないため、書き出した画像から文字だけを編集することはできません。元写真も保管してください。
