Files
go-maze/maze/render.go

107 lines
2.5 KiB
Go
Raw Permalink Normal View History

2026-02-26 13:45:37 +02:00
package maze
import (
"fmt"
"image"
"image/color"
"image/png"
"os"
)
var (
// DefaultWallColor is used for wall cells.
DefaultWallColor = color.RGBA{R: 0, G: 0, B: 0, A: 255}
// DefaultPathColor is used for open maze cells.
DefaultPathColor = color.RGBA{R: 255, G: 255, B: 255, A: 255}
// DefaultSolutionColor is used to highlight solution cells.
DefaultSolutionColor = color.RGBA{R: 0, G: 180, B: 0, A: 255}
)
// RenderOptions controls how a maze image is rendered.
type RenderOptions struct {
Scale int
WallColor color.RGBA
PathColor color.RGBA
SolutionColor color.RGBA
HighlightPath bool
}
// DefaultRenderOptions returns baseline rendering options.
func DefaultRenderOptions() RenderOptions {
return RenderOptions{
Scale: 5,
WallColor: DefaultWallColor,
PathColor: DefaultPathColor,
SolutionColor: DefaultSolutionColor,
HighlightPath: false,
}
}
// RenderImage converts a maze grid into an RGBA image.
//
// If options.HighlightPath is true, Solve is used and solution cells are painted
// with options.SolutionColor.
func RenderImage(grid Grid, options RenderOptions) (*image.RGBA, error) {
width, height, err := validateGrid(grid)
if err != nil {
return nil, err
}
if options.Scale <= 0 {
return nil, fmt.Errorf("scale must be greater than zero")
}
img := image.NewRGBA(image.Rect(0, 0, width*options.Scale, height*options.Scale))
var solutionPath [][]bool
if options.HighlightPath {
solutionPath, err = Solve(grid)
if err != nil {
return nil, err
}
}
for cellY := 0; cellY < height; cellY++ {
startY := cellY * options.Scale
for cellX := 0; cellX < width; cellX++ {
startX := cellX * options.Scale
pixel := options.WallColor
if grid[cellY][cellX] == 1 {
pixel = options.PathColor
if options.HighlightPath && solutionPath[cellY][cellX] {
pixel = options.SolutionColor
}
}
for dy := 0; dy < options.Scale; dy++ {
row := img.Pix[(startY+dy)*img.Stride:]
for dx := 0; dx < options.Scale; dx++ {
offset := (startX + dx) * 4
row[offset+0] = pixel.R
row[offset+1] = pixel.G
row[offset+2] = pixel.B
row[offset+3] = pixel.A
}
}
}
}
return img, nil
}
// SavePNG renders a maze image and writes it to a PNG file.
func SavePNG(grid Grid, outputPath string, options RenderOptions) error {
img, err := RenderImage(grid, options)
if err != nil {
return err
}
f, err := os.Create(outputPath)
if err != nil {
return err
}
defer f.Close()
return png.Encode(f, img)
}