Path-From-Image

BlitzMax Forums/BlitzMax Programming/Path-From-Image

SpaceAce(Posted 2007) [#1]
I don't usually release code this sloppy or incomplete, but I couldn't find anything like it on this site, so I thought I'd share. If this belongs somewhere else, mods please move it.

Simple path extractor:

This code reads an image and extracts a path from it. You supply an image and a starting pixel (the starting pixel should be at one extreme end of the path). Starting from the starting pixel, the code traces the path until it reaches the end of the path.

* This code is for simple paths; the path cannot intersect or touch itself.
* All pixels on the path must have the exact same alpha, red, green and blue components.
* The path must be exactly one pixel wide in all places.
* This simple path extractor generates code to be plugged into your program. Right now, it is configured to generate code for use with sswift's sprite library. Modify the "Cs = " lines to suit your coding needs.

To use:

Draw a path in an image processing program (all one color and alpha), save the image and replace "CirclePath.png" with the correct filename.

Set the StartX and StartY values to the first pixel of the desired path.

Change the "CS = " lines to suit your needs.

Compile and run.

Global StartX# = 799, StartY# = 195
Global X# = StartX, Y# = StartY
Global LastPixel = -1 ' 0 = down, 1 = left, 2 = up, 3 = right, 4 = bottom right, 5 = bottom left, 6 = top left, 7 = top right
Global argb%
Global Cs$ = "", Code:TList = New TList
Global PM:TPixmap = LockImage(LoadImage("CirclePath.png"))
Global OutFile$ = "code.txt"
Global stream:TStream = OpenStream(OutFile, False, True)

argb = ReadPixel(PM, X, Y)
Cs = "MyPath.AddPoint(" + X + ", " + Y +", True, False)"
Code.AddLast(Cs)

While (GetNextPixel() <> 0)
  Cs = "MyPath.AddPoint(" + X + ", " + Y +", False, False)"
  Code.AddLast(Cs)
Wend

While (Code.Count() > 0)
	stream.WriteLine(String(Code.RemoveFirst()))
WEnd

Print "Done"

Function GetNextPixel()
	If (Y+1 < PM.height And LastPixel <> 0 And ReadPixel(PM, X, Y+1) = argb) Y = Y+1 ; LastPixel = 2 ; Return True
	If (X-1 >= 0 And LastPixel <> 1 And ReadPixel(PM, X-1, Y) = argb) X = X-1 ; LastPixel = 3 ; Return True
	If (Y-1 >= 0 And LastPixel <> 2 And ReadPixel(PM, X, Y-1) = argb) Y = Y-1 ; LastPixel = 0 ; Return True
	If (X+1 < PM.width And LastPixel <> 3 And ReadPixel(PM, X+1, Y) = argb) X = X+1 ; LastPixel = 1 ; Return True
	If (X+1 < PM.width And Y+1 < PM.height And LastPixel <> 4 And ReadPixel(PM, X+1, Y+1) = argb) X = X+1 ; Y = Y+1 ; LastPixel = 6 ; Return True
	If (X-1 >= 0 And Y+1 < PM.height And LastPixel <> 5 And ReadPixel(PM, X-1, Y+1) = argb) X = X-1 ; Y = Y+1 ; LastPixel = 7 ; Return True
	If (X-1 >= 0 And Y-1 >= 0 And LastPixel <> 6 And ReadPixel(PM, X-1, Y-1) = argb) X = X-1 ; Y = Y-1 ; LastPixel = 4 ; Return True
	If (X+1 < PM.width And Y-1 >= 0 And LastPixel <> 7 And ReadPixel(PM, X+1, Y-1) = argb) X = X+1 ; Y = Y-1 ; LastPixel = 5 ; Return True
	Return False
End Function


I'd love to see this expanded on to handle self-intersecting paths, an interface, etc, but I don't think I will ever get around to it since this is working beautifully for me, so far.

SpaceAce