-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
91 lines (80 loc) · 2.04 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
package main
import (
"encoding/json"
"flag"
"fmt"
"github.com/nfnt/resize"
"github.com/timrourke/swatchout/kmeans"
"image"
_ "image/gif"
_ "image/jpeg"
_ "image/png"
"log"
"os"
)
type rgbaOutput struct {
R int `json:"r"`
G int `json:"g"`
B int `json:"b"`
A float32 `json:"a"`
}
func main() {
// Take in `-numcolors={int} "{path_to_file.jpg}"` command-line args
numColors := flag.Int("numcolors", 5, "Number of colors to generate")
flag.Parse()
filePath := flag.Args()
if len(filePath) == 0 {
log.Fatal("Must specify a filename.")
}
// Read in image
reader, err := os.Open(filePath[0])
if err != nil {
log.Fatal(err)
}
defer reader.Close()
// Decode image
originalImage, _, err := image.Decode(reader)
if err != nil {
log.Fatal(err)
}
// Resize image to fit within 200x200 pixels (larger images do not improve
// the selection of colors for a palette significantly)
m := resize.Resize(200, 200, originalImage, resize.NearestNeighbor)
bounds := m.Bounds()
// Construct a slice containing rgba values for every pixel in the image
lengthX := bounds.Max.X - bounds.Min.X
lengthY := bounds.Max.Y - bounds.Min.Y
dimensions := lengthX * lengthY
pixels := make([][]float64, dimensions, dimensions)
pixelNum := 0
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
for x := bounds.Min.X; x < bounds.Max.X; x++ {
r, g, b, a := m.At(x, y).RGBA()
rF := float64(r)
gF := float64(g)
bF := float64(b)
aF := float64(a)
pixels[pixelNum] = []float64{rF, gF, bF, aF}
pixelNum++
}
}
// Run a k-means algorithm to group colors into clusters
swatch, _ := kmeans.Cluster(pixels, *numColors)
// Build structs for json output
output := make([]rgbaOutput, *numColors, *numColors)
for idx, rgba := range swatch {
color := rgbaOutput{
R: int(rgba[0]+1) >> 8,
G: int(rgba[1]+1) >> 8,
B: int(rgba[2]+1) >> 8,
A: float32((rgba[3] + 1) / 65536),
}
output[idx] = color
}
// Encode json
jsonOutput, err := json.Marshal(output)
if err != nil {
fmt.Println("error:", err)
}
os.Stdout.Write(jsonOutput)
}