有時候,咱們但願對一個圖片或一個複雜圖形的顏色,進行處理,那麼這時候能夠採用Paint
的setColorFilter
方法,一個最多見的例子,就是圖片的濾鏡,固然,那裏面的算法可能更加複雜。算法
ColorFilter
的分類關於ColorFilter
,源碼中是這麼解釋的,它能夠對Paint
所繪製區域的每一個像素進行顏色的改變。canvas
/**
* A color filter can be used with a {@link Paint} to modify the color of
* each pixel drawn with that paint. This is an abstract class that should
* never be used directly.
*/
複製代碼
當咱們使用ColorFilter
的時候,不同直接使用它,而是使用它的子類:數組
ColorMatrixColorFilter
LightingColorFilter
PoterDuffColorFilter
ColorMatrixColorFilter
ColorMatrixColorFilter
的經過ColorMatrix
構造,而ColorMatrix
則由一個長度爲20
的float
數組構造,傳入該數組後把該數組先從左到右,再從上到下排列,造成一個4*5
的矩陣。bash
[ a, b, c, d, e,
f, g, h, i, j,
k, l, m, n, o,
p, q, r, s, t ]
複製代碼
以後,再用矩陣和目標的RGBA
進行計算,最後獲得新的RGBA
,它的計算方法爲:ide
R’ = a*R + b*G + c*B + d*A + e;
G’ = f*R + g*G + h*B + i*A + j;
B’ = k*R + l*G + m*B + n*A + o;
A’ = p*R + q*G + r*B + s*A + t;
複製代碼
注意,新的RGBA
會被限制在0-255
的範圍內。在實際使用的時候,咱們先經過一個ColorMatrix
輔助類來肯定須要相乘的這個顏色矩陣,以後再把它做爲ColorMatrixColorFilter
構造函數的參數來構造它。 咱們通常有兩種用法:改變畫筆的顏色,或者改變整個Bitmap
的像素點的顏色。下面咱們用第二種方式來舉例。函數
private void drawColorMatrixFilter(Canvas canvas) {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
//1,獲得一個顏色矩陣
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(0.5f);
//2.經過顏色矩陣構建ColorMatrixColorFilter對象
ColorMatrixColorFilter colorMatrixColorFilter = new ColorMatrixColorFilter(colorMatrix);
Paint matrixPaint = new Paint();
//3.把構建的對象設置給Paint
matrixPaint.setColorFilter(colorMatrixColorFilter);
canvas.drawBitmap(bitmap, 0, 0, matrixPaint);
}
複製代碼
最終咱們會獲得一個蒙了灰的圖片: ui
固然咱們也能夠先設置畫筆的顏色,而後給它設置一個顏色矩陣,這樣最後花上去的圖形的就是就是等於畫筆顏色和矩陣一塊兒計算的結果。LightingColorFilter
用來模擬光照的效果,它定義了兩個參數來和原color
相乘,第一個colorMultiply
原來相乘,而第二個參數colorAdd
用來相加,而且會忽略其中的Aplha
參數,這個32
位的表示0xAARRGGBB
,計算的公式爲:this
R' = R * colorMultiply.R + colorAdd.R G' = G * colorMultiply.G + colorAdd.G
B' = B * colorMultiply.B + colorAdd.B 複製代碼
須要注意的是這個倍數爲整形,也就是咱們只能增大,不能減少。spa
private void drawLightingColorFilter(Canvas canvas) {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
//1.構建一個LightingColorFilter
LightingColorFilter lightingColorFilter = new LightingColorFilter(3, 0);
Paint matrixPaint = new Paint();
//2.設置給畫筆
matrixPaint.setColorFilter(lightingColorFilter);
//3.繪製
canvas.drawBitmap(bitmap, 0, 0, matrixPaint);
}
複製代碼
最終會獲得下面的結果: code
能夠看到,對於本來RGB
爲
0
的像素點,它不會作任何改變,它只會改變那些本來有顏色的像素點。
PorterDuffColorFilter
混合模式,其構造函數爲PorterDuffColorFilter(int dstColor, PorterDuff.Mode mode)
,其中color
爲16
進制的終點顏色,mode
爲混合策略,它會根據起點顏色Sc
,起點透明度Sa
,終點顏色Dc
和終點透明度Da
最終計算得出要顯示的RGBA
。
* A color filter that can be used to tint the source pixels using a single
* color and a specific {@link PorterDuff Porter-Duff composite mode}.
複製代碼
其中mode
爲PorterDuff.Mode
,其對應的模式和計算公式以下:
public enum Mode {
/** [0, 0] */
CLEAR (0),
/** [Sa, Sc] */
SRC (1),
/** [Da, Dc] */
DST (2),
/** [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] */
SRC_OVER (3),
/** [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] */
DST_OVER (4),
/** [Sa * Da, Sc * Da] */
SRC_IN (5),
/** [Sa * Da, Sa * Dc] */
DST_IN (6),
/** [Sa * (1 - Da), Sc * (1 - Da)] */
SRC_OUT (7),
/** [Da * (1 - Sa), Dc * (1 - Sa)] */
DST_OUT (8),
/** [Da, Sc * Da + (1 - Sa) * Dc] */
SRC_ATOP (9),
/** [Sa, Sa * Dc + Sc * (1 - Da)] */
DST_ATOP (10),
/** [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] */
XOR (11),
/** [Sa + Da - Sa*Da,
Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */
DARKEN (16),
/** [Sa + Da - Sa*Da,
Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */
LIGHTEN (17),
/** [Sa * Da, Sc * Dc] */
MULTIPLY (13),
/** [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */
SCREEN (14),
/** Saturate(S + D) */
ADD (12),
OVERLAY (15);
Mode(int nativeInt) {
this.nativeInt = nativeInt;
}
/**
* @hide
*/
public final int nativeInt;
}
複製代碼
其中,Sa
表示起點的Alpha
值,而Sc
表示起點的color
值,對於Dx
也是同理,最終會獲得[Ra, Rc]
,這樣組成以後就是終點對應像素點的顏色。
private void drawPorterDuffColorFilter(Canvas canvas) {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
Paint paint = new Paint();
paint.setColorFilter(new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.DARKEN));
canvas.drawBitmap(bitmap, 0, 0, paint);
}
複製代碼
最終會獲得下面的結果:
後面咱們會發現PorterDuff.Mode
中定義的這些
Mode
不單單用於顏色合成,還用於圖像合成。