Ooops
October 28, 2020, 11:28:24 PM

Author Topic: [bb] FloodFill - Really!!! by Adam Novagen [ 1+ years ago ]  (Read 1445 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
Title : FloodFill - Really!!!
Author : Adam Novagen
Posted : 1+ years ago

Description : FLOODFILL
By Adam Novagen

After just an hour & a half of typing, I've finally perfected a Flood Fill routine, like those used in paint programs! It can theoretically fill any size image region, and any shape too!
Depending on computer configuration, graphics mode, and the number of pixels to be filled, the fill can take anywhere from 5 to 1000 milliseconds (.005 to 1 seconds); just trust the code!

HOW TO USE FLOODFILL()
FloodFill() is declared like this (not verbatim):
<div class="quote"> FloodFill(Image,Fill X,Fill Y,Fill Red,Fill Green,Fill Blue)
</div>
Image is the image to be filled; I'm afraid the routine doesn't work directly on graphics buffers. Fill X & Y are the starting coordinates for the fill, and Fill Red, Green and Blue are the RGB color values to fill with.

THE TESTING LOOP
This file contains a small testing loop at the end. It draws an image of your choice at 0,0, and shows the mouse location with a flashing pixel. Left-clicking on the image will fill that part with a random color; the FloodFill() RGB values in the testing loop are set to Rand(255). The Esc key ends the program, as usual.

OPTIONAL CODE
The FloodFill() routine contains two sets of optional code, which at the moment has been commented with a semicolon (;). The first line, the interrupt line, is a special "Panic Button" line that lets the Esc key end the program at any point during the execution of FloodFill(). You might want to uncomment this until you have faith in FloodFill's ability to avoid crashes & freezes, but trust me, you won't need it forever!
The second bit of optional code lets you watch the fill in action (theoretically.) Depending on your computer configuration, this will probably slow FloodFill() down, but it's worth watching at least once; in a small image, that is!

ADDITIONAL FUNCTIONS: PIXELRED/GREEN/BLUE()
PixelRed(), PixelGreen(), and PixelBlue() are function used by FloodFill to obtain color information of certain pixels without changing the actual Color R,G,B settings. However, you can also use them like this:
<div class="quote"> PixelRed(Pixel X,Pixel Y)
</div>
PixelGreen() & Blue() are declared the same way, and all three return a value from 0 to 255.

FINAL NOTES
All the variables in the FloodFill routine, except for the Pixel type, are preceded by "Ghz_Lib_Var_". This is to minimize the possibility of you accidentally creating a variable with the same name, thus causing FloodFill() or your program to generate bugs. "Ghz_Lib_Var_" is used because FloodFill() and the Pixel functions are all used in the Gigahertz Games Command Library. Gigahertz_Library_Variable = Ghz_Lib_Var, get it? You can mess around with these variables if you really want to get into the FloodFill routine, but I only recommend that for expert Blitzers.

Enjoy!


Code :
Code: BlitzBasic
  1. Type Pixel
  2.         Field X,Y
  3. End Type
  4.  
  5.  
  6. Function FloodFill(FillImage,FX,FY,FR,FG,FB);COMPLETE
  7.  
  8.  
  9. If FX < 0 Or FX > ImageWidth(FillImage) - 1 Or FY < 0 Or FY > ImageHeight(FillImage) - 1
  10.         RuntimeError("GHZLIB ERROR" + Chr(10) + "Invalid coordinates: " + FX + "," + FY + Chr(10) + "Coords must be within image boundaries")
  11. EndIf
  12.  
  13.  
  14. Local CurrentBuffer = GraphicsBuffer()
  15. Local CurrentRed = ColorRed()
  16. Local CurrentGreen = ColorGreen()
  17. Local CurrentBlue = ColorBlue()
  18.  
  19.  
  20. SetBuffer ImageBuffer(FillImage)
  21. LockBuffer
  22.  
  23.  
  24. Local TarR = PixelRed(FX,FY)
  25. Local TarG = PixelGreen(FX,FY)
  26. Local TarB = PixelBlue(FX,FY)
  27.  
  28.  
  29. Color FR,FG,FB
  30. WritePixelFast FX,FY,FB + (FG * 256) + (FR * (256 * 256))
  31. Pixel.Pixel = New Pixel
  32. PixelX = FX
  33. PixelY = FY
  34.  
  35.  
  36. Repeat
  37. Local PixelsRemaining = False
  38. For Pixel.Pixel = Each Pixel
  39. Local PixelLeft = False
  40. Local PixelAbove = False
  41. Local PixelRight = False
  42. Local PixelBelow = False
  43. Local PixelX = PixelX
  44. Local PixelY = PixelY
  45. If PixelX > 0;check left
  46.         If PixelRed(PixelX - 1,PixelY) = TarR And PixelGreen(PixelX - 1,PixelY) = TarG And PixelBlue(PixelX - 1,PixelY) = TarB
  47.                 PixelLeft = True
  48.                 PixelsRemaining = True
  49.         EndIf
  50. EndIf
  51. If PixelY > 0;check above
  52.         If PixelRed(PixelX,PixelY - 1) = TarR And PixelGreen(PixelX,PixelY - 1) = TarG And PixelBlue(PixelX,PixelY - 1) = TarB
  53.                 PixelAbove = True
  54.                 PixelsRemaining = True
  55.         EndIf
  56. EndIf
  57. If PixelX < ImageWidth(FillImage) - 1;check right
  58.         If PixelRed(PixelX + 1,PixelY) = TarR And PixelGreen(PixelX + 1,PixelY) = TarG And PixelBlue(PixelX + 1,PixelY) = TarB
  59.                 PixelRight = True
  60.                 PixelsRemaining = True
  61.         EndIf
  62. Else
  63.         PixelRight = False
  64. EndIf
  65. If PixelY < ImageHeight(FillImage) - 1;check below
  66.         If PixelRed(PixelX,PixelY + 1) = TarR And PixelGreen(PixelX,PixelY + 1) = TarG And PixelBlue(PixelX,PixelY + 1) = TarB
  67.                 PixelBelow = True
  68.                 PixelsRemaining = True
  69.         EndIf
  70. Else
  71.         PixelBelow = False
  72. EndIf
  73. ;If KeyDown(1) Then End
  74. Delete Pixel
  75. PixelNum = PixelNum - 1
  76. ;LockBuffer
  77. If PixelLeft = True
  78.         Pixel.Pixel = New Pixel
  79.         PixelX = PixelX - 1
  80.         PixelY = PixelY
  81.         PixelNum = PixelNum + 1
  82.         PixelLeft = False
  83.         WritePixelFast PixelX,PixelY,FB + (FG * 256) + (FR * (256 * 256))
  84. EndIf
  85. If PixelAbove = True
  86.         Pixel.Pixel = New Pixel
  87.         PixelX = PixelX
  88.         PixelY = PixelY - 1
  89.         PixelNum = PixelNum + 1
  90.         PixelAbove = False
  91.         WritePixelFast PixelX,PixelY,FB + (FG * 256) + (FR * (256 * 256))
  92. EndIf
  93. If PixelRight = True
  94.         Pixel.Pixel = New Pixel
  95.         PixelX = PixelX + 1
  96.         PixelY = PixelY
  97.         PixelNum = PixelNum + 1
  98.         PixelRight = False
  99.         WritePixelFast PixelX,PixelY,FB + (FG * 256) + (FR * (256 * 256))
  100. EndIf
  101. If PixelBelow = True
  102.         Pixel.Pixel = New Pixel
  103.         PixelX = PixelX
  104.         PixelY = PixelY + 1
  105.         PixelNum = PixelNum + 1
  106.         PixelBelow = False
  107.         WritePixelFast PixelX,PixelY,FB + (FG * 256) + (FR * (256 * 256))
  108. EndIf
  109. ;!UNCOMMENT THE FOLLOWING CODE TO SEE FLOODFILL IN ACTION!
  110. ;UnlockBuffer
  111. ;SetBuffer CurrentBuffer
  112. ;DrawImage FillImage,0,0
  113. ;Flip
  114. ;SetBuffer ImageBuffer(FillImage)
  115. ;LockBuffer
  116. Next
  117. Until PixelsRemaining = False
  118.  
  119. UnlockBuffer
  120. SetBuffer CurrentBuffer
  121. Color CurrentRed,CurrentGreen,CurrentBlue
  122.  
  123.  
  124. End Function
  125.  
  126.  
  127. Function PixelGreen(Ghz_Lib_Var_PixelX,Ghz_Lib_Var_PixelY)
  128.  
  129.  
  130. Local Ghz_Lib_Var_CurrentRed = ColorRed()
  131. Local Ghz_Lib_Var_CurrentGreen = ColorGreen()
  132. Local Ghz_Lib_Var_CurrentBlue = ColorBlue()
  133.  
  134. GetColor(Ghz_Lib_Var_PixelX,Ghz_Lib_Var_PixelY)
  135. Local Ghz_Lib_Var_Green = ColorGreen()
  136.  
  137. Color Ghz_Lib_Var_CurrentRed,Ghz_Lib_Var_CurrentGreen,Ghz_Lib_Var_CurrentBlue
  138.  
  139. Return Ghz_Lib_Var_Green
  140.  
  141.  
  142. End Function
  143.  
  144.  
  145. Function PixelRed(Ghz_Lib_Var_PixelX,Ghz_Lib_Var_PixelY)
  146.  
  147.  
  148. Local Ghz_Lib_Var_CurrentRed = ColorRed()
  149. Local Ghz_Lib_Var_CurrentGreen = ColorGreen()
  150. Local Ghz_Lib_Var_CurrentBlue = ColorBlue()
  151.  
  152. GetColor(Ghz_Lib_Var_PixelX,Ghz_Lib_Var_PixelY)
  153. Local Ghz_Lib_Var_Red = ColorRed()
  154.  
  155. Color Ghz_Lib_Var_CurrentRed,Ghz_Lib_Var_CurrentGreen,Ghz_Lib_Var_CurrentBlue
  156.  
  157. Return Ghz_Lib_Var_Red
  158.  
  159.  
  160. End Function
  161.  
  162.  
  163. Function PixelBlue(Ghz_Lib_Var_PixelX,Ghz_Lib_Var_PixelY)
  164.  
  165.  
  166. Local Ghz_Lib_Var_CurrentRed = ColorRed()
  167. Local Ghz_Lib_Var_CurrentGreen = ColorGreen()
  168. Local Ghz_Lib_Var_CurrentBlue = ColorBlue()
  169.  
  170. GetColor(Ghz_Lib_Var_PixelX,Ghz_Lib_Var_PixelY)
  171. Local Ghz_Lib_Var_Blue = ColorBlue()
  172.  
  173. Color Ghz_Lib_Var_CurrentRed,Ghz_Lib_Var_CurrentGreen,Ghz_Lib_Var_CurrentBlue
  174.  
  175. Return Ghz_Lib_Var_Blue
  176.  
  177.  
  178. End Function
  179.  
  180.  
  181. ;!TESTING LOOP
  182. ;To use this mini-program, just click anywhere on the image.
  183. ;The cursor is represented by a flashing pixel.
  184. Graphics 800,600,0,2
  185. Global Image = LoadImage("sample image 1.bmp");replace "image.bmp" with a valid filename
  186. SetBuffer BackBuffer()
  187. SeedRnd MilliSecs()
  188. While Not KeyDown(1)
  189. Cls
  190. If MouseHit(1) Then FloodFill(Image,MouseX(),MouseY(),Rand(255),Rand(255),Rand(255))
  191. DrawImage Image,0,0
  192. Color Rand(255),Rand(255),Rand(255)
  193. Plot MouseX(),MouseY();the makeshift cursor
  194. Flip
  195. Wend
  196. End


Comments :


_33(Posted 1+ years ago)

 Very handy, thank you!My pimped up version (for archival purpose):
Code: [Select]
Graphics 800,600,0,2
Global Image = LoadImage("apple_logo_640x480.jpg") ; <---- put image filename here
SetBuffer BackBuffer()
SeedRnd MilliSecs()
While Not KeyDown(1)
Cls
If MouseHit(1) Then FloodFill(Image,MouseX(),MouseY(),Rand(255),Rand(255),Rand(255))
DrawImage Image,0,0
Color 255,255,255
Plot MouseX(),MouseY()
Flip
Wend
End


Type Pixel
Field X,Y
End Type

Function FloodFill(FillImage, Fill_X, Fill_Y, FR, FG, FB)
Local width% = ImageWidth(FillImage)
Local height% = ImageHeight(FillImage)

If Fill_X < 0 Or Fill_X > width - 1 Or Fill_Y < 0 Or Fill_Y > height - 1
Return ; Coords ouside image boundaries
EndIf

Local CurrentBuffer = GraphicsBuffer()
SetBuffer ImageBuffer(FillImage)
LockBuffer

Local Current_RGB% = ReadPixelFast(Fill_X, Fill_Y)

Local RGB% = FB + FG Shl 8 + FR Shl 16
Pixel.Pixel = New Pixel
PixelX = Fill_X
PixelY = Fill_Y
WritePixelFast PixelX,PixelY,RGB

Repeat
Local PixelsRemaining = False
For Pixel.Pixel = Each Pixel
PixelX = PixelX
PixelY = PixelY
PixelLeft = False
PixelAbove = False
PixelRight = False
PixelBelow = False
If PixelX > 0;check left
If Current_RGB = ReadPixelFast(PixelX - 1,PixelY) Then
PixelLeft = True
PixelsRemaining = True
EndIf
EndIf
If PixelY > 0;check above
If Current_RGB = ReadPixelFast(PixelX,PixelY - 1) Then
PixelAbove = True
PixelsRemaining = True
EndIf
EndIf
If PixelX < width - 1;check right
If Current_RGB = ReadPixelFast(PixelX + 1,PixelY) Then
PixelRight = True
PixelsRemaining = True
EndIf
EndIf
If PixelY < height - 1;check below
If Current_RGB = ReadPixelFast(PixelX,PixelY + 1) Then
PixelBelow = True
PixelsRemaining = True
EndIf
EndIf
Delete Pixel
If PixelLeft = True
Pixel.Pixel = New Pixel
PixelX = PixelX - 1
PixelY = PixelY
PixelLeft = False
WritePixelFast PixelX,PixelY,RGB
EndIf
If PixelAbove = True
Pixel.Pixel = New Pixel
PixelX = PixelX
PixelY = PixelY - 1
PixelAbove = False
WritePixelFast PixelX,PixelY,RGB
EndIf
If PixelRight = True
Pixel.Pixel = New Pixel
PixelX = PixelX + 1
PixelY = PixelY
PixelRight = False
WritePixelFast PixelX,PixelY,RGB
EndIf
If PixelBelow = True
Pixel.Pixel = New Pixel
PixelX = PixelX
PixelY = PixelY + 1
PixelBelow = False
WritePixelFast PixelX,PixelY,RGB
EndIf
Next
Until PixelsRemaining = False
UnlockBuffer
SetBuffer CurrentBuffer
End Function


 

SimplePortal 2.3.6 © 2008-2014, SimplePortal