LoginSignup
2
2

More than 5 years have passed since last update.

HSPで画像の切り取り表示と同時に変形も

Posted at

HSPで画像の一部だけを表示したいときは基本的にはgcopy命令ですが、もっと高度な切り取りをするならgsquare命令です。長方形以外の切り方ができる上に、同時に様々な変形を施すことができます。ただ、ちょっと使い方がややこしかったのでメモ。

リファレンスにはどう書いてるの

冒頭部分では

任意の四角形を描画

gsquare p1,p2,p3,p4,p5

p1=0~(0) : コピー元のウィンドウID (マイナス値ならば塗りつぶし)
p2=変数名 : コピー先X座標が格納される数値型配列変数名
p3=変数名 : コピー先Y座標が格納される数値型配列変数名
p4=変数名 : コピー元X座標が格納される数値型配列変数名
p5=変数名 : コピー元Y座標が格納される数値型配列変数名

解説
任意の4点を持つ四角形をコピーまたは塗りつぶします。
p1で、画像コピー元のウィンドウIDを指定します。

p2,p3にはコピー先の座標4つを配列に格納した変数を指定します。
p4,p5にはコピー元の座標4つを配列に格納した変数を指定します。
配列変数には、左上(0),右上(1),右下(2),左下(3) の順番に座標を入れておく必要があります。

とあります。

どういうことか

この命令では、

  • まずp4, p5の説明より 画像を四角形であればいかなる形にも切り取ることができます
  • さらに、p2, p3の説明より 切り取ってできた図形を変形して描画する機能まで備わっています。

かなりいろいろできそうです。

つかいかた

  1. 切り取り対象の画像を読み込む
  2. コピー先(描画範囲)の座標を決める
  3. その座標をX, Yごとに配列化しておく
  4. コピー元(切り取り範囲)についても同様にする
  5. gSquare命令で描画する

切り取り対象の画像を読み込む

使われる画像は一度別のバッファに読みこまれていなければなりません。

celload命令

もしくは

buffer命令からのpicload命令

を使って、画像を読み込みましょう。

celload "Origin.png", 1 //ウィンドウIDは適当でおk

OR

buffer 1 //ウィンドウIDは適当でおk
picload "Origin.png"

コピー先の座標を決める・その座標をX, Yごとに配列化しておく

ややこしいのはここです。

コピー先の長方形の頂点4つのX座標、Y座標ごとに4要素の配列(座標配列と呼びましょう)を用意して引数として渡さなければならないのですが、

リファレンスには

配列変数には、左上(0),右上(1),右下(2),左下(3) の順番に座標を入れておく必要があります。

とあります。座標配列の中身はこの順番でないと意図した動きをしません(違う順番にした時の動きは実例を参照してください)。左上から、時計回りに格納しましょう1。(図を参照)

指定方法.png

また、配列は整数のみです。ddimで宣言した配列では落ちます。

上の図の例でいけば、コードは以下のようになります。

dim copyToX, 4 
dim copyToY, 4
//ddim copyToX, 4 //ERROR: 実数不可!アニメーションさせたい等の理由で実数計算をした後はint()で囲うべし

//X座標について設定
copyToX(0) = a //copyToX.0 = aも可
copyToX(1) = c
copyToX(2) = e
copyToX(3) = g

//Y座標について設定
copyToY(0) = b
copyToY(1) = d
copyToY(2) = f
copyToY(3) = h

コピー元も同様にする

座標の与え方はコピー先と同様です。X座標、Y座標ともに配列を用意し格納します。

dim copyFromX, 4
dim copyFromY, 4

//後はコピー先の設定と同様

ちなみにコピー元の指定は省略できません。もしウィンドウ全体を描画の対象にしたい(つまり変形のみ行いたい)ときは、画像を読み込む際に以下のようにgsel命令で描画対象を移動して、

gsel 1 //描画対象の画像の入っているウィンドウIDに切り替え

copyFromX(0) = 0
copyFromX(1) = ginfo_winX
copyFromX(2) = ginfo_winX
copyFromX(3) = 0

copyFromY(0) = 0
copyFromY(1) = 0
copyFromY(2) = ginfo_winY
copyFromY(3) = ginfo_winY

gsel 0 //戻すのを忘れずに

とやればいいでしょう。


gsquare命令を実行

あとはgSquare命令を打つだけです。順番を間違えないようにしましょう(buffer命令を使用して読み込んだ場合はgsel 0を忘れずに)。


gsquare 1, copyToX, copyToY, copyFromX, copyFromY

ウィンドウID, コピー座標、コピー座標、コピー座標、コピー座標 の順番です。

これで切り取り・変形の加えられた画像が描画されます。描画は、gmode命令の影響を受けます23

実例

画像を切り取って表示したい

コピー元の座標を切り取る範囲にしましょう。コピー先は、その切り取った範囲と全く同じ形の四角形になるように設定します45
以下の例では、コピー元から台形状に画像を切り出して描画しています。画像は次のものを使います。名前はOrigin.pngです。

Origin.png

imgCrop.hsp
screen 0, 640, 480

cls 4

celload "Origin.png", 1

dim copyToX, 4 
dim copyToY, 4
dim copyFromX, 4
dim copyFromY, 4

//コピー元
//X座標について設定
copyFromX(0) = 20
copyFromX(1) = 130
copyFromX(2) = 130
copyFromX(3) = 20

//Y座標について設定
copyFromY(0) = 60
copyFromY(1) = 40
copyFromY(2) = 110
copyFromY(3) = 90

//コピー先(形が同じになるように注意して)
//X座標について設定
copyToX(0) = 0
copyToX(1) = 110
copyToX(2) = 110
copyToX(3) = 0

//Y座標について設定
copyToY(0) = 20
copyToY(1) = 0
copyToY(2) = 70
copyToY(3) = 50

gsquare 1, copyToX, copyToY, copyFromX, copyFromY

imgCrop.png


画像を変形したい

コピー先の座標を変えましょう。拡大・縮小もできます。

以下の例では、画像の切り取りは行わず、輪郭が先ほどの例の出力と同じ形になるように画像を変形させています。

imgWarp.hsp
screen 0, 640, 480

celload "Origin.png", 1

cls 4

dim copyToX, 4 
dim copyToY, 4
dim copyFromX, 4
dim copyFromY, 4

//コピー元
gsel 1 //描画対象のウィンドウIDを指定する

copyFromX(0) = 0
copyFromX(1) = ginfo_winX
copyFromX(2) = ginfo_winX
copyFromX(3) = 0

copyFromY(0) = 0
copyFromY(1) = 0
copyFromY(2) = ginfo_winY
copyFromY(3) = ginfo_winY

gsel 0 //戻すのを忘れずに

//コピー先
//X座標について設定
copyToX(0) = 0
copyToX(1) = 110
copyToX(2) = 110
copyToX(3) = 0

//Y座標について設定
copyToY(0) = 20
copyToY(1) = 0
copyToY(2) = 70
copyToY(3) = 50

gsquare 1, copyToX, copyToY, copyFromX, copyFromY

imgWarp.png


回転・反転もできちゃう

リファレンスには

配列変数には、左上(0),右上(1),右下(2),左下(3) の順番に座標を入れておく必要があります。

とありましたが、
この座標配列の中身を、1つずつ前(もしくは後ろ)にシフトするなどしてその順番を狂わせると、画像が回転・反転されて描画されます6

imgRotate.hsp

screen 0, 640, 480

cls 4

celload "Origin.png", 1

dim copyToX, 4 
dim copyToY, 4
dim copyFromX, 4
dim copyFromY, 4

//コピー元
gsel 1 //描画対象のウィンドウIDを指定する


copyFromX(0) = 0
copyFromX(1) = ginfo_winX
copyFromX(2) = ginfo_winX
copyFromX(3) = 0

copyFromY(0) = 0
copyFromY(1) = 0
copyFromY(2) = ginfo_winY
copyFromY(3) = ginfo_winY

gsel 0 //戻すのを忘れずに

//コピー先
//X座標について設定
copyToX(0) = 150
copyToX(1) = 150
copyToX(2) = 0
copyToX(3) = 0

//Y座標について設定
copyToY(0) = 0
copyToY(1) = 150
copyToY(2) = 150
copyToY(3) = 0

gsquare 1, copyToX, copyToY, copyFromX, copyFromY

imgRotate.png

ただし、gSquare命令は回転に対してはあまり実用的ではありません。

回転を行うならば、専用の命令gRotate命令が存在しています。この命令は回転のない長方形の切り抜きにも対応しているため、そういう場合はそっちを使いましょう。もし回転のある長方形や長方形以外を切り取ったあとに回転したい場合は、gSquare命令のみを使ってゴリゴリやることもできることにはできますが、例えば

  1. 別のウィンドウIDを初期化
  2. そこにgSquareで切り取った図形をそのまま描き込む
  3. そのウィンドウ全体をgRotate命令で回転して描画

という処理をしたほうが現実的です。

反転処理に関しては(何もincludeしない場合は)この命令が最適のようです。もし反転処理でもっと簡単な手がありましたらコメント・編集リクエストで指摘お願いします。


三角形に切る?!?

切り取り位置が自由に設定できるということは、

4点のうち2点を同一の点にすれば、三角形に切り抜けるんじゃね?

そこで実験してみました。画像は先ほどと同じものを使います。

うまくいけば、元の画像を右上から対角線で切ったとき下側に来る半分が描画されるはずです。

実験用コード

imgCropTri.hsp

screen 0, 640, 480

cls 4

celload "Origin.png", 1

dim copyToX, 4 
dim copyToY, 4
dim copyFromX, 4
dim copyFromY, 4

//コピー元
gsel 1 //描画対象のウィンドウIDを指定する

/* コピー元の座標指定の1番目と2番目が同じ点を示しています。
 * 右下に頂角を持つ直角二等辺三角形になるはず...
 */
copyFromX(0) = 0
copyFromX(1) = 0
copyFromX(2) = ginfo_winX
copyFromX(3) = 0

copyFromY(0) = 0
copyFromY(1) = 0
copyFromY(2) = ginfo_winY
copyFromY(3) = ginfo_winY

gsel 0 //戻すのを忘れずに

//コピー先
//X座標について設定
copyToX(0) = 0
copyToX(1) = 0
copyToX(2) = 150
copyToX(3) = 0

//Y座標について設定
copyToY(0) = 0
copyToY(1) = 0
copyToY(2) = 150
copyToY(3) = 150

gsquare 1, copyToX, copyToY, copyFromX, copyFromY

結果

imgCropTri.png

完 全 勝 利


まとめ

  • gSquare命令は、回転のない長方形に限らず、四角形全て・果てには三角形状に任意の画像を切り取ることが可能な命令。
  • 画像を切り取るだけでなく、変形処理もできる。切り取ってからの変形(回転・反転を含む)も許されている。
  • その自由度から、切り取り範囲・描画範囲はどんな形であれ4つの点すべてについて必ず指定しなければならない。
  • 回転のない長方形に切りたいときはgcopy命令を、回転のない長方形の範囲を回転させて描画したい場合はgRotate命令を使おう。


  1. 特に、コピー先やコピー元が回転のない長方形のときに、(回転のない長方形は対角上の2点を与えれば確定するため)X座標(Y座標)の配列には左右(上下)の位置2個だけを格納していれば良いと考えがちですが、それを実行すると妙なものが描画されてしまいます。この命令はかなり自由度が高く、コピー元もコピー先も四角形ならどんな図形でも切り取り変形して描画できるという仕様になっているため、長方形であれ、4つの頂点すべてについて格納しなければなりません(だから回転のない長方形を切り取るときにはgcopyを使ったほうがいいのです)。もし各々の座標配列に2つの数値を入れるという仕様なら、コピー先やコピー元が正方形や長方形・ひし形以外の四角形になることができません。 

  2. ただしアルファブレンド(gmode 7)は効きません。 

  3. コピー元とコピー先で画面モードが違う(パレットとフルカラー)と落ちるので注意しましょう。 

  4. 長方形以外の形に切った時でも難しくありません。各頂点を時計回りする際に、前の頂点との座標の差が同じになるようにすればいいのです。 

  5. 回転のない長方形に切るならgcopy命令を使いましょう。その方が楽です。 

  6. 変に狂わせると描画範囲がねじれたり妙なものが描画されたりしますのでご注意を。 

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2