您的位置:首页 > Web前端

(转载)Xfermodes的扩展应用- 图像擦除和还原效果

2012-09-13 01:59 267 查看
最近在学习Android图形API,看到sdk中demo里的Xfermodes实例,于是结合之前学的做了一个简单的图像擦除和还原的效果,感觉比较好玩,分享下作为TestRoid第一篇^^。

Sdk中自带的例子如图所示,

是几种不同的Xfermodes效果,这些效果很显而易见,无非是一个黄色圆(Dst)和蓝色矩形(Src)的显示。比如SrcOver就是蓝色矩形显示在黄色圆前面; SrcIn就是两个图形交集显示为Src也就是蓝色矩形的那部分。我主要是用里面的Xor效果来实现这里的例子,PorterDuff.Mode.XOR,即两块非透明区域重叠部分显示为透明。

如果单是做图像擦除的效果也就用不到这个东西咯,所以嘛,重点是在还原的效果。因此这个例子的思路是,建立一块与原图大小相同的mask bitmap,然后在这块mask上进行操作,这样就不会影响原图,这里我用了触摸画线的例子在mask上画点东西,然后通过Xermodes中的XOR模式与原图进行合成,得到我们想要看到的效果。是不是有点Photoshop的味道啦,hoho。

原理图在这,随手画的,呵呵

废话不多说直接上效果图(OK,这个是用模拟器截得,有点卡=.=):

下面是一些代码片段:

初始化mask

[java] view plaincopy

private void initBmpMask()

{

if(mImgDesRect != null)

{

int w = (int) mImgDesRect.width();

int h = (int) mImgDesRect.height();

if(mEraseMaskBitmap == null)

{

mEraseMaskBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); //初始化一块和显示图片大小相同的bitmap

mEraseMaskBitmap.eraseColor(Color.TRANSPARENT);//设置为透明

}

}

if(mEraseMaskBitmap != null)

mCanvas = new Canvas(mEraseMaskBitmap); //得到要操作的mask

}

初始化画笔样式等:

[java] view plaincopy

private void initErasePaint(){

mErasePaint = new Paint();

mErasePaint.setAntiAlias(true);

mErasePaint.setDither(true);

mErasePaint.setColor(0xFF000000);

mErasePaint.setStyle(Paint.Style.STROKE);

mErasePaint.setStrokeJoin(Paint.Join.ROUND);

mErasePaint.setStrokeCap(Paint.Cap.ROUND);

mErasePaint.setStrokeWidth(20);

}

响应触屏消息在mask上画图:

[c-sharp] view plaincopy

public boolean onTouchEvent(MotionEvent event) {

int action = event.getAction();

float x = event.getX() - mImgDesRect.left;

float y = event.getY() - mImgDesRect.top;

switch (action) {

case MotionEvent.ACTION_DOWN:

mErasePath.reset();

mErasePath.moveTo(x, y);

mX = x;

mY = y;

invalidate();

break;

case MotionEvent.ACTION_MOVE:

float dx = Math.abs(x - mX);

float dy = Math.abs(y - mY);

if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {

mErasePath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);

mX = x;

mY = y;

// commit the path to offscreen

mCanvas.drawPath(mErasePath, mErasePaint);

}

invalidate(); //refresh

break;

case MotionEvent.ACTION_UP:

mErasePath.lineTo(mX, mY);

mCanvas.drawPath(mErasePath, mErasePaint);

mErasePath.reset();

invalidate();

break;

}

return true;

}

切换擦除(erase)和还原(unerase)功能,只要改变Paint的Xfermode:

[java] view plaincopy

public void switchEraseMode(boolean bErase){

if(mErasePaint == null)

initErasePaint();

if(bErase)

mErasePaint.setXfermode(null);

else

mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));//清除样式

}

在OnDraw中,把原图和mask通过XOR样式画到canvas上,就可以看到擦除的效果啦:

[java] view plaincopy

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

if(mImgBitmap != null)

{

Paint paint = new Paint();

int sc = canvas.saveLayer(mImgDesRect.left, mImgDesRect.top, mImgDesRect.right, mImgDesRect.bottom, null,

Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG

| Canvas.HAS_ALPHA_LAYER_SAVE_FLAG

| Canvas.FULL_COLOR_LAYER_SAVE_FLAG

| Canvas.CLIP_TO_LAYER_SAVE_FLAG);

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));

canvas.drawBitmap(mImgBitmap, new Rect(0, 0, mImgBitmap.getWidth(), mImgBitmap.getHeight()), mImgDesRect, null);

canvas.drawBitmap(mEraseMaskBitmap, new Rect(0, 0, mEraseMaskBitmap.getWidth(), mEraseMaskBitmap.getHeight()), mImgDesRect, paint);

paint.setXfermode(null);

canvas.restoreToCount(sc);

}

}

好了,显示上擦除和“反擦”效果就完成了。

例程上传了,可以这里下载:http://download.csdn.net/source/3240693

里面顺便加上了把擦除效果保存下来的,/sdcard/out.png

注:为了视觉效果,例子里加上了一张背景图,让擦除后透明效果明显点。不过保存时这背景图是不会和原图一起保存的。(太懒了。。。)

例子是边学边做的,比较粗糙,欢迎交流,Thx~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: