swk's log 最新ページ

ppt2eps - from swk's log

2010-09-19 Sun

* PowerPoint から LaTeX 用の EPS ファイルを全自動で生成する [ppt2eps] 3 users

最近,というかもうここ数年はずっと,LaTeX で作る原稿用の図は (グラフや写真は別として) ほとんど PowerPoint で描いている.ベストな選択だとは思わないが,利便性のバランスが一番取れていると思う (主として,似た図の使い回しの面で).

ところで,PowerPoint の各スライド (= 各ページ) の図を EPS にする作業は,普通にやるとそこそこ面倒である.それを全自動化しようというがこの記事の話.具体的には,make コマンド一発で EPS の生成から TeX ファイルのタイプセットまで全自動で実行できる.もちろん,PowerPoint のあらゆる機能を試して問題が起きないか確認したわけではないので,ご注意願います.


動作原理の本質的なところは,以下のページの方法と同一である.つまり,プリンタドライバに PostScript (以下 PS) を吐かせて,psselect と ps2eps で EPS に変換する.

これに対してこの記事の新たな貢献は以下の3点:
(1) 完全自動 (出力する PS ファイル名の都度入力が不要)
(2) EPS ファイル1つ1つに任意のファイル名をつけられる
(3) (PPT ファイルごとではなく) EPS ファイルごとに更新判定をする

簡単に説明すると,(1) 従来法では,PS ファイルを出力するときに手動で出力ファイル名を入れる必要があったのだが,その必要がなくなった.また, (2) 個々の出力 EPS ファイルには連番のファイル名をつけるしかなかったのが,各ファイルに自由に名前をつけられるようになった.これは割と重要で,連番ファイル名になっていると,PowerPoint 上でスライドの順番を入れ替えたりスライドを削除したりすると大混乱が生じる.やはり番号ではなく名前で管理したい.最後に (3) だが,従来法だと PPT ファイルが更新される度に,その中の全スライドの EPS を出力し直すことになってしまう.実は ps2eps は結構遅いので,これはあまり嬉しくない.更新されたスライドだけ EPS に変換できるのが望ましい.

ほぼ同様の仕組みが,以下のページで Ruby スクリプトとして実装されている (ことにさっき気づいた).PowerPoint から WMF を出力して,wmf2eps と epstool で EPS を生成している.wmf2eps がシェアウェアなのが難点だが,その点が障壁にならない場合は WMF 経由の方がスマートかもしれない. epstool は ps2eps より速くて (図ごとの更新判定が不要なくらい) 快適だが,図の周辺部の切り取り処理がちょっと甘いようだ (周辺の文章がちょっと隠れてしまう場合がある).

必要なもの

  • MS Windows (動作確認は XP SP3)
  • MS PowerPoint (動作確認は 2003 SP3)
  • Ghostscript (動作確認は Cygwin の GhoscScript 8.62 と Win32 用 Ghostscript 7.07)
  • Cygwin (以下のコマンドに path を通しておく)

    • psselect (W32TeX のフルインストールに含まれる.ない場合は psutils を入れる)
    • ps2eps
    • perl
    • make

  • PS をファイルに吐き出せるプリンタドライバ

Cygwin は別に本質的ではないけど,いろいろ依存している.Cygwin を使わないようにすることもできると思うが,対応予定なし.動作確認に使っているソフトウェア群 (特に PowerPoint そのもの) が古いので,最近のものだと何か問題があるかも知れない.

PowerPoint から印刷することで PS をファイルに吐き出せるようなプリンタドライバを用意する必要がある.Windows XP の場合,MS Publisher Imagesetter なるものが用意されてるので,これをセットアップする.セットアップ方法の説明はこのページが詳しいが,簡単にまとめると,

プリンタとFAX → プリンタのインストール (プリンタの追加ウィザード起動):
→ このコンピュータに接続されているローカルプリンタ (プラグアンドプレイはチェックしない)
→ 次のポートを使用 → FILE:(ファイルへ出力)
→ 製造元: Generic,プリンタ: MS Publisher Imagesetter
→ プリンタ名を指定 (任意の文字列でよいが,以下では「Generic PostScript Writer」とする)

プリンタとFAX → Generic Postscript Writer のプロパティ:
→ 全般 → 印刷設定 → 詳細設定
→ PostScript オプション: 「エラーが軽減するよう最適化」

MS Publisher Imagesetter の代わりに AdobePS プリンタを使うという選択肢もある (そっちの方がメジャー?) のだが,縦書きテキストボックスがあるとうまく EPS 化できなくなるようだ.MS Publisher Imagesetter の方は,試した範囲ではそのような問題はおきないようである.一応,AdobePS プリンタのセットアップ方法はこのページが詳しい.

インストール

の 2 つをどこかに置いておく.prn2eps.pl には実行許可を出しておく.

まとめてダウンロード (この記事の公開時の版) (最新版)

使い方

  • Makefile を用意して適宜設定する.(雛型: [この記事の公開時の版] [最新版])
  • PowerPoint で図を描く.各スライドに 1 枚の図を描くようにする.各スライドのノート部分で出力する EPS ファイル名を指定する.
  • make を実行する.

Makefile では,まず変数 PRN2EPS,PPTPRINT に prn2eps.pl と ppt_printout_ps.vbs を置いた場所のフルパスを指定する.PRINTER に,PS ファイルを吐き出すプリンタ名を指定する.TeX や PPT のソースファイル名は,変数 TARGET,SRCTEX,SRCFIG に指定する.見ればわかると思う.

PPT ファイルの周りには副産物のファイルがいろいろと生成されるため,個人的には fig/ とかの専用ディレクトリを掘っておくのが好みである.もちろん必須ではない.

PPT ファイルはいくつあっても構わない.EPS を出力したいスライドのノート領域に「@file=filename」のように書いておくと,filename.eps が生成される.ファイル名は,PPT ファイルの置いてある場所からの相対パスになる.ノート領域に @file=... という記述がないスライドは単に無視される.

なお,出力ファイル名が重複するともちろんまずいのだが,そのチェックはしていない.チェック機構の実装は容易と思われる.

設計と実装

EPS ファイルの生成は,ppt_printout_ps.vbs と prn2eps.pl を順に実行することで行われる.以下では,実際の動作順ではなく説明しやすい順で,その設計と実装についてメモしておく.

まず PowerPoint ファイル xxx.ppt から PS ファイル xxx.prn を出力する.これは VBScript で自動で実行できる (PowerPoint.Application オブジェクトの Presentations メンバの PrintOut メソッドを呼ぶ). ppt_printout_ps.vbs がこれを実行する.

生成された PS ファイル xxx.prn から psselect で各スライドを切り出す.

psselect 3 xxx.prn > xxx3.ps

とすると xxx.prn の 3 ページ目が xxx3.ps に書き出される.

この PS ファイルを ps2eps で EPS 化するわけだが,オプションの指定の仕方にいろいろとバッドなノウハウが必要で,私の環境では少なくとも以下のものが必要だった.

  • -f: 出力ファイルの上書きを許す
  • -B: 入力ファイルの Bounding Box 情報を無視する
  • -C: 周辺領域をクリップする.
  • -R +: 90度回転する

-C オプションは,図の周囲にある白い領域を切り捨てるためのもので,これがないと図の周辺の文章などが隠れてしまう.-C オプションをつければ, TeX ソースファイルの \includegraphics の clip=yes は不要のようだ.逆に,-C 無しで clip=yes があっても私の環境ではダメだった.

PowerPoint のページ設定が横向き印刷になっている場合,オプション無しで ps2eps すると向きが変わってしまう.-R + で 90 度回転させる必要がある.ページ設定を縦向きにする場合は不要なようだ.あるいは,TeX ソースファイルの \includegraphics で angle=270 と指定してもよいのだが,面倒くさいのと,一部ツール (例えば latex2html) で問題が生じる場合があるので,EPS 化の時点で回転しておくに越したことはないだろう.

そしてここからが凶悪な部分なのだが,なんと -C と -R は共存できない.どうも図が一部消えてしまう.よい解決方法が思いつかないので

ps2eps -R + -B -f xxx3.ps
ps2eps -C xxx3.eps

のように 2 回に分けて実行するというダサい手段を取っている.なお,この結果出力されるファイル名は xxx3.eps.eps になるので忘れずリネームしておく.

さて,ここまでは xxx.ppt の 3 ページめを xxx3.eps というファイルに出力するとして話を進めてきたが,出力ファイル名を PowerPoint のノート領域で指定したい.i ページめのノート領域の内容は,前述の PowerPoint.Application オブジェクトの Presentations.Slides(i).NotesPage.Shapes(2) (PowerPoint のバージョンによっては NotesPage.Shapes.Placeholders[2] かもしれない) から取り出せるので,そこから @file=... を抜き出して使えばよい.現在の実装では, ppt_printout_ps.vbs がノート領域の全テキストを xxx.note.txt に書き出すようにして,prn2eps.pl がそれを読み込んでから psselect や ps2eps を呼び出すようにしている.

さて,残るは更新判定である.スライドごとの更新時刻情報がどこかにあったりしないかと思って探したが見当たらなかった.よって内容を見比べるしかなさそうだ.psselect で取り出した PS ファイルを比べるのはどうだろうと思ったが,どういうわけか,PowerPoint は内容に変化のないスライドでも毎回かなり異なる PS ファイルを吐いてしまう.(WMF を出力させても同様である)

結局,いまいちな解だが各スライドを PNG ファイルとして出力して,その内容の変化の有無を判断することにした.PNG ファイルの出力は前述の Slides(i) の Export メソッドで行える.ppt_printout_ps.vbs が各スライドの PNG を書き出し,prn2eps.pl がその MD5 を計算する.xxx.ppt の各スライドの MD5 は xxx.md5 に記録しておいて,MD5 が一致するものは前回生成した EPS ファイルを再利用することにする.毎回全スライドの PNG を生成するのはダサいといえばダサいが,ps2eps に比べると圧倒的に速いので,まあよしとする.

Makefile の雛形では,ppt ← prn ← md5 と依存するようになっている. xxx.ppt が xxx.md5 より新しかったら更新がかかる.pdf ルールで使われている pdfopen/pdfclose はここにある.なお,コメントアウトされている方の pdf ルールは Adobe Distiller 用で,拡張子 ps のファイルに Distiller が関連付けられていることが想定されている.


補足: フォントの埋め込み

以前 [2007-08-15-1] 書いた通り,PDF ファイルを提出するときに「すべてのフォントを埋め込め」と指示されることがよくある.以前の記事で書いたのは LaTeX 本文に由来する Times フォント (とか) を埋め込む方法だったが,もちろん図に含まれるフォントについてもちゃんとケアしてやる必要がある.

で,この記事の方法で生成する EPS ファイルの場合,プリンタドライバの設定でフォントを埋め込むようにしておくと,だいたい大丈夫なように見える.具体的には,

プリンタとFAX → Generic Postscript Writer のプロパティ:
→ 全般 → 印刷設定 → 詳細設定
→ TrueTypeフォント: 「ソフトフォントとしてダウンロード」

とする.ただしフォント名がその都度生成されるよくわからない名前になるようで (PowerPoint が吐く PS ファイルが毎回異なるのもこの辺が原因か?),あまり気持ちのよい PDF ファイルにはならないのが残念なところである.その辺りが気になる場合は,ここでは「デバイス フォントと代替」を選んでおいて,後から Distiller とかで何とかする方針の方がよいかもしれない.

[ コメントを全部見る / コメントを書く] [ TrackBack ( )] [固定リンク]

* [かがみ] なるほど,気づきませんでした.`cygpath -wa $<` `cygp... (2011-03-20 10:04:08)

* [ばば] 便利に利用させていただいております。サンプルのMakefileの中でwscrip... (2011-03-18 11:09:09)

最終更新時間: 2010-09-19 13:47


Shingo W. Kagami - swk(at)kagami.org