文章目录

      • 1.PorterDuffXfermode 简介
      • 2.PorterDuffXfermode 类型介绍
      • 3.PorterDuffXfermode 使用场景
            • 圆形头像
            • 叠加图片还可以实现橡皮擦和加载效果等
      • 4.PorterDuffXfermode 在Drawable中的应用

1.PorterDuffXfermode 简介

在《Android 图片裁剪之三剑式(一)》中讲述了图片裁剪的2种方式(clipPath/bitmaShader),本文探索最后一式裁剪:PorterDuffXfermode 。
PorterDuffXfermode 是画布绘制的合成模式,也就是两张图像混合后的显示模式,与setColorFilter很相似,我们可以使用它画出各种神奇的效果。

2.PorterDuffXfermode 类型介绍

API中为我们提供了18中模式:

  • Mode.CLEAR 清除图像
  • Mode.SRC 只显示源图像(上层图片)
  • Mode.DST 只显示目标图像(下层图片)
  • Mode.SRC_IN 只在源图像和目标图像相交的地方绘制【源图像】
  • Mode.DST_IN 只在源图像和目标图像相交的地方绘制【目标图像】
  • Mode.SRC_OUT 只在源图像和目标图像不相交的地方绘制【源图像】
  • Mode.DST_OUT 只在源图像和目标图像不相交的地方绘制【目标图像】
  • Mode.SRC_ATOP 在源图像和目标图像相交的地方绘制【源图像】,在不相交的地方绘制【目标图像】
  • Mode.DST_ATOP 在源图像和目标图像相交的地方绘制【目标图像】,在不相交的地方绘制【源图像】
  • Mode.SRC_OVER 将源图像放在目标图像上方
  • Mode.DST_OVER 将目标图像放在源图像上方
  • Mode.XOR 在源图像和目标图像相交的地方之外绘制它们
  • Mode.DARKEN 变暗,较深的颜色覆盖较浅的颜色,若两者深浅程度相同则混合
  • Mode.LIGHTEN 变亮,与DARKEN相反
  • Mode.OVERLAY 叠加
  • Mode.SCREEN 滤色,色调均和,保留两个图层中较白的部分,较暗的部分被遮盖
  • Mode.MULTIPLY 正片叠底,源图像素颜色值乘以目标图像素颜色值除以255得到混合后图像像素颜色值
  • Mode.ADD 饱和相加,对图像饱和度进行相加
    网上效果图:

    我测试了常见的几种:

3.PorterDuffXfermode 使用场景

圆形头像

主要采用了SRC_IN模式来实现,图标图片是圆形bitmap,源头像是具体图片,先看效果:

主要代码:

class XfermodeImage(context: Context?, attrs: AttributeSet?) : View(context, attrs), Runnable {    private var mPaint = Paint()    private var bitmap = BitmapFactory.decodeResource(resources, com.anan.testkotlin.R.mipmap.ic_launcher)    private var innerRadius = 0    private var halfHeight = height / 2    private var mHandler = android.os.Handler()    private var xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)    init {        mPaint.isAntiAlias = true        mPaint.style = Paint.Style.FILL        //设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰        mPaint.isDither = true        //加快显示速度,本设置项依赖于dither和xfermode的设置        mPaint.isFilterBitmap = true    }    /**     * 设置图片     */    fun setImageResource(drawable: Int) {        bitmap = BitmapFactory.decodeResource(resources, drawable)        invalidate()    }    override fun onDraw(canvas: Canvas?) {        super.onDraw(canvas)        /**         * 设置View的离屏缓冲。在绘图的时候新建一个“层”,所有的操作都在该层而不会影响该层以外的图像         * 必须设置,否则设置的PorterDuffXfermode会无效         */        val sc = canvas!!.saveLayer(0f, 0f, width.toFloat(), height.toFloat(), mPaint, Canvas.ALL_SAVE_FLAG)        halfHeight = height / 2        // 先画目标图,再画原图        if (bitmap != null) {                        if (innerRadius > 0 && innerRadius < halfHeight) {                canvas?.drawBitmap(getCircleBitmap(innerRadius), 0f, 0f, mPaint)                mPaint.xfermode = xfermode            }            canvas?.drawBitmap(bitmap, 0f, 0f, mPaint)            mPaint.xfermode = null        }        /**         * 还原画布,与canvas.saveLayer配套使用         */        canvas.restoreToCount(sc)    }    private fun getCircleBitmap(radius: Int): Bitmap {        val bm = Bitmap.createBitmap(height, height, Bitmap.Config.ARGB_8888)        val c = Canvas(bm)        val p = Paint(Paint.ANTI_ALIAS_FLAG)        p.color = Color.WHITE        c.drawCircle(halfHeight.toFloat(), halfHeight.toFloat(), radius.toFloat(), p)        return bm    }    /**     * 开启动画     */    fun startScaleAnim(drawable: Int) {        bitmap = BitmapFactory.decodeResource(resources, drawable)        innerRadius = height / 10        invalidate()        mHandler.postDelayed(this, 100)    }    override fun run() {        if (innerRadius < halfHeight) run {            innerRadius = innerRadius + height / 10            postInvalidate()            handler.postDelayed(this, 100)        } else {            innerRadius = halfHeight            postInvalidate()        }    }}
叠加图片还可以实现橡皮擦和加载效果等

这里实现就不具体叙述了

4.PorterDuffXfermode 在Drawable中的应用

主要是setColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode)方法,该方法给图片添加一个颜色图层,实现混合效果。
如:图片变暗

BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), coverImageBitmap); //进行对应像素的比较,取较暗值,如果色值相同则进行混合bitmapDrawable.mutate().setColorFilter(ContextCompat.getColor(mContext, R.color.me_forground), PorterDuff.Mode.DARKEN); iv_head_bg.setBackground(bitmapDrawable);

更多相关文章

  1. Android(安卓)中的图形图像的渲染
  2. Android(安卓)Drawable的那些事儿
  3. Android(安卓)绘图机制:canvas初解
  4. Android仿人人客户端(v5.7.1)——网络模块时序图
  5. Android视图绘画与属性动画
  6. Android(安卓)动画框架(一)转
  7. android之monkeyrunner截图及图像对比
  8. Android投票自定义View
  9. Android(安卓)硬件加速的优缺点

随机推荐

  1. Android一直震动源码
  2. Android(安卓)休眠与唤醒
  3. Android(安卓)boot process stub
  4. Google Android's Gingerbread Update Co
  5. setting proxy for Android(安卓)SDK Man
  6. Android采用SAX解析XML文档
  7. Android(安卓)actrivityrealut
  8. Android(安卓)Studio编译失败问题(aapt2)
  9. android 程序漰溃 后台handle处理类
  10. android:parentActivityName