Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Matrix矩陣詳解

Android Matrix矩陣詳解

編輯:關於Android編程

Android中有兩個比較重要的矩陣,ColorMatrix和Matrix。ColorMatrix用來改變bitmap的顏色和透明度,Matrix用來對bitmap平移、縮放、錯切。

ColorMatrix(色彩矩陣)

Android中Bitmap色彩用了一個[R, G, B, A],4*1的矩陣來保存。
image_1al1ljmtjdjfb2f12fb1aku1t6o13.png-3kB
如果想改變一個Bitmap的色彩該怎麼辦?現在來了解下ColorMatrix的相關知識。ColorMatrix 是一個4*5的矩陣。
image_1al1lctohqcr4rflnr103ij7mm.png-7.6kB
我們用[R’, G’, B’, A’]來保存新的bitmap色彩,4*5必須和5*1矩陣相乘才能得到4*1矩陣,於是運算關系如下:
image_1alm721n317ds1j9uigg1nvmd1k9.png-15.5kB
根據矩陣乘法通過如下運算,便能如下求出一個新的色彩矩陣了。

為什麼要使用4*5矩陣而不是4*4矩陣?。因為只有4*5矩陣可以單獨改變一種顏色值。比如你改變e,只會影響R’。

ColorMatrix的默認矩陣如下圖所示
image_1al1nirqafabpm1f24fpd1cnk2n.png-4.2kB
可以看出,進行色彩變換運算後色彩值仍然不變。
image_1alm7iacech41osilg81v021nug13.png-25.2kB
知道ColZ喎?/kf/ware/vc/" target="_blank" class="keylink">vck1hdHJpeLXE1MvL49StwO2686OsztLDx77Nv8nS1Nf2uty24MrCx+nBy6GjPC9wPg0KPGgzIGlkPQ=="黑白圖片">黑白圖片

黑白圖片的去色原理:只要把RGB三通道的色彩信息設置成一樣;即:R=G=B,那麼圖像就變成了灰色,並且,為了保證圖像亮度不變,同一個通道中的R+G+B應該接近1。
在matlab中按照 0.2989 R,0.5870 G 和 0.1140 B 的比例構成像素灰度值。
在OpenCV中按照 0.299 R, 0.587 G 和 0.114 B 的比例構成像素灰度值。
在Android中按照0.213 R,0.715 G 和 0.072 B 的比例構成像素灰度值。
這些比例主要是根據人眼中三種不同的感光細胞的感光強度比例分配的,因此並沒有一個確切值,不同工具調試出來的效果也不盡相同。

知道了RGB相關配色後,相關核心代碼如下。

    private Bitmap handleColorMatrix(){
        Canvas canvas = new Canvas(mTempBmp); // 創建一個畫布
        Paint paint = new Paint(); // 新建paint
        paint.setAntiAlias(true); //抗鋸齒
        //黑白
       ColorMatrix colorMatrix = new ColorMatrix(new float[]{  
        0.213f, 0.715f, 0.072f, 0, 0,  
        0.213f, 0.715f, 0.072f, 0, 0,  
        0.213f, 0.715f, 0.072f, 0, 0,  
        0,       0,    0, 1, 0,  
}); 
        paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));// 設置顏色變換效果
        canvas.drawBitmap(mOriginBmp, 0, 0, paint);
        return mTempBmp;
    }

運行測試效果如下。
1.gif-95.4kB

色彩偏移和縮放

image_1al4hanss62c10nr1mjevkf1pk912.png-5kB
我們可以通過增加最後一列的值來相應增加或減少某種顏色的值。
image_1al4hhdi9rmi13el15dh8cd9ns1f.png-6.2kB
也可以通過改變對角線上的比例來進行色彩縮放。
比如給紅色增加20.

    ColorMatrix colorMatrix = new ColorMatrix(new float[]{
            1, 0, 0, 0, 20,
            0, 1, 0, 0, 0,
            0, 0, 1, 0, 0,
            0, 0, 0, 1, 0,
    });

1.gif-125.7kB
給綠色擴大到1.2倍。

    ColorMatrix colorMatrix = new ColorMatrix(new float[]{
            1, 0, 0, 0, 0,
            0, 1.2f, 0, 0, 0,
            0, 0, 1, 0, 0,
            0, 0, 0, 1, 0,
    });

1.gif-128.8kB
此外ColorMatrix提供了一個setScale來進行色彩縮放。

       /**
     * Set this colormatrix to scale by the specified values.
     */
    public void setScale(float rScale, float gScale, float bScale,
                         float aScale) {
        final float[] a = mArray;

        for (int i = 19; i > 0; --i) {
            a[i] = 0;
        }
        a[0] = rScale;
        a[6] = gScale;
        a[12] = bScale;
        a[18] = aScale;
    }

色彩飽和度

ColorMatrix提供了一個setSaturation通過改變對角線上的比例來改變飽和度。

    /**
     * Set the matrix to affect the saturation of colors.
     *
     * @param sat  飽和度的值,取值0,1
     */
    public void setSaturation(float sat) {
        reset();
        float[] m = mArray;

        final float invSat = 1 - sat;
        final float R = 0.213f * invSat;
        final float G = 0.715f * invSat;
        final float B = 0.072f * invSat;

        m[0] = R + sat; m[1] = G;       m[2] = B;
        m[5] = R;       m[6] = G + sat; m[7] = B;
        m[10] = R;      m[11] = G;      m[12] = B + sat;
    }

可以看出,當sat取值為0時,即是黑白圖片。

色彩旋轉

看到旋轉一詞,可能有點蒙,何為色彩旋轉?我們可以將RGB看做是一個坐標系(r,g,b)。
那麼坐標系如下。
image_1almh3cbj1vnntrbrdm1702coe2a.png-8.6kB
所以,我們可以把一個色彩值看成三維空間裡的一個點,色彩值的三個分量可以看成該點的坐標(三維坐標)。假如,我們現在需要圍繞藍色軸進行旋轉,我們對著藍色箭頭觀察由紅色和綠色構造的平面。然後順時針旋轉α度。
image_1alovtm7opj311go1spk2mmft6m.png-20.2kB
在圖中,我們可以看到,在旋轉後,原R在R軸的分量變為:R*cosα,且原G分量在旋轉後在R軸上也有了分量,所以我們要加上這部分分量,因此最終的結果為R’=R*cosα+G*sinα,同理,在計算G’時,因為R的分量落在了負軸上,所以我們要減去這部分,故G’=G*cosα-R*sinα;
於是,我們可以求出矩陣如下。
image_1almfosbk111l186nsuscqdqet13.png-7.4kB
同理,圍繞紅色軸旋轉的矩陣如下。
image_1almfu6po1fern6b8l4cl617j1g.png-7.1kB
圍繞綠色軸旋轉的矩陣如下。
image_1almg1sjf1oj178o19t2ditekv1t.png-7.4kB

同樣,ColorMatrix提供了一個setRotate(int axis, float degrees)來進行色彩旋轉。

    public void setRotate(int axis, float degrees) {
        reset();
        double radians = degrees * Math.PI / 180d;
        float cosine = (float) Math.cos(radians);
        float sine = (float) Math.sin(radians);
        switch (axis) {

        case 0:  // 圍繞紅色軸旋轉
            mArray[6] = mArray[12] = cosine;
            mArray[7] = sine;
            mArray[11] = -sine;
            break;

        case 1:   // 圍繞綠色軸旋轉
            mArray[0] = mArray[12] = cosine;
            mArray[2] = -sine;
            mArray[10] = sine;
            break;

        case 2:  // 圍繞藍色色軸旋轉
            mArray[0] = mArray[6] = cosine;
            mArray[1] = sine;
            mArray[5] = -sine;
            break;
        default:
            throw new RuntimeException();
        }
    }

Matrix(矩陣)

介紹完ColorMatrix,現在來看看Matrix。Android中Bitmap的每一個像素點用x,y坐標表示。同樣,在經過平移旋轉等運算後,我們需要用一個新坐標x’,y’來表示。Matrix是一個3*3的矩陣。至於為什麼是3*3,同樣,需要單獨進行偏移。於是運算關系如下。
image_1alma4slvs83gke1dnkhll1dkv1g.png-35.2kB
關於Matrix的內容,http://www.cnblogs.com/qiengo/archive/2012/06/30/2570874.html這篇介紹的非常詳細,原理和ColorMatrix基本差不多,這類知識關鍵在於矩陣的計算上,這裡就不贅述了,下面例舉出常用api。

setTranslate//設置平移矩陣
setScale //設置縮放矩陣
setRotate //設置旋轉矩陣。
setSkew //設置錯切矩陣
...

preTranslate(float dx, float dy) //先乘平移矩陣,M' = M * T(dx, dy)
preScale(float sx, float sy) //先乘縮放矩陣,M' = M * S(sx, sy)
preRotate(float degrees, float px, float py)//先乘旋轉矩陣,M' = M * R(degrees, px, py)
preSkew(float kx, float ky)//先乘錯切矩陣,M' = M * K(kx, ky)
...


postTranslate(float dx, float dy) //後乘平移矩陣,M' = T(dx, dy) * M
postScale(float sx, float sy) //後乘縮放矩陣,M' = S(sx, sy) * M
postRotate(float degrees, float px, float py)//後乘旋轉矩陣,M' = R(degrees, px, py) * M
postSkew(float kx, float ky)//後乘錯切矩陣,M' = K(kx, ky) * M
...

由於矩陣的乘法運算不滿足交換律,所以Matrix先乘和後乘是有區別的,先乘就是矩陣運算中的右乘,後乘就是矩陣運算中的左乘。即M' = M * T(dx, dy)M' = T(dx, dy) * M的區別。

最後

關於Matrix的應用,下篇分析圖片縮放預覽庫PhotoView源碼時再進行詳細介紹。
 

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