setLayerType(View.LAYER_TYPE_SOFTWARE, null);
//新建图层
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
//核心绘制代码
...
//还原图层
canvas.restoreToCount(layerId);
//opColor:一个十六进制的AARRGGBB形式的颜色值
//tolerance:表示容差
//mode:取值为Mode.TARGET(表示将指定的颜色替换掉)和Mode.AVOID(表示将Mode.TARGET的相反区域颜色替换掉)
public AvoidXfermode(int opColor, int tolerance, Mode mode);
容差概念:
AvoidXfermode原理:
//mode:表示混合模式,枚举值有18个,表示各种混合模式,每种模式对应一种算法
public PorterXfermode(PorterDuff.Mode mode);
Enum Values | 算法 |
---|---|
ADD | Saturate(S + D) |
CLEAR | [0, 0] |
DARKEN | [Sa + Da - Sa * Da, Sc * (1-Da) + Dc * (1-Sa) + min(Sc, Dc)] |
DST | [Da, Dc] |
DST_ATOP | [Sa, Sa* Dc+ Sc * (1-Da)] |
DST_IN | [Sa * Da, Sa * Dc] |
DST_OUT | [Da * (1-Sa), Dc*(1-Sa)] |
DST_OVER | [Sa+(1-Sa)* Da, Rc = Dc + (1-Sa) + max(Sc, Dc)] |
LIGHTEN | [Sa + Da - Sa* Da, Sc * (1-Da)+Dc*(1-Sa) + max(Sc, Da)] |
MULTIPLY | [Sa * Da, Sc * Dc] |
OVERLAY | |
SCREEN | [Sa + Da - Sa* Da, Sc + Dc - Sc * Dc] |
SRC | [Sa, Sc] |
SRC_ATOP | [Da, Sc* Da + (1-Sa)* Dc] |
SRC_IN | [Sa * Da, Sc* Da] |
SRC_OUT | [Sa * (1-Da),Sc*(1-Da)] |
SRC_OVER | [Sa+(1-Sa)* Da, Rc=Sc+(1-Sa)* Dc] |
XOR | [Sa+Da-2* Sa * Da, Sc*(1-Da) + (1-Sa)* Dc] |
参数 | 说明 |
---|---|
Sa | Source alpha 表示源图像的Alpha通道 |
Sc | Source color 表示源图像的颜色 |
Da | Destination alpha 表示目标图像的Alpha通道 |
Dc | Destination color 表示目标图像的颜色 |
[1,2] | 1表示计算后的Alpha通道,2代表计算后的颜色值 |
DST:目标图像
SRC:源图像
eg: SRC_IN模式
public PorterDuffXfermodeView(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(LAYER_TYPE_SOFTWARE, null);
dstBmp = makeDst(width, height);
srcBmp = makeSrc(width, height);
paint = new Paint();
}
private Bitmap makeDst(int w, int h){
Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bm);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
//画一张空白的图片,然后再图片上画一个黄色的圆形,中间有一个圆形的位图,除圆形以外其他都是空白像素
p.setColor(0xFFFFCC44);
canvas.drawOval(new RectF(0, 0, w, h), p);
return bm;
}
private Bitmap makeSrc(int w, int h){
Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bm);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(0xFF66AAFF);
canvas.drawRect(0, 0, w,h, p);
return bm;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int layId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
canvas.drawBitmap(dstBmp, 0, 0, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(srcBmp, width/2, height/2, paint);
paint.setXfermode(null);
canvas.restoreToCount(layId);
}
首先我们绘制的黄色圆形时目标图像, 蓝色圆形时源图像,对于模式SRC_IN [Sa * Da, Sc * Da]来说,当目标图像为看空白像素时,计算结果为空白像素(因为Da=0),当目标图像不透明,相交部分显示源图像像素。
1.饱和度相加:
Mode.ADD
//ADD模式:对src和dst两张土拍你相交区域的饱和度进行相加
Saturate(S + D)
2.变亮模式:
Mode.LIGHTEN
//一般用于灯光效果
[Sa + Da - Sa * Da, Sc*(1-Da)+Dc*(1-Sa)+max(Sc,Dc)]
3.变暗模式:
Mode.DARKEN
[Sa + Da - Sa * Da, Sc*(1-Da)+Dc*(1-Sa)+min(Sc,Dc)]
4.正片叠底:
Mode.MULTIPLY
[Sa * Da, Sc * Dc]
5.叠加模式:
Mode.OVERLAY
Google并未给出相应的算法
6.滤色模式:
Mode.SCREEN
[Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]