Canvas.drawBitmap について
周りを見渡しても桜が咲いているのはこの木だけか。不思議だなという顔をしている柴犬です。
概要
カメラの撮影した画像をピンチ操作で広げたり回したりしていろいろ試してみました。
規則性がありそうでないようなよくわかりませんので調べてみました。
結果、規則性は分かりませんでした。
人間の操作感覚に合うように行列計算しているんだと理解しました。
1冊だけでは理解の助けにはならないので買い足しました。
2024年2月26日現在
WEBのみでは断片的で覚えにくいので最初に購入した Kotlin の本です。
Canvas.drawBitmap
Canvas.drawBitmap は引数により7パターンもあります。
このなかで使うのが一番上の引数のものです。引数に Matrix を持ち何やら得体のしれないものです。
Graphics.Matrix
Matrix の公式HPの説明は次のURLにあります。Matrix には opengl.Matrix など複数あり間違えないようにしなければいけません。
JAVA
https://developer.android.com/reference/android/graphics/Matrix
KOTLIN
https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/Matrix
コンストラクタは次のようです。
Matrix()
次の表はメッソドをまとめたものです。
M’ = other * M
M’ = R(degrees, px, py) * M
M’ = S(sx, sy, px, py) * M
M’ = K(kx, ky, px, py) * M
M’ = T(dx, dy) * M
M’ = other * M
M’ = M * R(degrees, px, py)
M’ = M * S(sx, sy, px, py)
M’ = M * K(kx, ky, px, py)
M’ = M * T(dx, dy)
detector.getScaleFactor
ScaleGestureDetector.SimpleOnScaleGestureListener の onScale の中で次のようなコードを使っています。
ピンチ操作開始時
_focusx = detector.getFocusX();
_focusy = detector.getFocusY();
ピンチ操作中
_lastscalefactor = detector.getScaleFactor();
相似で拡大縮尺移動
drawmatrix.postScale(_lastscalefactor,
_lastscalefactor,
_focusx,
_focusy);
公式HPの説明は次のURLにあります。
https://developer.android.com/reference/android/view/ScaleGestureDetector
前のスケール イベントから現在のイベントまでのスケール係数を返します。 スケール係数は、getCurrentSpan() / getPreviousSpan() で与えられるとあります。
getCurrentSpan() は「焦点を通る進行中のジェスチャを形成する各ポインター間の平均距離(pixels)を返します。」とあります。
getPreviousSpan() は「焦点を通る進行中のジェスチャを形成する各ポインター間の以前の平均距離(pixels)を返します。」とあります。
ですので、式の意味はピンチ操作開始時の焦点の XY 座標(_focusx, _focusy)とスケール係数を基にS(sx, sy, px, py) 行列計算して Matrix を得るということになります。S(sx, sy, px, py) の中身は分かりませんでしたが、人間の操作感覚に合った行列計算をさせているようです。
Matrix.postTranslate
GestureDetector.SimpleOnGestureListener の onScroll の中で次のようなコードを使っています。
onScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
drawmatrix.postTranslate(-distanceX, -distanceY);
なぜ -distanceX、-distanceY とマイナスが付くのか不思議に思いました。 distanceX、distanceY ではいけないのか。
考えてみました。キャンバス自体を右に動かす場合は座標系を右に動かすので例えば原点は右に動くのでデバイスから見ると原点までの距離がマイナスになる。右へ指を動かすことはマイナス方向であると言えそうである。キャンバスが固定の場合は右へ描画を動かすことは原点までの距離がプラスにならなければならないから方向が逆になる。
間違いかもしれませんが、スクロールの決め事はキャンバスを動かすことが基礎にあるので、キャンバスの上にあるものを動かすシンメトリックはマイナスにすると理解しました。
今週初めの寒さで開花が遅れていた桜が満開になりました。綺麗でした。
今回はここまでとします。