ImageMagickのdrawで描くとき-gravityオプションの挙動がよく分からない件

ImageMagickには図形やテキストを描画する機能がいくつか用意されています。その中でdrawという機能を用いて図形やテキストを描く場合に、キャンバスの座標基準を変更したいという場合が出てきたとします。座標基準の変更には-gravityオプションが使えるのですが、その挙動がよく分からないので解説を書いておくことにしました。
初めに基礎的なところを解説していますが、必要ない方は途中から始まる本題まで読み飛ばして下さい。

基礎的な解説

ImageMagickの座標は基本的には、(x, y)座標で表すとキャンバスの左上が(0, 0)で右にいくほどxの値が増え、下にいくほどyの値が増えます。数学のグラフで見るような座標とは軸の扱いが異なるため、初めて座標を意識した場合には疑問に思う場合はあるかと思います。
ImageMagickに限らず、2D描画、3D描画の世界では様々な座標の取り方があり、ソフトによってどのような扱いがされるかはまちまちだったりします。高度なものは理解するのが困難なものもありますが、基本的には座標の違いは軸の方向くらいなものなのでそう難しく考える必要はありません。とりあえずは違いがあるってことだけ認識しておけばいいでしょう。

初めに触れたようにImageMagickにはdraw以外にもテキストなどを描画する機能があります。textやannotateという機能、また座標ということになるとその他の画像の合成や変形に関する機能も関連してきます。しかし全部について解説するのはめんどう過ぎるため、今回はdraw機能についてだけ触れることにします。あっちこっちに話が飛ぶと、ただでさえ機能が多いImageMagickの話が無駄にややこしく感じるだけなので。

さてdrawを用いる場合には、座標は-gravityオプションで変更することが出来ます。コマンドラインから
$ convert -list gravity

とすると、ImageMagickではどのような設定が使えるかが表示されます。設定は「Center」以外は方角で表されているでしょう。「North」や「SouthWest」など。-gravityオプションでその方角のどれかを指定すると、その方角の位置が(0, 0)になります。ただし指定する方角によっては軸の方向(どっちがプラスでどっちがマイナスか)も変わって来るものもあります。そのへんは実際に使ってみて確認して下さい。

本題

さて本題の
「ImageMagickのdrawで描くときgravityオプションの挙動がよく分からない件」
に入ります。

とりあえず例を挙げるので見て下さい。
これはImageMagickのconvertコマンドでキャンバスにdraw機能を用いて3つのオブジェクト(円、直線、テキスト)を描いたものです。この図ではまだ-gravityオプションは用いていません。デフォルトの座標になっています。この図を描いたときのコマンドは以下の通り
convert -size 1000x1000 xc:skyblue -fill white -stroke black -strokewidth 3 \
-draw "circle 700,700 700,500" \
-pointsize 100\
-draw "text 0, 100 'Text : 0, 100'" \
-draw "line 100,200 400,700"\
test01.png

オブジェクトが3つあるのですが、ここではテキストの座標にだけ注目して下さい。テキストの座標は
(0, 100)
と指定しています。
(例としては(0, 0)にしたかったのですが、それだとテキストがキャンバス外に描かれてしまうのでy軸の数字を上げて下にずらしています)

ここで-gravityオプションを有効にして「Center」を指定します。
するとキャンバス中央が(0, 0)となるため、テキストはキャンバス中央に来るようになります。(0, 100)ではちょっとややこしいので下に(0, 0)でテキストを描いた図も貼っておきます。
コードは以下のようになります。
convert -size 1000x1000 xc:skyblue -fill white -stroke black -strokewidth 3 \
-gravity Center\
-draw "circle 700,700 700,500" \
-pointsize 100\
-draw "text 0, 100 'Text 0, 100'" \
-draw "line 100,200 400,700"\
test02.png

さて、テキストの位置だけ見れば-gravityオプションで座標が新たに設定出来たということになります。しかし、一緒に描いた円と直線についても注目してみて下さい。本来なら新たな座標が設定されたのなら、それに合わせて円や直線が描かれる位置が変わってくるはずです。しかし実際にはテキストの位置しか変わっていません。 つまりこの例では
「-gravityオプションはテキストオブジェクトにのみ有効」
になっているようです。同じdraw機能なのだから座標を指定すればそれで済むという単純な話では無いわけです。むしろこれでは1つのキャンバスに2つの座標が存在してしまうために扱いがめんどうになってしまっています。
ここまでの話でなんとなく-gravityオプションの挙動は分かると思うのですが、より話を確実にするためにマニュアルやリファレンスを読んで見ることにします。
とりあえず該当していそうなところへのリンクを貼っておきますが、読んでみるとやはり
draw機能では-gravityオプションはテキストオブジェクトにのみ有効」
のようです(imageオブジェクトでも可?)。

将来的にこの扱いがどうなるかはわかりませんが、とりあえず現時点でdraw機能を使用する場合は、この点を押さえて使う必要があります。

またこの話はあくまでもdraw機能に限っての話です。他の機能においても-gravityオプションは有効な場合もあるのですが、挙動については個別に調べていく必要があります。自分がこれまで簡単に使っていた範囲では今回の話のdrawのような変わった挙動になったことはないのですが、また何か気がついたらブログに書いておくことにします。

コメント