android using flood fill algorithm getting out of memory exception

前端 未结 3 666
误落风尘
误落风尘 2020-12-18 18:07

after your suggestions i got working code:

public class FingerPaint extends Activity {

private RelativeLayout drawingLayout;
private MyView myView;
@Overrid         


        
3条回答
  •  悲&欢浪女
    2020-12-18 18:16

    Use Async Task. Running every operation on Main Ui thread may cause's out of memory exception. My suggestion , use threads. Do Floodfill in background. Check this link. May help You. Fill the complete canvas but keep the bound fill area as it is like circle, rectangle

        private Paint paint;
    private Path path;
    Bitmap mBitmap;
    ProgressDialog pd;
     final Point p1 = new Point();
    Canvas canvas;
    private static final float TOUCH_TOLERANCE = 4;
    float mX,mY;
    
    public DrawingView(Context context ) {
        super(context);
    
        this.paint = new Paint();
        this.paint.setAntiAlias(true);
        pd= new ProgressDialog(context);
        this.paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeWidth(5f);
        mBitmap= BitmapFactory.decodeResource(getResources(), R.drawable.rose_sketch);
        this.path = new Path();
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        this.canvas=canvas;
        this.paint.setColor(Color.GREEN);
        canvas.drawBitmap(mBitmap, 0, 0,paint);
    
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
    
        float x = event.getX();
        float y = event.getY();
        switch(event.getAction())
        {
        case MotionEvent.ACTION_DOWN:
        //final Point p1 = new Point();
        p1.x=(int) x;
        p1.y=(int) y;
        final int sourceColor=  mBitmap.getPixel((int)x,(int) y);
        final int targetColor = paint.getColor();
        new TheTask(mBitmap, p1, sourceColor, targetColor).execute();
        invalidate();    
        }
        return true;
    }
    
    public void clear() {
        path.reset();
        invalidate();
    }
    public int getCurrentPaintColor() {
        return paint.getColor();
    }
    class TheTask extends AsyncTask {
    
        Bitmap bmp;
        Point pt;
        int replacementColor,targetColor;
    
        public TheTask(Bitmap bm,Point p, int sc, int tc)
        {
            this.bmp=bm;
            this.pt=p;
            this.replacementColor=tc;
            this.targetColor=sc;
            pd.setMessage("Filling....");
            pd.show();
        }
        @Override
        protected void onPreExecute() {
            pd.show();
    
        }
    
        @Override
        protected void onProgressUpdate(Integer... values) {
    
        }
    
        @Override
        protected Void doInBackground(Void... params) {
            FloodFill f= new FloodFill();
            f.floodFill(bmp,pt,targetColor,replacementColor);
            return null;
        }
    
        @Override
        protected void onPostExecute(Void result) {     
            pd.dismiss();
            invalidate();
        }
    }
    }
    

    USE FLOODFILL NOW.

     public class FloodFill {
    public void floodFill(Bitmap image, Point node, int targetColor,
            int replacementColor) {
        int width = image.getWidth();
        int height = image.getHeight();
        int target = targetColor;
        int replacement = replacementColor;
        if (target != replacement) {
            Queue queue = new LinkedList();
            do {
                int x = node.x;
                int y = node.y;
                while (x > 0 && image.getPixel(x - 1, y) == target) {
                    x--;
                }
                boolean spanUp = false;
                boolean spanDown = false;
                while (x < width && image.getPixel(x, y) == target) {
                    image.setPixel(x, y, replacement);
                    if (!spanUp && y > 0
                            && image.getPixel(x, y - 1) == target) {
                        queue.add(new Point(x, y - 1));
                        spanUp = true;
                    } else if (spanUp && y > 0
                            && image.getPixel(x, y - 1) != target) {
                        spanUp = false;
                    }
                    if (!spanDown && y < height - 1
                            && image.getPixel(x, y + 1) == target) {
                        queue.add(new Point(x, y + 1));
                        spanDown = true;
                    } else if (spanDown && y < height - 1
                            && image.getPixel(x, y + 1) != target) {
                        spanDown = false;
                    }
                    x++;
                }
            } while ((node = queue.poll()) != null);
        }
    }
    }
    

    Edit:

    One of the users commented that the solution @ Android flood-fill algorithm works faster than the solution posted here. So take look at the solution in the link although i haven't tested it myself.

提交回复
热议问题