読者です 読者をやめる 読者になる 読者になる

TeX Alchemist Online

TeX を使って化学のお仕事をしています。

【改訂版】dvipdfmx で複数ページPDF/AIファイルを \includegraphics する

昨日,TeX & LaTeX Advent Calendar 2014 用の記事「dvipdfmx で複数ページPDF/AIファイルを \includegraphics する」をアップしましたが,早速反響と進歩がありました。

昨日の記事の最後に

本来的には,extractbb を改修して,「2ページ目以降のバウンディングボックス情報を出力する機能」を実装するのが理想的な解決手段です。 それが実装されれば,この拡張版 pdfinfo やその自動起動設定はもはや不要になります。

将来的に extractbb 自体にその機能が実装されることを願いつつ,とりあえず現状で機能する暫定的解決策として,この拡張版 pdfinfo をご紹介いたしました。

と書きましたが,これをお読みになった角藤先生が早速対応してくださり,extractbb 本体にこの問題を解決する改修を施してくださいました(W32TeX ChangeLog 2014/12/03, TeX Live SVN r35728, r35729)。 これにより,昨日の記事のような回りくどい解決法は,もはや過去のものとなりました。

一方,Illustrator図版におけるナントカBoxの決まり方や,dvipdfmxのBox選択に関する記述は,最新版でも依然として通用する情報です。 そこで,昨日の記事を,この最新仕様に対応するよう書き換えた改訂版の記事として,改めてアップいたします。

目次

対象バージョン

この記事の記述は,以下のTeX環境を前提としています。

  • W32TeX 2014/12/03版以降
  • TeX Live 2015 以降

この記事で述べる方法は TeX Live 2014 以前には適用できませんのでご注意ください。また,実験環境は次の通りです。

  • OS X Yosemite 10.10.1
  • Adobe Illustrator CS6

背景

昨年の Advent Calendar の記事でも述べましたが,日頃の化学教材の作成にあたり,図版作成には主に Adobe Illustrator を使っています。その際,次のように,少しずつ異なる同系統の図をたくさん用意する必要がある場面が多々あります。

f:id:doraTeX:20141203041041p:plain

その際,これらを1枚1枚別々のファイルにするのではなく,上図のように複数ページ(アートボード)を持つIllustratorファイルとして作成した方が,図版作成の作業効率やファイル管理の観点からは都合が良いと言えるでしょう。

かつては,日本で主流の (u)pLaTeX + dvipdfmx のワークフローの場合,このような複数ページ図版の取り扱いは厄介でした。ですが,最新版ではその問題が解決されています。

この記事では,その最新機能の使い方をお知らせいたします。

結論

先に結論から。次のようにすれば複数ページPDFまたはIllustrator AIファイル*1の各ページの図版をロードできます。

1. TeX Live 2015 以降 または W32TeX (2014/12/03版以降)をインストールする

すると,texmf-dist/tex/latex/dvipdfmx-def/dvipdfmx.def も新 extractbb に対応した新版に更新されます。

2. extractbb の自動起動を許可

W32TeX や TeX Live 2015 の場合はデフォルトで許可されています。

3. \includegraphics を page オプション付きで使う

次のように,graphicx パッケージをロードした上で,\includegraphicspage オプション付きで使うと,裏で extractbb が自動起動し,指定したページの図版が適切なサイズで貼り込まれます。PDF でも Illustrator AI ファイルでも有効です。

\documentclass{article}
\usepackage[dvipdfmx,hiresbb]{graphicx}
\begin{document}
\includegraphics[page=2]{fig1.pdf}

\includegraphics[page=3]{fig2.ai}
\end{document}

背景説明:extractbb は何をしているのか

dvipdfmxドライバが読み込まれたgraphicxパッケージにおいて,\includegraphics は次のような挙動をします。

  1. \includegraphics[bb=0 0 100 100] のように,TeXソースにbbオプションを直接与えた場合には,そのバウンディングボックス情報が組版に用いられる。(この方法をとるためには,「このPDFファイルに対して dvipdfmx が認識するバウンディングボックスはどのようなサイズか」を事前に調べておく必要があります。)
  2. 事前に extractbb によって 画像ファイル名.xbb というファイルを生成している場合,そこに書き込まれているバウンディングボックス情報が用いられる。
  3. どちらにも該当しない場合,コンパイル時にその場で extractbb が起動され*2,その場で測定したバウンディングボックス情報が標準出力からのパイプ入力を介してTeX側に伝えられる。(xbbファイルは生成されない。)

このうち,利便性が高いのは 3. の extractbb の自動起動に任せる方法です。というのは,1. や 2. の方法の場合,図版を修正して大きさが変われば,その都度バウンディングボックス情報を更新せねばなりません。3. の方法の場合,extractbb を毎回起動することによる若干のパフォーマンス低下はありますが,図版を頻繁に更新する状況下では,3. の方法にはそのデメリットを補って余りある利便性があると言えるでしょう。

PDFの5つのナントカBox

さて,extractbbでサイズを測定して画像をロードしたとき,「Preview.app や Adobe Acrobat で見たときと画像の切り取られ方が違う」という経験をすることが多々あります。この理由を正確に理解するには,まずPDFの5つのBoxに関する複雑な事情を理解する必要があります。

PDFは,各ページごとに,次の5種類のボックス(通称ナントカBox)を持ちます(ナントカBoxの記事より引用)。

  • MediaBox: 用紙(等の媒体)に実際に印刷される領域。一般の人が行う(非専門的な)印刷行程ではこのボックスのみが指定(および使用)されることが多く,その場合は「用紙サイズ」を表す。
  • CropBox: 最も一般的な意味での,「そのページの(外形を込めた)内容」を表す領域。
  • BleedBox: 専門的な印刷工程における,「断ち落としサイズ」に相当する領域。
  • TrimBox: 専門的な印刷工程における,「仕上がりサイズ」に相当する領域。
  • ArtBox: PDF 文書を画像として用いる場合の,「その画像の(外形を込めた)内容」を表す領域。

一般には,Preview.app や Adobe Acrobat で開いたときには CropBox の領域がページとして表示されるようになっています。

Box省略時の規則(PDFの仕様)

まず,これら5つのBoxのサイズが全て明示的に記述されているとは限りません。省略された場合は,次のような規則で決まることがPDFの仕様で規定されています。

  • MediaBox の値は必ず明示される。
  • CropBox の値が明示されていない場合は,MediaBox と同じと解釈される。
  • BleedBox,TrimBox,ArtBox の値が明示されていない場合は,CropBox と同じと解釈される。

dvipdfmxのBoxの選択

一方,dvipdfmxがTeX文書に図版を挿入する際に選択するBoxは,PDFの仕様とは無関係に,次の規則で決まります。

CropBox→ArtBox→TrimBox→BleedBox→MediaBox の順で明示されている最初のものを使う。

したがって,CropBoxが明示されていない図版の場合,Preview.app や Adobe Acrobat で開いたときの「見える範囲」とは異なるサイズでTeX文書に貼り込まれる可能性があるのです。

ナントカBoxの調べ方

PDFの5つのナントカBoxのサイズは,例えば Xpdf に付属の pdfinfo というツールで調べることができます。例えば,あるPDFの2ページ目のナントカBoxのサイズを取得するには,次のようにします。

$ pdfinfo -box -f 2 -l 2 fig.pdf
Title:          Empty
Creator:        Adobe Illustrator CS6 (Macintosh)
Producer:       Adobe PDF library 10.01
CreationDate:   Thu Oct  2 11:41:16 2014
ModDate:        Tue Dec  2 23:10:16 2014
Tagged:         no
Form:           none
Pages:          16
Encrypted:      no
Page    2 size: 171.381 x 132.312 pts (rotated 0 degrees)
Page    2 MediaBox:     0.00     0.00   171.38   132.31
Page    2 CropBox:      0.00     0.00   171.38   132.31
Page    2 BleedBox:     0.00     0.00   171.38   132.31
Page    2 TrimBox:      8.50     8.50   162.88   123.81
Page    2 ArtBox:      27.32    24.10   129.97   100.61
File size:      290892 bytes
Optimized:      no
PDF version:    1.5

このようにして,5つのBoxのサイズが分かりました。

ただし,どのBoxが明示指定されたBoxで,どのBoxが暗黙に決定されたものかこの出力からは判断できません。pdfinfoは,PDFの仕様に従い,非明示のBoxに対しては,他のBoxから暗黙的に決定されたBoxの値を表示しているからです。

例えば,上記の例の出力の場合,ArtBoxのサイズが他と異なりますので,ArtBoxが明示指定されていることが分かります。しかし,この出力からは,CropBoxがこの値に明示的に指定されているのか,MediaBoxから暗黙に決まったのかが判断できません。CropBoxが明示指定されているのであればdvipdfmxはCropBoxを使いますが,暗黙に決まったのであればArtBoxを使います。よって,dvipdfmx が用いるボックスがどれであるのかは,pdfinfo の出力結果からは判断できず,一般には extractbb を実行してみて初めて分かるのです。

Illustrator の図版のナントカBox

Illustrator のデフォルトの設定でPDF/AIファイルを保存した場合,5つのナントカBoxの情報は通常次のようになるようです*3

f:id:doraTeX:20141203042408p:plain

  • MediaBox:アートボードの赤枠に明示指定される。
  • TrimBox:アートボードの白い部分に明示指定される。
  • ArtBox:図版自体を取り囲む外接長方形とアートボードの白い部分の共通部分に明示指定される。
  • CropBox:明示指定されず,MediaBoxの値から暗黙に決まる。
  • BleedBox:AI形式の場合はMediaBoxと同じ値に明示指定される。PDF形式の場合は明示指定されず,(かつCropBoxも明示指定されていないので結果的に)MediaBoxと同じ値に暗黙に設定される。

したがって,上記の

CropBox→ArtBox→TrimBox→BleedBox→MediaBox の順で明示されている最初のものを使う。

というルールに従えば,Illustratorの図版に対しては,dvipdfmxは通常ArtBoxをバウンディングボックスとして使用することが分かります。

他のツールでトリミングした場合

しかし,こうしてIllustratorで作成した図版を,さらに他のツールで編集すると,状況は複雑化します。手元で実験してみると次のようになりました。

Preview.app で「範囲選択」→「切り取り」した場合

  • CropBox が新たに明示指定され,選択された範囲に指定される。
  • MediaBox, BleedBox, TrimBox, ArtBoxは変更されない。

Adobe Acrobat の「トリミングツール」でトリミングした場合

  • CropBox が新たに明示指定され,選択された範囲に指定される。
  • MediaBox は変更されない。
  • BleedBox, TrimBox, ArtBox は CropBox と同じ値に変更(明示指定)される。

いずれにせよ,このようなトリミングを行うと,新規にCropBoxが明示指定されます。その結果,dvipdfmxが使用するバウンディングボックスはCropBoxに変わります。したがって,事後に他のツールで編集される可能性がある場合,「dvipdfmxはIllustrator図版に対しては必ずArtBoxをbbとして用いる」とは言えないことが分かります。

pdfinfo を拡張する

以前こんなことを言っていました。

幸い,pdfinfo はオープンソースのツールなので,必要だと思う機能は自分で追加することができます。そこで,pdfinfo の独自拡張版を作成しました。

拡張版 pdfinfo の新仕様

この拡張版は,オリジナルの pdfinfo を次のように拡張しています。

  1. デフォルトで全ページのボックス情報を出力します。
  2. 明示指定されておらず,暗黙に決定されたナントカBoxには [Implicit] というラベルを付けて出力します。
  3. 各ページについて,dvipdfmx が選択するBoxには [dvipdfmx BB] というラベルを付けて出力します。
  4. PDFの仕様では,MediaBoxは最も大きなボックスであるべきで,もしもその他の4つのボックスの指定値が MeidaBox からはみ出している場合,MediaBox のサイズでクリップすることになっています。オリジナルの pdfinfo はその仕様に従った値を表示します。それに対し,dvipdfmx / extractbb は,MediaBox からはみ出たボックスを選択する場合,MediaBox によるクリップを行いません。そこで,この拡張版 pdfinfo では,dvipdfmx の仕様に従い,各ボックス値としてはまずは MediaBox によるクリップを行わない値を表示し,MediaBox によるクリップ後の値は別行に改めて表示する形に改変してあります。(これは,この拡張版は dvipdfmx の仕様を極力模倣しようという意図で改変されているからです。)
  5. 新オプション -extractbb を指定すると,extractbb -O の動作を模倣します。すなわち,-f オプションで指定されたページの,dvipdfmxが認識するバウンディングボックスの情報を,extractbb と同じ書式で標準出力にアウトプットします。

この結果,pdfinfo の出力は次のようになります。

$ pdfinfo fig1.pdf
Title:          fig1
Creator:        Adobe Illustrator CS6 (Macintosh)
Producer:       Mac OS X 10.10.1 Quartz PDFContext
CreationDate:   Wed Dec  3 01:55:15 2014
ModDate:        Wed Dec  3 01:55:15 2014
Tagged:         no
Form:           none
Pages:          3
Encrypted:      no
Page size:      242.189 x 166.796 pts (rotated 0 degrees)
------------------------------------------------------------------------
Page    1 MediaBox:     0.00     0.00   242.19   166.80
Page    1 CropBox:      0.00     0.00   242.19   166.80   [Implicit]
Page    1 BleedBox:     0.00     0.00   242.19   166.80   [Implicit]
Page    1 TrimBox:      8.50     8.50   233.69   158.29
Page    1 ArtBox:      56.76    52.38   187.18   114.42   [dvipdfmx BB]
------------------------------------------------------------------------
Page    2 MediaBox:     0.00     0.00   224.28   117.61
Page    2 CropBox:      0.00     0.00   224.28   117.61   [Implicit]
Page    2 BleedBox:     0.00     0.00   224.28   117.61   [Implicit]
Page    2 TrimBox:      8.50     8.50   215.78   109.11
Page    2 ArtBox:      48.49     8.50   156.40    55.23   [dvipdfmx BB]
------------------------------------------------------------------------
Page    3 MediaBox:     0.00     0.00   159.43   215.19
Page    3 CropBox:      7.90    85.69   100.99   183.20   [dvipdfmx BB]
Page    3 BleedBox:     0.00     0.00   159.43   215.19
Page    3 TrimBox:      8.50     8.50   150.93   206.69
Page    3 ArtBox:      38.39    23.82   137.23   149.43
------------------------------------------------------------------------
File size:      11395 bytes
Optimized:      no
PDF version:    1.3

これにより,各ページのナントカBoxの明示指定の有無,および dvipdfmx が用いるBoxがどれであるかが一目瞭然に分かります。

拡張版 pdfinfo の入手法

拡張版 pdfinfo のMac用バイナリはGitHubのリリースページに置いてあります。10.6 SnowLeopard以上で動くようになっています。

その他のOSの場合,GitHubレポジトリからソース一式をダウンロードしてコンパイルします*4

$ ./configure
$ make pdfinfo

すると,xpdf ディレクトリの中に pdfinfo の実行バイナリが生成されますので,適切なディレクトリに配置してください。

ナントカBoxの違いを実感する

実験のため,fig1.pdf, fig2.aiという2つの画像ファイルを用意しました。これらは,Illustrator で次のように3つのアートボードを持つ書類として作成したものです。

f:id:doraTeX:20141203105205p:plain
Illustratorで作成した3ページからなる図版

この Illustrator 書類を,PDFおよびAI形式で書き出しました。ただし,fig1.pdf については,Illustrator で保存した後,Preview.app で開き,3ページ目の一部を範囲選択してトリミングしました。

その結果,fig1.pdf の Preview.app 上での見た目は次のようになっています。

f:id:doraTeX:20141203105532p:plain
fig1.pdf の3ページ目を Preview.app でトリミングした

このように,Preview.app 上ではCropBox(明示の場合はその値,非明示の場合はMediaBoxから暗黙に決められる値)の領域が1ページとして見えています

実験用ファイルのナントカBox

テスト用ファイルのナントカBoxは次のようになっています。

$ pdfinfo fig1.pdf
------------------------------------------------------------------------
Page    1 MediaBox:     0.00     0.00   242.19   166.80
Page    1 CropBox:      0.00     0.00   242.19   166.80   [Implicit]
Page    1 BleedBox:     0.00     0.00   242.19   166.80   [Implicit]
Page    1 TrimBox:      8.50     8.50   233.69   158.29
Page    1 ArtBox:      56.76    52.38   187.18   114.42   [dvipdfmx BB]
------------------------------------------------------------------------
Page    2 MediaBox:     0.00     0.00   224.28   117.61
Page    2 CropBox:      0.00     0.00   224.28   117.61   [Implicit]
Page    2 BleedBox:     0.00     0.00   224.28   117.61   [Implicit]
Page    2 TrimBox:      8.50     8.50   215.78   109.11
Page    2 ArtBox:      48.49     8.50   156.40    55.23   [dvipdfmx BB]
------------------------------------------------------------------------
Page    3 MediaBox:     0.00     0.00   159.43   215.19
Page    3 CropBox:      7.90    85.69   100.99   183.20   [dvipdfmx BB]
Page    3 BleedBox:     0.00     0.00   159.43   215.19
Page    3 TrimBox:      8.50     8.50   150.93   206.69
Page    3 ArtBox:      38.39    23.82   137.23   149.43
------------------------------------------------------------------------
$ pdfinfo fig2.ai
------------------------------------------------------------------------
Page    1 MediaBox:     0.00     0.00   242.19   166.80
Page    1 CropBox:      0.00     0.00   242.19   166.80   [Implicit]
Page    1 BleedBox:     0.00     0.00   242.19   166.80
Page    1 TrimBox:      8.50     8.50   233.69   158.29
Page    1 ArtBox:      56.76    52.38   187.18   114.42   [dvipdfmx BB]
------------------------------------------------------------------------
Page    2 MediaBox:     0.00     0.00   224.28   117.61
Page    2 CropBox:      0.00     0.00   224.28   117.61   [Implicit]
Page    2 BleedBox:     0.00     0.00   224.28   117.61
Page    2 TrimBox:      8.50     8.50   215.78   109.11
Page    2 ArtBox:      48.49     8.50   156.40    55.23   [dvipdfmx BB]
------------------------------------------------------------------------
Page    3 MediaBox:     0.00     0.00   159.43   215.19
Page    3 CropBox:      0.00     0.00   159.43   215.19   [Implicit]
Page    3 BleedBox:     0.00     0.00   159.43   215.19
Page    3 TrimBox:      8.50     8.50   150.93   206.69
Page    3 ArtBox:      38.39    23.82   137.23   149.43   [dvipdfmx BB]
------------------------------------------------------------------------

fig1.pdf の3ページ目だけが,CropBoxが明示指定されていることが分かります。

実験

次のようなTeXソースをコンパイルすると,どの部分が切り取られるでしょうか。

\documentclass[twocolumn]{article}
\usepackage[dvipdfmx,hiresbb]{graphicx}
\begin{document}
\fboxsep=0pt
\fboxrule=1pt
\parindent=0pt

\section{fig1.pdf}
\fbox{\includegraphics[page=1,clip]{fig1.pdf}}\par
\fbox{\includegraphics[page=2,clip]{fig1.pdf}}\par
\fbox{\includegraphics[page=3,clip]{fig1.pdf}}

\newpage

\section{fig2.ai}
\fbox{\includegraphics[page=1,clip]{fig2.ai}}\par
\fbox{\includegraphics[page=2,clip]{fig2.ai}}\par
\fbox{\includegraphics[page=3,clip]{fig2.ai}}
\end{document}

これを

$ ptex2pdf -l test

でコンパイルすると,次の出力が得られます。

f:id:doraTeX:20141203105938p:plain

fig1.pdf の3枚目に対しては CropBox,それ以外のページについては ArtBox がバウンディングボックスとして認識されて貼り込まれていることが分かります。CropBox が用いられた fig1.pdf の3枚目を除いては,Preview.app上での見た目のページサイズとTeXに貼り込まれるサイズとは一致していないことが実感できるでしょう。

参考記事

  1. dvipdfmx で画像する時に色々とアレな話 - マクロツイーター
  2. ナントカBoxの話(1) - マクロツイーター
  3. ナントカBoxの話(2) - マクロツイーター
  4. ナントカBoxの話(3) - マクロツイーター
  5. ナントカBoxの話(4) - マクロツイーター
  6. bbox とか ナントカBox に関する補足 - マクロツイーター

*1:最近のIllustratorでは,Illustrator PDF形式で保存しても,AI形式で保存しても,出来上がるものはほとんど同じで,どちらもPDFとして扱うことができます。TeX Live 2014 以降の dvipdfmx ドライバは,拡張子が .ai のファイルもPDFと同等に扱って \includegraphics できるようになっています。

*2:そのためには texmf.cnf で extractbb の自動起動を許可しておく必要があります。

*3:このあたり,今一つ実験不足です。より確かな情報をお持ちの方がおられましたらぜひご教示ください。

*4:これはUnix系OSでのコンパイル法。Windows環境では付属の ms_make.bat を利用すればコンパイルできるのかもしれません。しかし手元にWindows環境がないため試せておりません。