世界一巨大なPDFが想像以上にでかすぎる! PDFファイルの内部構造とAcrobatで巨大なPDFを作成する方法も解説
Post on:2024年2月21日
いやー、こんなこと考えたこともなかったです。
PDFの最大サイズって、どのくらいだと思いますか?
ここで紹介するPDFファイルのページサイズはなんと、38万キロメートル!
地球と月の間の距離とほぼ同じです。
Making a PDF that’s larger than Germany
by Alex Chan
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
はじめに
これまでにも何度か目にしたことがあったのですが、ソーシャルメディアにこんなポストがありました。「PDFドキュメントには最大サイズがある」と。
Maximum size of a PDF, version 7: 381 km × 381 km.https://t.co/Sxz37HMYD1 pic.twitter.com/a4bkgZAjgq
— Terrible Maps (@TerribleMaps) June 30, 2023
これに似たのを最初に見たのは、2007年でしょうか。そしてこのポストはこの主張に対するポストとしてかなり象徴されたものです。裏付けとなる証拠や説明はなく、純粋な事実として述べられています。上記のポストは、1枚のPDFがドイツの国土面積の半分をカバーすることをただ受け入れろということであり、なぜ381x381kmが最大なのか何の理由も示されていません。
そこで、私は疑問に思いました。
これほど大きなPDFを作成した人は本当にいる?
それは難しい?
もっと大きなPDFを作ることはできない?
私は数年前にPDFの前身であるPostScriptを勉強してみたことがあるのですが、それはとても楽しい経験でした。しかし、PDFの内部を詳しく調べたことがなかったので、これは良い機会だと思いました。
では、さっそく調べてみましょう!
この主張はどこからきているのか?
これらの主張には「実は」という文言が添えられていることが多く、リプライには「PDF自体の制限ではなく、PDFリーダーのアプリの制限である」と説明されています。通常、WikipediaのPDFをリンクして説明しています。
ページのサイズはフォーマット自体によって制限されることはありません。ただし、Adobe Acrobatは1,500万x1,500万インチ、つまり225兆in2(145.161 km2の制限があります。
参照リンクをみると、PDF 1.7の仕様が見つかります。付録の項目でこれについてさらに詳しく説明されています。
PDF 1.6以前のバージョンでは、デフォルトのユーザースペースの単位のサイズは1/72インチで固定されています。Acrobatのバージョン 4.0以前のビューアでは、許容ページサイズの最小値はデフォルで72x72単位(1x1インチ)で、最大値は3240x3240単位(45x45インチ)です。Acrobatのバージョン 5.0以降では、許容ページサイズの最小値は3x3単位(約0.04x0.04インチ)で、最大値は14,400x14,400単位(200x200インチ)です。
PDF 1.6以降では、デフォルトのユーザースペースの単位のサイズは、ページ辞書のUserUnitで設定できます。Acrobat 7.0では、UserUnitの最大値75,000をサポートしており、これによってページの最大値は15,000,000インチ(14,400*75,000*1/72)となり、最小値は1.0(デフォルト)となります。
1,500万インチはちょうど381キロメートルで、前述のポストの数字と一致します。そして、この制限はPDF 1.6で初めて登場し、Adobe Acrobatの「バージョン7」です。おそらく、これが主張の由来でしょう。
この「最大」値を超えるPDFを作成したらどうなると思いますか?
PDFファイルの内部構造
私はこれまでPDFドキュメントの内部を詳しく調べたことはありません。ちらっと16進エディタで見たことはありましたが、実際にどのように機能するかを理解したことはありませんでした。今回、PDFを直接編集する方法を学ぶ良い機会だと思いました。
まずは、PDFの内部構造を説明している良い記事を見つけたので、ChatGPTにいくつか質問してみたところ、簡単なファイルをいくつか手動で作成できるようになりました。
PDFは非常に多くの機能をサポートしていることは分かっているので、下記は単純化しすぎかもしれませんが、私が作成した頭の中のイメージです。
PDFファイルの内部構造(私が作成した頭の中のイメージ)
PDFファイルの始まりと終わりは、常に同じです。バージョン番号(%PDF-1.6
)とファイル終了のマーカー(%%EOF
)です。
バージョン番号の後には、オブジェクト(Objects
)の長いリストが続きます。オブジェクトにはPDFファイルに含まれるさまざまなもの、ページ、テキスト、グラフィックなどその種類はたくさんあります。
オブジェクトのリストの後には、オブジェクトの参照テーブルであるxref
または相互参照テーブルが続きます。これはファイル内のすべてのオブジェクトを指します。オブジェクト1は先頭から10バイト後、オブジェクト2は20バイト後、オブジェクト3は30バイト後であることが分かります。このテーブルを見ることで、PDFビューワーアプリはファイル内にオブジェクトがいくつあり、どこにあるのかを知ることができます。
trailer
には、ページ数や暗号化の有無など、ドキュメント全体に関するメタデータが含まれています。
最後にstartxref
値はxrel
テーブルの開始点へのポインタです。ここからPDFビューワーアプリはスタートします。ファイルの終わりからstartxref
値を見つけるまで動作し、xrel
テーブルを読み込んですべてのオブジェクトについて学習します。
この知識により、私は最初のPDFを手動で書くことができました。下記のコードをexample.pdf
というファイル名にして保存し、PDFビューワーアプリで開くと、赤い四角のページが表示されるはずです。
% The first object. The start of every object is marked by:
%
% <object number> <generation number> obj
%
% (The generation number is used for versioning, and is usually 0.)
%
% This is object 1, so it starts as 1 0 obj
. The second object will
% start with 2 0 obj
, then 3 0 obj
, and so on. The end of each object
% is marked by endobj
.
%
% This is a "stream" object that draws a shape. First I specify the
% length of the stream (54 bytes). Then I select a colour as an
% RGB value (1 0 0 RG
= red), then I set a line width (5 w
) and
% finally I give it a series of coordinates for drawing the square:
%
% (100, 100) ----> (200, 100)
% |
% [s = start] |
% ^ |
% | |
% | v
% (100, 200) <---- (200, 200)
%
1 0 obj
<<
/Length 54
>>
stream
1 0 0 RG
5 w
100 100 m
200 100 l
200 200 l
100 200 l
s
endstream
endobj
% The second object.
%
% This is a "Page" object that defines a single page. It contains a
% single object: object 1, the red square. This is the line 1 0 R
.
%
% The "R" means "Reference", and 1 0 R
is saying "look at object number 1
% with generation number 0" -- and object 1 is the red square.
%
% It also points to a "Pages" object that contains the information about
% all the pages in the PDF -- this is the reference 3 0 R
.
2 0 obj
<<
/Type /Page
/Parent 3 0 R
/MediaBox [0 0 300 300]
/Contents 1 0 R
>>
endobj
% The third object.
%
% This is a "Pages" object that contains information about the different
% pages. The 2 0 R
is reference to the "Page" object, defined above.
3 0 obj
<<
/Type /Pages
/Kids [2 0 R ]
/Count 1
>>
endobj
% The fourth object.
%
% This is a "Catalog" object that provides the main structure of the PDF.
% It points to a "Pages" object that contains information about the
% different pages -- this is the reference 3 0 R
.
4 0 obj
<<
/Type /Catalog
/Pages 3 0 R
>>
endobj
% The xref table. This is a lookup table for all the objects.
%
% I'm not entirely sure what the first entry is for, but it seems to be
% important. The remaining entries correspond to the objects I created.
xref
0 4
0000000000 65535 f
0000000851 00000 n
0000001396 00000 n
0000001655 00000 n
0000001934 00000 n
% The trailer. This contains some metadata about the PDF. Here there
% are two entries, which tell us that:
%
% - There are 4 entries in the xref
table.
% - The root of the document is object 4 (the "Catalog" object)
%
trailer
<<
/Size 4
/Root 4 0 R
>>
% The startxref marker tells us that we can find the xref table 2196 bytes
% after the start of the file.
startxref
2196
% The end-of-file marker.
%%EOF
私はこのファイルを元に、図形を追加したり、表示方法を変更したり、異なるページに異なる図形を配置したりといった簡単な作業をしました。そして、テキストを使えるようにしばらく試みましたが、それは私には無理でした。
なぜ誰もPDFファイルを手書きしないのかがすぐに明らかになりました。すべての参照テーブルを作成するのは非常に面倒です。でも、やってみて良かったです。すべてのPDFオブジェクトとその参照を操作することで、PDFの基本モデルを理解できたように感じました。他のアプリで作成された「本物」のPDFをいくつか開いてみましたが、さらに多くのオブジェクトやオブジェクトの種類が含まれており、少なくとも何が起こっているのかの一部を理解することができました。
PDFを手作業で編集できるようになった今、巨大なPDFを作成するにはどうしたらよいでしょうか?
PDFのページサイズを変更する: /MediaBox と /UserUnit
PDFのファイル内では、各ページのサイズは個々の「Page
」オブジェクトに設定されています。そしてこれにより異なるページを異なるサイズにすることができます。
1 2 3 4 5 6 |
<< /Type /Page /Parent 3 0 R /MediaBox [0 0 300 300] /Contents 1 0 R >> |
MediaBox
では、ページの幅と高さ(上記では300x300の正方形)が設定されています。デフォルトの単位サイズは1/72インチなので、ページは300x72 = 4.17インチになります。実際にこのPDFをAdobe Acrobatで開くと、次のようにプロパティが表示されます。
PDFのプロパティ(Adobe Acrobat)
MediaBox
の値を変更することで、ページを大きくすることができます。たとえば、値を600 600
に変更すると、Acrobatでは8.33x8.33インチであると表示されます。いい感じですね!
Acrobatが許容する最大値である14400 14400
まで大きくすると、ページは200.00x200.00インチになったと表示されます(制限を超えようとするとアラートが表示されます)。
しかし、200インチでは381キロメートルにははるかに足りません。これはデフォルトの単位である1/72インチを使用しているためです。UserUnit
の値を追加することで、単位を大きくすることができます。たとえば、値を2
に変更すると、ページが両方の寸法で2倍になります。
1 2 3 4 5 6 7 |
<< /Type /Page /Parent 3 0 R /MediaBox [0 0 14400 14400] /UserUnit 2 /Contents 1 0 R >> |
上記のように変更すると、Acrobatはページのサイズを400.00x400.00インチとして表示しました。
UserUnit
の値を最大値である75000
まで上げると、Acrobatはページのサイズを15,000,000.00x15,000,000.00インチ、つまり381キロメートルと表示し、最初の主張と一致します。確かめたい人は、biggest.pdfをダウンロードしてみてください。
MediaBox
とUserUnit
の値を大きくして、より大きなサイズのページを作成しようとしても、Acrobatはそれを無視します。ページのメタデータではそれより大きいと表示されている場合でも、ページのサイズは1,500万インチであると言い続けます(UserUnit
を75000
より大きくしても、これは無言で行われます。ページのサイズが制限されていることを示唆するアラートやエラーは表示されません)。
追記(2024/2/1):
この記事のオリジナルバージョンでは、いくつか余分なゼロが紛れ込んでいました。10億インチではなく、100万インチでした。間違いを見つけくれたHacker Newsのmrbに感謝します。
これはおそらく問題ありません。UserUnit
値は実際にはあまり使用されていないと思われます。Stack Overflowのアンサーにそのような回答がありました。ネット上でもそのような例は見つかりませんでした。macOSに組み込まれているプレビュー.appはこの値を完全に無視し、すべてのPDFを単位サイズが1/72インチであるかのように扱います。
ただし、プレビュー.appはAcrobatとは異なり、MediaBox
に入れることができる内容に上限はありません。1の後に0が12個続くような幅を設定してもまったく問題ありません。
PDFのプロパティ(プレビュー.app)
そのサイズは、地球と月の間の距離とほぼ同じになります。定規を使って確認してもらう必要はありますが、少なくともドイツよりも大きいことは間違いありません。
私はまだ続けられる、そして実際に続けました。最終的にプレビューが宇宙全体(約37兆光年四方)よりも大きいと主張するPDFが完成しました。中身はほとんど空の空間ですが、まぁ宇宙も同様です。
そのPDFを試してみたい場合は、ここからダウンロードできます。
※印刷は、絶対にしないでください。
Acrobatで開くと、ページサイズは「38,095,556.000x38,095,556.000」と表示されますw
PDFのプロパティ(Adobe Acrobat)
sponsors