如何实现刮擦Bitmap图像?

时间:2014-02-26 08:32:47

标签: android

当我们划伤图像时,我需要显示像你赢的文本视图。 现在我有一个像下面这样的代码,但是当我们划伤图像时,性能非常慢。我该如何移动以获得更多功能。请帮帮我。

public class MyScratchCard extends ImageView implements View.OnTouchListener{
        private int mWidth = 0;
        private int mHeight = 0;
        private Paint   mPaint;
//  private Paint nPaint;
        Bitmap bitmap;
        Canvas pcanvas ;
        int x = 0;
        int y =0;
        int r =0;

        private int imageX;
        private int imageY;
        private int[] pixels;
        private Random rnd = new Random();
        private int lastStatus;
        private int status;
        private float circleX;
        private float circleY;
        private float circleR = 30;
        private float lastX;
        private float lastY;

        public MyScratchCard(Context context) {
                super(context);
        }


        public MyScratchCard(Context context, AttributeSet attrs, int defStyle) {
                super(context, attrs, defStyle);
        }


        public MyScratchCard(Context context, AttributeSet attrs) {
                super(context, attrs);
        }


        private void init() {
                Log.v("Panel", "STROKE");

                setFocusable(true);
                setBackgroundColor(Color.TRANSPARENT);
                mPaint = new Paint();
                mPaint.setAlpha(0);
                mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
                mPaint.setStrokeCap(Paint.Cap.BUTT);
                mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));//.Mode.DST_IN));
                mPaint.setAntiAlias(false);
                // getting image from resources
                Bitmap bm1 = BitmapFactory.decodeResource(getResources(),R.drawable.scratch);
                bm1 = Bitmap.createScaledBitmap(bm1, mWidth, mHeight, true);


                // converting image bitmap into mutable bitmap
                bitmap =  Bitmap.createBitmap(bm1.getWidth(), bm1.getHeight(), Config.ARGB_8888);
                pcanvas = new Canvas();
                pcanvas.setBitmap(bitmap);                   // drawXY will result on that Bitmap
                pcanvas.drawBitmap(bm1,0,0,null);

                pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
                this.setOnTouchListener(this);
        }
                @Override
                        protected void onDraw(Canvas canvas) {

                        //pcanvas.drawRect(cBK, nPaint);
                        // draw a circle that is  erasing bitmap
//                      pcanvas.drawCircle(x, y, r, mPaint);
//                      canvas.drawBitmap(bitmap, 0, 0,null);

//                      drawCircle(bitmap, imageX, imageY, 20);
                        switch(status) {
                        case MotionEvent.ACTION_UP:
                                switch(lastStatus) {
                                        case MotionEvent.ACTION_MOVE:
                                                if (Math.pow(circleX - lastX, 2) + Math.pow(circleY - lastY, 2) <= Math.pow(circleR, 2) / 2) {
                                                        drawCircle(bitmap, (int)circleX - imageX, (int)circleY - imageY, (int)circleR);
                                                }
                                                else {
                                                        drawLine(bitmap, circleX - imageX, circleY - imageY, lastX - imageX,lastY - imageY, (int)circleR);
                                                }
                                                break;
                                        case MotionEvent.ACTION_DOWN:
                                                drawCircle(bitmap, (int)circleX - imageX, (int)circleY - imageY, (int)circleR);
                                                break;
                                }
                                boolean result = isScratched(bitmap, 10);
                                if (result) Log.v(VIEW_LOG_TAG, ">> SCRATCHED");
                                break;
                        case MotionEvent.ACTION_DOWN:
                                drawCircle(bitmap, (int)circleX - imageX, (int)circleY - imageY, (int)circleR);
                                break;
                        case MotionEvent.ACTION_MOVE:
                                if (Math.pow(circleX - lastX, 2) + Math.pow(circleY - lastY, 2) <= Math.pow(circleR, 2) / 2) {
                                        drawCircle(bitmap, (int)circleX - imageX, (int)circleY - imageY, (int)circleR);
                                }
                                else {
                                        drawLine(bitmap, (int)circleX - imageX, (int)circleY - imageY, (int)lastX - imageX, (int)lastY - imageY, (int)circleR);
                                }
                                break;
                        }
                        canvas.drawBitmap(bitmap, 0, 0, null);
                        super.onDraw(canvas);
                }

                private void drawCircle(Bitmap bitmap, int centerX, int centerY,int r) {
                        int h = bitmap.getHeight();
                        int w = bitmap.getWidth();
                        bitmap.getPixels(pixels, 0, w, 0, 0, w, h);
                        drawCircle(pixels, centerX, centerY, r, h, w, 0);
                        try {
                                bitmap.setPixels(pixels, 0, w, 0, 0, w, h);
                        }
                        catch (Exception e) {
                                e.printStackTrace();
                        }
                }

                private void drawCircle(int[]pixels, int centerX, int centerY, int r, int h, int w, int color) {
                        int x;
                        int y;
                        for (x = Math.max(centerX - r, 0); x <= centerX + r && x < w; x++) {
                                for (y = Math.max(centerY - r, 0); y <= centerY + r && y < h; y++) {
                                        if (Math.pow(centerX - x, 2) + Math.pow(centerY - y, 2) <= Math.pow(r * 3 / 4 + (rnd.nextInt() % ((float)r / 4)), 2)) {
                                                pixels[x + y * w] = color;
                                        }
                                }
                        }
                }

                private void drawLine(Bitmap bitmap, float x1, float y1, float x2, float y2, int r) {
                        int h = bitmap.getHeight();
                        int w = bitmap.getWidth();
                        int x;
                        int y;
                        int xLimit;
                        int yLimit;
                        int xInit;
                        int yInit;


                        xLimit = (int) Math.min(Math.max(x1, x2) + r, w - 1);
                        yLimit = (int)Math.min(Math.max(y1, y2) + r, h - 1);
                        xInit = (int)Math.max(Math.min(x1, x2) - r, 0);
                        yInit = (int)Math.max(Math.min(y1, y2) - r, 0);
                        bitmap.getPixels(pixels, 0, w, 0, 0, w, h);

                        for (x = xInit; x <= xLimit; x++) {
                                for (y = yInit; y <= yLimit; y++) {
                                        double a1;
                                        double a2;
                                        double b1;
                                        double b2;
                                        double x3;
                                        double y3;

                                        if (x2 - x1 == 0) {
                                                x3 = x1;
                                                y3 = y;
                                        }
                                        else if (y2 - y1 == 0) {
                                                x3 = x;
                                                y3 = y1;
                                        }
                                        else {
                                                a1 = (y2 - y1)/(x2 - x1);
                                                a2 = - 1 / a1;
                                                b1 = y1 - a1 * x1;
                                                b2 = y - a2 * x;
                                                x3 = (b2 - b1)/(a1 - a2);
                                                y3 = a1 * x3 + b1;
                                        }
                                        if (Math.pow(x3 - x, 2) + Math.pow(y3 - y, 2) <= Math.pow(r * 3 / 4 + (rnd.nextInt() % (r / 4)), 2)) {
                                                int tmpPixel = pixels[x + y * w];
                                                pixels[x + y * w] = 0;
                                                if (tmpPixel != 0) {
                                                        // 消した箇所の色を適当に散らす
                                                        int x4;
                                                        int y4;

                                                        if (rnd.nextInt() / 2 == 1) {
                                                                x4 = Math.min(Math.max((int) (x - (Math.abs(y1 - y2) + r) * 4), xInit), xLimit);
                                                                y4 = Math.min(Math.max((int) (y - (Math.abs(x1 - x2) + r) * 4), yInit), yLimit);
                                                        }else {
                                                                x4 = Math.min(Math.max((int) (x + (Math.abs(y1 - y2) + r) * 4), xInit), xLimit);
                                                                y4 = Math.min(Math.max((int) (y + (Math.abs(x1 - x2) + r) * 4), yInit), yLimit);
                                                        }
                                                        drawCircle(pixels, x4, y4, 1, h, w, tmpPixel);
                                                }
                                        }
                                }
                        }

                        try {
                                bitmap.setPixels(pixels, 0, w, 0, 0, w, h);
                        }
                        catch (Exception e) {
                                e.printStackTrace();
                        }
                }

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                        lastStatus = status;
                        status = event.getAction();
                        switch(status) {
                                case MotionEvent.ACTION_MOVE:
                                case MotionEvent.ACTION_DOWN:
                                case MotionEvent.ACTION_UP:
                                        lastX = circleX;
                                        lastY = circleY;
                                        circleX = event.getX();
                                        circleY = event.getY();
                                        break;
                        }
                        invalidate();

                        return true;
                }

                @Override
        public boolean onTouchEvent(MotionEvent event) {

                // set paramete to draw circle on touch event
                imageX = (int) event.getX();
                imageY = (int) event.getY();

                // Atlast invalidate canvas
                invalidate();
                return true;
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                // TODO 自動生成されたメソッド・スタブ
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                mWidth = MeasureSpec.getSize(widthMeasureSpec);
                mHeight = MeasureSpec.getSize(heightMeasureSpec);
                Log.v("", String.format("w %d h %d", mWidth, mHeight));
                this.setMeasuredDimension(mWidth, mHeight);
                init();
        }

        private boolean isScratched(Bitmap bitmap, int scratchedPercent) {

                boolean result = false;
                int count = 0;//Counter to count pixels
                int c;
                int height = bitmap.getHeight();
                int width = bitmap.getWidth();
                int size = height * width;
                //Looping over all pixels
                for (int i = 0; i < width; i++) {
                        for (int j = 0; j < height; j++) {
                        c = bitmap.getPixel(i, j);//Get the current pixel.

                        if (c == Color.TRANSPARENT) {//Checking pixel
                                count++;//increase counter
                                //Do what ever you want, you have got the pixel that have
                                // R = 153 AND G = 184 AND B = 226
                        }
                        }
                }
                double percent = (count *100/ size);
                Log.v(VIEW_LOG_TAG, String.format(">> isScratched was called count="+ count));
                Log.v(VIEW_LOG_TAG, String.format(">> isScratched was called size="+ size));
                Log.v(VIEW_LOG_TAG, String.format(">> isScratched was called percent="+ percent));
                if ( percent >= scratchedPercent) {
                        result = true;
                }
                return result;
        }
}

0 个答案:

没有答案