文章目录

      • 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 饱和相加,对图像饱和度进行相加
    网上效果图:
    Android 图片裁剪之三剑式(二)_第1张图片
    我测试了常见的几种:
    Android 图片裁剪之三剑式(二)_第2张图片

3.PorterDuffXfermode 使用场景

圆形头像

主要采用了SRC_IN模式来实现,图标图片是圆形bitmap,源头像是具体图片,先看效果:
Android 图片裁剪之三剑式(二)_第3张图片
主要代码:

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 选择本地图片并截剪图片保存到,sdcard指定目录中
  2. Android的Btimap处理大图片解决方法
  3. 如何实现手势缩放图片
  4. 直播软件源码Android 多个ImageView拖拽互换图片
  5. 【Android 界面效果6】Android 控件之ImageSwitcher图片切换器
  6. android图片上传
  7. Android Glide加载图片成圆形
  8. GifView控件,android显示gif图片

随机推荐

  1. EditText设置不自动弹出键盘
  2. android桌面快捷方式添加 删除 更新 自动
  3. MediaScannerReceiver
  4. 2011.07.18——— android AlphaBitmap
  5. android:gravity的值可以使用|连接多个属
  6. Android——AppWidgetProvider应用
  7. Android获取当前WiFi的MAC地址-适配所有
  8. Android 中ListView的应用
  9. Android休眠唤醒机制简介(一)
  10. Android屏幕横屏竖屏设置技巧