aewarnick Posted July 17, 2003 Posted July 17, 2003 public static void FillArea(Bitmap editBitmap, int x, int y, Color replThisColor, Color withThisColor) { if(editBitmap.GetPixel(x,y)==replThisColor) { editBitmap.SetPixel(x,y, withThisColor); int l= x-1; int r= x+1; int u= y-1; int d= y+1; if(r < editBitmap.Width) { if(editBitmap.GetPixel(r, y)==replThisColor) FillArea(editBitmap, r, y, replThisColor, withThisColor); } if(d < editBitmap.Height) { if(editBitmap.GetPixel(x, d)==replThisColor) FillArea(editBitmap, x, d, replThisColor, withThisColor); } if(l > -1) { if(editBitmap.GetPixel(l, y)==replThisColor) FillArea(editBitmap, l, y, replThisColor, withThisColor); } /*if(u > -1) { if(editBitmap.GetPixel(x, u)==replThisColor) FillArea(editBitmap, x, u, replThisColor, withThisColor); }*/ } I always get a stack overflow right away if I have all 4 directions running. Is there a better way to do this? Quote C#
*Experts* Nerseus Posted July 18, 2003 *Experts* Posted July 18, 2003 Your code will keep hitting the same pixels over and over. You could try passing something like a "direction" to your function so that you know which way you were coming from. Using that direction you would NO check the IF for pixels in that direction. For example, say you had a 3x3 grid. The first pixel is in the upper left. Say your second pixel is to the right, so you call your function again. When checking the pixels around this second pixel (top middle pixel in the 3x3) you don't want to go back and do anything with the top left pixel since you've already visited it. By using a direction you can avoid that. That's the easiest change, using your existing code. A better solution involves more work as you would create a structure to know which pixels you'd already hit. With my solution (just using a direction), you'll still revisit pixels but not indefinately. Isn't there some kind of FloodFill function built into GDI or GDI+? I don't know... -Nerseus Quote "I want to stand as close to the edge as I can without going over. Out on the edge you see all the kinds of things you can't see from the center." - Kurt Vonnegut
*Gurus* divil Posted July 18, 2003 *Gurus* Posted July 18, 2003 Yes, there is a GDI FloodFill method. Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
ballisticnylon Posted July 19, 2003 Posted July 19, 2003 This looked relevant. http://www.codeproject.com/useritems/FloodFill.asp?print=true Quote "It may be roundly asserted that human ingenuity cannot concoct a cipher which human ingenuity cannot resolve." - Edgar Allan Poe, 1841 I long to accomplish great and noble tasks, but it is my chief duty to accomplish humble tasks as though they were great and noble. The world is moved along, not only by the mighty shoves of its heroes, but also by the aggregate of the tiny pushes of each honest worker. - Helen Keller
aewarnick Posted July 19, 2003 Author Posted July 19, 2003 (edited) It looks like he left something out- using the points he added... I didn't notice the first time divil, that you did not write a + after GDI. It is an api call. I'll just stick with my own. Edited July 19, 2003 by aewarnick Quote C#
aewarnick Posted July 19, 2003 Author Posted July 19, 2003 Now it is even worse. I don't even get an error, the program just quits! Are you suggesting using an array list and looping through each element(point structure) to see if I did that one already? public static void FloodFill(Bitmap editBitmap, int x, int y, Color replThisColor, Color withThisColor, char direction) { if(editBitmap.GetPixel(x,y)==replThisColor) { editBitmap.SetPixel(x,y, withThisColor); int l= x-1; int r= x+1; int u= y-1; int d= y+1; if(direction != 'R') { if(r < editBitmap.Width) { if(editBitmap.GetPixel(r, y)==replThisColor) FloodFill(editBitmap, r, y, replThisColor, withThisColor, 'L'); } } if(direction != 'D') { if(d < editBitmap.Height) { if(editBitmap.GetPixel(x, d)==replThisColor) FloodFill(editBitmap, x, d, replThisColor, withThisColor, 'U'); } } if(direction != 'L') { if(l > -1) { if(editBitmap.GetPixel(l, y)==replThisColor) FloodFill(editBitmap, l, y, replThisColor, withThisColor, 'R'); } } if(direction != 'U') { if(u > -1) { if(editBitmap.GetPixel(x, u)==replThisColor) FloodFill(editBitmap, x, u, replThisColor, withThisColor, 'D'); } } } } Quote C#
Hamburger1984 Posted July 21, 2003 Posted July 21, 2003 I thought this was an interesting problem and searched for a way to solve it - first I ran into the same problems mentioned above (stack overflow/app exiting without throwing any exception etc...) but then I remembered my Math lessons - Pythagoras!! one of his most famous discoverys says that the sides of a rectangular triangle always have the relationship (a*a) + (b*b) = (c*c) where a and b have a 90° angle between each other. I used this to calculate the distance between start and current point. what I tried to do is minimizing double "pixel-checking" by checking wheter the distance © from the current point to the startpoint is shorter than the next point I'm about to work on. if this is the case - keep working.... if not leave it. this method has one disadvantage - it doesn't fill "around corners" but maybe this is a approach you can use... Hope this helps! Andreas ...the code: Private Sub FloodFill(ByVal BMP As Bitmap, ByVal Start As Point, ByVal SearchCol As Color, ByVal ReplaceCol As Color) Try If Start.X < BMP.Width And Start.X > -1 And Start.Y < BMP.Height And Start.Y > -1 Then If BMP.GetPixel(Start.X, Start.Y).Equals(SearchCol) And Not BMP.GetPixel(Start.X, Start.Y).Equals(ReplaceCol) Then Console.WriteLine("Starting FloodFill at " + Start.ToString()) Console.WriteLine("replacing " + SearchCol.ToString() + " with " + ReplaceCol.ToString()) BMP.SetPixel(Start.X, Start.Y, ReplaceCol) internalFloodFill(BMP, Start, New Point(Start.X, Start.Y - 1), SearchCol, ReplaceCol) Console.WriteLine("") Console.WriteLine("- -") internalFloodFill(BMP, Start, New Point(Start.X + 1, Start.Y), SearchCol, ReplaceCol) Console.WriteLine("") Console.WriteLine("- -") internalFloodFill(BMP, Start, New Point(Start.X, Start.Y + 1), SearchCol, ReplaceCol) Console.WriteLine("") Console.WriteLine("- -") internalFloodFill(BMP, Start, New Point(Start.X - 1, Start.Y), SearchCol, ReplaceCol) Console.WriteLine("") Console.WriteLine("- -") Console.WriteLine("Done!!") End If End If Catch e As Exception Console.WriteLine("ERROR in FloodFill") Console.WriteLine(e.Message) End Try End Sub Private Sub internalFloodFill(ByVal BMP As Bitmap, ByVal Start As Point, ByVal CurrPos As Point, ByVal SearchCol As Color, ByVal ReplaceCol As Color) Try If CurrPos.X < BMP.Width And CurrPos.X > -1 And CurrPos.Y < BMP.Height And CurrPos.Y > -1 Then If BMP.GetPixel(CurrPos.X, CurrPos.Y).Equals(SearchCol) And Not BMP.GetPixel(CurrPos.X, CurrPos.Y).Equals(ReplaceCol) Then Console.Write(".") BMP.SetPixel(CurrPos.X, CurrPos.Y, ReplaceCol) Dim newPos As New Point(CurrPos.X, CurrPos.Y - 1) If newPos.X < BMP.Width And newPos.X > -1 And newPos.Y < BMP.Height And newPos.Y > -1 Then If (Math.Abs(newPos.X - Start.X)) ^ 2 + (Math.Abs(newPos.Y - Start.Y)) ^ 2 > (Math.Abs(CurrPos.X - Start.X)) ^ 2 + (Math.Abs(CurrPos.Y - Start.Y)) ^ 2 Then If BMP.GetPixel(newPos.X, newPos.Y).Equals(SearchCol) And Not BMP.GetPixel(newPos.X, newPos.Y).Equals(ReplaceCol) Then internalFloodFill(BMP, Start, newPos, SearchCol, ReplaceCol) End If End If End If newPos.Y += 2 If newPos.X < BMP.Width And newPos.X > -1 And newPos.Y < BMP.Height And newPos.Y > -1 Then If (Math.Abs(newPos.X - Start.X)) ^ 2 + (Math.Abs(newPos.Y - Start.Y)) ^ 2 > (Math.Abs(CurrPos.X - Start.X)) ^ 2 + (Math.Abs(CurrPos.Y - Start.Y)) ^ 2 Then If BMP.GetPixel(newPos.X, newPos.Y).Equals(SearchCol) And Not BMP.GetPixel(newPos.X, newPos.Y).Equals(ReplaceCol) Then internalFloodFill(BMP, Start, newPos, SearchCol, ReplaceCol) End If End If End If newPos.Y -= 1 newPos.X -= 1 If newPos.X < BMP.Width And newPos.X > -1 And newPos.Y < BMP.Height And newPos.Y > -1 Then If (Math.Abs(newPos.X - Start.X)) ^ 2 + (Math.Abs(newPos.Y - Start.Y)) ^ 2 > (Math.Abs(CurrPos.X - Start.X)) ^ 2 + (Math.Abs(CurrPos.Y - Start.Y)) ^ 2 Then If BMP.GetPixel(newPos.X, newPos.Y).Equals(SearchCol) And Not BMP.GetPixel(newPos.X, newPos.Y).Equals(ReplaceCol) Then internalFloodFill(BMP, Start, newPos, SearchCol, ReplaceCol) End If End If End If newPos.X += 2 If newPos.X < BMP.Width And newPos.X > -1 And newPos.Y < BMP.Height And newPos.Y > -1 Then If (Math.Abs(newPos.X - Start.X)) ^ 2 + (Math.Abs(newPos.Y - Start.Y)) ^ 2 > (Math.Abs(CurrPos.X - Start.X)) ^ 2 + (Math.Abs(CurrPos.Y - Start.Y)) ^ 2 Then If BMP.GetPixel(newPos.X, newPos.Y).Equals(SearchCol) And Not BMP.GetPixel(newPos.X, newPos.Y).Equals(ReplaceCol) Then internalFloodFill(BMP, Start, newPos, SearchCol, ReplaceCol) End If End If End If End If End If Catch e As Exception Console.WriteLine("ERROR in internalFloodFill") Console.WriteLine(e.Message) End Try End Sub Quote
aewarnick Posted July 21, 2003 Author Posted July 21, 2003 Thank you. If you can get it to fill correctly I will probably invest. Quote C#
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.