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
|
package colors
import (
"fmt"
"math"
)
type HSL struct {
H int // 0-360
S int // 0-100
L int // 0-100
}
func (h HSL) String() string {
return fmt.Sprintf("hsl(%d, %d%%, %d%%)", h.H, h.S, h.L)
}
func (h HSL) ToPrecise() PreciseColor {
// Normalize H, S, L
hue := float64(h.H) / 360.0
sat := float64(h.S) / 100.0
light := float64(h.L) / 100.0
var r, g, b float64
if sat == 0 {
// Achromatic case
r, g, b = light, light, light
} else {
var q float64
if light < 0.5 {
q = light * (1 + sat)
} else {
q = light + sat - (light * sat)
}
p := 2*light - q
r = hueToRGB(p, q, hue+1.0/3.0)
g = hueToRGB(p, q, hue)
b = hueToRGB(p, q, hue-1.0/3.0)
}
return PreciseColor{R: r, G: g, B: b}
}
func hueToRGB(p, q, t float64) float64 {
if t < 0 {
t += 1
}
if t > 1 {
t -= 1
}
if t < 1.0/6.0 {
return p + (q-p)*6*t
}
if t < 1.0/2.0 {
return q
}
if t < 2.0/3.0 {
return p + (q-p)*(2.0/3.0-t)*6
}
return p
}
func (h HSL) FromPrecise(p PreciseColor) ColorSpace {
r := p.R
g := p.G
b := p.B
max := math.Max(math.Max(r, g), b)
min := math.Min(math.Min(r, g), b)
delta := max - min
light := (max + min) / 2
var sat, hue float64
if delta == 0 {
// Achromatic case
hue, sat = 0, 0
} else {
if light < 0.5 {
sat = delta / (max + min)
} else {
sat = delta / (2 - max - min)
}
switch max {
case r:
hue = (g-b)/delta + (6 * boolToFloat64(g < b))
case g:
hue = (b-r)/delta + 2
case b:
hue = (r-g)/delta + 4
}
hue /= 6
}
return HSL{
H: int(math.Round(hue * 360)),
S: int(math.Round(sat * 100)),
L: int(math.Round(light * 100)),
}
}
func boolToFloat64(b bool) float64 {
if b {
return 1
}
return 0
}
|