Acetaminophen’s diary

化学に関すること,TeXに関すること,ゆきだるまに関すること。

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 出力の場合】

TeX →…→ PDF →[pdfcrop類似処理でクロップ+余白付与]→
  PDF →[mudraw]→ 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 XAPI をフル活用するためであり、最終的な出力がよりきれいになるように gs と OS XAPI を使い分けている。大雑把には

  • 文字のアウトライン化は OS XAPI より gs が綺麗
  • PDFのビットマップ化は gs より OS XAPI が綺麗

となるようである。

【テキスト情報を残す 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 出力の場合】

TeX →…→ PDF →[pdfcrop類似処理でクロップ+余白付与]→
  PDF →[mudraw]→ 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 XAPI によるビットマップ化が美しいため、これを用いるためにまず 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 の数式を IllustratorInkscape にアウトライン化して貼り込む」という用途に対応できたはずである*5

複数ページ処理について

複数ページの画像を生成するにあたり、Mac 版 TeX2img は OS XAPI で PDF の総ページ数を取得する。Windows 版は新たに搭載した PDFium でページ数を取得する*6

 

あとがき

以上が最新の TeX2img 内部変換処理の解説である。

  • アウトライン化の需要が大きいことを考慮し、PDF/EPS の出力に epswrite/eps2write を用いた変換スキームを実装していること
  • テキスト保持 PDF の出力では、オリジナルの pdfcrop 単独では不可能な「特定のページのみをクロップ+余白付与」を実装していること
  • アウトライン化を行い、かつテキスト情報を保持(すなわちコピー&ペーストが可能)した SVG ファイルを出力する mudraw を用いていること

などがご理解いただければ幸いである。アウトライン化すれば例えば

f:id:acetaminophen:20141018204220p:plain

のように Illustrator を用いてエフェクトをかけることもできる(図は物理のかぎしっぽより)*7し、ソースが XML テキストで記述されている SVG は最近の HTML5 が推進されている現在ますます需要が高まっていくはずである。

 

参考 1:TeX2img の使いかたの解説

参考 2:pdftex と gs を用いた Windows バッチファイルによる pdfcrop の再実装

これだけ情報があれば、内部処理の解説としては十分?

*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 のフォント形式は特殊なのでうまくいかない可能性がある。