文章目录
1 简介
在自定义控件或者对图片进行特殊处理的时候,常常需要使用到图像混合操作,这就需要 Xfermode
,实现 Xfermode
的子类主要有三个类 :
AvoidXfermode
PixelXorXfermode
PorterDufferXfermode
其中 PixelXorXfermode
在 API 16 中已经过时了,基本用不到。AvoidXfermode
在 API 16 也已经过时了,但是没有合适的替换类,由于它不支持硬件加速,所以使用的时候要禁用硬件加速,不过奇怪的是高版本 SDK 已经没有这个类,没找到这个类。这篇文章主要介绍 PorterDuffXfermode
的使用。
2 使用
我们先来看 PorterDuffXfermode
的构造函数
public PorterDuffXfermode(PorterDuff.Mode mode)
它只有一个参数,表示混合模式,它是一个枚举类,一共有 18 种,每一种对应着一种算法。
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 * (1 - Da), Sc * (1 - Da)]
DST_IN (6),
// [Da * (1 - Sa), Dc * (1 - Sa)]
SRC_OUT (7),
// [Da, Sc * Da + (1 - Sa) * Dc]
DST_OUT (8),
// [Da, Sc * Da + (1 - Sa) * Dc]
SRC_ATOP (9),
// [Sa, Sa * Dc + Sc * (1 - Da)]
DST_ATOP (10),
//[Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)]
XOR (11),
// Saturate(S + D)
ADD (12),
// [Sa * Da, Sc * Dc]
MULTIPLY (13),
// [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]
SCREEN (14),
OVERLAY (15);
// [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),
Mode(int nativeInt) {
this.nativeInt = nativeInt;
}
public final int nativeInt;
}
其中:
Sa
:全称Source alpha
,表示源图像的Alpha
通道;Sc
:全称Source color
,表示源图像的颜色;Da
:全称Destination alpha
,表示目标图像的Alpha
通道;Dc
:全称Destination color
,表示目标图像的颜色;
2.1 颜色叠加的模式
源图像
目标图像
示例代码
public class PorterDuffXfermodeDemoView extends View {
private Paint mPaint;
private Bitmap mBitmapDst;
private Bitmap mBitmapSrc;
public PorterDuffXfermodeDemoView(Context context) {
this(context, null);
}
public PorterDuffXfermodeDemoView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public PorterDuffXfermodeDemoView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBitmapSrc = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_star);
mBitmapDst = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_news);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(100,100);
canvas.drawColor(Color.WHITE);
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
canvas.drawBitmap(mBitmapDst,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR ));
canvas.drawBitmap(mBitmapSrc,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
}
序号 | Mode | 效果 | 简介 |
---|---|---|---|
0 | 不设置Xfermode | ![]() | |
1 | ADD(饱和度相加) | ![]() | 重合区域饱和度相加 |
2 | LIGHTEN(变亮) | ![]() | 重合区域变亮 |
3 | DARKEN(变暗) | ![]() | 重合区域变暗 |
4 | MULTIPLY(正片叠底) | ![]() | 源图像素颜色值乘以目标图像素颜色值除以255即得混合后图像像素的颜色值,黑色与任何颜色混合都会得黑色 |
5 | OVERLAY(叠加) | ![]() | 叠加,源色与目标色混合产生一种中间色 |
6 | SCREEN(滤色) | ![]() | 滤色,产生色彩均和效果 |
7 | SRC | ![]() | 只显示源图像 |
8 | SRC_IN | ![]() | 重合区域绘制源图像,目标图像有空白像素,所对应的绘制区域也是空白像素 |
9 | SRC_OUT | ![]() | 不重合区域绘制源图像 |
10 | SRC_OVER | ![]() | 目标图像顶部绘制源图像 |
11 | SRC_ATOP | ![]() | 重合区域绘制源图像,不重合区域绘制目标图像 |
12 | DST | ![]() | 只绘制目标图像 |
13 | DST_IN | ![]() | 重合区域绘制目标图像 |
14 | DST_OUT | ![]() | 不重合区域绘制目标图像 |
15 | DST_OVER | ![]() | 源图像上方绘制目标图像 |
16 | DST_ATOP | ![]() | 重合区域绘制目标图像,不重合区域绘制源图像 |
17 | CLEAR | ![]() | 清除 |
18 | XOR | ![]() | 不重合区域绘制,重合区域不绘制 |
3 总结
- 目标图像和源图像混合,需要生成颜色叠加效果,使用颜色叠加模式,上表的(1-6);
- 不需要叠加效果,只需要根据某种图片透明度像素来裁剪时,需要使用
SRC
或者DST
模式。 - 清空图像,使用
CLEAR
模式