Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android matrix 詳解與進階(一)

android matrix 詳解與進階(一)

編輯:關於Android編程

1 概述

這裡我們會詳細講解matrix的各個方法,以及它的用法。matrix叫做矩陣,在前面講解 ColorFilter 的文章中,我們講解了ColorMatrix,他是一個4*5的矩陣。而這裡,我們講解的Matrix不是用於處理顏色的,而是處理圖形的。他是一個3*3的矩陣。

2 原理

先看看matrix的矩陣是什麼樣子的:

這裡寫圖片描述

這裡可以查看Matrix的代碼得到。那麼這個矩陣分別代表了什麼呢,這裡通過他們的名字可以看出,scale是縮放,skew是錯切(canvas變換中有講過),trans是平移,persp代表透視(官方文檔中,也沒有詳細講解,透視在這裡只做簡單介紹)。這裡需要把矩陣根據他們的作用劃分為4塊:

這裡寫圖片描述

如上圖所示,這四塊區域各有作用。後面會詳細講解各個作用,先來看看這個矩陣是如何影響圖像的。先看看屏幕的坐標系:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxpbWcgYWx0PQ=="這裡寫圖片描述" src="/uploadfile/Collfiles/20160519/20160519092735209.png" title="\" />

看上圖,這裡表示了屏幕的坐標系,其中的x,y軸是大家所熟知的,但是其實,一個物體他是存在於一個三維空間的,所以必然會有z軸。我們的屏幕,就像是一個窗口,透過它,我們看到了屏幕後面的世界,那裡面有各種物體,我們看到的是映射在x,y平面上的一個投射圖像。屏幕就像是一個鏡頭一樣,將裡面的物體映射到x,y平面上,成為一個二維的圖像。那麼如果,我們把屏幕這個鏡頭沿著z軸,拉遠或者拉進,那麼圖像會有什麼變化呢,肯定會變小或者變大。就好比坐在飛機上透過窗口看地面的汽車,和在地面上看到的大小是不同的。

結論就是,在屏幕上顯示的像素,不僅僅有x,y坐標,其實還有z軸的影響。所以這裡對應的像素描述由一個3行一列的矩陣來表示:

這裡寫圖片描述

x,y分別代表x,y軸上的坐標,而1代表屏幕在z軸上的坐標為默認的。如果將1變大,那麼屏幕會拉遠, 圖形會變小。

現在我們來看看matrix怎麼作用於每個像素的值。這裡需要用到矩陣的乘法,首先需要明確的是,矩陣的前乘和後乘是不相同的,也就是說不滿足乘法交換律。

這裡我們通過一個旋轉變換來看看原理,其實一張圖片圍繞一個點旋轉,也就是所有的點都圍繞一個點旋轉,所以只需要關注一個點的情況即可:

假定有一個點 ,相對坐標原點順時針旋轉後的情形,同時假定P點離坐標原點的距離為r,如下圖:

這裡寫圖片描述

那麼就有:

這裡寫圖片描述

換做矩陣運算就如下圖:

這裡寫圖片描述

從這裡就可以看出,矩陣中的值,是如何作用於像素點的x,y坐標以及z軸遠近。

同時,可以看到,上面的矩陣四塊區域的切分也是因為矩陣乘法的操作決定的,由於這裡的乘法運算中,左上角的四個值,可以和x,y值做乘法運算,所以可以影響到旋轉等操作,而右上角的模塊,只能做加法,所以只能影響到平移。右下角的模塊主要管z軸,自然就可以進行等比的縮放了,左下角的模塊一般不去動他,否則會把x,y值加入到z軸中來,會不可控。

3 基本方法解析

講解完了matrix作用於像素點的原理之後,我們逐個講解它的方法。

(1) 構造函數

public Matrix()
public Matrix(Matrix src)

構造函數有兩個,第一個是直接創建一個單位矩陣,第二個是根據提供的矩陣創建一個新的矩陣(采用deep copy)

單位矩陣如下:

這裡寫圖片描述

(2) isIdentity與isAffine

public boolean isIdentity()//判斷是否是單位矩陣
public boolean isAffine()//判斷是否是仿射矩陣

是否是單位矩陣很簡單,就不做講解了,這裡是否是仿射矩陣可能大家不好理解。

首先來看看什麼是仿射變換。仿射變換其實就是二維坐標到二維坐標的線性變換,保持二維圖形的“平直性”(即變換後直線還是直線不會打彎,圓弧還是圓弧)和“平行性”(指保持二維圖形間的相對位置關系不變,平行線還是平行線,而直線上點的位置順序不變),可以通過一系列的原子變換的復合來實現,原子變換就包括:平移、縮放、翻轉、旋轉和錯切。這裡除了透視可以改變z軸以外,其他的變換基本都是上述的原子變換,所以,只要最後一行是0,0,1則是仿射矩陣。

(3) rectStaysRect

public boolean rectStaysRect()

判斷該矩陣是否可以將一個矩形依然變換為一個矩形。當矩陣是單位矩陣,或者只進行平移,縮放,以及旋轉90度的倍數的時候,返回true。

(4) reset

public void reset()

重置矩陣為單位矩陣。

(5) setTranslate

public void setTranslate(float dx, float dy)

設置平移效果,參數分別是x,y上的平移量。
效果圖如下:

這裡寫圖片描述

代碼如下:

Matrix matrix = new Matrix();
canvas.drawBitmap(bitmap, matrix, paint);

matrix.setTranslate(100, 1000);
canvas.drawBitmap(bitmap, matrix, paint);

(6) setScale

public void setScale(float sx, float sy, float px, float py)
public void setScale(float sx, float sy)

兩個方法都是設置縮放到matrix中,sx,sy代表了縮放的倍數,px,py代表縮放的中心。這裡跟上面比較類似不做講解了。

(7) setRotate

 public void setRotate(float degrees, float px, float py)
 public void setRotate(float degrees)

和上面類似,不再講解。

(8) setSinCos

public void setSinCos(float sinValue, float cosValue, float px, float py)
public void setSinCos(float sinValue, float cosValue)

這個方法乍一看可能有點蒙,其實在前面的原理中,我們講解了一個旋轉的例子,他最終的矩陣效果是這樣的:

這裡寫圖片描述

其實旋轉,就是使用了這樣的matrix,顯而易見,這裡的參數就清晰了。
sinValue:對應圖中的sin值
cosValue:對應cos值
px:中心的x坐標
py:中心的y坐標

看一個示例,我們把圖像旋轉90度,那麼90度對應的sin和cos分別是1和0。

這裡寫圖片描述

看代碼如下:

Matrixmatrix = new Matrix();
matrix.setSinCos(1, 0, bitmap.getWidth() / 2, bitmap.getHeight() / 2);
canvas.drawBitmap(bitmap, matrix, paint);

(9) setSkew

public void setSkew(float kx, float ky, float px, float py)
public void setSkew(float kx, float ky)

錯切,這裡kx,ky分別代表了x,y上的錯切因子,px,py代表了錯切的中心。不了解錯切了在前面canvas變換中去查看,這裡不再講解。

(10) setConcat

public boolean setConcat(Matrix a,Matrix b)

將當前matrix的值變為a和b的乘積,它的意義在下面的 進階方法中來探討。

4 進階方法解析

上面的基本方法中,有關於變換的set方法都可以帶來不同的效果,但是每個set都會把上個效果清除掉,例如依次調用了setSkew,setTranslate,那麼最終只有setTranslate會起作用,那麼如何才和將兩種效果復合呢。Matrix給我們提供了很多方法。但是主要都是2類:

preXXXX:以pre開頭,例如preTranslate
postXXXX:以post開頭,例如postScale

他們分別代表了前乘,和後乘。看一段代碼:

Matrix matrix = new Matrix();
matrix.setTranslate(100, 1000);
matrix.preScale(0.5f, 0.5f);

這裡matrix前乘了一個scale矩陣,換算成數學式如下:

這裡寫圖片描述

從上面可以看出,最終得出的matrix既包含了縮放信息也有平移信息。
後乘自然就是matrix在後面,而縮放矩陣在前面,由於矩陣前後乘並不等價,也就導致了他們的效果不同。我們來看看後乘的結果:

這裡寫圖片描述

可以看到,結果跟上面不同,並且這也不是我們想要的結果,這裡縮放沒有更改,但是平移被減半了,換句話說,平移的距離也被縮放了。所以需要注意前後乘法的關系。

來看看他們對應的效果圖:

前乘:

這裡寫圖片描述

後乘:

這裡寫圖片描述

可以明顯看到,後乘的平移距離受了影響。

了解清除了前後乘的意義,在使用的過程中,多個效果的疊加時,一樣要注意,否則效果達不到預期。

後面一篇我們繼續講解matrix的高階用法

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved