Ghostscript のこと(2):不具合?
(前回の続き)
追記:2015-03-14 21:30
アウトライン化の挙動について新たな知見が得られたため、一部書き換えた。
Ghostscript の Windows/Mac における挙動の差異
ここまで詳細に Ghostscript のアウトライン化機能を説明してきたが、以上の説明は、Mac 用の gs9.15 についてはすべて正しい。一方、Windows 版については一部正しくない。というのも、ここに Windows 版固有の不具合が含まれてくるからである。しかも、Windows 版バイナリは主なものに TeX Live の rungs.exe と角藤さんによる移植版の gswin32c.exe が存在するため、話はさらにややこしくなった。
TeX Live の rungs は、OS が Windows ならば gswin32c.exe を、それ以外なら gs を呼ぶだけである。しかし、名称が同じとはいえ、TeX Live 同梱の gswin32c.exe と W32TeX 向けの角藤版 gswin32c.exe では(基本的には同じだが)細かい初期設定が異なり、完全には同一でないらしい*1。
Ghostscript 9.15 の実験
はじめに Windows 版 gs9.15 で eps2write を通す実験をした結果、観察された現象を一覧にしておく。入力コマンドは以下の通り(ただし gs とは Windows では rungs.exe または gswin32c.exe を意味する)。
gs -q -sDEVICE=eps2write -dNoOutputFonts -sOutputFile="output-%d.eps" -dNOPAUSE -dBATCH -r20016 "input.pdf"
- エラーコード12の発生、あるいはエラーコードを吐く前のフリーズ(具体的には
GPL Ghostscript 9.15: ERROR -12 closing eps2write device. See gs/psi/ierrors.h for code explanation.
というエラーが出る) - オプション -dNoOutputFonts があるのにアウトライン化されず、ビットマップ化される
- 「_teA2A8.tmp」「_teA2A9.tmp」…といった謎の16進数の連番一時ファイルが作業ディレクトリに生成する
TeX Live の場合は、-dNoOutputFonts があるか否か、解像度に関わらず
- 本文が「aiueo」だけのシンプルなファイルだと ERROR -12 が発生(アウトライン化は成功)
- 例のロゴ「TikZ_Rz.tex」はエラー無し(ただしビットマップ化)
W32TeX の場合は、-dNoOutputFonts があるか否か、解像度に関わらず
- 本文が「aiueo」だけのシンプルなファイルだと ERROR -12 が発生、謎の一時ファイル生成(アウトライン化は成功)
- 例のロゴ「TikZ_Rz.tex」は ERROR -12 が発生、謎の一時ファイル生成(しかもビットマップ化)
これらの現象は TeX2img を通した場合でもコマンドラインから手動で実行した場合でも同じであった。
複数ページ処理における gs9.10/9.15 の挙動の差異
以上のような現象に悩んでいたところ、あることを発見した。
前回と今回の記事の今までの部分で Windows 用コマンドとして書いてきたものと、Mac 用コマンドとして書いてきたものの決定的な違いが存在した。
-sOutputFile="tmp-%d.eps" とするか -sOutputFile="tmp.eps" とするか
という件である。つまり、PDF ファイルのページを連番 EPS ファイルとして出力するか、単一の EPS ファイルを指定してそれに書き込むかである。
まず Mac 用 Ghostscript について、寺田さんが gs9.10 と gs9.15 で実験した結果
【Mac 用 gs9.10 の場合:epswrite】
- 「-%d」なしの場合は、PDF のページ数によらず単一の EPS ファイルができる(正常)。
- 「-%d」ありの場合は、PDF のページ数より常に一枚多くの EPS ファイルを生成し、最後の一枚が白紙(BB 情報のみ)である(異常)。
【Mac 用 gs9.15 の場合:eps2write】
- 「-%d」なしの場合は、PDF のページ数によらず単一の EPS ファイルができる(正常)。
- 「-%d」ありの場合は、PDF のページ数と同数の EPS ファイルを生成し、余分なページを生じない(正常)。
次に Windows 用 Ghostscript について、阿部さんと僕が同じく gs9.10 と gs9.15 で実験した結果
【Windows 用 gs9.10 の場合:epswrite】
- 「-%d」なしの場合は、PDF のページ数によらず単一の EPS ファイルができる(正常)。
- 「-%d」ありの場合は、PDF のページ数より常に一枚多くの EPS ファイルを生成し、最後の一枚が白紙(BB 情報のみ)である(異常)。
【Windows 用 gs9.15 の場合:eps2write】
- 「-%d」なしの場合は、PDF のページ数によらず単一の EPS ファイルができる(正常)。
- 「-%d」ありの場合は、やはり PDF のページ数より常に一枚多くの EPS ファイルを生成するが、最後の一枚が 0 バイトである(異常)。
この Windows 用 gs9.15 についてもう少し詳しく書いておくと、「-%d」ありの場合には ERROR -12 またはフリーズが発生し、例の .tmp が生成していたが、「-%d」無しの場合には ERROR -12 もフリーズも発生せず、.tmp も出なかった*2。
初めにこの現象に気づいたきっかけは Windows 版だったので、最初は gs9.15 の eps2write が最後の余分な一枚のアウトプットに何らかの理由で失敗し、0バイトのファイルにしてしまっているのではないかとも思ったのだが、Mac 版の結果を考慮すると
- -%d による複数ページ出力時に1ページ多く出るのは異常で、epswrite の不具合であった
- この問題を eps2write で直したつもりだったが、Mac版では直ったがWindows版は直っていない
と考えられる。
アウトライン化の不具合?
例のロゴをアウトライン化した PDF/EPS で出力しようとすると、-dNoOutputFonts オプションの有無にかかわらず完全なアウトライン化が不可能であった。Windows と Mac の Ghostscript でテストした結果
- gs では、今も昔も「TikZ_Rz.pdf」は“相性が悪く”、これを自然な形にアウトライン化することはできない。
- gs 9.10 の epswrite では“不完全アウトライン化”しようとしていた。その結果、低解像度の場合はパス数がなんとか許容範囲に入って“不完全アウトライン化”できるものの、高解像度の場合はパス数が膨大になりすぎてエラーを起こしていた。
- gs 9.15 の eps2write では“不完全アウトライン化”するほかないような“相性の悪い”PDF に対しては、解像度設定にかかわらずアウトライン化を早々と諦め、ビットマップ化を強制することでエラーを防いでいる。
のように推測した(Thanks: 寺田さん)。
ようやく TeX2img へ
以上の検証結果を考慮すると、ようやく今回の TeX2img の両バージョンのアップデートが十分に理解できるようになる。Ghostscript の挙動を踏まえた TeX2img の画像変換ワークフローも本ブログに説明している(本記事執筆時点での知見を踏まえた解説はこちら:Ghostscript についてさらに得た知見は、新しい記事へ)。