-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmix.go
139 lines (113 loc) · 2.54 KB
/
mix.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
package color
import (
"math"
"github.com/shelepuginivan/color/internal/degrees"
"github.com/shelepuginivan/color/internal/percents"
)
// MixCMYK calculates the average color in CMYK colorspace from an arbitrary
// number of colors.
func MixCMYK(colors ...Color) *CMYK {
if len(colors) == 0 {
return &CMYK{0, 0, 0, 0}
}
var (
c, m, y, k float64
total = float64(len(colors))
)
for _, color := range colors {
cmyk := color.CMYK()
c += percents.ToFloat(cmyk.C)
m += percents.ToFloat(cmyk.M)
y += percents.ToFloat(cmyk.Y)
k += percents.ToFloat(cmyk.K)
}
return &CMYK{
C: percents.FromFloat(c / total),
M: percents.FromFloat(m / total),
Y: percents.FromFloat(y / total),
K: percents.FromFloat(k / total),
}
}
// MixHSL calculates the average color in HSL colorspace from an arbitrary
// number of colors.
func MixHSL(colors ...Color) *HSL {
if len(colors) == 0 {
return &HSL{0, 0, 0}
}
var (
sumX = 0.0
sumY = 0.0
sumS = 0.0
sumL = 0.0
n = float64(len(colors))
)
for _, color := range colors {
hsl := color.HSL()
// Convert hue to radians
rad := degrees.ToRadians(hsl.H)
// Convert hue to a point on a circle
sumX += math.Cos(rad)
sumY += math.Sin(rad)
// Sum up saturation and lightness
sumS += float64(hsl.S)
sumL += float64(hsl.L)
}
// Average the points on the circle and convert back to hue.
var (
arctan = math.Atan2(sumY/n, sumX/n)
avgH = degrees.FromRadians(arctan)
)
// Average saturation and lightness.
var (
avgS = int(math.Round(sumS / n))
avgL = int(math.Round(sumL / n))
)
return &HSL{avgH, avgS, avgL}
}
// MixLab calculates the average color in Lab colorspace from an arbitrary
// number of colors.
func MixLab(colors ...Color) *Lab {
if len(colors) == 0 {
return &Lab{0, 0, 0}
}
var (
sumL = 0.0
sumA = 0.0
sumB = 0.0
total = float64(len(colors))
)
for _, color := range colors {
lab := color.Lab()
sumL += lab.L
sumA += lab.A
sumB += lab.B
}
var (
avgL = sumL / total
avgA = sumA / total
avgB = sumB / total
)
return &Lab{avgL, avgA, avgB}
}
// MixRGB calculates the average color in RGB colorspace from an arbitrary
// number of colors.
func MixRGB(colors ...Color) *RGB {
if len(colors) == 0 {
return &RGB{0, 0, 0}
}
var (
r, g, b float64
total = float64(len(colors))
)
for _, color := range colors {
rgb := color.RGB()
r += float64(rgb.R)
g += float64(rgb.G)
b += float64(rgb.B)
}
return &RGB{
R: uint8(math.Round(r / total)),
G: uint8(math.Round(g / total)),
B: uint8(math.Round(b / total)),
}
}