PHPでTeXを表示する

(1/1)
PHP で mimeTeX を使って、TeX を表示するプログラムを作る。

TeX と mimeTeX

TeX は、Mac や Windows 上で動作する WYSIWYG なワープロが普及する以前、複雑な数式やグラフを組版するための手段として考案されたソフトウェアである。
これにマクロパッケージを組み込み、さらに組版処理を手軽にしたものが LaTeX である。
たとえば、二次方程式の解の公式  mimetex  は、LaTeX では以下のように記述する。

\frac{-b\pm\sqrt{b^2-4ac}}{2a}



mimeTeX は、LaTeX のサブセットを画像表示するためのソフトウェアである。
mimeTeX は単独の小さな実行ファイルであり、Web との相性もよい。

mimeTeX のインストール

mimeTeX公式サイト の "Download" をクリックし入手したソースを gcc でコンパイルする。

SSH が利用できない環境であれば、PHP を介して gcc を起動する。
ダウンロードしたソースをアップロードし、同じディレクトリに以下のような PHP スクリプトを配置し、CGI モードで実行すればよい。

#!/usr/local/bin/php
system("gcc -DAA mimetex.c gifsave.c -lm -o mimetex.cgi");
print "*** Compile finished ***\n"



Windows や Mac ユーザーは、公式サイトの下の方にあるコンパイル済のバイナリファイルへのリンクがあるので、これを利用すればよい。

コンパイルできた mimetex.cgi(Windows では mimetex.exe)は、実行可能なディレクトリに設置する。
ただし、Windows の場合は、ディレクトリ名にスペースが含まれていると関数  system  で実行できないことがあるので、"Program Files" 以下や、"Apache Group" 以下には配置しない方が良い。

サンプル・プログラム

ダウンロードしたスクリプトを実行するには mimeTeX が必要である。

また、ここから実行できるプログラムでは「ダウンロード」機能を利用することはできない。ダウンロードしたスクリプトであれば利用できるようになっている。

プログラムを実行する

ダウンロード(PHP4/5/7 共用)

サンプル・プログラムの流れ

PHPでTeXを表示する
プログラムは 1 本の PHP スクリプトである。
HTML FORM で入力した TeX 文を読み取り、ラジオボタンによって、後述する 3 つの処理へ分岐する。

サンプル・プログラムの解説:初期化処理

0009: // 初期化処理 ================================================================
0010: $InternalEncoding = 'UTF-8';
0011: mb_internal_encoding($InternalEncoding);
0012: $MySelf = basename($_SERVER['SCRIPT_NAME']);
0013: 
0014: /**
0015:  * mimeTeX のCGIパス
0016:  * @global bool $CGIMimeTeX
0017: */
0018: $CGIMimeTeX = '/cgi-bin/mimetex.cgi'; //事前にインストールすること
0019: $CGIMimeTeX = 'http://localhost/pahoo/cgi-bin/mimetex.exe';  //事前にインストールすること
0020: 
0021: /**
0022:  * mimeTeX実行ファイルの存在する場所
0023:  * @global string $ExecMimeTeX
0024: */
0025: //$ExecMimeTeX = '/usr/local/bin/mimetex.cgi';       //Linux(例)
0026: $ExecMimeTeX = 'D:/mimetex/mimetex.exe';            //Windows(例)
0027: 
0028: /**
0029:  * TeX画像を保存する場所(データ保存を選んだときに限り保存)
0030:  * @global string $SaveTeX
0031: */
0032: //$SaveTeX = '/usr/local/data/';       //Linux(例)

まず、mimetex に関するインストール情報を、変数 $CGIMimeTeX$ExecMimeTeX に代入する。また、変数 $SaveTeX には、画像を保存する際のディレクトリ名を代入する。

処理選択は配列変数 $SelectFuncs に記述している。
この要素を書き換えることで、処理の追加/削除ができる。

サンプル・プログラムの解説:画像ファイル名

0108: 
0109: /**
0110:  * 画像ファイル名を生成する(パス名、拡張子を除く)
0111:  * @param string $tex TeX文
0112:  * @return string ファイル名
0113: */
0114: function makeImageFname($tex) {
0115:     return md5($tex);        //md5ハッシュ

TeX画像をダウンロードや保存するときのファイル名は、何でもいいのだが、ここではハッシュ関数  md5  を用いることにした。TeX 文をハッシュ化し、32 文字固定長の 16進数にすることができる。

サンプル・プログラムの解説:画像表示処理

0117: 
0118: /**
0119:  * HTML BODYを作成する
0120:  * @param string $tex TeX文
0121:  * @param string $res 結果のHTMLタグ
0122:  * @return bool TRUE/FALSE
0123: */
0124: function makeCommonBody($tex$res) {
0125:     global $SelectFuncs$MySelf;
0126: 
0127:     //処理選択ラジオボタン
0128:     $str_radio = '';
0129:     $i = 1;
0130:     foreach ($SelectFuncs as $key=>$val) {
0131:         $str_radio .= "<input type=\"radio\" name=\"funcs\" value=\"{$key}\" {$val['checked']} />{$val['title']} ";
0132:         $i++;
0133:     }
0134: 
0135: $body =<<< EOD
0136: <body>
0137: <h1>■mimeTeXを使う</h1>
0138: <form name="MyForm" method="POST" action="{$MySelf}">
0139: TeX文:
0140: <input type="text" name="tex" size="80" value="{$tex}" />
0141: <input type="submit" name="exec" value="作成" />
0142: <br />
0143: {$str_radio}
0144: </form>
0145: 
0146: <p>
0147: <b>【使い方】</b>
0148: <ol>
0149: <li>[<b>テキスト</b>]に TeX 文を入力してください。</li>
0150: <li>実行したい処理をラジオボタンで選択してください。
0151:     <ol type="a">
0152:     <li>画面表示:処理結果(gif画像)を画面に表示します。</li>
0153:     <li>ダウンロード:処理結果(gif画像)をブラウザからダウンロードします。</li>
0154:     <li>データ保存:処理結果(gif画像)をサーバの指定フォルダに保存します。</li>
0155:     </ol>
0156: </li>
0157: <li>[<b>作成</b>] ボタンを押してください。</li>
0158: </ol>
0159: </p>
0160: <hr />
0161: {$res}
0162: </body>
0163: 
0164: EOD;
0165:     return $body;
0166: }
0167: 
0168: /**
0169:  * 画面表示処理
0170:  * @param string $tex TeX文
0171:  * @return string 表示HTML
0172: */
0173: function display($tex) {
0174:     global $CGIMimeTeX;
0175:     global $HtmlHeader$HtmlFooter;
0176: 
0177:     $url = $CGIMimeTeX . "?{$tex}";
0178:     $res ="<img src=\"{$url}\" />";
0179:     $HtmlBody = makeCommonBody($tex$res);
0180: 
0181:     return ($HtmlHeader . $HtmlBody . $HtmlFooter);

デフォルトでは、TeX 文を gif画像に変換し、同じ画面の下の方に表示する。
これは、mimetex.cgi の基本機能で簡単に実現できる。つまり、img タグの src として mimetex.cgi を指定すればいい。

Web サイトで mimetex を用いる場合は、この機能を利用するのが基本である。

サンプル・プログラムの解説:ダウンロード処理

0183: 
0184: /**
0185:  * ダウンロード処理
0186:  * @param string $tex TeX文
0187:  * @return なし
0188: */
0189: function download($tex) {
0190:     global $ExecMimeTeX$SaveTeX;
0191:     global $SaveTeX;
0192: 
0193:     /**
0194:      * TeX画像をテンポラリへ出力する
0195:      * (※)-dオプションでstdoutへ出力させた場合、
0196:      *      PHP処理と同期がとれないことがあったため、
0197:      *      代替策としてテンポラリ出力を採用した。
0198:     */
0199:     $imagefname = makeImageFname($tex) . '.gif';
0200: //  $fname = sys_get_temp_dir() . $imagefname;     //PHP5以上
0201:     $fname = $SaveTeX . $imagefname;
0202:     $exec = "{$ExecMimeTeX} -e {$fname} \"{$tex}\"";
0203:     system($exec);
0204: 
0205:     //テンポラリから読み込む
0206:     $img = '';
0207:     $infp = fopen($fname, 'rb');
0208:     while (! feof($infp))    $img .= fgets($infp, 4096);
0209:     fclose($infp);
0210: 
0211:     //テンポラリを削除
0212:     unlink($fname);
0213: 
0214:     //ダウンロード出力
0215:     header("Content-Type: image/gif");
0216:     header("Content-Disposition: attachment; filename={$imagefname}");
0217:     echo $img;

ダウンロード処理は、gif画像をブラウザを介してクライアントにダウンロードできるようにする機能である。TeX画像をローカルで利用したいような場合を想定し、この機能を用意した。
mimetex の -e オプションを用いて実現している。

じつは、mimetex には、gif画像データを標準出力に出力するという -d オプションがあり、これを利用すれば簡単に実現できる。しかし、-d オプションを使った場合、出力までのタイムラグが少しあるようである。このため、PHP 処理側と足並みが合わず、標準出力へのデータを全て拾うことができないことがあった。
そこで、次善策として、いったん -e オプションを使って gif画像をテンポラリファイルに書き出し、それをブラウザにダウンロードするようにした。

ダウンロード出力の際、関数  header  を使って必要な http ヘッダを送信するようにしてある。

サンプル・プログラムの解説:画像保存処理

0219: 
0220: /**
0221:  * TeX画像保存処理
0222:  * @param string $tex TeX文
0223:  * @return string 表示HTML
0224: */
0225: function saveimage($tex) {
0226:     global $ExecMimeTeX$SaveTeX;
0227:     global $HtmlHeader$HtmlFooter;
0228: 
0229:     $imagefname = makeImageFname($tex) . '.gif';
0230:     $fname = $SaveTeX . $imagefname;
0231: 
0232:     $exec = "{$ExecMimeTeX} -e {$fname} \"{$tex}\"";
0233:     system($exec);
0234:     $res = "保存に成功しました => {$fname}";
0235: 
0236:     $HtmlBody = makeCommonBody($tex$res);
0237: 
0238:     return ($HtmlHeader . $HtmlBody . $HtmlFooter);

画像保存処理は、gif画像を変数 $SaveTeX で示されるサーバのディレクトリに保存する。ダウンロード処理のテンポラリファイルを、そのまま保存するような流れである。

Web サイト上で mimetex を利用する場合は、前述のように、cgi 方式を用いるのが基本だが、これだとサーバに負荷がかかる。そこで、あらかじめ gif画像に変換しておき、これを html 上に表示するようにすることを想定し、この機能を用意した。
ただし、サーバに保存するため、ここで実行できるサンプル・プログラムからは選択できないようになっている。ダウンロードした PHP スクリプトでは利用できるようになっているので、各自のサーバ環境で試してみていただきたい。

サンプル・プログラムの解説:処理の分岐

0040: 
0041: /**
0042:  * 処理選択肢
0043:  * @global array $SelectFuncs
0044: */
0045: $SelectFuncs = array(
0046:     //関数名               タイトル             ラジオボタンcheked
0047:     'display'    => array('title'=>'画面表示',     'checked'=>'checked'),
0048:     'download'   => array('title'=>'ダウンロード', 'checked'=>''),
0049:     'saveimage'  => array('title'=>'データ保存',   'checked'=>'')

0240: 
0241: // メイン・プログラム ======================================================
0242: if (isset($_POST['exec'])) {
0243:     $tex  = $_POST['tex'];
0244:     $func = $_POST['funcs'];
0245:     if (setSelectFunc($func) == FALSE) {
0246:         $func = getSelectFunc();
0247:     }
0248: else {
0249:     $tex  = $sampleTeX;
0250:     $func = getSelectFunc();
0251: }
0252: 

分岐処理は、変数 $SelectFuncs にテーブルとして用意している。この項目を増やして、対応する関数を増やせば、機能を拡張できるようになっている。

処理の分岐は、可変関数を使っている。つまり、変数 $func に代入された関数名にしたがって処理を分岐するようになっている。

参考サイト

(この項おわり)
header