-
Notifications
You must be signed in to change notification settings - Fork 0
/
mergedimage.go
141 lines (119 loc) · 3.69 KB
/
mergedimage.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package graphics
// https://github.com/ozankasikci/go-image-merge/blob/master/go-image-merge.go
import (
"image"
"image/color"
"image/draw"
)
// Specifies how the grid pixel size should be calculated
type gridSizeMode int
const (
// The size in pixels is fixed for all the grids
fixedGridSize gridSizeMode = iota
// The size in pixels is set to the nth image size
gridSizeFromImage
)
// Grid holds the data for each grid
type Grid struct {
Image image.Image
BackgroundColor color.Color
OffsetX int
OffsetY int
Grids []*Grid
}
// MergedImage is responsible for merging the given images
type MergedImage struct {
Grids []*Grid
ImageCountDX int
ImageCountDY int
BaseDir string
FixedGridSizeX int
FixedGridSizeY int
GridSizeMode gridSizeMode
GridSizeFromNth int
}
// NewMergedImage returns a new *MergedImage instance
func NewMergedImage(grids []*Grid, imageCountDX, imageCountDY int, opts ...func(*MergedImage)) *MergedImage {
mi := &MergedImage{
Grids: grids,
ImageCountDX: imageCountDX,
ImageCountDY: imageCountDY,
}
for _, option := range opts {
option(mi)
}
return mi
}
// OptBaseDir is an functional option to set the BaseDir field
func OptBaseDir(dir string) func(*MergedImage) {
return func(mi *MergedImage) {
mi.BaseDir = dir
}
}
// OptGridSize is an functional option to set the GridSize X & Y
func OptGridSize(sizeX, sizeY int) func(*MergedImage) {
return func(mi *MergedImage) {
mi.GridSizeMode = fixedGridSize
mi.FixedGridSizeX = sizeX
mi.FixedGridSizeY = sizeY
}
}
// OptGridSizeFromNthImageSize is an functional option to set the GridSize from the nth image
func OptGridSizeFromNthImageSize(n int) func(*MergedImage) {
return func(mi *MergedImage) {
mi.GridSizeMode = gridSizeFromImage
mi.GridSizeFromNth = n
}
}
func (m *MergedImage) mergeGrids(images []image.Image) (*image.RGBA, error) {
var canvas *image.RGBA
imageBoundX := 0
imageBoundY := 0
if m.GridSizeMode == fixedGridSize && m.FixedGridSizeX != 0 && m.FixedGridSizeY != 0 {
imageBoundX = m.FixedGridSizeX
imageBoundY = m.FixedGridSizeY
} else if m.GridSizeMode == gridSizeFromImage {
imageBoundX = images[m.GridSizeFromNth].Bounds().Dx()
imageBoundY = images[m.GridSizeFromNth].Bounds().Dy()
} else {
imageBoundX = images[0].Bounds().Dx()
imageBoundY = images[0].Bounds().Dy()
}
canvasBoundX := m.ImageCountDX * imageBoundX
canvasBoundY := m.ImageCountDY * imageBoundY
canvasMaxPoint := image.Point{canvasBoundX, canvasBoundY}
canvasRect := image.Rectangle{image.Point{0, 0}, canvasMaxPoint}
canvas = image.NewRGBA(canvasRect)
// Draw grids one by one
for i, grid := range m.Grids {
img := images[i]
x := i % m.ImageCountDX
y := i / m.ImageCountDX
minPoint := image.Point{x * imageBoundX, y * imageBoundY}
maxPoint := minPoint.Add(image.Point{imageBoundX, imageBoundY})
nextGridRect := image.Rectangle{minPoint, maxPoint}
if grid.BackgroundColor != nil {
draw.Draw(canvas, nextGridRect, &image.Uniform{grid.BackgroundColor}, image.Point{}, draw.Src)
draw.Draw(canvas, nextGridRect, img, image.Point{}, draw.Over)
} else {
draw.Draw(canvas, nextGridRect, img, image.Point{}, draw.Src)
}
if grid.Grids == nil {
continue
}
// Draw top layer grids
for _, grid := range grid.Grids {
gridRect := nextGridRect.Bounds().Add(image.Point{grid.OffsetX, grid.OffsetY})
draw.Draw(canvas, gridRect, grid.Image, image.Point{}, draw.Over)
}
}
return canvas, nil
}
// Merge merges the images according to given configuration
func (m *MergedImage) Merge() (*image.RGBA, error) {
var images []image.Image
for _, grid := range m.Grids {
images = append(images, grid.Image)
}
return m.mergeGrids(images)
}