func (im *ImageMap) Neighbors(node astar.Node, edges []astar.Edge) ([]astar.Edge, error) { x := int(node) % im.Width y := int(node) / im.Width off := y*im.YStride + x*im.XStride c := im.Pix[off] if x > 0 { edges = append(edges, astar.Edge{Node: node - 1, Cost: 1 + colorCost(c, im.Pix[off-im.XStride])}) if y > 0 { edges = append(edges, astar.Edge{Node: node - 1 - astar.Node(im.Width), Cost: math.Sqrt2 + colorCost(c, im.Pix[off-im.XStride-im.YStride])}) } if y < im.Height-1 { edges = append(edges, astar.Edge{Node: node - 1 + astar.Node(im.Width), Cost: math.Sqrt2 + colorCost(c, im.Pix[off-im.XStride+im.YStride])}) } } if x < im.Width-1 { edges = append(edges, astar.Edge{Node: node + 1, Cost: 1 + colorCost(c, im.Pix[off+im.XStride])}) if y > 0 { edges = append(edges, astar.Edge{Node: node + 1 - astar.Node(im.Width), Cost: math.Sqrt2 + colorCost(c, im.Pix[off+im.XStride-im.YStride])}) } if y < im.Height-1 { edges = append(edges, astar.Edge{Node: node + 1 + astar.Node(im.Width), Cost: math.Sqrt2 + colorCost(c, im.Pix[off+im.XStride+im.YStride])}) } } if y > 0 { edges = append(edges, astar.Edge{Node: node - astar.Node(im.Width), Cost: 1 + colorCost(c, im.Pix[off-im.YStride])}) } if y < im.Height-1 { edges = append(edges, astar.Edge{Node: node + astar.Node(im.Width), Cost: 1 + colorCost(c, im.Pix[off+im.YStride])}) } return edges, nil }
func main() { if len(os.Args) < 2 { log.Fatal("syntax: imagepath [path]") } rd, err := os.Open(os.Args[1]) if err != nil { log.Fatal(err) } defer rd.Close() img, _, err := image.Decode(rd) if err != nil { log.Fatal(err) } log.Println("Processing image") im, err := NewImageMap(img) if err != nil { log.Fatal(err) } if len(os.Args) > 2 { wr, err := os.Create("cpu.prof") if err != nil { log.Fatal(err) } defer wr.Close() if err := pprof.StartCPUProfile(wr); err != nil { log.Fatal(err) } } log.Println("Finding path") var memStats runtime.MemStats runtime.ReadMemStats(&memStats) totalAlloc := memStats.TotalAlloc t := time.Now() path, err := astar.FindPath(im, 0, astar.Node(img.Bounds().Dx()-1+img.Bounds().Dx()*(img.Bounds().Dy()-1))) pprof.StopCPUProfile() if err != nil { log.Fatal(err) } log.Printf("\t%d ms", time.Since(t).Nanoseconds()/1e6) runtime.ReadMemStats(&memStats) log.Printf("\t%d MB allocated", (memStats.TotalAlloc-totalAlloc)/(1024*1024)) log.Printf("Nodes in path: %d", len(path)) log.Println("Rendering path") for _, node := range path { x := int(node) % img.Bounds().Dx() y := int(node) / img.Bounds().Dx() im.Set(x, y, color.RGBA{0, 255, 0, 255}) } log.Println("Encoding/writing output image") wr, err := os.Create("out.jpg") if err != nil { log.Fatal(err) } if err := jpeg.Encode(wr, img, nil); err != nil { log.Fatal(err) } wr.Close() }