Loading...
Logo
Processing Forum

Scrible and color

in General Discussion  •  Other  •  1 year ago  
Hi all, 

So, I came across this tutorial,  http://processing.org/learning/topics/continuouslines.html and now I know how to scrible. I wanted to implement an added functionality, where if we encircle a scrible, the circled section gets colored. Like flood fill. That is, if I scrible around a car's image, on completing the scrible around the car's border, the car turns red colored. Please help with a code snippet if possible. If you think this question should have been asked under "Programming questions", I shall do so. Thanks a lot. 

Replies(8)

Not so easy... So, if you "enclose" "some shape", hopefully closed, you want to detect the shape (there might be several ones), and fill them?

Mmm, might be simpler to use flood fill from a clicked point, no?
Well, if you assume that you only want to enclose one shape at a time, you could just keep track of the lines drawn (as an ArrayList of points, say), and then check each new line drawn to see if it overlaps with any of the previous lines (there's a formula for that, I'm sure(?)) - once you find a pair of lines that cross each other, you know that the lines between those two form a shape, which you can then color in with a triangle strip...

I am using phi.lhos idea to have a separate clicked point that is used as a starting point for flood fill.

Thus no need to detect the fill area automatically.

First you paint with the mouse.

When you have your area / car, press and hold any key (keyboard). Then the program behaves different.

Then click in the fill area / car with the mouse (or in a few fill areas).

Release the key (keyboard) afterwards and draw again (mouse) as you did before.

(The flood code is also from phi.lho from another thread btw.)



Copy code
  1. // Toxi's flood fill code, updated to modern Java and Processing and to my taste... :-P
  2. // Also generalized to work on any PImage
  3. // http://processing.org/discourse/yabb2/YaBB.pl?num=1138719727
  4. FloodFill1 myFloodFill ;
  5. //
  6. void setup() {
  7.   size(900, 900);
  8.   noFill();
  9.   // strokeWeight(23);
  10. }
  11. //
  12. void draw () {
  13.   if (keyPressed) {
  14.     if (mousePressed) {
  15.       loadPixels();
  16.       myFloodFill = new FloodFill1();
  17.       myFloodFill.DoFill(mouseX, mouseY, color(255, 0, 0));
  18.       updatePixels();
  19.     }
  20.   }
  21.   else {
  22.     if (mousePressed) {
  23.       line(mouseX, mouseY, pmouseX, pmouseY);
  24.     }
  25.   }
  26. }
  27. // =====================================================================
  28. // I create a class to share variables between the functions...
  29. public class FloodFill1
  30. {
  31.   protected int iw; // Image width
  32.   protected int ih; // Image height
  33.   protected color[] imagePixels;
  34.   protected color backColor; // Color found at given position
  35.   protected color fillColor; // Color to apply
  36.   // Stack is almost deprecated and slow (synchronized).
  37.   // I would use Deque but that's Java 1.6, excluding current (mid-2009) Macs...
  38.   protected ArrayList stack = new ArrayList();
  39.   //
  40.   public FloodFill1()
  41.   {
  42.     iw = width;
  43.     ih = height;
  44.     imagePixels = pixels; // Assume loadPixels have been done before
  45.   }
  46.   //
  47.   public FloodFill1(PImage imageToProcess)
  48.   {
  49.     iw = imageToProcess.width;
  50.     ih = imageToProcess.height;
  51.     imagePixels = imageToProcess.pixels; // Assume loadPixels have been done before if sketch image
  52.   }
  53.   //
  54.   public void DoFill(int startX, int startY, color fc)
  55.   {
  56.     // start filling
  57.     fillColor = fc;
  58.     backColor = imagePixels[startX + startY * iw];
  59.     // don't run if fill color is the same as background one
  60.     if (fillColor == backColor)
  61.       return;
  62.     stack.add(new PVector(startX, startY));
  63.     while (stack.size () > 0)
  64.     {
  65.       PVector p = (PVector) stack.remove(stack.size() - 1);
  66.       // Go left
  67.       FillScanLine((int) p.x, (int) p.y, -1);
  68.       // Go right
  69.       FillScanLine((int) p.x + 1, (int) p.y, 1);
  70.     }
  71.   }
  72.   //
  73.   protected void FillScanLine(int x, int y, int dir)
  74.   {
  75.     // compute current index in pixel buffer array
  76.     int idx = x + y * iw;
  77.     boolean inColorRunAbove = false;
  78.     boolean inColorRunBelow = false;
  79.     // fill until boundary in current scanline...
  80.     // checking neighbouring pixel rows
  81.     while (x >= 0 && x < iw && imagePixels[idx] == backColor)
  82.     {
  83.       imagePixels[idx] = fillColor;
  84.       if (y > 0) // Not on top line
  85.       {
  86.         if (imagePixels[idx - iw] == backColor)
  87.         {
  88.           if (!inColorRunAbove)
  89.           {
  90.             // The above pixel needs to be flooded too, we memorize the fact.
  91.             // Only once per run of pixels of back color (hence the inColorRunAbove test)
  92.             stack.add(new PVector(x, y-1));
  93.             inColorRunAbove = true;
  94.           }
  95.         }
  96.         else // End of color run (or none)
  97.         {
  98.           inColorRunAbove = false;
  99.         }
  100.       }
  101.       if (y < ih - 1) // Not on bottom line
  102.       {
  103.         if (imagePixels[idx + iw] == backColor)
  104.         {
  105.           if (!inColorRunBelow)
  106.           {
  107.             // Idem with pixel below, remember to process there
  108.             stack.add(new PVector(x, y + 1));
  109.             inColorRunBelow = true;
  110.           }
  111.         }
  112.         else // End of color run (or none)
  113.         {
  114.           inColorRunBelow = false;
  115.         }
  116.       }
  117.       // Continue in given direction
  118.       x += dir;
  119.       idx += dir;
  120.     } //
  121.   } // func
  122. } // class
  123. // ----------------------------------------------------------



Thanks a lot Chrisir, I'll try it now. 
I might have to modify it a bit, because it would be great if the car gets colored as soon as I complete the border. For example, if I draw a square type shape, the moment I finish drawing, the point of starting co-incides with the end-point, the shape gets colored. But this is a very helpful start. Thanks again. 
Chrisir: hello, as you remember, I asked two questions lately: 1- this floodfill one, 2- undo the drawing one.. Finally, I was trying to work on them, and merge both the codes to create something where one can choose an image, then draw anything over it, use backspace to undo (lines, and if possible the colored patch too), and if an enclosed shape is created, then on keypress+click=colors that section. I hope I am able to convey things properly, think of MS paint's related features. 

I am attaching my code here: 
https://docs.google.com/open?id=0Bz9yO_rpFwfWOHpraEFpWkVRdjZiVlRKc1p1ZUhPZw (the code is trimmed version of your project, so you'll understand it fairly quickly)

Basically, currently the code is doing things partially..when there's no image in the background, the color feature works, but the undo does not.. I was trying to play with the Buch2 file's draw() function. When image is added, then the flood feature does not work, etc etc. I guess not much work is needed to get the expected result, but I might be missing something. Can you please help me on that? Thanks so much!!! 


that's very complicate


I made a new version here
http://www.openprocessing.org/visuals/?visualID=53545

Thanks a lot!! 
There's an issue though, that when we undo after there's a colored patch. So undo only undoes the lines, and not the patch, this causes a weird spread all over the patch. This is probably because pixels of patch aren't saved in the ArrayList for the undo. Hmmm... Thanks again! 


that's right.

you can make an undo for the fill as well.