TeX2img (Windows/Mac) の動作の詳細(改訂版)
【最終更新:2015-03-26】この記事は TeX2img の画像変換に関連した処理の解説であり、Windows 版 1.5.0 以降と Mac 版 1.9.2 以降において有効である。以前のバージョンはこちら。
(追記:2015-07-20)本日公開の TeX2img for Mac 1.9.4 で若干の変更箇所あり;後日改訂予定だが、とりあえずサブブログで紹介。
TeX2img による画像変換処理
TeX2img Windows 版 1.5.0 と Mac 版 1.9.2 は、出力可能な画像形式を増やした。それと同時に、以前のバージョンと比較して画像変換スキームを大きく変更した部分があるため、その詳細を解説する(変更部分はこちらを参照)。類似の画像変換スクリプトを自前で作成したい場合にも、本記事の内容が役に立つはずである。
TeX2img の Win/Mac 両バージョンは(ユーザが同じように処理したつもりでも)出力結果が微妙に異なる。そこで、これは個別に説明する必要がある。
TeX2img Windows 版の変換方式
Windows 版は以下のように処理する。
【テキスト情報を残す PDF 出力の場合】
TeX →…→ PDF →[pdfcrop類似処理でクロップ+余白付与]→ PDF
TeX Live や W32TeX には pdfcrop という「クロップ+余白付与」を行う Perl スクリプトが含まれている。しかし Windows 環境(特に W32TeX の場合)では Perl インタプリタを必ずしも搭載していないので、pdfcrop を利用できない場合が考えられる。しかも、pdfcrop 自身は複数ページ PDF を単一ファイルで出力するため、別々のファイルに分割出力すべく独自に pdfcrop の類似処理を TeX2img 内部に実装した。この処理で「クロップ+余白付与」を実現した。
【アウトライン化 PDF 出力の場合】
TeX →…→ PDF →[gs (eps(2)write)でアウトライン化+クロップ]→
EPS →[BB情報を編集して余白付与]→[gs (pdfwrite)]→ PDF
eps(2)write は「アウトライン化+クロップ」を行う。デフォルトでは -r20016 固定で解像度調節は無効だが、基本設定で「低解像度での処理を行う」を ON にすると解像度調節が有効になり、-r オプションの値は 解像度レベル×72 となる。
【アウトライン化 EPS 出力の場合】
TeX →…→ PDF →[gs (eps(2)write)でアウトライン化+クロップ]→
EPS →[BB情報を編集して余白付与]→ EPS
eps(2)write はデフォルトでは -r20016 固定で解像度調節は無効だが、基本設定で「低解像度での処理を行う」を ON にすると解像度調節が有効になり、-r オプションの値は 解像度レベル×72 となる。
【アウトライン化 EMF 出力の場合】
TeX →…→ PDF →[gs (eps(2)write)でアウトライン化+クロップ]→
EPS →[BB情報を編集して余白付与]→[gs (pdfwrite)]→ PDF →[pdfiumdraw]→ EMF
アウトライン化 PDF を出力するスキームに続き、Google が開発したオープンソースの PDF レンダリングエンジン PDFium をもとに独自に開発した pdfiumdraw というプログラムを利用する。
【アウトライン化(+テキスト情報保持)SVG 出力の場合】
テキスト保持 PDF を出力するスキームに続き、MuPDF の mudraw を使用して「アウトライン化を行い、かつテキスト情報は保持」した SVG ファイルを出力できる。
【JPG/PNG/BMP 出力の場合】
TeX →…→ PDF →[gs (eps(2)write)でアウトライン化+クロップ]→
EPS →[BB情報を編集して余白付与]→[gs (jpeg/pngalpha/bmp16m)]→ JPG/PNG/BMP
アンチエイリアスの有無によらずスキームは同じであり*1、-dTextAlphaBits および -dGraphicsAlphaBits オプションに
を与えている。eps(2)write の -r オプションの値は 解像度レベル×72 となる。余白付与は EPS ソースの BoundingBox 情報の編集によって行うが、余白の単位はデフォルトでは px であり、ピクセル単位で (指定された余白) 分に対応する余白を付加する。単位を bp に指定すると PDF/EPS と同じ処理により BoundingBox 情報の編集を行うため、結果としてはピクセル単位で (指定された余白)*(解像度レベル) 分に対応する余白を付加したことになる*2。なお、PNG については透過処理の有無で gs のデバイスを変更し
- 透過処理 ON の場合は pngalpha
- 透過処理 OFF の場合は png16m
を使用するようになっている。
TeX2img Mac 版の変換方式
Mac 版は以下のように処理する。Windows 版に比べて若干複雑になるが、これは高機能な OS X の API をフル活用するためであり、最終的な出力がよりきれいになるように gs と OS X の API を使い分けている。大雑把には
となるようである。
【テキスト情報を残す PDF 出力の場合】
TeX →…→ PDF →[pdfcrop類似処理でクロップ+余白付与]→ PDF
TeX Live (MacTeX) に含まれている pdfcrop という「クロップ+余白付与」を行う Perl スクリプトの類似処理を TeX2img 内部に実装した。pdfcrop 自身は複数ページ PDF を単一ファイルで出力するが、TeX2img は別々のファイルに分割出力する*3。
【アウトライン化 PDF 出力の場合】
TeX →…→ PDF →[gs (eps(2)write)でアウトライン化+クロップ]→
EPS →[epstopdf (gs)]→ PDF →[pdfcrop類似処理で余白付与]→ PDF
eps(2)write は「アウトライン化+クロップ」を行う。デフォルトの「画質優先モード」では -r20016 固定で解像度調節は無効だが、変換処理で「速度優先モード」に変更すると解像度スケール調節が有効になる。このとき、-r オプションの値は 解像度レベル×144 となる。gs の epstopdf は Perl インタプリタを用いる pdfwrite のラッパだと考えて差し支えない。
【アウトライン化 EPS 出力の場合】
TeX →…→ PDF →[gs (eps(2)write)でアウトライン化+クロップ]→
EPS →[BB情報を編集して余白付与]→ EPS
eps(2)write はデフォルトの「画質優先モード」では -r20016 固定で解像度調節は無効だが、変換処理で「速度優先モード」に変更すると解像度スケール調節が有効になる。このとき、-r オプションの値は 解像度レベル×144 となる。
【アウトライン化(+テキスト情報保持)SVG 出力の場合】
テキスト保持 PDF を出力するスキームに続き、MuPDF の mudraw を使用して「アウトライン化を行い、かつテキスト情報は保持」した SVG ファイルを出力できる。
【JPG/PNG/BMP/GIF/TIFF 出力(画質優先モード)の場合】
TeX →…→ PDF →[gs (eps(2)write)でアウトライン化+クロップ]→
EPS →[epstopdf (gs)]→ PDF →[OS XのQuartz APIでビットマップ化+余白付与]→ JPG/PNG/BMP/GIF/TIFF
変換処理はデフォルトで「画質優先モード」である。OS X の API によるビットマップ化が美しいため、これを用いるためにまず epswrite/eps2write によってアウトライン化 EPS を作成して再び epstopdf によって PDF に変換する。画質優先のため -r20016 固定で解像度調節は無効である。
【JPG/PNG/BMP/GIF/TIFF 出力(速度優先モード)の場合】
TeX →…→ PDF →[pdfcrop類似処理でクロップ]→
PDF →[OS XのQuartz APIでビットマップ化+余白付与]→ JPG/PNG/BMP/GIF/TIFF
変換処理で「速度優先モード」に変更すると、そもそも JPG/PNG 処理の結果は元ファイルがテキスト保持かアウトラインかは問題とならないため、eps(2)write を通さずに pdfcrop 類似処理を用いることにした。これによって、結果的には gs9.14 以前の epswrite でまれに起こる VMerror を根本から回避することができる。
その他細かい注意点
いくつか画像変換の過程で必要となる内部処理について、注意点をあげておく。
TeX2img の余白付与機能
以前の記事で説明した通り eps2write により生成した EPS のソースにはバイナリが含まれることがある。EPS ファイルへの余白付与は EPS の BoundingBox 情報を書き換えることによって実装されている*4が、この書き換えでバイナリ部分を破壊しないような方式を採用している。詳細は Windows 版と Mac 版のソースコードを参照。
フォントのアウトライン化
前回の記事で説明した方法を採用し、eps(2)write でのアウトライン化を完成させた。これで、TeX2img の使用用途のうちで結構大きな部分を占めるであろう「TeX の数式を Illustrator や Inkscape にアウトライン化して貼り込む」という用途に対応できたはずである*5。
複数ページ処理について
複数ページの画像を生成するにあたり、Mac 版 TeX2img は OS X の API で PDF の総ページ数を取得する。Windows 版は新たに搭載した PDFium でページ数を取得する*6。
あとがき
以上が最新の TeX2img 内部変換処理の解説である。
- アウトライン化の需要が大きいことを考慮し、PDF/EPS の出力に epswrite/eps2write を用いた変換スキームを実装していること
- テキスト保持 PDF の出力では、オリジナルの pdfcrop 単独では不可能な「特定のページのみをクロップ+余白付与」を実装していること
- アウトライン化を行い、かつテキスト情報を保持(すなわちコピー&ペーストが可能)した SVG ファイルを出力する mudraw を用いていること
などがご理解いただければ幸いである。アウトライン化すれば例えば
のように Illustrator を用いてエフェクトをかけることもできる(図は物理のかぎしっぽより)*7し、ソースが XML テキストで記述されている SVG は最近の HTML5 が推進されている現在ますます需要が高まっていくはずである。
参考 1:TeX2img の使いかたの解説
参考 2:pdftex と gs を用いた Windows バッチファイルによる pdfcrop の再実装
- 劣化版 pdfcrop の改善版 (tcpdfcrop.bat)
- 劣化版 pdfcrop(fork 元:ZR 氏作)
- 複数ページ処理の実装方法の提案(ZR 氏)
要は、同じ「LaTeXコードからPDF画像を作る」という作業であっても、その作業の目的をきちんと考えて、適切な方法を使い分けることが必要だということ。#TeX
— ZR-TeXnobabbler(既定値) (@zr_tex8r) 2014, 10月 18
これだけ情報があれば、内部処理の解説としては十分?
*1:従来 Windows版1.4.0 以前では、オプションでインストールが推奨されている ImageMagick を用いてアンチエイリアスを行っていたが、gs 単独でアンチエイリアスの有無を調節できることが判明したため、追加インストールを求めずにアンチエイリアスを行うスキームに変更した。
*2:“対応する”という表現を用いたのには意味がある。実際の処理は、BB 情報編集で「余白単位が bp ならば PDF/EPS と同じ値で付加し、px ならば PDF/EPS の場合の値を解像度レベルで割った値で付加」している。
*3:従来の Mac版1.8.9.1 以前では Mac に内蔵されている Perl インタプリタを活用して pdfcrop をそのまま用いていたが、これは単に TeX コンパイルと pdfcrop を続けて実行するにすぎず、TeX2img で行う必要性をあまり感じなかったかもしれない。しかし、今回の独自実装で pdfcrop 自身に不可能な「別々のファイルに分割出力」を可能にしたことで、TeX2img の優位性が確立された。
*4:詳しくは「EPS のソースの %%BoundingBox: や %%HiResBoundingBox: の行を書き換えることによって余白を作って」いる。
*5:ただし、gs9.15 の eps2write で -dNoOutputFonts オプションを付与しても、言うことを聞かない場合もある。例えば以前書いた通り、TeX2img を介してもコマンドラインから操作しても、例のロゴは Windows/Mac ともにアウトライン化に失敗した。
*6:以前の Windows 版 1.2.5 から 1.4.0 までは pdfinfo を用いていたが、依存プログラムを減らすことに成功した。
*7:TeX のフォントをシステムにインストールすれば Illustrator の機能でテキストのアウトライン化が可能かもしれないが、TeX のフォント形式は特殊なのでうまくいかない可能性がある。