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
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);
}
}
}
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;
}
}
}
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.