Matrixクラスを使ってBitmapを加工する


過去にTechBoosterでは、Canvasを使ったノウハウを公開しています。
Viewをカスタマイズ(独自実装)する
ScaleGestureDetectorを使ってピンチイン、ピンチアウトを認識する
Canvasの状態を保存/復帰させる

本エントリでは、CanvasにBitmapを表示する際にMatrixクラスを用いて簡易に加工(移動/回転/拡大縮小/歪み)を行う方法を紹介します。
Matrixクラスを使ってBitmapを加工することで、図形のドラッグによる移動や、ピンチアウトによる拡大などタッチパネルを持つデバイスならではの操作感を持たせることが可能となります。

※タッチパネル上のジェスチャー(フリックやピンチアウトなど)に関する記事は以下を参考にどうぞ。
ScaleGestureDetectorを使ってピンチイン、ピンチアウトを認識する

それでは続きをどうぞ。

CanvasへのBitmapの表示

ScaleGestureDetectorを使ってピンチイン、ピンチアウトを認識するで紹介したように、Viewを拡張したクラスを作成し、CanvasへBitmapを描画します。

CanvasへのBitmapの描画にはCanvasクラスのdrawBitmapメソッドを利用します。
drawBitmapメソッドには引き数の異なるオーバーロードメソッドが複数存在しますが、本エントリではMatrixを利用して画像加工を行いたいため、drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)を利用します。

描画処理は、ViewクラスのonDrawメソッドで行います。
onDrawメソッドは描画を行う際に呼び出されるメソッドで引き数にCanvasを持ちます。
また、invalidateメソッドを呼び出す事で、任意のタイミングでonDrawメソッドを呼び出すことも可能です。

本エントリでは、onDrawメソッド内では特別な処理を行わず、Bitmapを描画するのみです。
Canvasの状態管理については、Canvasの状態を保存/復帰させるのエントリが参考になります。

■src/MatrixDrawView.java

public class MatrixDrawView extends View {
	private Paint mPaint = new Paint();
	private Matrix mMatrix = new Matrix();
	private Bitmap image = null;

	public MatrixDrawView(Context context) {
		super(context);
		initView();
	}

	private void initView(){
		image = BitmapFactory.decodeResource(getResources(), R.drawable.tb);
		// 省略
	}

	// 省略
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		canvas.drawBitmap(image, mMatrix, mPaint);
	}

12行目でdrawableディレクトリに格納しておいたテックブースターの画像を読み込んでいます。
20行目でCanvasクラスのdrawBitmapメソッドを呼び出しBitmapを描画しています。
mMatrixを後述のメソッド内で変更を加えinvalidateメソッドを呼び出すことで、加工したBitmap画像を描画することができます。

移動(translate)を行う

X軸方向,Y軸方向への移動量をピクセル単位で指定することで、Bitmapを平行移動することができます。
平行移動を行う為にはMatrixクラスのpostTranslateメソッドを利用します。

サンプルソースコードは以下の様になります。

■src/MatrixDrawView.java

	public void trancelate(float dx, float dy){
		mMatrix.postTranslate(dx, dy);
		invalidate();
	}

2行目でpostTransrateメソッドを呼び出しています。
Matrixに変更を加えた後は、描画を行いたい為に3行目でinvalidateメソッドを呼び出しています。
translateのイメージ図は以下の通りになります。

本エントリのサンプルでは、カスタマイズしたViewを表示しているActivityのActionItemの押下時に上記メソッドを呼び出しています。
ActionItemの利用方法については、下記エントリをご参考にどうぞ。
オプションメニューの使い方 / Getting Started

拡大縮小(scale)を行う

X軸方向,Y軸方向への倍率を指定することで、Bitmapを拡大縮小することが可能です。
拡大縮小を行う為には、MatrixクラスのpostScaleメソッドを利用します。
postScaleメソッドには引き数に拡大縮小の基点を指定することができるオーバーロードメソッドも用意されています。
基点を指定しない場合には、Canvasの左上を基点として拡大縮小を行います。

本エントリでのサンプルコードは以下の通りです。

■src/MatrixDrawView.java

	public void scale(float sx, float sy){
		mMatrix.postScale(sx, sy);
		invalidate();
	}

2行目でpostScaleメソッドを呼び出しています。
Matrixに変更を加えた後は、描画を行いたい為に3行目でinvalidateメソッドを呼び出しています。
scaleのイメージ図は以下の通りになります。

回転(rotate)を行う

回転する角度を指定することで、Bitmapを回転することができます。
回転にはMatrixクラスのpostRotateメソッドを利用します。
postRotateメソッドには、拡大縮小を行うpostScaleメソッドと同じように基点を指定することができるオーバーロードメソッドが用意されています。
基点を指定しない場合には、Canvasの左上を基点として回転を行います。

本エントリのサンプルコードは以下の通りです。

■src/MatrixDrawView.java

	public void rotate(float degrees){
		mMatrix.postRotate(degrees);
		invalidate();
	}

2行目でpostRotateメソッドを呼び出しています。
Matrixに変更を加えた後は、描画を行いたい為に3行目でinvalidateメソッドを呼び出しています。
rotateのイメージ図は以下の通りになります。

歪み(skew)を行う

MatrixクラスのpostSkewメソッドを利用することで、Bitmapに対して歪み効果を与えることができます。
Matrixクラスで扱うことができる歪み効果は、アフィン変換と呼ばれる対になる二辺が平行の関係を保ったままの変換となります。
postSkewメソッドの引き数には、X軸方向,Y軸方向の傾きを指定します。

本エントリのサンプルコードは以下の通りです。

■src/MatrixDrawView.java

	public void skew(float kx, float ky){
		mMatrix.postSkew(kx, ky);
		invalidate();
	}

2行目でpostSkewメソッドを呼び出しています。
Matrixに変更を加えた後は、描画を行いたい為に3行目でinvalidateメソッドを呼び出しています。
skewのイメージ図は以下の通りになります。

3 Comments