DoJaのアフィン変換
iアプリをチョコチョコといじってみてて、DoJaのアフィン変換描画を試してみました。
アフィン変換の行列計算も、難しくはないけど、なにげに面倒なので、計算結果でも書いておきます。
だれかの役に、たつんじゃないかなと。
作ってみたサンプルが、画像のやつで、こちら。
http://shin-ishimaru.cocolog-nifty.com/iapp/AffineDraw/Download.html
DoJaのアフィン変換描画APIがGraphicsの中にあります。
public void drawImage(Image image,
int[] matrix)イメージに 2 次元のアフィン変換をかけて描画します。
イメージ上の座標 (x, y) の画素は、 以下のような行列演算によって求められる座標 (x', y') に描画されます。
[ x'] 1 [ m00 m01 m02 ] [ x ]
[ y'] = ------ [ m10 m11 m12 ] [ y ]
[ 1 ] 4096 [ 0 0 4096 ] [ 1 ]
回転させて、指定の座標(dx, dy)に表示したい時は、回転行列に移動をくっつけて、
[ 4096*cosθ -4096*sinθ dx ]
[ 4096*cosθ 4096*sinθ dy ]
[ 0 0 4096]
とかしてしまいますが、これで計算してしまうと、画像の一番左上の点を軸に回転してしまう。
回転するんだったら、画像の中心を軸にして回転してほしいので、その分ずらす必要がある。
その移動量をex, eyとすると、
[ 4096*cosθ -4096*sinθ dx ][ 1 0 ex]
[ 4096*cosθ 4096*sinθ dy ][ 0 1 ey] =
[ 0 0 4096][ 0 0 1 ]
[ 4096*cosθ -4096*sinθ (cosθ*ex - sinθ*ey + dx)*4096 ]
[ 4096*cosθ 4096*sinθ (sinθ*ex + cosθ*ey + dy)*4096 ]
[ 0 0 4096 ]
これでOK。
ここまで来ると、もうひとつ欲張って、拡大、縮小も入れたくなってくるところ。
X方向の倍率をsx、Y方向の倍率をsyとすると、
[ 4096*cosθ -4096*sinθ dx ][sx 0 0][ 1 0 ex]
[ 4096*cosθ 4096*sinθ dy ][ 0 sy 0][ 0 1 ey] =
[ 0 0 4096][ 0 0 1 ][ 0 0 1 ]
[ 4096*cosθ -4096*sinθ (cosθ*ex*sx - sinθ*ey*sy + dx)*4096 ]
[ 4096*cosθ 4096*sinθ (sinθ*ex*sx + cosθ*ey*sy + dy)*4096 ]
[ 0 0 4096 ]
これを、実際のJavaのコードで関数化して書いてみると、こんな感じ。
/**
* 回転、拡大して描画
* @param i 描画するイメージ
* @param x 描画する位置X
* @param y 描画する位置Y
* @param r 回転角度(4096MAX)
* @param sx X方向の拡大
* @param sy Y方向の拡大
*/
void drawRotScale( Image i, int x, int y, int r, float sx, float sy ){
int []m = new int[6];
m[0] = (int)(Math.cos(r)*sx);
m[1] = (int)(-Math.sin(r)*sy);
m[2] = (int)(Math.cos(r)*(-i.getWidth()/2)*sx - Math.sin(r)*(-i.getHeight()/2)*sy + x*4096);
m[3] = (int)(Math.sin(r)*sx);
m[4] = (int)(Math.cos(r)*sy);
m[5] = (int)(Math.sin(r)*(-i.getWidth()/2)*sx + Math.cos(r)*(-i.getHeight()/2)*sy + y*4096);
g.drawImage(i,m);
}
DoJaのMath.sin, cosは4096倍された数値が返ってくるため、コード上は計算式より、4096かけてるところが少ないのに注意。
ソースコードは、ここに置いときます。
画像は、んぱかさんのシューティングゲームサンプルから借用。
D703iでは、結構さくさく動作。
スーパーファミコンみたいで、良い感じですな。
drawImageに使われてる式が、なにげに4096かけたり割ったりしている、ちょっと変わった式なんで、計算してみないとよくわからず、計算してみたって感じですね。
最近のコメント