逐一认识PorterDuff.Mode

setXfermode(Xfermode xfermode)

Xfermode被称为过渡模式,我们也可以称之为图像混合模式。Xfermode有三个实现类:AvoidXfermode, PixelXorXfermode以及PorterDuffXfermode。前两个类因为不支持硬件加速在API level 16被标记为Deprecated了,用也可以,但是需要关闭硬件加速.在最新的API中,只能看到PorterDuffXfermode这个子类。

在自定义View时,当一个Xfermode被分配给Paint,那么使用该Paint时,就使用了该模式。

/**
 * 设置或者清除过渡模式
 * xfermode 可以设置为Null,用于清除之前设置的Xfermode
 */
public Xfermode setXfermode(Xfermode xfermode) {
    int newMode = xfermode != null ? xfermode.porterDuffMode : Xfermode.DEFAULT;
    int curMode = mXfermode != null ? mXfermode.porterDuffMode : Xfermode.DEFAULT;
    if (newMode != curMode) {
        nSetXfermode(mNativePaint, newMode);
    }
    mXfermode = xfermode;
    return xfermode;
}

PorterDuffXfermode

PorterDuffXfermode用于图形合成时的图像过渡模式计算,它的概念来自于1984年在ACM SIGGRAPH计算机图形学出版物上发表了“Compositing digital images(合成数字图像)”的Tomas Porter和Tom Duff,有兴趣的可以查阅下。在其构造方法里只有一个参数 PorterDuff.Mode,由它来指定图形合成时颜色值的计算方式。

public PorterDuffXfermode(PorterDuff.Mode mode) {
    porterDuffMode = mode.nativeInt;
}

这种图像混合模式,实现也是十分简单。

Paint paint = new Paint();
canvas.drawBitmap(destinationImage, 0, 0, paint);

PorterDuff.Mode mode = // choose a mode
paint.setXfermode(new PorterDuffXfermode(mode));

canvas.drawBitmap(sourceImage, 0, 0, paint);

PorterDuff.Mode

PorterDuff.Mode又分为Alpha合成模式和混合模式。图像合成就是将源像素和背景像素的颜色进行混合,最终显示的颜色取决于其RGB颜色分量和Alpha值。以PorterDuff.Mode.SRC_IN为例:

public enum Mode {

    ***

    /** 
      * Aout = Asrc × (1 - Adst)
      * Cout = Csrc + (1 - Asrc) × Cdst
      */
    SRC_IN      (5),



    Mode(int nativeInt) {
        this.nativeInt = nativeInt;
    }

    /**
     * @hide
     */
    public final int nativeInt;
}

在上述代码中,解释了该模式下Alpha和颜色值的计算方式。其中:

  • Aout:合成后图片的Alpha通道
  • Cout:合成后的RGB颜色分量
  • Asrc:源图片的Alpha通道
  • Csrc:源图片的RGB颜色分量
  • Adst:目标图片的Alpha通道
  • Cdst:目标图片的RGB颜色分量

这也就是说,在SRC_IN模式中,Asrc × (1 - Adst) 计算的值是合成后的Alpha通道,而Csrc + (1 - Asrc) × Cdst计算的值是合成后的RGB颜色分量,合成后的图片以得到的这个ARGB来显示。

为了方便验证这些效果,自定义了一个View:

class XfermodeView : View {

    lateinit var mPaint: Paint
    // 源图
    lateinit var mSource: Bitmap
    // 目标图
    lateinit var mDst: Bitmap
    // 过渡模式
    var mXfermode: Xfermode? = null

    ***

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)

        /*
         * 将绘制操作保存到新的图层(更官方的说法应该是离屏缓存)
         */
        val sc = canvas?.saveLayer(0f, 0f, width.toFloat(), height.toFloat(), null, Canvas.ALL_SAVE_FLAG)

        // 先绘制dis目标图
        canvas?.drawBitmap(mDst, 0f, 0f, mPaint)

      
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值