RMagick/ImageMagickで位置決めをする Gravityの挙動まとめ
RubyからImageMagickを呼び出すRMagickを使って,センタリングした注釈を入れようとしたのですが,センタリングがうまく行かず,混乱に陥ったので備忘録としてまとめておきます.
やろうとしたことは,横400,縦25の画像で,(200,0)に文字列を描くと,
となるので(青い線は丁度真ん中の所),
としたいという事.もちろん,描く文字列に可能な限り依存したくない.
センタリングには,オブジェクトの配置を指定するGravityを利用して,gravityをCenterGravityにすれば良いかと思い,
gc = Magick::Draw.new
gc.gravity(Magick::CenterGravity)
gc.text(200, 0, "centering")
誤っていた点は,Gravityが,文字の場所だけでなく,座標系(座標の向きと原点)も変化させる点です.
予め正しくセンタリングされた図(2番目に示した図)のソース(関連部分)を示すと,
gc = Magick::Draw.new
gc.gravity(Magick::NorthGravity)
gc.text(0, 0, "center")
と,GravityがNorthGravity.そして,座標は(0,0)になります.
以下,詳細な説明.
例えば,デフォルトのNorthWestGravityでは,
左上が0,0で,x軸が左から右方向に取られ,y軸が上から下方向に取られています(普通の画像の座標系).次の図は,(0,0)の位置にGravity名(NorthWestGravity).(20,180),(180,80)などの座標は,その座標から文字列を開始した場合に文字列が書かれる場所,つまり
として文字が書かれた場所を示しています(背景の升目は,10ずつ引かれています).
NorthWestGravityでは,文字列は指定した点((20,180)など)を文字列の左上の点として描かれます.
一方,GravityをCenterGravityにすると,x軸,y軸の向きに変更はありませんが,画像の中心が原点になります.更に,文字列は,x軸方向もy軸方向も,センタリングされます(文字列を描くよう指定した点が文字列の中心になります).
また,GravityをSouthEastGravityにすると,x軸が画像の右から左に,y軸が下から上にとられます.原点も,画像の右下になります.更に,文字列は,指定した点が描画する文字列の右下になります.
このように,座標の向きも原点も変化するので,注意が必要です.
以下,全Gravityのまとめ.
Gravityには,9種類あります.(赤文字は気をつける場所)
- NorthWestGravity
- 座標系は,x軸が右方向,y軸が下方向,原点は画像左上.
- NorthGravity
- 座標系は,x軸が右方向,y軸が下方向,原点は画像中央上.
- NorthEastGravity
- 座標系は,x軸が左方向,y軸が下方向,原点は画像右上.
- WestGravity
- 座標系は,x軸が右方向,y軸が下方向,原点は画像左中央.
- CenterGravity
- 座標系は,x軸が右方向,y軸が下方向,原点は画像真ん中.
- EastGravity
- 座標系は,x軸が左方向,y軸が下方向,原点は右中央.
- SouthWestGravity
- 座標系は,x軸が右方向,y軸が上方向,原点は画像左下.
- SouthGravity
- 座標系は,x軸が右方向,y軸が上方向,原点は画像中央下.
- SouthEastGravity
- 座標系は,x軸が左方向,y軸が上方向,原点は画像右下.
以上.
下のスクリプトは,以上の画像を描いたスクリプトです.RMagickのマニュアルのサンプルプログラム( http://www.simplesystems.org/RMagick/doc/draw.html#gravity )を改変しました.RMagickをrubygemsを使ってインストールしたので,rubygemsをrequireしています.gems経由ではなくインストールした方は,この1行は要らないでしょう.
#!/usr/bin/env ruby require 'rubygems' require 'RMagick' gravities = [Magick::NorthWestGravity,Magick::NorthGravity,Magick::NorthEastGravity, Magick::WestGravity,Magick::CenterGravity,Magick::EastGravity, Magick::SouthWestGravity,Magick::SouthGravity,Magick::SouthEastGravity] gravities.each do |gravity| puts gravity imgl = Magick::ImageList.new imgl.new_image(400,200, Magick::HatchFill.new('white', 'lightcyan2')) gc = Magick::Draw.new # Draw blue lines to indicate positioning gc.stroke('blue') gc.fill('transparent') gc.rectangle(20,20, 380,180) gc.line(200,20, 200,180) gc.line(20,100, 380,100) # Draw compass points. gc.gravity(gravity) gc.stroke('transparent') gc.fill('black') gc.text( 0, 0, gravity.to_s) [-180,0,180].each do |x| [-180, -100, -20, 20,100,180].each do |y| gc.text(x, y, "(#{x},#{y})") end end gc.draw(imgl) imgl.border!(1,1, "lightcyan2") imgl.write("grav_" + gravity.to_s + ".gif") end