マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

bbox とか ナントカBox に関する補足

アレな話の補足の類の何か。

ImageMagick を用いてビットマップ画像の bbox を調べる

ImageMagick の identify コマンドに -verbose オプションを付けて実行すると、画像についてのかなり詳細な情報が得られ、その中に bbox に関するものも含まれる。例えば、某 wiki の某記事に掲載の PNG 画像 apple.png の場合は以下の出力が得られる。

> identify -verbose apple.png
Image: apple.png
  Format: PNG (Portable Network Graphics)
  Mime type: image/png
  Class: DirectClass
  Geometry: 426x496+0+0
  Resolution: 59.06x59.06
  Print size: 7.213x8.39824
  Units: PixelsPerCentimeter
  Type: Grayscale
……(以下300行ほど省略)

この中で、解像度の単位(Units)が PixelsPerCentimeter(px/cm)であることに注意すると、画像の寸法が判る。

  • ピクセル単位での寸法(Geometry): 426 px × 496 px
  • 解像度(Resolution): 59.06 px/cm(= 150.0124 dpi)
  • 物理的な寸法(Print size): 7.213 cm × 8.39824 cm (≒ 204.46 bp × 238.06 bp)

ここから、画像の bbox は「0 0 204.46 238.06」((graphicx パッケージの流儀だと、特に bp 単位に直さなくても「0 0 7.213cm 8.39824cm」と単位付きで書けば通用する。))と決定できる。

ただし、identify -verbose の出力は大量になるのが難点である。解像度とピクセル数を手っ取り早く知るには、-format オプションで出力書式を指定すればよいようである。((%x/%y は横/縦方向の解像度、%w/%h は幅/高さのピクセル数を示す。))以下の例では解像度を dpi 単位で出力している。((px/cm 単位で出力する場合は PixelsPerInchPixelcPerCentimeter に変える。ちなみに、PNG 画像の規格では、解像度は常に px/m 単位での整数で記録されている。dpi 単位の表示は処理途中での丸め誤差が入っているように見える。))

>identify -units PixelsPerInch -format "%xx%y/%wx%h" apple.png
150.00999999999999x150.00999999999999/426x496

物理的寸法を得るのはやや複雑になる。次のようにすれば bp 単位での bbox の値そのものが出力される。*1

>identify -units PixelsPerCentimeter -format "0 0 %[fx:w*72/2.54/resolution.x] %[fx:h*72/2.54/resolution.y]" apple.png
0 0 204.463 238.06

なお、ビットマップ画像が解像度情報を持っていない場合、dvipdfmx や pdfTeX ではそれを 72 dpi と見做す。実は、ImageMagick も解像度の既定値を 72 dpi としているので、解像度情報のない画像でも上記のコマンドは「辻褄の合う」値を返す。ただし、一番最後の「bbox 値の出力」は上手くいかないようである。((もちろん、この場合は "0 0 %w %h" が正解。))

参考:ImageMagick でビットマップ画像の解像度を変更する

「bbox の取得」とは直接関係がないが、事のついでに、ImageMagick の convert コマンドを用いて、画像の解像度を変更する*2方法を述べておく。例えば、先述の PNG 画像 apple.png の解像度を 96 dpi に変更した画像ファイル apple-96dpi.png を得るには次のコマンドを実行する。

>convert -units PixelsPerInch apple.png -density 96 apple-96dpi.png

引数の先頭に -units PixelPerInch が要ることに注意。((入力側のファイルの解像度が px/cm で記録されている場合(PNG 画像の場合は常に px/m だが ImageMagick はこれを px/cm に変換して扱う)、そのままでは -density の数値も px/cm と見做される。予め -units を指定しておくと、“その後で”読み込まれたファイルの解像度が指定の単位に変換される。))

ところで、解像度情報を「除去」する方法って用意されてないのかな?*3

qpdf を利用して PDF 文書のストリーム圧縮を解除する

例の記事で、DecodeParms への対策として述べた、「ストリームの圧縮を全て解除する」操作を qpdf で行う方法を述べる。*4次のコマンドを実行すると、image.pdf の中の全てのストリームデータの圧縮*5を解除したものを image-nocomp.pdf として出力する。

>qpdf --stream-data=uncompress image.pdf image-nocomp.pdf

補足:

  • PDF バージョンおよび ナントカBox については元のファイルのものが保持される。
  • もちろん、DecodeParms 対策だけでなく、「圧縮されているからアレ」的問題全般の回避策として使える。
qpdf を利用して複数ページの PDF の特定ページを抽出する

次のコマンドを実行すると、images.pdf の 2 ページ目の内容を image-2.pdf として書き出す。*6

>qpdf --pages images.pdf 2 -- images.pdf image-2.pdf

補足:

  • PDF バージョンおよび ナントカBox については元のファイルのものが保持される。
  • 出力先の(今の場合「元の」でもある)ファイルの PDF バージョンが 1.5 以上の場合、qpdf はメタデータを書き出す時に DecodeParms 付(!)の圧縮を利用するようである。このままだと dvipdfmx で扱えないので、さらに前節で述べた圧縮解除のオプションを指定する必要がある。
    >qpdf --stream-data=uncompress --pages images.pdf 2 -- images.pdf image-2.pdf
pdfinfo を利用して PDF の ナントカBox の値を調べる

pdfinfo は PDF 文書についてのメタ情報を表示するためのツールである。*7-box オプション付きで実行すると ナントカBox の値が出力に含まれる。

>pdfinfo -box tiger.pdf
Title:          untitled
Producer:       Acrobat Distiller 6.0.1 (Windows)
CreationDate:   01/14/05 11:33:29
ModDate:        01/14/05 11:33:53
Tagged:         no
Form:           none
Pages:          1
Encrypted:      no
Page size:      550 x 568 pts
MediaBox:           0.00     0.00   550.00   568.00
CropBox:            0.00     0.00   550.00   568.00
BleedBox:           0.00     0.00   550.00   568.00
TrimBox:            0.00     0.00   550.00   568.00
ArtBox:             0.00     0.00   550.00   568.00
File size:      41391 bytes
Optimized:      yes
PDF version:    1.4

pdfinfo のボックス情報表示は複数ページの PDF 文書(画像)にも対応している。次のように、-f-l で範囲を指定すればよい。((-f が開始ページ番号、-l が終了ページ番号を示す。-f の既定値は 1 であり、-l が省略された場合は、-f で指定したページのみが対象となり、この場合は出力に「Page xxx」の文字列が含まれないようである。))

C>pdfinfo -box -f 1 -l 2 images.pdf
Creator:        TeX
Producer:       pdfTeX-1.40.14
CreationDate:   08/17/14 17:55:10
ModDate:        08/17/14 17:55:10
Tagged:         no
Form:           none
Pages:          2
Encrypted:      no
Page    1 size: 50 x 50 pts
Page    2 size: 100 x 100 pts
Page    1 MediaBox:     0.00     0.00   100.00   100.00
Page    1 CropBox:     25.00    25.00    75.00    75.00
Page    1 BleedBox:    25.00    25.00    75.00    75.00
Page    1 TrimBox:     25.00    25.00    75.00    75.00
Page    1 ArtBox:      25.00    25.00    75.00    75.00
Page    2 MediaBox:     0.00     0.00   200.00   200.00
Page    2 CropBox:     50.00    50.00   150.00   150.00
Page    2 BleedBox:    50.00    50.00   150.00   150.00
Page    2 TrimBox:     50.00    50.00   150.00   150.00
Page    2 ArtBox:      50.00    50.00   150.00   150.00
File size:      10516 bytes
Optimized:      no
PDF version:    1.5

これを利用すれば、「extractbb が複数ページ PDF ファイルに非対応」の問題を回避できそうであるが、これについては問題点がある。各々のページについて、dvipdfmx での bbox は 5 つの ナントカBox の値の何れかになるのだが、その判断方法がかなり独特で、たとえ全ての値が判明していても判断できない場合があるのである。ただし大抵の場合は、以下の規則が適用できると思われる。

  • MediaBox 以外の 4 つの ナントカBox の値が全て一致しているならば(MediaBox の一致は問わない)、それが dvipdfmx の判断する bbox となる。
    • 例えば、tiger.pdf の「dvipdfmx での bbox」は「0.00 0.00 550.00 568.00」。
    • images.pdf の 1 ページ目の「dvipdfmx での bbox」は「25.00 25.00 75.00 75.00」。
    • images.pdf の 2 ページ目の「dvipdfmx での bbox」は「50.00 50.00 150.00 150.00」。

*1:もっと簡単な方法があるかも知れないが。

*2:ここでは「解像度を変更する」という表現は「ビットマップデータは変更せずに画像のメタ情報中の解像度の値だけを変える」(つまり物理的寸法は変更される)ことを意味する。

*3:私は取りあえず、「一度 PPM 形式に変換して再度元の形式に戻す」という強引な方法を採っている。(解像度情報は PPM 形式ではサポートしていないのでこれに変換すると確実に消えてしまう。)

*4:qpdf は W32TeX の配布の中に含まれている。

*5:DecodeParms の指定の有無にかかわらず。

*6:images.pdf が 2 回指定されているが、後者は PDF 文書のメタデータの継承元を示している。

*7:本来は Xpdf という X Window System 上の PDF ビューワに付属するツールである。W32TeXTeX Live は本体の xpdf は含んでいないが付属ツールの幾つかを収録している。