Android(安卓)图片裁剪之三剑式(二)
16lz
2022-06-10
文章目录
- 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);
更多相关文章
- Android(安卓)中的图形图像的渲染
- Android(安卓)Drawable的那些事儿
- Android(安卓)绘图机制:canvas初解
- Android仿人人客户端(v5.7.1)——网络模块时序图
- Android视图绘画与属性动画
- Android(安卓)动画框架(一)转
- android之monkeyrunner截图及图像对比
- Android投票自定义View
- Android(安卓)硬件加速的优缺点