猫の手ツール

Algorithm & UI/UX

クライアントサイドで完結させる
画像PDF変換の最適化戦略

サーバーに一切画像を送信せず、ブラウザのメモリ上だけでPDFを構築する。この「プライバシー第一」の設計を実現するために導入した、メモリ消費を抑える最適化アルゴリズムと、多様な画像サイズをA4に収めるフィッティングロジックについて解説します。

このツールの入力から出力まで

現行コードの確認日:

入力
順番に並べたい画像を複数選びます。縦長と横長が混ざった入力でも、各画像の幅と高さを使います。
処理
読み込んだ画像をJPEGへ縮小し、jsPDFで1枚につきA4の1ページを追加します。画像比率を保ってページ中央へ収め、余白を作ります。
出力
画像ごとに1ページの A4 PDF を作ります。

まず確認する点:一覧の順序がPDFのページ順です。文字の検索性ではなく、生成PDFを拡大したときの細い文字の読みやすさを確認します。

仕上がりの例

猫の写真2枚を、1枚ずつ別ページに配置したPDFの例です。

加工前・加工後
左は愛猫2匹の横長写真と猫1匹の縦長写真。右は保存したPDFの1ページ目と2ページ目を並べた表示。

保存したPDFの2ページを、比較用に並べて表示しています。

加工前・加工後

左は愛猫2匹の横長写真と猫1匹の縦長写真。右は保存したPDFの1ページ目と2ページ目を並べた表示。

掲載画像はサイトにある既存の公開作例です。保存済みの資料では運営者の愛猫の写真を使用しています。今回の確認日が、この作例を実行した日を表すわけではありません。

保存済み検証記録の条件を見る

資料の種類は「ツールの出力画像を保存した記録」です。公開作例と保存済み記録で素材や色などが異なる場合があるため、下の数値は保存済み検証記録の条件として読んでください。

写真2枚を、縦横比を保って1枚ずつ別のA4ページへ最大化。写真の向きに合わせた2ページのPDFを実際に保存し、各ページを表示。

記録の入力画像
800×667px (JPEG)、800×1066px (JPEG)
保存済みPDFを表示した記録画像
994×703px (PNG)、703×994px (PNG)
保存済み記録の主な操作・出力条件
画面の項目記録の値現行コードの初期値・範囲
記録のPDFページ数2ページ—

資料ファイルの作成日は実行日として扱っていません。個別端末の処理速度や、ほかの写真に対する検出・加工の精度を測定した資料でもありません。

実装の確認箇所:src/pages/image/to-pdf/index.astro。以下のコード抜粋と出力条件は、この本番実装に基づいて説明します。

仕組みを読み進めるときは、async / awaitと並行処理(画像やライブラリの取得を待つ処理の順序)、File APIとObject URL(選んだ画像の読み込みとBlob URLの解放)が参考になります。

1. 2段階の適応型リサイズ・パイプライン

スマホで撮影した写真は1枚数MB〜十数MBに達することがあります。これらをそのまま複数枚読み込むと、ブラウザのメモリが枯渇し、タブがクラッシュする原因となります。

本ツールでは、ファイルを読み込んだ直後に「1段階目の粗いリサイズ」を行い、サムネイル用データの作成時に Canvas を用いて「2段階目の縮小」を行うパイプラインを採用しています。これにより、HEICなどの重い形式も軽量なJPEGに変換され、PDF に埋め込む画像の画素数と容量を減らします。大量の画像を保持するとメモリ不足になる場合があります。

1枚をページ内へ切り取らずに収める計算です。pageWidth・pageHeight の単位は mm を想定します。

function pdfFit(iw, ih, pageWidth, pageHeight) {
  const scale = Math.min(pageWidth / iw, pageHeight / ih);
  const width = iw * scale, height = ih * scale;
  return { x: (pageWidth - width) / 2, y: (pageHeight - height) / 2, width, height };
}

2. アスペクト比を維持する動的センタリング・アルゴリズム

PDF作成時、画像によって向き(縦・横)や比率はバラバラです。本実装では、jsPDFのページ設定を動的に切り替えつつ、A4の枠内に画像を「アスペクト比を維持しながら最大サイズで配置」する計算を行っています。

特に、ページ比率と画像比率を比較し、縦に合わせるか横に合わせるかを分岐させることで、どのような形状の画像でも中央に綺麗にレイアウトされます。

出力の仕様と確認する点

画像ごとに1ページの A4 PDF を作ります。画像の幅が高さより大きければ横向き、それ以外は縦向きです。比率を保ってページ中央に配置するので、画像を切り落とす代わりに余白ができます。

読み込み段階に長辺 2500px の制限があり、一覧に保持する画像はさらに長辺 1500px 以下の JPEG(品質指定 0.8)にします。PDF はこの JPEG を埋め込むため、元画像の画質や寸法をそのまま保つ変換ではありません。

並び順がページ順になります。画像内の文字を認識する OCR はなく、検索・選択できるテキストにはなりません。細い文字の書類は、作成した PDF を拡大して読みやすさを確認してください。