`
aliusa
  • 浏览: 84268 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

利用PorterDuff.Mode做橡皮擦效果

阅读更多
http://stackoverflow.com/questions/3467334/erase-bitmap-parts-using-porterduff-mode
假如我有一张背景图片,
在背景图片上覆盖绘制了一层半透明的绿色
当我们用手指涂抹屏幕的时候,手指涂抹过的地方绿色就被擦除,露出下面原先被遮挡住的背景图片
1.利用canvas的drawPath做擦除效果。
效果如下:



实现代码:
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Bitmap.Config;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;

public class Eraser_Use_drawPath extends Activity {

    private int SCREEN_W;

    private int SCREEN_H;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));

    }

    class MyView extends View {
        private Bitmap mBitmap;
        private Canvas mCanvas;
        private Paint mPaint;
        private Path  mPath;
        private float mX, mY;
        private static final float TOUCH_TOLERANCE = 4;
        
        public MyView(Context context) {
            super(context);
            setFocusable(true);
            setScreenWH();
            setBackGround();
            
            // 1.if cover is a image,you can open MENU_ITEM_COMMENT bellow
            //Bitmap bm = createBitmapFromSRC();
            // if you want to set cover image's alpha,you can open MENU_ITEM_COMMENT bellow
            //bm = setBitmapAlpha(bm, 100);
            // if you want to scale cover image,you can open MENU_ITEM_COMMENT bellow
            //bm = scaleBitmapFillScreen(bm);

            // 2.if cover is color
            Bitmap bm = createBitmapFromARGB(0x8800ff00, SCREEN_W, SCREEN_H);
            setCoverBitmap(bm);

        }

        private void setScreenWH() {
            // get screen info
            DisplayMetrics dm = new DisplayMetrics();
            dm = this.getResources().getDisplayMetrics();
            // get screen width
            int screenWidth = dm.widthPixels;
            // get screen height
            int screenHeight = dm.heightPixels;

            SCREEN_W = screenWidth;
            SCREEN_H = screenHeight;
        }

        private Bitmap createBitmapFromSRC() {
            return BitmapFactory.decodeResource(getResources(),
                                                R.drawable.cover);
        }

        /**
         * 
         * @param colorARGB should like 0x8800ff00
         * @param width
         * @param height
         * @return
         */
        private Bitmap createBitmapFromARGB(int colorARGB, int width, int height) {
            int[] argb = new int[width * height];

            for (int i = 0; i < argb.length; i++) {

                argb[i] = colorARGB;

            }
            return Bitmap.createBitmap(argb, width, height, Config.ARGB_8888);
        }

        /**
         * 
         * @param bm
         * @param alpha ,and alpha should be like ox00000000-oxff000000
         * @note set bitmap's alpha
         * @return
         */
       /* private Bitmap setBitmapAlpha(Bitmap bm, int alpha) {
            int[] argb = new int[bm.getWidth() * bm.getHeight()];
            bm.getPixels(argb, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm
                    .getHeight());


            for (int i = 0; i < argb.length; i++) {

                argb[i] = ((alpha) | (argb[i] & 0x00FFFFFF));
            }
            return Bitmap.createBitmap(argb, bm.getWidth(), bm.getHeight(),
                                       Config.ARGB_8888);
        }*/
        
        /**
         * 
         * @param bm
         * @param alpha ,alpha should be between 0 and 255
         * @note set bitmap's alpha
         * @return
         */
        private Bitmap setBitmapAlpha(Bitmap bm, int alpha) {
            int[] argb = new int[bm.getWidth() * bm.getHeight()];
            bm.getPixels(argb, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm
                    .getHeight());

            for (int i = 0; i < argb.length; i++) {

                argb[i] = ((alpha << 24) | (argb[i] & 0x00FFFFFF));
            }
            return Bitmap.createBitmap(argb, bm.getWidth(), bm.getHeight(),
                                       Config.ARGB_8888);
        }
        
        /**
         * 
         * @param bm
         * @note if bitmap is smaller than screen, you can scale it fill the screen.
         * @return 
         */
        private Bitmap scaleBitmapFillScreen(Bitmap bm) {
            return Bitmap.createScaledBitmap(bm, SCREEN_W, SCREEN_H, true);
        }

        
        private void setBackGround() {
            setBackgroundResource(R.drawable.background);
        }

        /**
         * 
         * @param bm
         * @note set cover bitmap , which  overlay on background. 
         */
        private void setCoverBitmap(Bitmap bm) {
            // setting paint
            mPaint = new Paint();
            mPaint.setAlpha(0);
            mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            mPaint.setAntiAlias(true);
            
            mPaint.setDither(true);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeJoin(Paint.Join.ROUND);
            mPaint.setStrokeCap(Paint.Cap.ROUND);
            mPaint.setStrokeWidth(20);
            
            //set path
            mPath =  new Path();;

            // converting bitmap into mutable bitmap
            mBitmap = Bitmap.createBitmap(SCREEN_W, SCREEN_H, Config.ARGB_8888);
            mCanvas = new Canvas();
            mCanvas.setBitmap(mBitmap);
            // drawXY will result on that Bitmap
            // be sure parameter is bm, not mBitmap
            mCanvas.drawBitmap(bm, 0, 0, null);
        }

       

        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawBitmap(mBitmap, 0, 0, null);
            mCanvas.drawPath(mPath, mPaint);
            super.onDraw(canvas);
        }
        
        private void touch_start(float x, float y) {
            mPath.reset();
            mPath.moveTo(x, y);
            mX = x;
            mY = y;
        }
        private void touch_move(float x, float y) {
            float dx = Math.abs(x - mX);
            float dy = Math.abs(y - mY);
            if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
                mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
                mX = x;
                mY = y;
            }
        }
        private void touch_up() {
            mPath.lineTo(mX, mY);
            // commit the path to our offscreen
            mCanvas.drawPath(mPath, mPaint);
            // kill this so we don't double draw
            mPath.reset();
        }
        
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX();
            float y = event.getY();
            
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    touch_start(x, y);
                    invalidate();
                    break;
                case MotionEvent.ACTION_MOVE:
                    touch_move(x, y);
                    invalidate();
                    break;
                case MotionEvent.ACTION_UP:
                    touch_up();
                    invalidate();
                    break;
            }
            return true;
        }
    }
}


2.利用canvas的drawCircle做擦除效果
效果如下:



实现代码:
package aliusa.cn;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Bitmap.Config;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;

public class Eraser_Use_drawCircle extends Activity {

    private int SCREEN_W;

    private int SCREEN_H;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));

    }

    class MyView extends View {
        private Bitmap mBitmap;
        private Canvas mCanvas;
        private Paint mPaint;
        int x = 0;

        int y = 0;

        int r = 0;
        
        public MyView(Context context) {
            super(context);
            setFocusable(true);
            setScreenWH();
            setBackGround();
            
            // 1.if cover is a image,you can open MENU_ITEM_COMMENT bellow
            Bitmap bm = createBitmapFromSRC();
            // if you want to set cover image's alpha,you can open MENU_ITEM_COMMENT bellow
            bm = setBitmapAlpha(bm, 100);
            // if you want to scale cover image,you can open MENU_ITEM_COMMENT bellow
            bm = scaleBitmapFillScreen(bm);

            // 2.if cover is color
            //Bitmap bm = createBitmapFromARGB(0x8800ff00, SCREEN_W, SCREEN_H);
            setCoverBitmap(bm);

        }

        private void setScreenWH() {
            // get screen info
            DisplayMetrics dm = new DisplayMetrics();
            dm = this.getResources().getDisplayMetrics();
            // get screen width
            int screenWidth = dm.widthPixels;
            // get screen height
            int screenHeight = dm.heightPixels;

            SCREEN_W = screenWidth;
            SCREEN_H = screenHeight;
        }

        private Bitmap createBitmapFromSRC() {
            return BitmapFactory.decodeResource(getResources(),
                                                R.drawable.cover);
        }

        /**
         * 
         * @param colorARGB should like 0x8800ff00
         * @param width
         * @param height
         * @return
         */
        private Bitmap createBitmapFromARGB(int colorARGB, int width, int height) {
            int[] argb = new int[width * height];

            for (int i = 0; i < argb.length; i++) {

                argb[i] = colorARGB;

            }
            return Bitmap.createBitmap(argb, width, height, Config.ARGB_8888);
        }

        /**
         * 
         * @param bm
         * @param alpha ,and alpha should be like ox00000000-oxff000000
         * @note set bitmap's alpha
         * @return
         */
       /* private Bitmap setBitmapAlpha(Bitmap bm, int alpha) {
            int[] argb = new int[bm.getWidth() * bm.getHeight()];
            bm.getPixels(argb, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm
                    .getHeight());


            for (int i = 0; i < argb.length; i++) {

                argb[i] = ((alpha) | (argb[i] & 0x00FFFFFF));
            }
            return Bitmap.createBitmap(argb, bm.getWidth(), bm.getHeight(),
                                       Config.ARGB_8888);
        }*/
        
        /**
         * 
         * @param bm
         * @param alpha ,alpha should be between 0 and 255
         * @note set bitmap's alpha
         * @return
         */
        private Bitmap setBitmapAlpha(Bitmap bm, int alpha) {
            int[] argb = new int[bm.getWidth() * bm.getHeight()];
            bm.getPixels(argb, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm
                    .getHeight());

            for (int i = 0; i < argb.length; i++) {

                argb[i] = ((alpha << 24) | (argb[i] & 0x00FFFFFF));
            }
            return Bitmap.createBitmap(argb, bm.getWidth(), bm.getHeight(),
                                       Config.ARGB_8888);
        }
        
        /**
         * 
         * @param bm
         * @note if bitmap is smaller than screen, you can scale it fill the screen.
         * @return 
         */
        private Bitmap scaleBitmapFillScreen(Bitmap bm) {
            return Bitmap.createScaledBitmap(bm, SCREEN_W, SCREEN_H, true);
        }

        
        private void setBackGround() {
            setBackgroundResource(R.drawable.background);
        }

        /**
         * 
         * @param bm
         * @note set cover bitmap , which  overlay on background. 
         */
        private void setCoverBitmap(Bitmap bm) {
            // setting paint
            mPaint = new Paint();
            mPaint.setAlpha(0);
            mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            mPaint.setAntiAlias(true);

            // converting bitmap into mutable bitmap
            mBitmap = Bitmap.createBitmap(SCREEN_W, SCREEN_H, Config.ARGB_8888);
            mCanvas = new Canvas();
            mCanvas.setBitmap(mBitmap);
            // drawXY will result on that Bitmap
            // be sure parameter is bm, not mBitmap
            mCanvas.drawBitmap(bm, 0, 0, null);
        }

       

        @Override
        protected void onDraw(Canvas canvas) {
         // draw a circle that is erasing bitmap
            mCanvas.drawCircle(x, y, r, mPaint);
            canvas.drawBitmap(mBitmap, 0, 0, null);
            super.onDraw(canvas);
        }
        
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            // set parameter to draw circle on touch event
            x = (int) event.getX();
            y = (int) event.getY();
            r = 20;
            // Atlast invalidate canvas
            invalidate();
            return true;
        }
    }
  • 大小: 52.7 KB
  • 大小: 56.6 KB
分享到:
评论

相关推荐

    Android画板开发之橡皮擦功能

    在橡皮擦功能中,我们使用 PorterDuff.Mode.CLEAR 模式来擦除图像。 三、实现橡皮擦功能 为了实现橡皮擦功能,我们需要添加一个橡皮擦的绘制模式。在上一篇文章中,我们已经实现了最简单的画笔模式,现在我们需要...

    XferMode实现常见特效.zip

    本文将深入探讨如何利用`XferMode`来实现标题中提到的各种特效,包括圆角效果、倒影效果、心电图效果、波浪效果、裁边效果、橡皮擦效果以及刮刮卡效果。 1. **圆角效果**: 圆角效果通常用于给图像或自定义视图...

    橡皮擦与画笔的demo.zip

    在Android中,我们可以通过设置画笔的Alpha值来模拟橡皮擦效果,或者使用BitmapShader配合PorterDuff.Mode来达到类似的效果。 首先,我们需要创建一个自定义的View,继承自View类。在这个自定义View中,我们需要...

    android橡皮擦刮奖效果

    在Android开发中,实现"刮刮乐"效果,即橡皮擦刮奖功能,是一种常见的交互设计,可以用于各种抽奖或者解谜应用中。这种效果的实现涉及到多个Android图形和UI相关的知识点,以下将详细解释相关技术。 1. **自定义...

    Xfermode16-PorterDuff及Xfermode.rar

    在实际应用中,比如创建一个自定义的画板应用,用户可以用手指画出贝塞尔曲线,此时可以利用PorterDuff的不同模式来实现橡皮擦效果(如设置为DstOut),或者实现颜色叠加、剪切等特效。另一个例子是在动画中,通过...

    安卓Android源码——橡皮擦与画笔的demo.zip

    橡皮擦效果可以通过两种方式实现:一是使用`PorterDuff.Mode.CLEAR`模式的`Paint`在当前`Bitmap`上清除颜色;二是创建一个与画板相同大小的白色`Bitmap`作为橡皮擦位图,当用户擦除时,将橡皮擦位图与画板进行复合...

    android擦除效果代码(橡皮擦)

    在Android开发中,实现"橡皮擦"效果,即用户可以擦除屏幕上的特定内容,通常涉及到绘图和触摸事件处理。这个功能广泛应用于绘画应用、图像编辑工具等,允许用户自由地擦除画布上的颜色或线条。下面将详细解释如何在...

    涂鸦画笔与橡皮擦

    在Android开发中,实现"涂鸦画笔与橡皮擦"功能是一项常见的需求,尤其在教育、绘画类应用中非常普遍。本项目提供了一个简单的涂鸦与橡皮擦的源码示例,可以帮助开发者理解如何在Android应用中实现类似的功能。 首先...

    Android橡皮擦与画笔的demo_涂鸦绘画.zip

    使用`PorterDuff.Mode.CLEAR`模式,我们可以将画布上的像素清除,达到橡皮擦的效果。当用户切换到橡皮擦模式时,我们只需要修改这个模式即可。 为了记录用户的绘图动作,我们可以使用MotionEvent来捕获触摸屏幕的...

    安卓手绘图片处理画板相关-橡皮擦与画笔的demo.rar

    在安卓中,实现橡皮擦功能通常意味着改变 `Paint` 的某些属性,使其具有擦除效果。一种常见方法是将 `Paint` 的 `Xfermode` 设置为 `PorterDuff.Mode.CLEAR`,这会清除画布上的颜色,达到“擦除”效果。 ```java ...

    Xfermode Demo

    1. **橡皮擦效果**:通过设置`PorterDuff.Mode.CLEAR`,你可以创建一个“橡皮擦”工具,擦除画布上的内容。 2. **图像合成**:`DST_OVER`模式可以用于将新图像叠加到已有图像上,常用于图像编辑应用。 3. **遮罩效果...

    安卓开发-橡皮擦与画笔的demo.zip

    在橡皮擦功能中,通常会创建一个透明度很高的`Paint`,以模拟擦除效果。 4. **保存与恢复Canvas状态**: 在复杂绘图过程中,为了防止局部修改影响全局,我们常常使用`save()`和`restore()`方法来保存和恢复Canvas的...

    Android高级应用源码-橡皮擦与画笔的demo.zip

    通常,我们可以通过将`Paint`的`Xfermode`设置为`PorterDuff.Mode.CLEAR`,这样在绘制时就会清除画布上的像素,达到擦除的效果。或者,也可以通过改变画笔的颜色为背景色,然后设置合适的透明度,模拟橡皮擦的效果。...

    安卓Andriod源码——橡皮擦与画笔的demo.zip

    在橡皮擦模式下,通常会设置`Xfermode`为`PorterDuff.Mode.CLEAR`,这使得画笔在绘图时能清除画布上的颜色,起到橡皮擦的效果。 3. **保存和回放绘图**:为了保存用户的绘画,开发者可能会使用`ArrayList`来存储...

    Android应用源码之橡皮擦与画笔的demo.zip

    对于橡皮擦功能,关键在于设置`Xfermode`模式为` PorterDuff.Mode.CLEAR`,这使得画笔在绘制时会清除目标像素的颜色,达到橡皮擦的效果。 3. **触摸事件TouchEvent** 用户交互通常是通过触摸屏幕来控制画笔和橡皮...

    android 刮刮乐

    我们可以使用Path类来跟踪用户的触摸动作,然后使用Paint对象的setXfermode()方法配合PorterDuff.Mode.CLEAR模式,使得触摸区域的背景图层显示出来,实现刮除效果。橡皮擦的大小和圆角可以通过调整Paint对象的...

    android实现的屏幕画笔

    7. **橡皮擦功能**:橡皮擦功能可以通过设置Paint的Xfermode为PorterDuff.Mode.CLEAR,使得画笔不再添加颜色,而是清除已有的颜色。 8. **撤销/重做功能**:利用栈数据结构,每次绘制操作都保存当前状态,当用户...

    Android简易画板源码

    橡皮擦功能可以通过设置`Paint`的`Xfermode`为`PorterDuff.Mode.CLEAR`,使得画出的部分清除原有颜色,达到擦除的效果。 7. **性能优化** 对于复杂的绘画操作,确保流畅性是非常重要的。可能需要使用硬件加速,...

Global site tag (gtag.js) - Google Analytics