-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
115 lines (94 loc) · 1.9 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package main
import (
"encoding/json"
"flag"
"fmt"
"image"
"image/draw"
"image/png"
"os"
"path/filepath"
)
type tile struct {
X int `json:"x"`
Y int `json:"y"`
Name string `json:"name"`
Img image.Image `json:"-"`
}
var tiles []*tile
const perRow = 8
var outFile = flag.String("out", "output.png", "png file to write the sprite sheet")
func main() {
flag.Parse()
if len(flag.Args()) < 1 {
fmt.Println("Usage: spritemapper --out /path/to/output.png image1.png image2.png")
os.Exit(1)
}
for _, name := range flag.Args() {
img, err := readPng(name)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
tiles = append(tiles, img)
}
w, h := spriteBounds()
rows := len(tiles) / perRow
canvas := image.NewRGBA(image.Rect(0, 0, perRow*w, h*rows))
x, y := 0, 0
for _, tile := range tiles {
dp := image.Point{x * w, y * h}
fb := tile.Img.Bounds()
r := image.Rectangle{dp.Add(fb.Min), dp.Add(fb.Max)}
tile.X = x
tile.Y = y
draw.Draw(canvas, r, tile.Img, fb.Min, draw.Over)
x += 1
if x >= perRow {
y += 1
x = 0
}
}
out, err := os.Create(*outFile)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if err := png.Encode(out, canvas); err != nil {
fmt.Println(err)
os.Exit(1)
}
tileJson, err := json.Marshal(tiles)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(string(tileJson))
}
func spriteBounds() (w, h int) {
bounds := tiles[0].Img.Bounds()
w, h = bounds.Size().X, bounds.Size().Y
for _, f := range tiles {
bounds = f.Img.Bounds()
if bounds.Size().X > w {
w = bounds.Size().X
}
if bounds.Size().Y > h {
h = bounds.Size().Y
}
}
return
}
func readPng(name string) (*tile, error) {
fileName := filepath.Base(name)
f, err := os.Open(name)
if err != nil {
return nil, err
}
defer f.Close()
img, err := png.Decode(f)
if err != nil {
return nil, err
}
return &tile{Img: img, Name: fileName}, nil
}