【ITニュース解説】A PDF merge can preserve mixed page sizes: verify the download, not the thumbnails
2026年10月23日に「Dev.to」が公開したITニュース「A PDF merge can preserve mixed page sizes: verify the download, not the thumbnails」について初心者にもわかりやすく解説しています。
ITニュース概要
PDFを結合する際、異なるページサイズが意図せず統一されてしまう場合がある。プレビューはあてにならないため、ダウンロード後に`pdfinfo`などのツールで各ページのサイズや順序を詳細に確認することが重要だ。
ITニュース解説
PDFファイルを複数結合する際、それぞれのページのサイズが異なる場合、結合後のプレビュー画面(サムネイル)では、あたかも全てのページが同じサイズになったかのように表示されることがある。しかし、これは単なるプレビューの表示上の都合であり、実際にダウンロードしたPDFファイルでは元の異なるページサイズがそのまま維持されている場合がある。このような挙動は、PDF結合ツールの契約内容が「指定されたページをこの順序で単に連結する」というものであるならば、それはむしろ正しい動作だ。もし全てのページを特定のサイズに統一したいのであれば、それは「サイズ変更」や「正規化」と呼ばれる別の操作であり、適切なスケーリングやトリミングといった個別の設定が必要となる。システムエンジニアとしてPDFを扱う際には、この「見かけ」と「実体」の違いを理解し、結合後のファイルが期待通りの状態になっているか、適切に検証する能力が求められる。
この検証では、PDF結合ツールが偶発的にページサイズを変更してしまわないかをチェックするために、特定のテストデータ(フィクスチャ)を用いる。このフィクスチャは、意図的に異なるページサイズを持つPDFファイルを用意する点が特徴だ。例えば、1ページ構成のA4サイズのカバーファイルと、LetterサイズとA4サイズが混在する2ページ構成のレポートファイルを使用する。これらのファイルは、それぞれが固有のテキストマーカーを持つように作成される。これは、後で結合されたPDFからテキストを抽出した際に、どのページがどの元のファイルから来たのか、そしてその順序が正しいかを識別するためだ。結合後のPDFファイルが、この順序通りに、つまりカバーページの後にレポートの最初のページ、そしてレポートの2ページ目が続く形で、それぞれのページサイズが正しく維持されているかを検証する。具体的な期待される出力は、最初のページがA4(幅595.2756 × 高さ841.8898単位)、2ページ目がLetter(幅612.0000 × 高さ792.0000単位)、3ページ目が再びA4(幅595.2756 × 高さ841.8898単位)となる。PDFのページサイズは「ポイント(pt)」という単位で表現され、デフォルトでは1ポイントが1/72インチに相当する。しかし、ファイルによっては「UserUnit」という設定でこの単位の倍率が変わる可能性もあるため、注意が必要である。
結合されたPDFのページに関する情報を詳しく得るには、PopplerというPDFツールキットに含まれるpdfinfoコマンドが非常に役立つ。このコマンドを使うと、結合後のPDFファイルが実際にどのようなページサイズを持っているか、そしてページの回転情報なども確認できる。例えば、pdfinfo -f 1 -l 3 -box merged.pdfというコマンドを実行すると、結合されたmerged.pdfファイルの1ページ目から3ページ目までの詳細情報が表示される。ここで特に重要なのは、-f(first page)と-l(last page)オプションを使って、検証したいページ範囲を明示的に指定することだ。もしこれらのオプションを指定せずに実行すると、pdfinfoは通常、最初のページの情報しか報告しない。今回のテストケースのように、途中のページに異なるサイズのページ(Letterサイズ)が含まれている場合、最初のページだけをチェックしてもその違いを見落としてしまう可能性があるため、全ての関連ページを検査することが不可欠だ。実際にmacOS上でPopplerを使ってダウンロードファイルを検査した結果では、ページ1がA4サイズ(595.276 x 841.89 pts)、ページ2がLetterサイズ(612 x 792 pts)、ページ3がA4サイズ(595.276 x 841.89 pts)と正確に報告され、元の異なるサイズが維持されていることが確認できた。また、pdfinfo -boxオプションの出力には、ページの表示領域を定義するMediaBoxやCropBoxといった情報も含まれる。幅と高さの情報だけでは、これらのボックスがオフセットされていたり、ページが回転していたり、非デフォルトのUserUnitが設定されていたりするファイルの場合、完全な状態を把握することはできないため、結合ツールの挙動が約束する内容に基づいて、これらのプロパティも元のソースページと比較することが重要となる。今回のフィクスチャは、原点が(0,0)で回転がなく、CropBoxがMediaBoxと同じ効果を持つページのみをチェックするシンプルなケースである。
ページの寸法が正しくても、結合されたファイルのページ順序が入れ替わってしまう可能性も考慮する必要がある。この順序の問題を確認するためには、pdftotextコマンドが有効だ。このコマンドは、PDFファイルからテキスト情報を抽出し、その内容を標準出力に表示できる。事前にテストデータに埋め込んでおいた明確なテキストマーカー(例えば「COVER - START HERE」「REPORT PAGE 1」「REPORT PAGE 2 - END」のような文字列)があれば、抽出されたテキストを検査することで、結合後のPDFでページが意図した順序で並んでいるかを簡単に確認できる。今回のテストでは、これらのマーカーが正しい順序で出現することが確認された。さらに厳密なチェックを行うには、pypdfのようなライブラリを用いて、出力された各ページの抽出テキスト全体を対応する元のソースページのテキストと比較する方法もある。これにより、単なるマーカーの順序だけでなく、ページコンテンツが忠実に転送されているかを検証できる。ただし、このテキスト抽出による検証は、視覚的な表示の忠実性や、スクリーンリーダーなどが読み上げる際の意味的な読み順を完全に保証するものではない。また、画像データのみで構成されるスキャンされたPDFの場合、抽出可能なテキストが全く存在しないため、この方法は適用できない点に留意すべきだ。
最終的な確認として、結合されたPDFファイルが視覚的に正しく表示されるかを検証する方法も存在する。これは、PDFファイルを画像形式(例えばPNG)にレンダリングし、その画像を直接目視で検査する方法だ。pdftoppmコマンドを使用すると、PDFの各ページを指定した画像フォーマットで出力できる。例えば、mkdir -p check; pdftoppm -f 1 -l 3 -scale-to 1400 -png merged.pdf check/pageというコマンドを実行すると、merged.pdfの1ページ目から3ページ目までを、幅が最大1400ピクセルになるようにスケーリングして、check/page-000001.pngのようなファイル名でPNG画像として出力する。ここで指定するスケーリング値は、出力される画像ファイルのサイズを制御するものであり、PDFファイル自体のページ寸法を書き換えるわけではない。生成されたPNG画像を画像ビューアで開き、注意深く確認する。特に、テキストの欠落、ページの端が意図せずクリッピングされていないか、予期しない空白領域がないかなどを検査する。結合されたファイルの間、つまり元のPDFファイルの切れ目にあたる部分で問題が発生しやすいので、その周辺は重点的に確認すると良い。画像として開くことで、PDF文書自体を実行したり、そのコンテンツを無条件に信頼したりすることなく、安全に視覚的な検証が可能となる。このテストフィクスチャの場合も、画像レンダリングと目視検査を行った結果、テキストの欠落や目に見えるクリッピングは発見されなかった。
PDFファイルの結合を扱う上で重要なのは、「ページの結合」と「ページサイズのリサイズ(正規化)」を明確に区別することだ。もし下流のシステムが、結合後の全てのページが特定のサイズ(例えばA4)であることを要求するならば、この操作を「正規化」として明確に定義し、その挙動、つまりアスペクト比の維持、ページコンテンツをフィットさせるかクロップするか、ページ上のどこに配置するか、ページの回転やMediaBox・CropBoxなどの扱い方を詳細に定める必要がある。pypdfのようなPDF操作ライブラリの変換ガイドでも、コンテンツの変更とページ寸法の変更は異なる操作として扱われている。単にページのボックス情報だけを変更し、それに対応するコンテンツの変換を適用しないと、コンテンツが正しく表示されずに隠れてしまう可能性がある。
ページ構造を保持する結合処理における実用的な回帰テストとしては、元のソースページのプロパティ(サイズ、回転、ボックス情報、コンテンツなど)と、結合後の出力ページのプロパティを、順序立ててリストアップし、それらが一致しているかを検証することが有効だ。これには、前述したテキストコンテンツのチェックや、レンダリングされた画像の目視検査を組み合わせることが望ましい。また、結合処理の受け入れ条件として、結合後のPDFファイルのバイトデータが元のファイル群を結合したものと完全に一致することを求めるべきではない。PDFファイルは、その内容が同じであっても、ファイル構造やメタデータの再書き込みによって、バイトデータレベルでは異なるシリアル化を持つことがあるためだ。必要なプロパティが維持されていれば、バイトレベルの差異は問題とならない場合が多い。
今回のテストは、フォーム、デジタル署名、パスワードで保護されたページ、回転されたページ、オフセットボックスを持つページ、スキャンされた画像のみのページ、あるいは大量のファイルを一度に処理するバッチ処理といった、より複雑なシナリオは対象としていない。これらの高度なケースは、それぞれに合わせた独自のテストデータと検証手順が必要となる。この小規模な混合サイズPDFのケースは、あくまで「異なるページサイズを持つPDFを結合した際に、結合ツールが静かにすべてのページサイズを統一してしまう(意図せずリサイズしてしまう)」という特定の誤った挙動を検出することを目的としている。