一、簡介
setColorFilter(ColorFilter filter)
設置顏色過濾,這個方法需要我們傳入一個ColorFilter參數同樣也會返回一個ColorFilter實例。我們在setColorFilter(ColorFilter filter)的時候可以直接傳入ColorMatrixColorFilter、LightingColorFilter或PorterDuffColorFilter的子類對象作為參數。這些類其實都是colorFilter的子類,下面我們來一個個分析下它們的作用。
二、ColorMatrixColorFilter
中文直譯為“色彩矩陣顏色過濾器”,我們要先了解什么是色彩矩陣。在Android中圖片是以RGBA像素點的形式加載到內存中的,修改這些像素信息需要一個叫做ColorMatrix類的支持,這個類其實定義的是一個矩陣,是一個4x5的float[]類型的矩陣:
ColorMatrix colorMatrix = new ColorMatrix(new float[]{ 1, 0, 0, 0, 0, // 紅色向量 0, 1, 0, 0, 0, // 綠色向量 0, 0, 1, 0, 0, // 藍色向量 0, 0, 0, 1, 0, // 透明度向量 });
其中,第一行表示的R(紅色)的向量,第二行表示的G(綠色)的向量,第三行表示的B(藍色)的向量,最后一行表示A(透明度)的向量,這一順序必須要正確不能混淆!你可能會問,那么列呢?我用圖例來表示一下。
這個矩陣不同的位置表示的R、G、B、A值,其范圍在0.0F至2.0F之間,1為保持原圖的RGB值。每一行的第五列數字表示”偏移值“。
何為偏移值?顧名思義當我們想讓顏色更傾向於紅色的時候就增大R向量中的偏移值,想讓顏色更傾向於藍色的時候就增大B向量中的偏移值,這是最最朴素的理解,但是事實上色彩偏移的概念是基於白平衡來理解的。
什么是白平衡呢?說得簡單點就是白色是什么顏色!在單反的設置參數中有個色彩偏移,其定義的就是白平衡的色彩偏移值,就是當你去拍一張照片的時候白色是什么顏色的,在正常情況下白色是(255, 255, 255, 255)但是“現實世界中我們是無法找到這樣的純白物體的”,所以在我們用單反拍照之前就會拿一個我們認為是白色的物體讓相機記錄這個物體的顏色作為白色,然后拍攝時整張照片的顏色都會依據這個定義的白色來偏移!而這個我們定義的“白色”(比如:255, 253, 251, 247)和純白(255, 255, 255, 255)之間的偏移值(0, 2, 4, 8)我們稱之為白平衡的色彩偏移。
測試一下:
我們想要繪制一個橙色的圓圈,橙色的效果如下:
我們建立一個矩陣,然后看看效果。
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 生成色彩矩陣 ColorMatrix colorMatrix = new ColorMatrix(new float[]{ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, }); mPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix)); // 設置畫筆顏色為自定義顏色 mPaint.setColor(Color.argb(255, 255, 128, 103)); // 繪制圓環 (x坐標,y坐標,半徑,畫筆) canvas.drawCircle(240, 600 / 2, 200, mPaint); }
看看效果:
你會發現顏色沒有任何變化,為什么呢?因為矩陣的1表示不做任何變化,也就是保持原樣。我們換一個下面的矩陣就能看到效果了。
說明:如果在eclipse實時預覽的話,它會提示說如果你設置了這個屬性,那么eclipse可能無法准確的給你一個預覽圖。別擔心,實際運行的時候就出來了。
// 生成色彩矩陣 ColorMatrix colorMatrix = new ColorMatrix(new float[]{ 0.5F, 0, 0, 0, 0, 0, 0.5F, 0, 0, 0, 0, 0, 0.5F, 0, 0, 0, 0, 0, 1, 0, });
我們來看看這個矩陣是怎么計算的。其實說白了就是矩陣之間的運算乘積:
矩陣ColorMatrix的一行乘以矩陣MyColor的一列作為矩陣Result的一行,這里MyColor的RGBA值我們需要轉換為[0, 1]。通過這種計算我們可以將我們自己設定的顏色和矩陣的顏色進行疊加,創立一個新的顏色。
再測試一下:
如果我們用它來給圖片改顏色,該怎么做呢?下面的例子將會演示一下。
原本圖片:
加上濾鏡后:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 生成色彩矩陣 ColorMatrix colorMatrix = new ColorMatrix(new float[]{ -1, 0, 0, 1, 1, 0, -1, 0, 1, 1, 0, 0, -1, 1, 1, 0, 0, 0, 1, 0, }); mPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix)); Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.kale); canvas.drawBitmap(bitmap,240,600,mPaint); }
這說明,我們可以通過設置濾鏡來設置bitmap。如果想要看更多的效果,可以去:http://blog.csdn.net/aigestudio/article/details/41316141 看看。
現在我們知道了,ColorMatrixColorFilter和ColorMatrix就是這么個東西,ColorMatrix類里面也提供了一些實在的方法,比如setSaturation(float sat)設置飽和度,而且ColorMatrix每個方法都用了陣列的計算,如果大家感興趣可以自己去深挖。
三、LightingColorFilter
顧名思義光照顏色過濾,這肯定是跟光照是有關的了。該類有且只有一個構造方法:
LightingColorFilter (int mul, int add)
mul全稱是colorMultiply意為色彩倍增,而add全稱是colorAdd意為色彩添加,這兩個值都是16進制的色彩值0xAARRGGBB。這個方法使用也是非常的簡單。還是拿上面那張圖片來說吧,比如我們想要去掉綠色:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 設置顏色過濾 mPaint.setColorFilter(new LightingColorFilter(0xFFFF00FF, 0x00000000)); Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.kale); canvas.drawBitmap(bitmap,240,600,mPaint); }
運行后你會發現綠色確實是沒了但是原來偏綠的部分現在居然成了紅色,當LightingColorFilter(0xFFFFFFFF, 0x00000000)的時候原圖是不會有任何改變的,如果我們想增加紅色的值,那么LightingColorFilter(0xFFFFFFFF, 0x00XX0000)就好,其中XX取值為00至FF。
四、PorterDuffColorFilter
PorterDuffColorFilter跟LightingColorFilter一樣,只有一個構造方法:
PorterDuffColorFilter(int color, PorterDuff.Mode mode)
這個構造方法也接受兩個值,一個是16進制表示的顏色值這個很好理解,而另一個是PorterDuff內部類Mode中的一個常量值,這個值表示混合模式。那么什么是混合模式呢?混合混合必定是有兩種東西混才行,第一種就是我們設置的color值而第二種當然就是我們畫布上的元素了!也就是說將畫布上的元素和我們設置的color進行混合,產生最終的效果。
你可以類比為PS中的混合模式,只是PS的圖層混合模式比Android更多更廣泛,但兩者同名混合模式所產生的效果是一樣的,也基於同樣的算法原理這里就不多說了。
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 設置顏色過濾 mPaint.setColorFilter(new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.DARKEN)); Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.kale); canvas.drawBitmap(bitmap,240,600,mPaint); }
但是這里要注意一點,PorterDuff.Mode中的模式不僅僅是應用於圖像色彩混合,還應用於圖形混合,比如PorterDuff.Mode.DST_OUT就表示裁剪混合圖。
參考自:
http://blog.csdn.net/aigestudio/article/details/41316141
http://blog.csdn.net/xanxus46/article/details/7883554
From AigeStudio(http://blog.csdn.net/aigestudio)Power by Aige 尊重原作者,感謝作者的分享!