Android Matrix

Matrix矩陣變幻

基本變幻

  • scal 縮放
  • translate平移
  • roate旋轉
  • concat合併
  • skew扭曲

基本介紹

Preconcats matrix相當於右乘矩陣,Postconcats matrix相當於左乘矩陣。倒影就是縮放爲負數

Matrix是一個3*3的矩陣,其值對應如下:
下面給出具體座標對應變形的屬性

|scaleX, skewX, translateX |
|skewY, scaleY, translateY |
|0 , 0 , scale |

常用方法

  • setTranslate(float dx,float dy):控制Matrix進行位移。
  • setSkew(float kx,float ky):控制Matrix進行傾斜,kx、ky爲X、Y方向上的比例。
  • setSkew(float kx,float ky,float px,floatpy):控制Matrix以px、py爲軸心進行傾斜,kx、ky爲X、Y方向上的傾斜比例。
  • setRotate(float degrees):控制Matrix進行depress角度的旋轉,軸心爲(0,0)。 setRotate(float
  • degrees,float px,float py):控制Matrix進行depress角度的旋轉,軸心爲(px,py)。
  • setScale(float sx,float sy):設置Matrix進行縮放,sx、sy爲X、Y方向上的縮放比例。
  • setScale(float sx,float sy,float px,floatpy):設置Matrix以(px,py)爲軸心進行縮放,sx、sy爲X、Y方向上的縮放比例。

注意:以上的set方法,均有對應的post和pre方法, Matrix調用一系列set,pre,post方法時,可視爲將這些方法插入到一個隊列. 當然,按照隊列中從頭至尾的順序調用執行.其中pre表示在隊頭插入一個方法, post表示在隊尾插入一個方法.而set表示把當前隊列清空,並且總是位於隊列的最中間位置,當執行了一次set後:pre方法總是插入到set前部的隊列的最前面,post方法總是插入到set後部的隊列的最後面

抽象的說pre方法是向前”生長”, post方法是向後”生長”,具體拿個例子來說,
比如一個matrix調用了下列一系列的方法:

matrix.preScale(0.5f, 1); matrix.preTranslate(10, 0);
matrix.postScale(0.7f, 1); matrix.postTranslate(15, 0);

則座標變換經過的4個變換過程依次是:

translate(10, 0) -> scale(0.5f, 1) -> scale(0.7f,1) -> translate(15, 0)

所以對matrix方法的調用順序是很重要的,不同的順序往往會產生不同的變換效果。 pre方法的調用順序和post方法的互不影響,即以下的方法調用和前者在真實座標變換順序裏是一致的,

matrix.postScale(0.7f, 1);matrix.preScale(0.5f, 1); 
matrix.preTranslate(10, 0);matrix.postTranslate(15, 0);

而matrix的set方法則會對先前的pre和post操作進行刷除,而後再設置它的值,比如下列的方法調用:

matrix.preScale(0.5f, 1); matrix.postTranslate(10, 0);
matrix.setScale(1, 0.6f); matrix.postScale(0.7f, 1);
matrix.preTranslate(15, 0); 

其座標變換順序是

translate(15, 0) -> scale(1, 0.6f) -> scale(0.7f, 1).
setScale

重新設置了矩陣的值,之前的兩個變換是無效的了,所以最終的顯示效果只有三個變換效果。
Canvas裏scale,translate, rotate, concat方法都是pre方法,如果要進行更多的變換可以先從canvas獲得matrix,變換後再設置回canvas.

示例:

/**
* @author leo
* @date 15-2-26
* 
*  練習使用Matrix對Bitmap進行處理
* 
*/
class MatrixView extends View{

Matrix matrix;
Paint mPaint;
Bitmap bitmap;

public MatrixView(Context context) {
super(context);
//初始化矩陣
matrix = new Matrix();
//矩陣平移, 使用時候和pre postTranslate效果一樣
// matrix.setRotate(30); matrix.preRotate(30), matrix.postRorate(30);


/**
* 關於下面兩種情況的說明 
* 第一種 :
* matrix.setTranslate(100, 100);
* matrix.postScale(2f, 2f);
* 實現這樣的矩陣,post左乘
* [2,0,0]     [1,0,100]      [2,0,200] 
* [0,2,0]  ×  [0,2,100]  =   [0,2,200] 
* [0,0,1]     [0,0,1  ]      [0,0,1  ] 
* 得到的就應該是縮放兩倍後,平移到x=200 y=200的位置
* 
* 第二種:
* matrix.setTranslate(100, 100);
* matrix.preScale(2f, 2f);
* 實現這樣的矩陣,pre右乘
*  [1,0,100]       [2,0,0]      [2,0,100] 
*  [0,1,100]   ×   [0,2,0]      [0,2,100] 
*  [0,0,1  ]       [0,0,1]      [0,0,1  ] 
* 得到的就應該是縮放兩倍後,平移到x=100 y=100的位置
*/

mPaint = new Paint();
Bitmap tmp = BitmapFactory.decodeStream(context.getResources().openRawResource(R.drawable.icon48x48_2));
bitmap = tmp.copy(Config.ARGB_8888, true);
if (tmp != bitmap) {
    tmp.recycle();
}

//垂直影像
/*
final float vertical[] = {
1.0F,  0.0F,  0.0F,
0.0F,  -1.0F, bitmap.getHeight(),
0.0F,  0.0F,  1.0F}; 
final float horat[] = {
-1.0F,  0.0F,  bitmap.getWidth(),
0.0F,  1.0F, 0.0F,
0.0F,  0.0F,  1.0F}; 
matrix.setValues(horat);
*/
}

@Override
protected void dispatchDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    super.dispatchDraw(canvas);
    canvas.drawColor(Color.WHITE);
    canvas.drawBitmap(bitmap, matrix, mPaint);
    //有陰影的
    // canvas.drawBitmap(getReflectedBitmap(bitmap), 0, 0, mPaint);

    // mPaint.setColor(Color.RED);
    // FontMetrics fm = mPaint.getFontMetrics();
    // canvas.drawText("I'm Chinese", 100, 100+(fm.descent - fm.ascent), mPaint);

    // matrix.setTranslate(100, 100);
    // matrix.postScale(2f, 2f);
    // canvas.drawBitmap(bitmap, matrix, mPaint);
    // canvas.drawText("I'm Chinese", 200, 200+(fm.descent - fm.ascent), mPaint);

    //使用set就是清空矩陣隊列,如果想要繼續上面矩陣變換可以如下:
    // Matrix m = new Matrix();
    // m.setScale(3.f, 3.f);
    // matrix.setConcat(matrix, m);
    // canvas.drawBitmap(bitmap, matrix, mPaint);
}

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章