画像の回転



標準命令には画像の回転方法はありません。
hspext.dllやその他グラフィック系のDLLを使うことになると思います。
そこで今回はDLLを使わないで回転してみようと思います。
ただ標準命令では速度がやたら遅いので、速度が必要ならやはりDLLが必要になります。

回転には角度を用いるので、「円形座標を使う」の方法で作成するサインコサインテーブルを使用します。

ここから説明する回転方法は「創作プログラミングの街」を参考にしてます。
(とても参考になります!!ソースさえ読めれば色々なスキルを習得できます!!)

ある点(x,y)から原点(0,0)を中心にθ度回転した座標(x',y')の式は、

x'=x cosθ-y sinθ
y'=x sinθ+y cosθ

だそうです。何故かは知りませんが。(笑
ただこれは通常数学で使うような角度の場合です。今回使用するサインコサインテーブルの形式はこれとは違います。
テーブルの形式にあわせると、

x'=-x sinθ-y cosθ
y'=x cosθ-y sinθ

となります。(この式を出すのが大変だった…)
この公式で画像を回転させようとして、普通に一点一点を移動させると、完全な形で描画されず、いくつかの穴が開いてしまいます。
サインコサインの精度が低いためでもありますが、かなり精度が高くなければ完全な形では移動できません。
ではどうするかというと、「この点をどこに移動するか」ではなく、「この点はどこから移動されてきたのか」を調べることにより、穴はなくなります。 (「創作プログラミングの街」そのまんま)
以上を踏まえて完成したモジュールが以下のソースです。

	r=10000	;円形の半径(精度)
	dim px,r*2+1	;座標格納用配列(なぜかこれでジャスト)
	fy=r
	repeat r+1
		x=cnt
		y2=r*r-(x*x)	;三平方の定理
		i=y2 : s=i
		repeat	;平方根計算ループ
			if i=0 : y=0 : break
			e=s : s=i/s+s>>1
			if s>=e : y=s : break
		loop
		repeat fy-y+1
			px.count=x
			count++	;格納座標の個数のカウント
		loop
		fy=y
	loop
	dim sin,360
	dim cos,360
	repeat 90,1	;cos.0は0でいいのでとばす
		c=count*cnt/90-1
		cos.cnt=px.c*10000/r	;第一象限コサイン
	loop
	repeat 90
		c=90-cnt
		sin.cnt=-cos.c	;第一象限サイン
	loop
	repeat 90,90
		c=cnt-90
		sin.cnt=cos.c	;第四象限サイン
		cos.cnt=-sin.c	;第四象限コサイン
	loop
	repeat 180,180
		c=cnt-180
		sin.cnt=-sin.c	;第二、第三象限サイン
		cos.cnt=-cos.c	;第二、第三象限コサイン
	loop

#module

#deffunc gspin int,int,int,int,int,int
	mref wid,0	;ウィンドウID
	mref centx,1	;回転の中心座標x
	mref centy,2	;回転の中心座標y
	mref sizex,3	;回転する画像の幅
	mref sizey,4	;回転する画像の高さ
	mref ang,5	;回転する角度

	angle=360-ang\360	;移動元なので逆
	begx=csrx : begy=csry
	repeat sizey
		cnt2=cnt
		repeat sizex
			cx=-(-sizex/2+cnt*sin@.angle)-(-sizey/2+cnt2*cos@.angle)/10000+centx
			cy=-sizex/2+cnt*cos@.angle-(-sizey/2+cnt2*sin@.angle)/10000+centy
			pos begx+cnt,begy+cnt2 : gcopy wid,cx,cy,1,1
		loop
	loop
return

#global

	dialog "bmp;*.jpg",16,"画像ファイル"
	if stat=0 : end

	buffer 2
	picload refstr
	picx=winx : picy=winy

	screen 0,picx,picy
	pos 0,0 : gspin 2,picx/2,picy/2,picx,picy,30	;30度回転
	stop

起動時に画像ファイルを選び、その画像を30度回転させて表示します。
計算式部分がやたら複雑ですが、公式と比べてみればわかると思います。


戻る