編輯:關於Android編程
Android中有兩個比較重要的矩陣,ColorMatrix和Matrix。ColorMatrix用來改變bitmap的顏色和透明度,Matrix用來對bitmap平移、縮放、錯切。
Android中Bitmap色彩用了一個[R, G, B, A],4*1的矩陣來保存。
如果想改變一個Bitmap的色彩該怎麼辦?現在來了解下ColorMatrix的相關知識。ColorMatrix 是一個4*5的矩陣。
我們用[R’, G’, B’, A’]來保存新的bitmap色彩,4*5必須和5*1矩陣相乘才能得到4*1矩陣,於是運算關系如下:
根據矩陣乘法通過如下運算,便能如下求出一個新的色彩矩陣了。
為什麼要使用4*5矩陣而不是4*4矩陣?。因為只有4*5矩陣可以單獨改變一種顏色值。比如你改變e,只會影響R’。
ColorMatrix的默認矩陣如下圖所示
可以看出,進行色彩變換運算後色彩值仍然不變。
知道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;
}
運行測試效果如下。
我們可以通過增加最後一列的值來相應增加或減少某種顏色的值。
也可以通過改變對角線上的比例來進行色彩縮放。
比如給紅色增加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.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,
});
此外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)。
那麼坐標系如下。
所以,我們可以把一個色彩值看成三維空間裡的一個點,色彩值的三個分量可以看成該點的坐標(三維坐標)。假如,我們現在需要圍繞藍色軸進行旋轉,我們對著藍色箭頭觀察由紅色和綠色構造的平面。然後順時針旋轉α度。
在圖中,我們可以看到,在旋轉後,原R在R軸的分量變為:R*cosα,且原G分量在旋轉後在R軸上也有了分量,所以我們要加上這部分分量,因此最終的結果為R’=R*cosα+G*sinα,同理,在計算G’時,因為R的分量落在了負軸上,所以我們要減去這部分,故G’=G*cosα-R*sinα;
於是,我們可以求出矩陣如下。
同理,圍繞紅色軸旋轉的矩陣如下。
圍繞綠色軸旋轉的矩陣如下。
同樣,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();
}
}
介紹完ColorMatrix,現在來看看Matrix。Android中Bitmap的每一個像素點用x,y坐標表示。同樣,在經過平移旋轉等運算後,我們需要用一個新坐標x’,y’來表示。Matrix是一個3*3的矩陣。至於為什麼是3*3,同樣,需要單獨進行偏移。於是運算關系如下。
關於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、概述Android提供了幾種動畫類型:View Animation 、Drawable Animation 、Property Animation 。View Ani
Android系統源碼閱讀(11):Android的InputManagerService的工作過程 請對照AOSP版本:6.0.1_r50。1. 創建InputMana
大家都知道,在實際工作中開發,進場需要將一個文件寫入到手機的存儲中。既然說到手機的存儲空間,那就先說說手機的存儲空間分類:1: 內部存儲空間RAM內存: 也就是手機的運行
限於篇幅的原因,在上篇文章中我們只學習了ActionBar基礎部分的知識,那麼本篇文章我們將接著上一章的內容繼續學習,探究一下ActionBar更加高級的知