commit 2f396d314b763f57bfc17f62a06dc9a5b36ac417 Author: mr0xb Date: Tue Dec 9 00:20:02 2025 -0500 initial commit diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..b972d17 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/mr0xb/spritestitch + +go 1.23 diff --git a/main.go b/main.go new file mode 100644 index 0000000..c01c6a3 --- /dev/null +++ b/main.go @@ -0,0 +1,113 @@ +package main + +import ( + "flag" + "fmt" + "image" + "image/draw" + _ "image/gif" + _ "image/jpeg" + "image/png" + "os" +) + +func main() { + outputPath := flag.String("o", "output.png", "output spritesheet path") + direction := flag.String("direction", "h", "join direction: h (horizontal) or v (vertical)") + flag.Parse() + + inputPaths := flag.Args() + if len(inputPaths) == 0 { + fmt.Println("Usage: spritestitch -o output.png [-direction h|v] sheet1.png sheet2.png ...") + os.Exit(1) + } + + if *direction != "h" && *direction != "v" { + fmt.Println("direction must be 'h' (horizontal) or 'v' (vertical)") + os.Exit(1) + } + + var images []image.Image + var bounds []image.Rectangle + + for _, path := range inputPaths { + imgFile, err := os.Open(path) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to open %s: %v\n", path, err) + os.Exit(1) + } + + img, _, err := image.Decode(imgFile) + imgFile.Close() + if err != nil { + fmt.Fprintf(os.Stderr, "failed to decode %s: %v\n", path, err) + os.Exit(1) + } + + images = append(images, img) + bounds = append(bounds, img.Bounds()) + } + + var totalWidth, totalHeight int + if *direction == "h" { + maxHeight := 0 + sumWidth := 0 + for _, b := range bounds { + w := b.Dx() + h := b.Dy() + sumWidth += w + if h > maxHeight { + maxHeight = h + } + } + totalWidth = sumWidth + totalHeight = maxHeight + } else { + maxWidth := 0 + sumHeight := 0 + for _, b := range bounds { + w := b.Dx() + h := b.Dy() + sumHeight += h + if w > maxWidth { + maxWidth = w + } + } + totalWidth = maxWidth + totalHeight = sumHeight + } + + outImg := image.NewRGBA(image.Rect(0, 0, totalWidth, totalHeight)) + + offsetX, offsetY := 0, 0 + for i, img := range images { + b := bounds[i] + w := b.Dx() + h := b.Dy() + + var dstRect image.Rectangle + if *direction == "h" { + dstRect = image.Rect(offsetX, 0, offsetX+w, h) + offsetX += w + } else { + dstRect = image.Rect(0, offsetY, w, offsetY+h) + offsetY += h + } + + draw.Draw(outImg, dstRect, img, b.Min, draw.Over) + } + + outFile, err := os.Create(*outputPath) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to create output file: %v\n", err) + os.Exit(1) + } + defer outFile.Close() + + if err := png.Encode(outFile, outImg); err != nil { + fmt.Fprintf(os.Stderr, "failed to encode PNG: %v\n", err) + os.Exit(1) + } + + fmt.Printf("Spritesheet written to %s\n", *outputPath) +}