Acetaminophen’s diary

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

TeX 出力から SVG への変換

この記事は、サブブログの 2015-03-10 ~ 2015-03-12 投稿記事から移転したものです。

TeX の出力を SVG 形式にしたい!

という訳で、検討メモを貼っておく。今回の検証は初めにすべて Mac で行い、そのあと Windows でも追試した。

 

目標

ウェブサイトに載せる画像としても利用したいし、拡大でギザギザになるのもいや。また、フォントがないと表示できないのも困るので、アウトライン化されたベクター画像を最終目的とする。すなわち、こんな感じの SVG 画像をつくりたい。(図中の青い点は、Illustrator で開いてパスのノードを選択した状態。)

f:id:acetaminophen:20150310152537p:image

以下では、検討した(実験した)順に掲載する。すなわち、上にあるものほど良い方法だという訳ではないことに注意。

 

1:Ghostscript で EPS から SVG

GhostscriptSVG 出力に対応しているという話(例えばこことかここ)を見つけたので、gs9.10 で試してみた。これは確かに成功する。

 $ gs -dBATCH -dNOPAUSE -sDEVICE=svg -sOutputFile=equation.svg equation.eps

しかし、gs9.15 では output device から svg が消えている調べてみると、Ghostscript の svgバイスは品質が良くなかったようで…。

Customer has already been notified that the SVG device is not of commercial quality.

いや、でもサポートをやめなくてもいいんじゃないかな…

 

2:dvisvgm で DVI から SVG

TeX Live や W32TeX には、dvisvgm というソフトウェアが収録されている(ここここ参照)。画像化の目的ではフォントのアウトライン化をしたいので、とりあえず DVI から SVG への変換を試してみる。-n オプションでフォントをパスに変換できるらしいので…

 $ dvisvgm -n equation.dvi

これでパスに変換できた。ただし、この方法では DVI を経由する方法しか対処できず、かつ map によるフォント埋め込みもできないという制約がある。

 

3:dvisvgm で EPS から SVG

同じく dvisvgm であるが、これなら先に PDF から EPS への変換を eps(2)write で行う(=アウトライン化)ことができるので、フォント埋め込みの問題も解消するはず。しかし、実際にやってみると

 $ dvisvgm -E equation.eps
ERROR: Ghostscript is required to process the EPS file

というわけで、(少なくとも自分の OS X 環境では)何もしないと Ghostscript のライブラリを認識できなかった…。

dvisvgm の FAQ によると dvisvgm のビルド方法には 3 種類あるらしく*1、それぞれで PostScript を扱う方法が異なる。3 つめのビルド方法では gs を使えないのだが、幸い MacTeX-2014 の TeX Live の場合は 2 番目のビルド方法らしく、--libgs オプションで場所を指定すれば使える。僕の場合は TeX Live とは独立に MacPorts でインストールした gs を使っているので

 $ dvisvgm --libgs=/opt/local/lib/libgs.dylib -E equation.eps

これで変換できた。ただし、人によっては MacPorts を使っていないはずだし、そもそもこのライブラリを TeX Live 側から発見することが不可能なので、一般性は無い。

ちなみに Windows ではこのような問題は発生しなかった(正しく gsdll32.dll/gsdll64.dll を認識してくれる模様)。

この「gs をどうやって見つけるか・見つけられるか」という課題のほかにも、この方法には以下の懸念点がある。

  • Illustrator で dvisvgm で出力した SVG を開くと「SVG Tiny に書き出し後に読み込むとクリッピングは失われます」というエラーが出る*2
  • そもそも dvisvgm の -E オプションや --eps オプションは 2013 年 3 月 1 日の version 1.2 で新設されたかなり最近の変更

というわけで、不便に感じる面も多そうだ。

 

4:pstoedit で EPS/PDF から SVG

pstoeditGPL ライセンスであるが、pstoedit の svg サポートは「シェアウェアプラグインでの対応」らしい。代わりにフリーで使えるのが plot-svg というオプション。

 $ pstoedit -f plot-svg -dt -ssp equation.eps equation.svg

この方法はここここを参照。ただし、後者によるとうまく画像を変換できない場合があるらしく、一般的な方法とするには少々不安である。

 

5:pdf2svg で PDF から SVG

GPL ライセンスの pdf2svg というものがある。これなら、既にアウトライン済みの PDF を使って SVG に変換できる! 品質も問題なく、特にエラーも発生しない

 $ pdf2svg input.pdf output.svg

というわけで、以上 5 つのなかではこれが最善のように感じる。

 

6:ImageMagick で PDF から SVG

ImageMagick の convert も SVG を出力可能である。convert は良く用いられているので一般性がありそうだが…

 $ convert equation.pdf equation.svg

この方法はベクター画像の PDF であっても勝手にビットマップ化してしまう。そのうえ、XML 的にも規格にあわない SVG ファイルを出力するのでブラウザで表示することもできない(Thanks: @golden_lucky さん)。

 

7:Potrace で PNM から SVG

こちらに書かれている方法。PNM とは PBM, PGM, PPM すなわち白黒・グレースケール・フルカラーの ASCII テキスト形式の画像フォーマットの総称(こちらが詳しい)で、ビットマップである。すなわち、この方法ではいったんビットマップ化した後に再度 Potrace によってアウトラインをトレースする。PNM の作成は ImageMagick の convert でも gs の pnm 系デバイスでも構わないが、アウトラインの精度を高めるためには解像度を高くしておきたいところ(なお解像度は適当に決めた)。

  • ImageMagick の convert の場合
     $ convert -density 500x500% equation.eps equation.pbm
     $ potrace -o equation.svg -s equation.pbm
    
  • gs の pbm device の場合
     $ gs -q -sDEVICE=pbm -sOutputFile=equation.pbm -r2400 -dNOPAUSE -dBATCH -dSAFER -dEPSCrop equation.eps
     $ potrace -o equation.svg -s equation.pbm
    

なお、PBM を選んだのは Potrace の仕様に従っている。

制約として、Potrace は白黒の 2 値画像しかトレースできない。カラー画像を処理しようとすると、下のようにもやもやしたパターンができる(元画像で「あいうえお」を黒、「かきくけこ」をピンクにしていた場合で試した。Potrace でトレースして得た SVGスクリーンショット)。

f:id:acetaminophen:20150311220258p:image

色を扱えないのは致命的だが、公式に「グレースケールやフルカラーの画像のトレースには事前に mkbitmap を使って閾値で 2 値化しておく」ということらしい。

 

8:Poppler の pdftocairo で PDF から SVG

Poppler という PDF ライブラリの中に、pdftocairo というツールが入っている。

 $ pdftocairo -svg equation.pdf

これは結果が(見た目・コードともに)綺麗。

 

9:MuPDF の mudraw で PDF から SVG

MuPDF という PDF ライブラリの中に、mudraw というツールが入っている。

 $ mudraw -o equation.svg equation.pdf

これも(見た目・コードともに)良い結果。

10:Inkscape で PDF から SVG

Inkscape でもできなくはないらしいので、やってみた。

 $ inkscape -z -f equation.pdf --export-plain-svg equation.svg

変換はできたが、なんだかソースが汚いようにみえる。--export-plain-svg というのは Inkscape の独自 SVG から標準 SVG への変換オプションのようなので、仕様がよくわからない…。

 

ちなみに TeX2img では

これらの検討のきっかけは、TeX2img で SVG 出力をサポートしたかったからである。TeX2img for Mac 1.8.9 では 5 番目の方法である pdf2svg を搭載した*3が、のちに 1.9.2 時点で mudraw を使う方法に変更されている。

*1:Why is dvisvgm's PostScript support disabled on my machine? の項を参照。

*2:原因はどうやら clipPath なるもの(例えばこちら)らしく、実際 dvisvgm が作った SVG のソースから clip-path='url(#clip1)' をすべて削除すると Illustrator のエラーが消える。

*3:ライブラリを含めてすべて同梱してしまうこの方法が一般性があって安全だとの判断。