Fill the complete canvas but keep the bound fill a

2019-01-18 08:04发布

问题:

possible duplicate

Hello friends,

I creating paint application, I have problem in that. If I draw the rectangle without fill and or another like bound area and change the background color then rectangle fill area also change means whole canvas color will be filled with the new background color. How to keep the background or fill the canvas area which was not bound, here is the image

this is the initial image

after change the background color getting this result

but how to getting like this way

回答1:

final Point p1 = new Point();
                p1.x=(int) x; //x co-ordinate where the user touches on the screen
                p1.y=(int) y; //y co-ordinate where the user touches on the screen  
 new TheTask(yourbitmap, p1, sourceColor,targetColor).execute();// use asyntask for efficiency

 class TheTask extends AsyncTask<Void, Integer, Void> {

    Bitmap bmp;
    Point pt;
    int replacementColor,targetColor;
    ProgressDialog pd;
 public TheTask(Bitmap bm,Point p, int sc, int tc)
 {
this.bmp=bm;
this.pt=p;
this.replacementColor=tc;
this.targetColor=sc;
pd= new ProgressDialog(context);
pd.setMessage("Filling....");
    }
    @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();
    }

Finally use a FloodFill algorithm to fill a closed area

    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<Point> queue = new LinkedList<Point>();
        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);
    }
}
}



回答2:

here is the code (you have to bound the shape on touch event otherwise it change the color of shape works):

public class ttt extends View {
MyShape myShape;
public ttt(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
    myShape = new MyShape();
    Paint paint = new Paint();
    paint.setColor(Color.WHITE);
    myShape.setPaint(paint);
}

@Override
protected void onDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    super.onDraw(canvas);
    myShape.onDraw(canvas);     
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    // TODO Auto-generated method stub
    int x = (int) event.getX();
    int y = (int) event.getY();

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        Paint paint = new Paint();
        paint.setColor(Color.BLUE);
        myShape.setPaint(paint);
        invalidate();
        break;

    default:
        break;
    }

    return super.onTouchEvent(event);
}

class MyShape {
    private Paint paint;
    public MyShape() {
        // TODO Auto-generated constructor stub
    }
    public void onDraw(Canvas canvas){
        canvas.drawCircle(15, 15, 30, getPaint());
    }
    /**
     * @param paint the paint to set
     */
    public void setPaint(Paint paint) {
        this.paint = paint;
    }
    /**
     * @return the paint
     */
    public Paint getPaint() {
        return paint;
    }

}

}



回答3:

You might also want to look at using the clip region as in these 2 questions:

  • Using clipRect - explanation
  • Canvas.clipPath(Path) not clipping as expected

Depending on what you want to do, they may be useful.

I found your question because I didn't know what to google for, and the answer I wanted was not using Flood Fill.