Hatena::ブログ(Diary)

アセトアミノフェンの気ままな日常

2015-07-15

「画像取り込み」周辺の仕様書を読んでみよう

そういえば、先日リンクした ZR さんの一連の記事では実際の仕様書を引用していない(または引用・参照元が明記されていない)ので、説得力がないという意見があるかもしれない。というわけで、ここで実際にそれらの解説記事が説明書に基づく方法であることを示しておこう。そして、その方法こそが僕がいう「正しい方法」なのである。

1-1. そもそも bb= と viewport= とは何なのか

まずは graphicx の仕様書(texdoc graphicx とすると grfguide.pdf が表示される)に書かれている bb= の説明と viewport= の説明 (New feature 1995/06/01) は以下のとおり。

bb: The argument should be four dimensions, separated by spaces. These denote the `Bounding Box' of the printed region within the file.
viewport: The viewport key takes four arguments, just like bb. However in this case the values are taken relative to the origin specified by the bounding box in the file. So to `view' the 1in square in the bottom left hand corner of the area specified by the bounding box, use the argument viewport=0 0 72 72.

つまり、bb は「“printed region” の Bounding Box を指定するため」、viewport は「画像の一部だけ表示したい場合にその範囲を bb の左下からの相対位置座標を使って指定するため」だと目的が仕様書に書かれているのだ。bb の説明中の printed region という用語が若干わかりにくいが、同じマニュアル中の具体例による説明部分に

To see the effect that the various options have consider the file a.ps. This file contains the bounding box specification
%%BoundingBox:0 0 72 72
That is, the printed region consists of a one-inch square, in the bottom left hand corner of the paper.

という記述がある。これを読めば、printed region は PostScript ファイルでいうところの %%BoundingBox: なる行に一致することがわかる*1。なお、PostScript でしか例を示さないのは「graphicx による画像挿入はドライバ依存で、すべてのドライバでサポートされている画像形式は PostScript だけだから」である。dvipdfmx ユーザにとってこれと等価な PDF/JPG/PNG の場合の %%BoundingBox: とは extractbb が吐くもの(後述)であり、pdfTeX ユーザにとっては pdfTeX が自力で求めるものである*2

以上の読解から

  • bb は BoundingBox(もちろん使用するドライバに適合する値)をユーザが指定したい場合に使うオプション
  • viewport は画像の一部分だけ見せたい場合に、その範囲を bb の左下からの相対位置で指定するオプション

であることが説明書どおりだと結論づけることができる。したがって、一部だけ表示したいのに bb を使うことは作成者にとって「想定外」なので、偶然期待通りになるかもしれないし、偶然期待はずれになるかもしれないのだ。

1-2. gs の bbox デバイスとは何か

gs の bbox デバイスは「PDF ファイル中の何かオブジェクトが書かれている範囲の、BoundingBox の左下からの相対座標」を示す仕様である。この点についても説明書の記述をみてみよう。

There is a special bbox "device" that just prints the bounding box of each page. You select it in the usual way:
gs -dSAFER -dNOPAUSE -dBATCH -sDEVICE=bbox
It prints the output in a format like this:
%%BoundingBox: 14 37 570 719
%%HiResBoundingBox: 14.308066 37.547999 569.495061 718.319158
Currently, it always prints the bounding box on stderr; eventually, it should also recognize -sOutputFile=.

By default, white objects don't contribute to the bounding box because many files fill the whole page with white before drawing other objects. This can be changed by:
<< /WhiteIsOpaque true >> setpagedevice

後半部分が bbox デバイスは「余白を除いた領域を返す」ことを意味しており、すぐ分かるとおりほかの extractbb や pdfTeX が判断する BoundingBox とは異なるので注意を要するわけである(ここが用語の混同を生む原因だが、gs の仕様と TeX 関連プログラムの仕様は独立なので無関係)。では gs の bbox デバイスがどこを原点0すなわち左下とみるかというと、PDF ファイルの場合は /MediaBox の値を参照するのである。なぜ MediaBox だとわかるかというと、説明書中で -dUseBleedBox/-dUseTrimBox/-dUseArtBox/-dUseCropBox というオプション(これらがいつ登場したかは後日)が説明されていて、その説明にいずれも

Sets the page size to the ****Box rather than the MediaBox.

と書かれていることから明確なのである。つまり、ページサイズはユーザがほかの Box を選ばない限り MediaBox の値が使われているといえるので

  • gs の bbox デバイスは PDF の余白を除いた領域を、/MediaBox の左下からの相対座標で返す

ということが読み取れる*3。したがって、「余白がある PDF の余白を取り去って \includegraphics したい」という目的に合うのは、gs の bbox の結果を bb= ではなくむしろ viewport= に指定することである*4

2. 値の単位はどうすべきか

次に、ピクセルでなくビッグポイント単位を使ってサイズを指定するという話は再び graphicx の説明書に戻る。

For the keys specifying the original size (i.e,, the bounding box, trim and viewport keys) the units can be omitted, in which case bp (i.e., PostScript points) are assumed.

このように説明書に書かれているから

  • 画像のサイズはデフォルト(特別に指定しない状態)では bp を前提とする

ということがすぐにわかり、ピクセル指定は作者にとって「想定外」なのだ。もしピクセル指定が期待通りになったとしても単なる偶然で、ビッグポイント指定はいかなる状況においても仕様どおりの正常な結果をもたらす(そうでないとしたらバグなので直されるべきだから)。

3. dvipdfmx にとっての正しい BoundingBox の定義は

先ほど BoundingBox の定義はドライバによって異なるので一概に定義できないと言った。では、今回問題になっている dvipdfmx が使う BoundingBox とは何なのか? それは extractbb の出力でなければならないことが man dvipdfmx(たとえば texdoc dvipdfmx.man1 で読める→こちら)に書かれている:

IMAGE BOUNDING BOXES
When including images with dvipdfmx, their bounding boxes should be generated by running extractbb. The result will be in an .xbb file; the xbb information is the same as for the PDF format.

では extractbb が吐く BoundingBox の説明は、man extractbb(たとえば texdoc extractbb.man1 や texdoc extractbb で出てくる→こちら)に書かれている。dvipdfmx には公式マニュアルといえるほど十分な文書がそもそも存在しないが、上記で根拠としては十分であろう(なかなか探し出せず、あべのりさんに教えてもらった)。

では、バッドノウハウとどう付き合うべきか

以上で「画像の一部表示には bb= を詐称します」や「画像はピクセルでも構いません」はバッドノウハウ*5であるということを証明し、情報を上で与えた。これらを使うかどうかは昨日も述べたとおり「個人の趣味なので自由」である。しかし、他人に教える(補完機能*6もこれと同じ)となると話は別である。最後に、これが僕だけの意見ではないことを示しておこう。本当の優しさとは教えてあげることだけではなく、(それが本来の正しい方法なのかそうでないのかを含めて)情報を十分に提供することではなかろうか。

何かの目的で、「マチガッテル方法」を流布しようと考えている人は、絶対に絶対に、「それがマチガッテル」という情報を含めることを忘れないでほしい。さもないと、初心者・初級者はそれを「正しい方法」だと誤解する。それは、結果として、“デマ拡散”に加担したことに他ならない。

*1:具体例の解説で「%%BoundingBox: 0 0 72 72」と書かれているのをみて「すなわち printed region は1インチの正方形である」と導いている。ということは「printed region は %%BoundingBox: という部分に書かれた範囲である」という前提が当然として話を進めているわけだ。同じ文書中で printed region という用語を異なる意味で用いることはありえないので、bb= の説明中に登場する printed region も「ファイル中に書き込まれた %%BoundingBox: の範囲」を意味すると解釈するのが正しい。

*2:BoundingBox の定義が graphicx のマニュアルに明記されていないのは当然で、なぜなら BoundingBox の値はドライバ依存だからである。実際、dvipdfm と dvipdfmx/pdfTeX では BoundingBox の値が異なる。それら全てを包括した概念として、graphicx のマニュアルは BoundingBox という用語を使っていると認識すべきである。

*3:なんとなく「絶対でなく相対である」説明が不足している気がするが、これは「Illustrator で作ったファイル(/CropBox 以外を明示)の /MediaBox だけを無理矢理書き換えてから gs の bbox デバイスにかける」という作業をすれば、改変前と後で結果が違うことを確認できる。また、-dUse****Box オプションを付ければ同じ PDF ファイルでも返ってくる値が異なることを確認できる;実際やってみたのがこちら

*4:ただし、これは /MediaBox 以外が明示的に異なる値で指定されていない場合に限る! なぜなら、extractbb は /MediaBox を最も優先度を低く設定しているからである。したがって、より正確には gs の bbox の値を viewport= に指定するなら、そのときはソース中に明示的に /MediaBox を bb= で与えるのが最も安全であるといえる。このあたりは後日記事にする予定である。

*5:僕にとっての「バッドノウハウ」という用語の定義は既に前回述べた。

*6:今問題としている YaTeX の「PDF の場合に bb= に gs の bbox デバイスが返す値を補完します」という仕様は、上で述べたとおり作者の想定外・説明書の範囲外である。また、「PNG/JPG の場合に bb= に gs の bbox デバイスが返す値を補完します」という仕様も、作者の想定外・説明書の範囲外である。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証