您的位置:首页 > Web前端

图形绘制中的PorterDuffXfermode

2015-11-13 21:51 387 查看
1、概述

在android图形渲染中 会使用到图像混合模式

<span style="font-size:18px;">setXfermode(Xfermode xfermode)</span>

Xfermode有三个子类

AvoidXfermode, PixelXorXfermode,这俩个均已经被淘汰

只剩 【PorterDuffXfermode】,这个模式是由俩个大牛Tomas Proter和Tom Duff名字来命名的,PorterDuffXfermode模式能为android图形渲染做啥呢,先来张经典图片



咋看有点晕,先解释一下

1.PorterDuff.Mode.CLEAR   :所绘制不会提交到画布上。

2.PorterDuff.Mode.SRC :  显示上层绘制图片

3.PorterDuff.Mode.DST : 显示下层绘制图片

4.PorterDuff.Mode.SRC_OVER :  正常绘制显示,上下层绘制叠盖。

5.PorterDuff.Mode.DST_OVER : 上下层都显示。下层居上显示。

6.PorterDuff.Mode.SRC_IN :  取两层绘制交集。显示上层。

7.PorterDuff.Mode.DST_IN :取两层绘制交集。显示下层。

8.PorterDuff.Mode.SRC_OUT :取上层绘制非交集部分。

9.PorterDuff.Mode.DST_OUT : 取下层绘制非交集部分。

10.PorterDuff.Mode.SRC_ATOP :取下层非交集部分与上层交集部分

11.PorterDuff.Mode.DST_ATOP : 取上层非交集部分与下层交集部分

12.PorterDuff.Mode.XOR : 异或:去除两图层交集部分

13.PorterDuff.Mode.DARKEN :取两图层全部区域,交集部分颜色加深

14.PorterDuff.Mode.LIGHTEN : 取两图层全部,点亮交集部分颜色

15.PorterDuff.Mode.MULTIPLY : 取两图层交集部分叠加后颜色

16.PorterDuff.Mode.SCREEN : 取两图层全部区域,交集部分变为透明色

后来还新增了俩种模式 ADD和OVERLAY

17.PorterDuff.Mode.ADD 饱和度叠加



18.PorterDuff.Mode.OVERLAY: 直接叠加



2、示例代码、

下面听过俩个例子来熟悉一下使用

首先来定义一个获取屏幕宽和高的工具代码

<span style="font-size:18px;">public class ScreenMeasureUtil {
//同时获取宽高
public static int[] getScreenHW(Activity activity) {
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
int Height = metrics.heightPixels;
int Width = metrics.widthPixels;
int HW[] = new int[]{Height, Width};
}

}</span>

 橡皮擦效果

自定义一个eraser的view,然后在之布局文件中引入这个控件即可 EraserView.java,注释很详细,这里使用了DST_IN模式(使用dst_out效果一样)

<span style="font-size:18px;">public class EraserView extends View {
//屏幕宽高
private int[] screenSize;
private int screenH;
private int screenW;
//PorterDuff Mode
private static final PorterDuff.Mode PD_MODE = PorterDuff.Mode.DST_IN;
private static final int MIN_MOVE_DIS = 5;//最小的移动距离:如果我们手指在屏幕上的移动距离小于此值则不会绘制
private float preTouchX, preTouchY;
//绘图
private Canvas mCanvas; //画布
private Paint mPaint;//画笔
private Path mPath;//路径
//前后背景
private Bitmap fgBitmap, bgBitmap;

public EraserView(Context context, AttributeSet attrs) {
super(context, attrs);
screenSize = ScreenMeasureUtil.getScreenHW((Activity) context);
screenH = screenSize[0];
screenW = screenSize[1];

initViews(context);

}

private void initViews(Context context) {
//实例化路径对象
mPath = new Path();

//实例化画笔开启抗锯齿和抗抖动
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
//画笔风格为描边
mPaint.setStyle(Paint.Style.STROKE);
//笔触类型为圆角
mPaint.setStrokeJoin(Paint.Join.ROUND);
//设置描边
mPaint.setStrokeCap(Paint.Cap.ROUND);
//设置描边宽度
mPaint.setStrokeWidth(20);
//设置混合模式
mPaint.setXfermode(new PorterDuffXfermode(PD_MODE));
//此处采用的是DST_IN模式必须要将画笔透明度设置为0
mPaint.setARGB(128, 255, 0, 0);

//前景图片的bitmap
fgBitmap = Bitmap.createBitmap(screenW, screenH, Bitmap.Config.ARGB_8888);
//填充进画布
mCanvas = new Canvas(fgBitmap);
//绘制画布背景颜色为灰色
mCanvas.drawColor(0xffacacac);
//获取底面背景图片
bgBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.bg_splash);
//缩放bitmap至屏幕大小
bgBitmap = Bitmap.createScaledBitmap(bgBitmap, screenW, screenH, true);
}

@Override
protected void onDraw(Canvas canvas) {
//绘制背景
canvas.drawBitmap(bgBitmap, 0, 0, null);
//绘制前景
canvas.drawBitmap(fgBitmap, 0, 0, null);
mCanvas.drawPath(mPath, mPaint);
}

@Override
public boolean onTouchEvent(MotionEvent event) {

float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPath.reset();
mPath.moveTo(x, y);
preTouchX = x;
preTouchY = y;
break;
case MotionEvent.ACTION_MOVE:
float dx = Math.abs(x - preTouchX);
float dy = Math.abs(y - preTouchY);
if (dx >= MIN_MOVE_DIS || dy >= MIN_MOVE_DIS) {
mPath.quadTo(preTouchX, preTouchY, (x + preTouchX) / 2, (y + preTouchY) / 2);
preTouchX = x;
preTouchY = y;
}
break;

}
//重绘视图
invalidate();
return true;

}
}
</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息