3 ポイント 投稿者 GN⁺ 2024-02-01 | 1件のコメント | WhatsAppで共有
  • インターネット上で広まっている「PDFの最大サイズは381km × 381km」という話は、PDF形式自体の限界ではなく、Adobe Acrobat 7.0の実装上の制限に由来する値
  • PDF 1.6以降では /UserUnit によって基本単位である 1/72インチを大きくでき、Acrobat 7.0の最大値 75,00015,000,000インチ という上限を作っている
  • 手作業で作るPDFは %PDF-1.6、オブジェクト一覧、xreftrailerstartxref%%EOF で構成され、ページサイズは /MediaBox/UserUnit の組み合わせで決まる
  • Acrobatは /MediaBox が14,400、または /UserUnit が75,000を超えても 15,000,000インチとして表示し、/UserUnit の超過は警告なしに無視する
  • macOS Preview.appは /UserUnit を無視するが、/MediaBox にはAcrobatのような上限を設けていないため、宇宙より大きなPDFのように表示されるファイルも作れる

381kmという制限はどこから来たのか

  • PDF文書の最大サイズが 381km × 381km だという主張は、昔からインターネット上で繰り返し広まっている
  • この数字はPDF形式の限界ではなく、Adobe Acrobatの実装上の制限に由来する
  • PDF 1.7仕様によると、ページサイズの制限は次のように整理される
    • PDF 1.6以前では、デフォルトのユーザー空間単位は 1/72インチ に固定されていた
    • Acrobat 5.0以降のデフォルトページサイズの最大値は 14,400 × 14,400 単位、つまり 200 × 200インチ
    • PDF 1.6以降では、ページ辞書の /UserUnit でデフォルトのユーザー空間単位の大きさを設定できる
    • Acrobat 7.0は /UserUnit の最大値 75,000 をサポートし、最大ページ寸法 15,000,000インチ を作れる
  • 15,000,000インチ は約 381km であり、「PDF version 7」という表現はPDFのバージョンではなく、Adobe Acrobat 7.0に由来するものとみられる

手作業で作るPDFの基本構造

  • PDFファイルは先頭にバージョン番号、末尾にEOF表示を持つ
    • 例: %PDF-1.6
    • 終端表示: %%EOF
  • バージョン番号の後には、ページ、テキスト、グラフィックなどを表すオブジェクト一覧が続く
  • xref はオブジェクトの位置を示す相互参照テーブル
    • PDFリーダーは各オブジェクトがファイルの先頭から何バイト離れているかを確認する
  • trailer は文書全体のメタデータを含む
    • ページ数
    • 暗号化の有無
    • 文書ルートオブジェクト
  • startxrefxref テーブルの開始位置を指す
    • PDFリーダーはファイル末尾で startxref の値を見つけ、xref テーブルへ移動する
  • 簡単なPDFファイルを作る記事を参考にすると、赤い四角形のあるPDFを手作業で作れる

オブジェクトとページ定義

  • サンプルPDFは4つの主要オブジェクトで構成される
    • オブジェクト1: 赤い四角形を描画する streamオブジェクト
    • オブジェクト2: 単一ページを定義する Page オブジェクト
    • オブジェクト3: 複数ページの情報を含む Pages オブジェクト
    • オブジェクト4: 文書の主要構造を提供する Catalog オブジェクト
  • Page オブジェクトは、ページ内容を別のオブジェクト参照でつなぐ
    • 1 0 R はオブジェクト番号1、世代番号0を参照する
    • 3 0 R はページ集合である Pages オブジェクトを参照する
  • 手作業でPDFを書くと、オブジェクト位置が変わるたびに xref テーブルの値を合わせ直す必要があり、非常に面倒
  • 2025年4月16日の更新で、サンプルコードの xref 0 4 が誤った値として訂正された
    • 実際の相互参照テーブルには5つの項目があるため、xref 0 5 が正しい

/MediaBox/UserUnit でページを大きくする

  • PDFのページサイズは各 Page オブジェクトで設定される
  • /MediaBox [0 0 300 300] は幅と高さがそれぞれ 300単位 のページを作る
    • デフォルト単位は1/72インチ
    • 300単位は約 4.17インチ
  • /MediaBox600 600 に変えると、Acrobatはページを 8.33 x 8.33 in と表示する
  • Acrobatで許容される /MediaBox の最大値 14400 14400200 × 200インチ と表示される
    • この値を超えるとAcrobatで警告が発生する
  • /UserUnit を追加すると、デフォルトのユーザー空間単位を大きくできる
    • /UserUnit 2 はページの両辺の寸法を2倍にする
    • /MediaBox [0 0 14400 14400]/UserUnit 2 を併用すると、Acrobatは 400.00 x 400.00 in と表示する
  • /UserUnit 75000 を適用すると、Acrobatはページを 15,000,000.00 × 15,000,000.00インチ と表示する
    • これは約381km × 381kmで、元の主張と一致する
    • サンプルファイル: biggest.pdf

AcrobatとPreviewの処理の違い

  • Acrobatは /MediaBox/UserUnit をさらに大きく設定しても、ページサイズを 15,000,000インチ と表示し続ける
  • /UserUnit の値を 75000 より大きく設定すると、警告やエラーなしに値が制限される
  • /UserUnit は実際の利用例が多くないようだ
    • Stack Overflowの回答でも、この値は広く使われていないとしている
    • オンラインで例を見つけるのは難しかった
  • macOS Preview.appは /UserUnit をサポートしていない
    • すべてのPDFをデフォルト単位 1/72インチ として処理する
  • その代わり、Preview.appはAcrobatと異なり、/MediaBox に大きな上限を設けていない
    • 1 の後に0が12個付いた幅も受け入れる
    • この幅は、おおよそ地球と月の間の距離に相当する
  • さらに大きな /MediaBox の値を入れると、Previewが約 37兆光年四方 のサイズのPDFとして表示するファイルも作れる
    • サンプルファイル: universe.pdf
    • 文書の大部分は空白で、印刷しないよう警告が付いている

1件のコメント

 
GN⁺ 2024-02-01
Hacker News のコメント
  • PDFは技術的にはいろいろな意味でひどいものの、自分の手元に保存しておける自己完結した静的ファイルである点は、いつ消えてもおかしくないユーザー敵対的な動的/SaaSウェブサイトと対照的で素晴らしい
    PDF/Aは本当のPDFに近く、危険な余計物の大半を取り除いてくれる
    奇妙なPDFのお遊びが好きなら、PDF/Aであり、CSVでもあり、同時にAmiga soundtracker modのサウンドトラックでもあるポリグロットファイルがある: https://www.lab6.com/6

    • Amazonがアカウントから本を回収し始めると、自分の手元に保存するという部分が重要になる
      https://www.nytimes.com/2009/07/18/technology/companies/18am...
    • PDFは実行可能なファイルである
      多くの人はJavaScriptの実行を心配する一方で、PDFファイルは特に問題視せずに使っている
    • PDF/Aは最近まで、そのファイルが本当にPDF/Aかどうかを簡単に確認する方法がなく、今はveraPDFがあるものの、かなり複雑なソフトウェアである
      任意のPDFをオープンソースソフトウェアでPDF/Aに変換するには、GhostscriptでPostScriptにしてから戻す方法しかないようだが、GhostscriptはAfferoライセンスなので、いろいろ問題が付いてくる可能性がある
      古いGPL版もあり、ほとんどのPDFで動くが、15年ほど前のものだ
      以前の職場でPDF/Aを扱わなければならなかったが、まったく楽しいものではなかった
    • 複数の出所から集めた数百万件のPDFをパースするプロジェクトで味わった苦痛のせいで、「PDFは優れたフォーマットだ」という言葉は受け入れがたい
      段落を再構成するだけでも大変な労力がかかり、表のパースは言うまでもない
      事実上の標準である割には、もっと良くなるべきだし、PDFのマニュアルも本当にひどい
    • グラフィック業界で働く立場からすると、本当のPDFはPDF/Xだと思う
  • 比較としてPNGを分析してみると、最大幅と高さは2147483647、つまり2^31 - 1である
    pHYsチャンクで指定できる最低密度は1メートルあたり1ピクセルなので、20億メートルは太陽の直径1.39ギガメートルより大きい: https://en.wikipedia.org/wiki/Orders_of_magnitude_(length)#g...
    sCALチャンクはASCII浮動小数点を使うため、はるかに大きな物理サイズも表現できる

    • sCALは画像そのものというより、画像が表す対象のサイズに関するものに近い
      1:10,000,000縮尺の世界地図はpHYs基準では幅10m未満だが、sCAL基準では約40,000km幅になる
  • PDFの幅をキロメートル単位で測り始めた瞬間、自分が良い技術記事を読んでいるのだと分かる

    • microSDカードは、ごく小さな空間に何百万マイルも収められる
  • 10年以上前にGame of LifeのPostScript実装で作ったPDFを思い出した
    まだ動作するようだが、macOS Previewをクラッシュさせる: https://andrewcutler.net/docs/joke/life.pdf

    • SonomaではPreviewはクラッシュしない
      ただしアニメーションは表示されず最終状態だけが見え、FirefoxのPDFビューアでは少しアニメーションが見える
      SkimもPreviewに似ているが、グリッドは表示しない
    • MontereyのMac OSではクラッシュせず、静的なGame of Lifeのレンダリングだけが見える
  • この記事はUmberto Ecoの知的遊戯を思い起こさせる
    特に「On the Impossibility of Drawing a Map of the Empire on a Scale of 1 to 1」を思い出す: https://s3.amazonaws.com/arena-attachments/881694/cb6119367b...

  • PreviewはMediaBoxに入れられる値の上限がAcrobatとは違ってなく、1の後ろに0を12個付けた幅も受け入れる
    書類インスペクタにはページサイズが352777777777.78 x 10.59cmと表示され、この幅はおおよそ地球と月の間の距離くらいになる
    太陽系の全惑星を横一列に並べても、この文書の中に余裕で収まる

    • 計算してみると、その文書は約373km²なのでドイツよりはるかに小さい
      結局、定規が必要だったわけだ
    • 7が1つ多すぎる
      352777777777.78cmは3,527,777.7777778kmである
    • 空白ではなく実際の内容で埋めるなら、そういうPDFのファイルサイズがどれくらいになるのか気になる
  • 面白い実験だ、alexwlchan
    記事には小さな誤りが2つあって、「15,000,000,000.00 in」と「ページサイズが150億インチ」と書いている部分は、1500万インチが正しい
    テキストの書式指定が難しいと言っていたが、「Hello World」という2語だけのPDF例なら、フォントオブジェクトを定義し、ストリーム内でTfでフォントを使い、Tdで位置を指定し、Tjでテキストを書けばよい

    • 数字のミスはどこかでするだろうと思っていたので、近いうちに修正するつもりだ
      テキスト例もありがとう。自分が試していたものと似ているように見えるが、どこかでミスしていたに違いない
    • PDF末尾のxrefは必須なのか気になる
      仕様上は必要なように見える
    • 「15,000,000,000.00 in」がなぜ150億ではなく1500万なのか、0の数を数えるのを手伝ってもらえる?
    • 「印刷しないでください」と言ってしまったら、7回より多く折れるかどうかをどうやって知ればいいんだ?
  • このあたりでSteven Wrightを言い換えたくなる
    「アメリカの地図を1枚持っている。実物大だ」

    • 携帯電話にアメリカの地図を入れているのだが、道案内が少し紛らわしい
      地図の上が自分の進んでいる方向なのか北なのか分からないし、昔の地図はいつも北が上だったのに、Google Mapsはそうではないように見えて混乱する
      90度回ると地図も一緒に回るのだが、回ったのが地図なのか自分なのかも分からなくなる
      止まっていると、どこへ向かっているのか地図には分からないので、方角を知るにはまず動かなければならないようだ
      スマートフォンを目の前に掲げると地図の上は空を向くが、地図は上から見下ろすべきなのかも分からない
      携帯電話でGoogle Mapsをうまく使うコツが気になる
    • Umberto Ecoも同じテーマで “On the Impossibility of Drawing a Map of the Empire on a Scale of 1 to 1” を書いている
      https://s3.amazonaws.com/arena-attachments/881694/cb6119367b...
    • 関連するジョークの中では、「自分の全身に自分自身のタトゥーを入れたい。ただし2インチ大きく」というのが昔から好きだった
      https://scomedy.com/quotes/10779
  • 「印刷しないでください」は、プリント爆弾になる準備ができた言葉のように聞こえる
    最後にプリンターを使ったとき、Windowsで印刷ジョブをキャンセルするのはほぼ不可能だった
    Wi-Fiプリンターが開放されていたり、セキュリティが甘かったりした時代は面白かった

    • Windowsで印刷ジョブをキャンセルするのは今でも不可能だ
      私が見つけた唯一信頼できる方法は、プリンターの電源を切ってキューから印刷ジョブを削除すること
      プリンターがすぐそばにないとだめで、なぜこんなに難しいのか分からない
    • もう少し確実な方法は、プリンターのプラグを抜き、コンピューターを窓の外へ投げ捨てることだ
    • 「印刷しないでください」を読んだ瞬間の最初の反応は、「あなたは私の母親じゃないでしょ」だった
  • 約30年前、Microsoftの夏季インターン面接で、面接官がExcelについてこれと非常によく似た質問をした
    こういうテーマは、人の好奇心と潜在的な問題を分解する能力を見るのに、いつでも良い題材になる