自定義View系列目錄
涉及方法
類别 | API | 描述 |
---|---|---|
旋轉 | setRotate | 設定(非輸入軸顔色的)色調 |
飽和度 | setSaturation | 設定飽和度 |
縮放 | setScale | 三原色的取值的比例 |
設定 | set、setConcat | 設定顔色矩陣、兩個顔色矩陣的乘積 |
重置 | reset | 重置顔色矩陣為初始狀态 |
矩陣運算 | preConcat、postConcat | 顔色矩陣的前乘、後乘 |
一、顔色矩陣
顔色矩陣是一個用來表示三原色和透明度的4x5的矩陣,表示為一個數組的形式
[ a, b, c, d, e,
f, g, h, i, j,
k, l, m, n, o,
p, q, r, s, t ]
顔色矩陣計算
一個顔色則使用
[R, G, B, A]
的方式進行表示,是以矩陣與顔色的計算方式則為
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcucTOlUUQlcTRlETQlUUQlgTRlUjQlgTOlkTRlkTQlYUOlcTRlIjQlkDOlgTRlMUOlITQlkTRl8CXkx2bvwVbvNmLuRGZ19Gbj5CdrJmLxFHOoBjYw12bvw1LcpDc0RHaiojIsJye.png)
從上述的公式可以看出,顔色矩陣的功能劃分如下
-
表示三原色中的紅色a, b, c, d, e
-
表示三原色中的綠色f, g, h, i, j
-
表示三原色中的藍色k, l, m, n, o
-
表示顔色的透明度p, q, r, s, t
- 第五列用于表示顔色的偏移量
使用示例
首先我們在不改變初始矩陣的情況下,來看一下圖檔的效果
private ColorMatrix mColorMatrix;
private Paint mPaint;
private Bitmap oldBitmap;
mColorMatrix = new ColorMatrix();
mPaint = new Paint();
// 設定畫筆的顔色過濾器
mPaint.setColorFilter(new ColorMatrixColorFilter(mColorMatrix));
Log.d("TAG", Arrays.toString(mColorMatrix.getArray()));
// 建立Bitmap
oldBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.header);
// 在畫布上顯示圖檔
canvas.drawBitmap(oldBitmap,0,0,mPaint);
// Log
TAG: [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
初始矩陣
現在我們建立一個矩陣,使用set方法來使用這個矩陣,改變圖檔的顔色
mColorMatrix.set(new float[]{
1,0.5f,0,0,0
,0,1,0,0,0
,0,0,1,0,0
,0,0,0,1,0});
紅矩陣
二、常用方法
1、旋轉
API如下:
/**
* 用于色調的旋轉運算
* axis=0 表示色調圍繞紅色進行旋轉
* axis=1 表示色調圍繞綠色進行旋轉
* axis=2 表示色調圍繞藍色進行旋轉
*/
public void setRotate(int axis, float degrees)
三原色坐标系
a、圍繞紅色軸旋轉
我們可以根據三原色來建立一個三維向量坐标系,當圍繞紅色旋轉時,我們将紅色虛化為一個點,綠色為橫坐标,藍色為縱坐标,旋轉θ°。
坐标系示例
紅色坐标系
根據平行四邊形法則R、G、B、A各值計算結果:
矩陣表示:
b、圍繞綠色軸旋轉
綠色虛化為一個點,藍色為橫坐标軸,紅色為縱坐标軸,旋轉θ°。
坐标系示例
綠色坐标系
根據平行四邊形法則R、G、B、A各值計算結果:
矩陣表示:
c、圍繞藍色軸旋轉
藍色虛化為一個點,紅色為橫坐标軸,綠色為縱坐标軸,旋轉θ°。
坐标系示例
藍色坐标系
根據平行四邊形法則R、G、B、A各值計算結果:
矩陣表示:
使用示例
這裡設定色調圍繞紅色軸旋轉90°
// 旋轉綠色、藍色
mColorMatrix.setRotate(0,90);
// Log
D/TAG: [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -4.371139E-8, 1.0, 0.0, 0.0, 0.0, -1.0, -4.371139E-8, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0, 0.0]
從Log中我們可以看出,其結果也驗證了我們的上述理論,圖檔效果如下:
旋轉矩陣
2、縮放
API如下:
/**
* rScale 表示紅色的數值的縮放比例
* gScale 表示綠色的數值的縮放比例
* bScale 表示藍色的數值的縮放比例
* aScale 表示透明度的數值的縮放比例
*/
public void setScale(float rScale, float gScale, float bScale,float aScale)
R、G、B、A各值計算結果:ColorMatrix的縮放方法,其實就是根據矩陣的運算規則,對
R、G、B、A
的數值分别進行縮放操作,當然在操作之前,會對現有的ColorMatrix進行初始化操作。
矩陣表示:
使用示例
這裡設定,所有的縮放比例為1.1
// 設定縮放比例
mColorMatrix.setScale(1.1f,1.1f,1.1f,1.1f);
// Log
D/TAG: [1.1, 0.0, 0.0, 0.0, 0.0, 0.0, 1.1, 0.0, 0.0, 0.0, 0.0, 0.0, 1.1, 0.0, 0.0, 0.0, 0.0, 0.0, 1.1, 0.0]
從Log中我們可以看出,其結果也驗證了對于縮放的了解,圖檔效果如下 :
縮放矩陣
我們還可以制作一個顔色通道,比如紅色 :
// 紅色通道
mColorMatrix.setScale(1,0,0,1);
// Log
D/TAG: [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
紅色通道
3、飽和度
API如下:
/**
* 設定矩陣顔色的飽和度
*
* sat 0表示灰階、1表示本身
*/
public void setSaturation(float sat)
灰階圖檔的去色原理:隻要把RGB的三色通道的數值設定為一樣,即
R=G=B
,那麼圖像就變成了灰色,同時為了保證圖像的亮度,需要使同一個通道中的
R+G+B
的結果接近1。setSaturation
方法可以根據一定比例,整體的增加或者減少顔色的飽和度,當設定0時,表示灰階圖檔;當設定為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 的比例構成像素灰階值
使用示例
這裡設定飽和度為0,測試下灰階效果
// 灰階
mColorMatrix.setSaturation(0f);
// Log
D/TAG: [0.213, 0.715, 0.072, 0.0, 0.0, 0.213, 0.715, 0.072, 0.0, 0.0, 0.213, 0.715, 0.072, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0, 0.0]
列印出的Log也驗證了上述對于圖檔灰階的說明,當然源碼中還有對于飽和度從0%——100%的計算,感興趣的同學可以檢視以下源碼。灰階圖檔效果如下:
飽和度矩陣
三、ColorMatrix相乘
1、設定
設定新的矩陣覆寫之前的内容,可以設定一個單獨的矩陣,也可以設定兩個矩陣的相乘。API如下:
public void set(ColorMatrix src)
public void set(float[] src)
public void setConcat(ColorMatrix matA, ColorMatrix matB)
這裡主要說一下
setConcat
方法,此方法表示兩個ColorMatrix相乘
矩陣表示為:
使用示例
mColorMatrixA = new ColorMatrix(new float[]{
1,0.3f,0,0,0
,0,1,0.3f,0,0.1f
,0,0.6f,1,0,0
,0,0,0,1,1
});
mColorMatrixB = new ColorMatrix(new float[]{
1,0,0,0,1
,0,1,0,0,0.5f
,0.1f,0.9f,0.8f,0,0
,0,0,0,1,0.8f
});
mColorMatrix = new ColorMatrix(new float[]{
0,0,0,0,0
,0,0,0,0,0
,0,0,0,0,0
,0,0,0,0,0
});
mColorMatrix.setConcat(mColorMatrixA,mColorMatrixB);
Log.d("TAGA", Arrays.toString(mColorMatrixA.getArray()));
Log.d("TAGB", Arrays.toString(mColorMatrixB.getArray()));
Log.d("TAGAB", Arrays.toString(mColorMatrix.getArray()));
// Log
D/TAGA: [1.0, 0.3, 0.0, 0.0, 0.0, 0.0, 1.0, 0.3, 0.0, 0.1, 0.0, 0.6, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0]
D/TAGB: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.1, 0.9, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.8]
D/TAGAB: [1.0, 0.3, 0.0, 0.0, 1.15, 0.030000001, 1.27, 0.24000001, 0.0, 0.6, 0.1, 1.5, 0.8, 0.0, 0.3, 0.0, 0.0, 0.0, 1.0, 1.8]
2、前乘
前乘相當于,目前矩陣乘以輸入的矩陣
這裡看一下源碼,可以更容易的了解:
1 2 3 4 | // 邏輯上相當于調用setConcat(this, prematrix) public void preConcat(ColorMatrix prematrix) { setConcat(this, prematrix); } |
從源碼上可以明顯的看出前乘的規則,preConcat(prematrix)方法相當于調用setConcat(this, prematrix)方法
使用示例
1 2 3 | mColorMatrix.reset(); mColorMatrix.preConcat(mColorMatrixA); mColorMatrix.preConcat(mColorMatrixB); |
上例多次調用preConcat,則相當于
3、後乘
後乘相當于,輸入的矩陣乘以目前矩陣
這裡看一下源碼,可以更容易的了解:
1 2 3 4 | // 邏輯上相當于調用setConcat(postmatrix, this) public void postConcat(ColorMatrix postmatrix) { setConcat(postmatrix, this); } |
從源碼上可以明顯的看出前乘的規則,postConcat(prematrix)方法相當于調用setConcat(postmatrix, this)
使用示例
1 2 3 | mColorMatrix.reset(); mColorMatrix.postConcat(mColorMatrixA); mColorMatrix.postConcat(mColorMatrixB); |
上例多次調用postConcat,因為矩陣滿足交換律,則相當于
四、總結
本文我們學習了ColorMatrix的原理,并分析了其
setRotate、setScale、setSaturation
方法以及矩陣的乘法(前乘、後乘)。如果在閱讀過程中,有任何疑問與問題,歡迎與我聯系。
部落格:www.idtkm.com
GitHub:https://github.com/Idtk
微網誌:http://weibo.com/Idtk
郵箱:[email protected]
五、參考
ColorMatrix
Paint之ColorMatrix與濾鏡效果
Android Matrix矩陣詳解
轉載:http://www.idtkm.com/2016/09/18/13%E3%80%81ColorMatrix/