混合模式之PorterDuffXfermode

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在这里插入图片描述
1ADD(饱和度相加)在这里插入图片描述重合区域饱和度相加
2LIGHTEN(变亮)在这里插入图片描述重合区域变亮
3DARKEN(变暗)在这里插入图片描述重合区域变暗
4MULTIPLY(正片叠底)在这里插入图片描述源图像素颜色值乘以目标图像素颜色值除以255即得混合后图像像素的颜色值,黑色与任何颜色混合都会得黑色
5OVERLAY(叠加)在这里插入图片描述叠加,源色与目标色混合产生一种中间色
6SCREEN(滤色)在这里插入图片描述滤色,产生色彩均和效果
7SRC在这里插入图片描述只显示源图像
8SRC_IN在这里插入图片描述重合区域绘制源图像,目标图像有空白像素,所对应的绘制区域也是空白像素
9SRC_OUT在这里插入图片描述不重合区域绘制源图像
10SRC_OVER在这里插入图片描述目标图像顶部绘制源图像
11SRC_ATOP在这里插入图片描述重合区域绘制源图像,不重合区域绘制目标图像
12DST在这里插入图片描述只绘制目标图像
13DST_IN在这里插入图片描述重合区域绘制目标图像
14DST_OUT在这里插入图片描述不重合区域绘制目标图像
15DST_OVER在这里插入图片描述源图像上方绘制目标图像
16DST_ATOP在这里插入图片描述重合区域绘制目标图像,不重合区域绘制源图像
17CLEAR在这里插入图片描述清除
18XOR在这里插入图片描述不重合区域绘制,重合区域不绘制

3 总结

  • 目标图像和源图像混合,需要生成颜色叠加效果,使用颜色叠加模式,上表的(1-6);
  • 不需要叠加效果,只需要根据某种图片透明度像素来裁剪时,需要使用 SRC 或者 DST 模式。
  • 清空图像,使用 CLEAR 模式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值