-
Notifications
You must be signed in to change notification settings - Fork 4
/
combine-images.go
103 lines (90 loc) · 1.7 KB
/
combine-images.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
package main
import (
"flag"
"fmt"
"image"
"image/draw"
"log"
"os"
"strconv"
"strings"
"text/scanner"
"github.com/qeedquan/go-media/image/imageutil"
)
var (
rule = flag.String("r", "", "specify ruleset")
)
func main() {
log.SetFlags(0)
log.SetPrefix("combine-images: ")
flag.Usage = usage
flag.Parse()
if flag.NArg() < 2 {
usage()
}
var imgs []*image.RGBA
args := flag.Args()
for _, arg := range args[:len(args)-1] {
img, err := imageutil.LoadRGBAFile(arg)
ck(err)
imgs = append(imgs, img)
}
out := combine(*rule, imgs)
err := imageutil.WriteRGBAFile(args[len(args)-1], out)
ck(err)
}
func usage() {
fmt.Fprintln(os.Stderr, "usage: combine-images [options] input ... output")
flag.PrintDefaults()
os.Exit(2)
}
func ck(err error) {
if err != nil {
log.Fatal(err)
}
}
func combine(rule string, imgs []*image.RGBA) *image.RGBA {
var (
bounds []image.Rectangle
scan scanner.Scanner
pos image.Point
maxw, maxh int
lineh int
num int
)
scan.Init(strings.NewReader(rule))
for i := 0; i < len(imgs); i++ {
bound := imgs[i].Bounds()
if num > 0 {
num--
} else {
ch := scan.Next()
if ch == ';' {
pos.Y += lineh
lineh = 0
} else if ch == scanner.Int {
text := scan.TokenText()
num, _ = strconv.Atoi(text)
}
}
bound = bound.Add(pos)
maxw += bound.Dx()
lineh = max(lineh, bound.Dy())
pos.X += bound.Dx()
bounds = append(bounds, bound)
}
for _, r := range bounds {
maxh = max(maxh, r.Max.Y)
}
out := image.NewRGBA(image.Rect(0, 0, maxw, maxh))
for i, img := range imgs {
draw.Draw(out, bounds[i], img, image.ZP, draw.Src)
}
return out
}
func max(a, b int) int {
if a > b {
return a
}
return b
}