Android 图形混合模式PorterDuffXfermode模式介绍

一、PorterDuffXfermode模式介绍

PorterDuffXfermode是设置两个图层的交集区域的显示方式,

分为目标图像(先画的图片)和源图像(后画的图片),图解如下:

简单说目标图像是底片,源图像是封面


先看一下官方的样图


两个图形一圆一方通过设置不同的模式会产生不同的组合效果,

在API中Android为我们提供了18种(比上图多了两种ADD和OVERLAY)模式: 

  • ADD:                饱和相加,对图像饱和度进行相加,不常用
  • CLEAR:             清除图像
  • DARKEN:          变暗,较深的颜色覆盖较浅的颜色,若两者深浅程度相同则混合
  • DST:                只显示目标图像
  • DST_ATOP:      在源图像和目标图像,相交的地方绘制【目标图像】,  不相交的地方绘制【源图像】,相交处的效果受到源图像和目标图像alpha的影响
  • DST_IN:           只在源图像和目标图像相交的地方绘制【目标图像】,绘制效果受到源图像对应地方透明度影响
  • DST_OUT:        只在源图像和目标图像不相交的地方绘制【目标图像】,在相交的地方根据源图像的alpha进行过滤,源图像完全不透明则完全过滤,完全透明则不过滤
  • DST_OVER:        将目标图像放在源图像上方
  • LIGHTEN:           变亮,与DARKEN相反,DARKEN和LIGHTEN生成的图像结果与Android对颜色值深浅的定义有关
  • MULTIPLY:        正片叠底,源图像素颜色值乘以目标图像素颜色值除以255得到混合后图像像素颜色值
  • OVERLAY:        叠加
  • SCREEN:         滤色,色调均和,保留两个图层中较白的部分,较暗的部分被遮盖
  • SRC:                只显示源图像
  • SRC_ATOP:        在源图像和目标图像相交的地方绘制【源图像】,在不相交的地方绘制【目标图像】,相交处的效果受到源图像和目标图像alpha的影响
  • SRC_IN:        只在源图像和目标图像相交的地方绘制【源图像】
  • SRC_OUT:    只在源图像和目标图像不相交的地方绘制【源图像】,相交的地方根据目标图像的对应地方的alpha进行过滤,目标图像完全不透明则完全过滤,完全透明则不过滤
  • SRC_OVER:    将源图像放在目标图像上方
  • XOR:            在源图像和目标图像相交的地方之外绘制它们,在相交的地方受到对应alpha和色值影响,如果完全不透明则相交处完全不绘制

二、PorterDuffXfermode 举例

举一个刮刮卡的例子

思路分析:

        //刮刮卡效果,分为上面遮罩和下面图片的方向

        //将手绘路径绘制到覆盖层,设置手绘路径和覆盖层为DST_IN模式

        //DST_IN:只在源图像和目标图像相交的地方绘制【目标图像】

        //这样遮罩和手触摸的位置便只显示相交的目标图像-遮罩,

        //再设置画笔为透明,次时由于透明度的影响,遮罩变为透明,于是被擦除了

1.画笔,图片的初始化

//PorterDuffXfermode 设置两个图层的交集区域的显示方式,dst是先画的图形,src是后画的图形
private void my_PorterDuffXfermode(){
    //刮刮卡效果,分为上面遮罩和下面图片的方向
    //将手绘路径绘制到覆盖层,设置手绘路径和覆盖层为DST_IN模式
    //DST_IN:只在源图像和目标图像相交的地方绘制【目标图像】
    //这样遮罩和手触摸的位置便只显示相交的目标图像-遮罩,
    //再设置画笔为透明,次时由于透明度的影响,遮罩变为透明,于是被擦除了

    //设置画笔
    paint = new Paint();
    paint.setStyle(Paint.Style.STROKE);
    paint.setAlpha(0);
    PorterDuffXfermode porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
    paint.setXfermode(porterDuffXfermode);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(50);
    paint.setStrokeJoin(Paint.Join.ROUND);      //设置连接样式
    paint.setStrokeCap(Paint.Cap.ROUND);        //设置画笔的线帽样式

    //目标图像
    bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.head);
    //源图像 位图大小`
    fgBitmap = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(),Bitmap.Config.ARGB_8888);
    //源图像 画一个灰色的遮罩
    mCanvas = new Canvas(fgBitmap);
    mCanvas.drawColor(Color.GRAY);
}

此时我们便有了刮刮卡的材料了

下面生成刮刮卡

2.绘制刮刮卡

在onDraw方法里先画底片,再画封面

canvas.drawBitmap(bitmap,0,0,null);     //画目标图像底片
canvas.drawBitmap(fgBitmap,0,0,null);   //画遮罩

此时我们便有刮刮卡了

下面再设置刮刮卡的擦除效果

2.触摸事件

添加onTouchEvent方法,响应触摸事件

通过path记录触摸路径

之后通过透明画笔绘制路径

绘制后通过invalidate();调用onDraw方法,重新绘制界面

@Override
public boolean onTouchEvent(MotionEvent event) {

    //用path保留画过的路径
    switch (event.getAction()){
        case MotionEvent.ACTION_DOWN:
            path.reset();
            path.moveTo(event.getX(),event.getY());
            break;
        case MotionEvent.ACTION_MOVE:
            path.lineTo(event.getX(),event.getY());
            break;
    }
    //通过透明画笔,绘制路径
    mCanvas.drawPath(path,paint);
    //触发onDraw事件
    invalidate();
    return true;
}

路径可以通过贝塞尔曲线绘制,会更真实

4.效果展示




阅读更多
版权声明:有需要的请联系QQ1634475153,欢迎技术交流 https://blog.csdn.net/jinmie0193/article/details/80815868
个人分类: android 进阶
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭