EPSグラフィック直書き入門
EPS (Encapsulated PostScript) 画像をテキストエディタで直書きする変態のためのチュートリアルです。EPSとは何か
ぐぐれEPSをテキストエディタで書くメリット
- マウスより正確に書けるし、微調整がしやすい
- 数値データを図形に変換できる
- PerlやRubyなどのスクリプトから図を出力できるようになる
- 描いたあとでIllustrator等に取り込んで編集できる
- SSHでリモートアクセスしてその場で図が書ける
- 周囲の人に変態認定される
基本的な書き方
EPSはJPEGやGIFなどのいわゆる画像ファイルとは異なり、「ページ記述言語」と呼ばれるプログラミング言語の一種です。 基本は「キャンパスの上で仮想的な筆を動かして図を描く」という考え方をします。
試しに、以下のようなソースを書いて test.eps
という名前で保存すれば、「点(100,100)を起点とした、1辺が100の正方形」を描くことができます。
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 0 300 300 newpath % 新しいパスを生成 100 100 moveto % ペンを(100,100)に移動 200 100 lineto % (200,100)まで直線を引く 200 200 lineto % (200,200)まで直線を引く 100 200 lineto % (100,200)まで直線を引く 100 100 lineto % (100,100)まで直線を引く stroke % このパスの輪郭を描く %%EOF
線の色を設定する
線の描写を指示するstroke
より前に、色を指定するコマンドであるsetrgbcolor
を入れると、線の色をRGB形式で指定できます。
RGB (赤、緑、青) の値はそれぞれ0〜1の範囲です。
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 0 300 300 newpath % 新しいパスを生成 100 100 moveto % ペンを(100,100)に移動 200 100 lineto % (200,100)まで直線を引く 200 200 lineto % (200,200)まで直線を引く 100 200 lineto % (100,200)まで直線を引く 100 100 lineto % (100,100)まで直線を引く 1 0 0 setrgbcolor % 赤色に設定 stroke % このパスの輪郭を描く %%EOF
線の太さを指定する
太さは色と同様にsetlinewidth
コマンドで
3 setlinewidthこのように指定します。 デフォルトの太さは1です。
塗りつぶし
「パスの輪郭を描写」を意味するstroke
の代わりにfill
を使えば塗りつぶしができます。
線と塗りつぶしを両方使いたいときは、gsave
を使ってパスを一旦保存し、塗りつぶしを行ったあとでgrestore
で保存したパスを開いて輪郭の描写を行います。
(順番を逆にすると、輪郭の一部が潰れてしまいます。)
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 0 300 300 newpath % 新しいパスを生成 100 100 moveto % ペンを(100,100)に移動 200 100 lineto % (200,100)まで直線を引く 200 200 lineto % (200,200)まで直線を引く 100 200 lineto % (100,200)まで直線を引く 100 100 lineto % (100,100)まで直線を引く gsave % パスを保存 1 0 0 setrgbcolor % 赤色に指定 fill % パスを塗りつぶす grestore % 保存したパスを開く 0 0 0 setrgbcolor % 黒色に指定 stroke % パスの輪郭を描く %%EOF
正三角形を描く
次に正三角形を描いてみましょう。
正三角形の座標を指定するためには、sinやcosを使ってあらかじめ計算してもいいのですが、 せっかくなのでEPSの計算機能を使用してみましょう。
EPSでは、100 100 add
と書くと、200
と同じ意味になります。
20 30 mul
ならば600
と同じです。
通常のプログラミング言語ならば100 + 100
と書くところですが、
EPSは演算子が最後に来ます。このような記法を逆ポーランド記法といいます。
さて本題に戻りますが、三角形を書くためには「ある点から、120度の方向に、距離100だけペンを進める」という表記を使います。
これは数式にすると、x座標が100*cos(120), y座標が100*sin(120)という値になります。
100*cos(120)をPostScriptの記法で描くと、
100 120 cos mul
となり、100*sin(120)は
100 120 sin mul
となります。よって、上述の「120度の方向に、距離100だけペンを進める」というコマンドは
100 120 cos mul 100 120 sin mul rlinetoと書きます。 これを解釈すると、まず
120 cos
の部分が計算されて-0.5
に、
120 sin
は0.866
となるので、このコードは
100 -0.5 mul 100 0.866 mul rlinetoと同じ意味になります。 次に、
100 -0.5 mul
は掛け算なので-50、100 0.866 mul
は86.6となるので
-50 86.6 rlinetoとなります。 最後の
rlineto
は、lineto
と違って「現在のペンの位置から、指定された座標だけ移動する」という相対座標を表しています。
以上のことを踏まえて、三角形を描くEPSは以下のようになります。
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 0 300 300 newpath % 新しいパスを生成 100 100 moveto % ペンを(100,100)に移動 100 0 rlineto % 相対座標(100,0)だけ線を引く 100 -0.5 mul 100 0.866 mul rlineto % 相対座標(100cos(120),100sin(120))まで直線を引く closepath % パスを閉じる stroke % パスの輪郭を描く %%EOF
円を描く
円弧を描くときはarc
というコマンドを使います。
角度の範囲が指定でき、0から360までにすると円になります。
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 50 50 150 150 newpath % 新しいパスを生成 100 100 20 0 360 arc % (100,100)を中心に、0度から360度へ半径20の円弧を描く stroke % パスの輪郭を描く %%EOF
変数・関数の使用
上に描いた方法で、この円を塗りつぶすことができます。 試しに、赤で塗りつぶし、黒で輪郭をつけた円を、x座標だけ変えて3個書いてみます。
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 50 200 150 newpath % 新しいパスを生成 50 100 20 0 360 arc % (50,100)を中心に、0度から360度へ半径20の円弧を描く gsave % パスを保存 1 0 0 setrgbcolor % 赤色に指定 fill % パスを塗りつぶす grestore % 保存したパスを開く 0 0 0 setrgbcolor % 黒色に指定 stroke % パスの輪郭を描く newpath % 新しいパスを生成 100 100 20 0 360 arc % (100,100)を中心に、0度から360度へ半径20の円弧を描く gsave % パスを保存 1 0 0 setrgbcolor % 赤色に指定 fill % パスを塗りつぶす grestore % 保存したパスを開く 0 0 0 setrgbcolor % 黒色に指定 stroke % パスの輪郭を描く newpath % 新しいパスを生成 150 100 20 0 360 arc % (150,100)を中心に、0度から360度へ半径20の円弧を描く gsave % パスを保存 1 0 0 setrgbcolor % 赤色に指定 fill % パスを塗りつぶす grestore % 保存したパスを開く 0 0 0 setrgbcolor % 黒色に指定 stroke % パスの輪郭を描く %%EOFやたら同じコードの繰り返しで嫌になってしまいますね。 こういう場合は、プログラミング言語的な考え方として、変数・関数を使います。
EPSでは変数に値を代入するときはdef
というコマンドを使います。
たとえばxに200という値を代入するときは
/x 200 defと書きます。これを用いて
/x 200 def /y 100 def x y 20 0 360 arcと書けば、
200 100 20 0 360 arcと同じ意味になります。 代入時には
/x
、参照時にはx
と書くので注意しましょう。
またEPSでは、数値だけでなく「図形そのもの」を変数に代入することができます。
/fig { (図形の描写) } defこのように書けば、変数figに図形を代入できる(つまり参照した時に図形の描写が行われる)ことができます。
たとえば、circle
という変数に円の描写を代入すると
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 50 200 150 /circle { newpath % 新しいパスを生成 100 100 20 0 360 arc % (100,100)を中心に、0度から360度へ半径20の円弧を描く gsave % パスを保存 1 0 0 setrgbcolor % 赤色に指定 fill % パスを塗りつぶす grestore % 保存したパスを開く 0 0 0 setrgbcolor % 黒色に指定 stroke % パスの輪郭を描く } def circle % 定義した変数を呼び出し、円を描写 %%EOFこのようにして円を描くことができます。 しかし、これでは最初に指定した(100,100)の位置にしか円が出せません。 そこで、座標を引数で指定できるようにします。これには
exch
コマンドを使います。
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 50 200 150 /circle { /y exch def % 引数の値を変数yに代入 /x exch def % 引数の値を変数xに代入 newpath % 新しいパスを生成 x y 20 0 360 arc % (x,y)を中心に、0度から360度へ半径20の円弧を描く gsave % パスを保存 1 0 0 setrgbcolor % 赤色に指定 fill % パスを塗りつぶす grestore % 保存したパスを開く 0 0 0 setrgbcolor % 黒色に指定 stroke % パスの輪郭を描く } def 50 100 circle % 引数(50,100)を指定してcircleを呼び出す 100 100 circle % 引数(100,100)を指定してcircleを呼び出す 150 100 circle % 引数(150,100)を指定してcircleを呼び出す %%EOFこれで先ほどと同じ画像を描写することができます。
おまけ
こないだ(2012/12/02)書いた第五使徒ラミエル。ソースコードはこちら。
製作時間は30分。