2008-11-16
先日,LaTeX の数式を PNG と SVG に変換する方法についての記事を載せた.この方法を使いやすくスクリプト化してみた.
準備:テンプレート LaTeX ファイルの用意 †
テンプレート(ひな型)となる LaTeX ファイルを用意する.以下のような構成が基本:
- KozGoProVI-Medium.otf
- KozMinProVI-Regular.otf
- pdffonts.map
- latex-eq.tex
これらのファイルを適当なフォルダにおく.ここでは ~/bin/linux/templates-eql 以下においてあるものとする. KozGoProVI-Medium.otf, KozMinProVI-Regular.otf は /opt/Adobe/Reader8/Resource/CIDFont/Koz*.otf へのシンボリックリンクで, pdffonts.map は以下のような「フォントマップファイル」だ:
rml H KozMinProVI-Regular.otf rmlv V KozMinProVI-Regular.otf gbm H KozGoProVI-Medium.otf gbmv V KozGoProVI-Medium.otf
これら3つは,PDFにフォントを埋め込むために必要だ.詳細は, LaTeX の数式を PNG と SVG に変換する を参照.
最後の latex-eq.tex は,以下のようなテンプレートだ:
\documentclass[11pt,a4j,fleqn,leqno]{jarticle}
\usepackage{latexsym}
\usepackage{array}
\usepackage{calc}
\usepackage{amsmath, amsfonts}
\usepackage{amssymb}
\usepackage{ascmac} % 枠つき環境
\usepackage[dvips]{graphicx}
\usepackage[dvips]{color}
\usepackage{epsfig,subfigure}
\usepackage{wrapfig}
\usepackage{calligra}
\usepackage{alltt}
% フォント変更
\usepackage{mathpple}
\renewcommand{\rmdefault}{ppl}
\renewcommand{\sfdefault}{phv}
\renewcommand{\ttdefault}{pcr}
\begin{document}
\pagestyle{empty}
\null\vfil
\input{main}
\vfil\null
\end{document}
この中で main.tex を呼び出しており, main.tex に数式のみ書けばよいようになっている.
スクリプト †
次に,指定されたファイル(数式が書かれているとする)を main.tex に置き換え,そこから PNG と SVG で出力するようにスクリプトを作成する.ちょっと長いが,以下のような感じ:
#! /bin/sh
usage="usage: eqlatex [-all|-svg|-png|-dvi] [latex-file]\n if [latex-file] is not specified, std-in is used."
templatedir=~/bin/linux/templates-eql # テンプレートがおいてあるディレクトリ
tmpdir=/tmp/eqlatex$$
outfile=eqlatex
pngres=180 # PNG化するときの解像度
outputmode="all"
if [ $# -ge 1 ] && [ "$1" == "-help" ]; then
echo -e $usage
exit 0
fi
if [ $# -ge 1 ]; then
case "$1" in
"-svg"|"-png"|"-dvi"|"-all")
outputmode=${1/-/}
shift;;
esac
fi
if [ $# -gt 1 ]; then
echo -e $usage
exit 1
fi
if [ -d $tmpdir ];then
rm -rf $tmpdir
fi
mkdir $tmpdir
if [ $# -eq 0 ]; then
cp /dev/stdin $tmpdir/main.tex
else
cp $1 $tmpdir/main.tex
outfile=`basename ${1/.tex/}`
fi
cp -a $templatedir/* $tmpdir
cd $tmpdir
ifile=latex-eq
fontsmap=pdffonts.map
error=1
if platex -halt-on-error ${ifile}.tex; then
if [ -n "`grep 'newlabel' ${ifile}.aux`" ]; then
platex -halt-on-error ${ifile}.tex
fi
if dvipdfmx -f ${fontsmap} -o ${ifile}.pdf ${ifile}.dvi; then
error=0
fi
fi
if (($error));then
echo 'error in compiling the latex source.'
echo "logs are saved to $tmpdir/${ifile}.log"
exit 1
fi
if [ $outputmode == 'all' ] || [ $outputmode == 'svg' ];then
gs -q -r20480 -sDEVICE=epswrite -sOutputFile=${ifile}.eps -dNOPAUSE -dBATCH -dSAFER -dEPSCrop -dEPSFitPage -dUseCropBox ${ifile}.pdf
pstoedit -f plot-svg -dt -ssp -sclip ${ifile}.eps | \
sed 's/<rect[^<>]\+id=\"background\"[^<>]*>//g' > ${outfile}.svg
fi
if [ $outputmode == 'all' ] || [ $outputmode == 'png' ];then
gs -q -sDEVICE=pngalpha -sOutputFile=${outfile}.png -r${pngres} -dNOPAUSE -dBATCH -dSAFER -dEPSCrop -dGraphicsAlphaBits=4 -dTextAlphaBits=4 -dMaxBitmap=50000000 ${ifile}.pdf
convert -trim +repage ${outfile}.png ${outfile}.png
fi
cd -
case $outputmode in
"all")
mv $tmpdir/${outfile}.{png,svg} .
echo "${outfile}.{svg,png} are generated";;
"svg"|"png")
mv $tmpdir/${outfile}.$outputmode .
echo "${outfile}.$outputmode is generated";;
"dvi")
mv $tmpdir/${ifile}.$outputmode ${outfile}.$outputmode
echo "${outfile}.$outputmode is generated";;
esac
echo "latex logs are saved to $tmpdir/${ifile}.log"
このスクリプト(ここでは eqlatex というファイル名で保存されているとする)は,以下のように使用する:
# (数式ファイル名).png, (数式ファイル名).svg が生成される:
eqlatex (数式ファイル名).tex
eqlatex -all (数式ファイル名).tex
# (数式ファイル名).png が生成される:
eqlatex -png (数式ファイル名).tex
# (数式ファイル名).svg が生成される:
eqlatex -svg (数式ファイル名).tex
# (数式ファイル名).dvi が生成される:
eqlatex -dvi (数式ファイル名).tex
# eqlatex.png, eqlatex.svg が生成される:
(数式を出力するコマンド) | eqlatex -all
例えば,
test.tex:
\def\mvec#1{\mathbf{\boldsymbol{#1}}}
\begin{align}
\frac{\partial{}y(\mvec{x}_n)}{\partial\mvec{w}}
= \frac{\partial(\mvec{w}^\top \mvec{\phi}(\mvec{x}_n) + b)}{\partial\mvec{w}}
&= \mvec{\phi}(\mvec{x}_n) \\
\frac{\partial{}L}{\partial\mvec{w}}
= \mvec{w} - \sum_{n=1}^{N}{a_n t_n\mvec{\phi}(\mvec{x}_n)} = 0
&\qquad\Longrightarrow\quad \mvec{w} = \sum_{n=1}^{N}{a_n t_n\mvec{\phi}(\mvec{x}_n)} \\
\frac{\partial{}L}{\partial{}b}
= - \sum_{n=1}^{N}{ a_n t_n } = 0
&\qquad\Longrightarrow\quad \sum_{n=1}^{N}{ a_n t_n } = 0 \\
\frac{\partial{}L}{\partial{}\xi_n}
= C - a_n - \mu_n = 0
&\qquad\Longrightarrow\quad a_n = C - \mu_n \quad\text{for~} n=1,2, \dots, {}N
\end{align}
に対して
eqlatex -png test.tex
を適用すると, test.png が生成される.
ほか, PNG 出力時の解像度を指定できるようにしてもいいかもしれない. テンプレート latex-eq.tex にマクロを書いておくと,使いやすくなると思う.
fixme:
- ページサイズをぴったりにできない (SVG)
- 日本語の句読点(,.)が出力されない