We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › Color fill / Paint bucket effect
Page Index Toggle Pages: 1
Color fill / Paint bucket effect (Read 722 times)
Color fill / Paint bucket effect
Dec 29th, 2007, 10:37pm
 
In Processing, if you have an image loaded, how would one go about programming a "paint bucket" function?

Like if you had a distribution of say 3 colors in large blobs in an image, if you click a red pixel it turns all adjacent red pixels to blue and then stops the loop until all adjacent pixels have been turned blue.

Would you just start with the first 8 adjacent cells, check their initial color then work outward from there? or is there a faster more efficient way?
Re: Color fill / Paint bucket effect
Reply #1 - Dec 30th, 2007, 2:41am
 
do you mean flood-fill?
(seen here: http://processing.org/discourse/yabb/YaBB.cgi?board=Syntax;action=display;num=1112372959 )



// MIKKEL CRONE KOSER
// BEYONDTHREE.COM
// FLOOD_FILL SKETCH *array-style
// APRIL 2005
 
void setup(){
 size(1400, 900, P3D);
 background(255);
 noFill();
 drawRandomBoxes();
}

void draw(){
}

void mousePressed(){
 floodFill(mouseX, mouseY, color((int)random(100, 200), (int)random(100, 200), 0));
}

// ******* FLOOD FILL *********
// original by Mark Wutka ( http://docs.rinet.ru/UJ11/ch31.htm )
// modified for processing by Mikkel Crone Koser ( www.beyondthree.com )
// modified syntax to work with Processing 0125 Beta by extrapixel.ch
//
// floodFill starts at a particular x and y coordinate and fills it, and all
// the surrounding pixels with a color.  It doesn't paint over black pixels,
// so they represent the borders of the fill.
// The easiest way to code a flood fill is by doing it recursively - you
// call flood fill on a pixel, color that pixel, then it calls flood fill
// on each surrounding pixel and so on.  Unfortunately, that usually causes
// stack overflows since recursion is pretty expensive.
// This routine uses an alternate method.  It makes a queue of pixels that
// it still has to fill.  It takes a pixel off the head of the queue and
// colors the pixels around it, then adds those pixels to the queue.  In other
// words, a pixel is really added to the queue after it has been colored.
// If a pixel has already been colored, it is not added, so eventually, it
// works the queue down until it is empty.
public void floodFill(int x, int y, int col)
{
 // If the pixel we are starting with is already black, we won't paint
 if (get(x, y) == (int)color(0,0,0)){
   return;
 }

 // Create the pixel queue.  Assume the worst case where every pixel in the
 // image may be in the queue.
 int pixelQueue[] = new int[width * height];
 int pixelQueueSize = 0;

 // Add the start pixel to the queue (we created a single array of ints,
 // even though we are enqueuing two numbers.  We put the y value in the
 // upper 16 bits of the integer, and the x in the lower 16.  This gives
 // a limit of 65536x65536 pixels, that should be enough.)

 pixelQueue[0] = (y << 16) + x;
 pixelQueueSize = 1;

 // Color the start pixel.
 set(x, y, col);

 // Keep going while there are pixels in the queue.
 while (pixelQueueSize > 0){

   // Get the x and y values of the next pixel in the queue
   x = pixelQueue[0] & 0xffff;
   y = (pixelQueue[0] >> 16) & 0xffff;

   // Remove the first pixel from the queue.  Rather than move all the
   // pixels in the queue, which would take forever, just take the one
   // off the end and move it to the beginning (order doesn't matter here).

   pixelQueueSize--;
   pixelQueue[0] = pixelQueue[pixelQueueSize];

   // If we aren't on the left side of the image, see if the pixel to the
   // left has been painted.  If not, paint it and add it to the queue.
   if (x > 0) {
     if ((get(x-1, y) != (int)color(0,0,0)) &&
       (get(x-1, y) != col))
     {
       set(x-1, y, col);
       pixelQueue[pixelQueueSize] =
         (y << 16) + x-1;
       pixelQueueSize++;
     }
   }

   // If we aren't on the top of the image, see if the pixel above
   // this one has been painted.  If not, paint it and add it to the queue.
   if (y > 0) {
     if ((get(x, y-1) != (int)color(0,0,0)) &&
       (get(x, y-1) != col))
     {
       set(x, y-1, col);
       pixelQueue[pixelQueueSize] =
         ((y-1) << 16) + x;
       pixelQueueSize++;
     }
   }

   // If we aren't on the right side of the image, see if the pixel to the
   // right has been painted.  If not, paint it and add it to the queue.
   if (x < width-1) {
     if ((get(x+1, y) != (int)color(0,0,0)) &&
       (get(x+1, y) != col))
     {
       set(x+1, y, col);
       pixelQueue[pixelQueueSize] =
         (y << 16) + x+1;
       pixelQueueSize++;
     }
   }

   // If we aren't on the bottom of the image, see if the pixel below
   // this one has been painted.  If not, paint it and add it to the queue.
   if (y < height-1) {
     if ((get(x, y+1) != (int)color(0,0,0)) &&
       (get(x, y+1) != col))
     {
       set(x, y+1, col);
       pixelQueue[pixelQueueSize] =

         ((y+1) << 16) + x;
       pixelQueueSize++;
     }
   }
 }

 updatePixels();
}

void drawRandomBoxes(){
 for(int i=0; i<30; i++){
   int x = (int)random(0, width);
   int y = (int)random(0, height);
   int w = (int)random(40, 400);
   int h = (int)random(40, 400);
   pushMatrix();
  // rotateZ(random(PI));
   rect(x, y, w, h);
   popMatrix();
 }
}  
Page Index Toggle Pages: 1