1 package colorful
2
3 import (
4 "image/color"
5 "math"
6 "math/rand"
7 "strings"
8 "testing"
9 )
10
11 var bench_result float64
12
13
14 func almosteq_eps(v1, v2, eps float64) bool {
15 if math.Abs(v1) > delta {
16 return math.Abs((v1-v2)/v1) < eps
17 }
18 return true
19 }
20
21
22 const delta = 1.0 / 256.0
23
24 func almosteq(v1, v2 float64) bool {
25 return almosteq_eps(v1, v2, delta)
26 }
27
28
29
30
31
32 var vals = []struct {
33 c Color
34 hsl [3]float64
35 hsv [3]float64
36 hex string
37 xyz [3]float64
38 xyy [3]float64
39 lab [3]float64
40 lab50 [3]float64
41 luv [3]float64
42 luv50 [3]float64
43 hcl [3]float64
44 hcl50 [3]float64
45 rgba [4]uint32
46 rgb255 [3]uint8
47 }{
48 {Color{1.0, 1.0, 1.0}, [3]float64{0.0, 0.0, 1.00}, [3]float64{0.0, 0.0, 1.0}, "#ffffff", [3]float64{0.950470, 1.000000, 1.088830}, [3]float64{0.312727, 0.329023, 1.000000}, [3]float64{1.000000, 0.000000, 0.000000}, [3]float64{1.000000, -0.023881, -0.193622}, [3]float64{1.00000, 0.00000, 0.00000}, [3]float64{1.00000, -0.14716, -0.25658}, [3]float64{0.0000, 0.000000, 1.000000}, [3]float64{262.9688, 0.195089, 1.000000}, [4]uint32{65535, 65535, 65535, 65535}, [3]uint8{255, 255, 255}},
49 {Color{0.5, 1.0, 1.0}, [3]float64{180.0, 1.0, 0.75}, [3]float64{180.0, 0.5, 1.0}, "#80ffff", [3]float64{0.626296, 0.832848, 1.073634}, [3]float64{0.247276, 0.328828, 0.832848}, [3]float64{0.931390, -0.353319, -0.108946}, [3]float64{0.931390, -0.374100, -0.301663}, [3]float64{0.93139, -0.53909, -0.11630}, [3]float64{0.93139, -0.67615, -0.35528}, [3]float64{197.1371, 0.369735, 0.931390}, [3]float64{218.8817, 0.480574, 0.931390}, [4]uint32{32768, 65535, 65535, 65535}, [3]uint8{128, 255, 255}},
50 {Color{1.0, 0.5, 1.0}, [3]float64{300.0, 1.0, 0.75}, [3]float64{300.0, 0.5, 1.0}, "#ff80ff", [3]float64{0.669430, 0.437920, 0.995150}, [3]float64{0.318397, 0.208285, 0.437920}, [3]float64{0.720892, 0.651673, -0.422133}, [3]float64{0.720892, 0.630425, -0.610035}, [3]float64{0.72089, 0.60047, -0.77626}, [3]float64{0.72089, 0.49438, -0.96123}, [3]float64{327.0661, 0.776450, 0.720892}, [3]float64{315.9417, 0.877257, 0.720892}, [4]uint32{65535, 32768, 65535, 65535}, [3]uint8{255, 128, 255}},
51 {Color{1.0, 1.0, 0.5}, [3]float64{60.0, 1.0, 0.75}, [3]float64{60.0, 0.5, 1.0}, "#ffff80", [3]float64{0.808654, 0.943273, 0.341930}, [3]float64{0.386203, 0.450496, 0.943273}, [3]float64{0.977637, -0.165795, 0.602017}, [3]float64{0.977637, -0.188424, 0.470410}, [3]float64{0.97764, 0.05759, 0.79816}, [3]float64{0.97764, -0.08628, 0.54731}, [3]float64{105.3975, 0.624430, 0.977637}, [3]float64{111.8287, 0.506743, 0.977637}, [4]uint32{65535, 65535, 32768, 65535}, [3]uint8{255, 255, 128}},
52 {Color{0.5, 0.5, 1.0}, [3]float64{240.0, 1.0, 0.75}, [3]float64{240.0, 0.5, 1.0}, "#8080ff", [3]float64{0.345256, 0.270768, 0.979954}, [3]float64{0.216329, 0.169656, 0.270768}, [3]float64{0.590453, 0.332846, -0.637099}, [3]float64{0.590453, 0.315806, -0.824040}, [3]float64{0.59045, -0.07568, -1.04877}, [3]float64{0.59045, -0.16257, -1.20027}, [3]float64{297.5843, 0.718805, 0.590453}, [3]float64{290.9689, 0.882482, 0.590453}, [4]uint32{32768, 32768, 65535, 65535}, [3]uint8{128, 128, 255}},
53 {Color{1.0, 0.5, 0.5}, [3]float64{0.0, 1.0, 0.75}, [3]float64{0.0, 0.5, 1.0}, "#ff8080", [3]float64{0.527613, 0.381193, 0.248250}, [3]float64{0.455996, 0.329451, 0.381193}, [3]float64{0.681085, 0.483884, 0.228328}, [3]float64{0.681085, 0.464258, 0.110043}, [3]float64{0.68108, 0.92148, 0.19879}, [3]float64{0.68106, 0.82106, 0.02393}, [3]float64{25.2610, 0.535049, 0.681085}, [3]float64{13.3347, 0.477121, 0.681085}, [4]uint32{65535, 32768, 32768, 65535}, [3]uint8{255, 128, 128}},
54 {Color{0.5, 1.0, 0.5}, [3]float64{120.0, 1.0, 0.75}, [3]float64{120.0, 0.5, 1.0}, "#80ff80", [3]float64{0.484480, 0.776121, 0.326734}, [3]float64{0.305216, 0.488946, 0.776121}, [3]float64{0.906026, -0.600870, 0.498993}, [3]float64{0.906026, -0.619946, 0.369365}, [3]float64{0.90603, -0.58869, 0.76102}, [3]float64{0.90603, -0.72202, 0.52855}, [3]float64{140.2920, 0.781050, 0.906026}, [3]float64{149.2134, 0.721640, 0.906026}, [4]uint32{32768, 65535, 32768, 65535}, [3]uint8{128, 255, 128}},
55 {Color{0.5, 0.5, 0.5}, [3]float64{0.0, 0.0, 0.50}, [3]float64{0.0, 0.0, 0.5}, "#808080", [3]float64{0.203440, 0.214041, 0.233054}, [3]float64{0.312727, 0.329023, 0.214041}, [3]float64{0.533890, 0.000000, 0.000000}, [3]float64{0.533890, -0.014285, -0.115821}, [3]float64{0.53389, 0.00000, 0.00000}, [3]float64{0.53389, -0.07857, -0.13699}, [3]float64{0.0000, 0.000000, 0.533890}, [3]float64{262.9688, 0.116699, 0.533890}, [4]uint32{32768, 32768, 32768, 65535}, [3]uint8{128, 128, 128}},
56 {Color{0.0, 1.0, 1.0}, [3]float64{180.0, 1.0, 0.50}, [3]float64{180.0, 1.0, 1.0}, "#00ffff", [3]float64{0.538014, 0.787327, 1.069496}, [3]float64{0.224656, 0.328760, 0.787327}, [3]float64{0.911132, -0.480875, -0.141312}, [3]float64{0.911132, -0.500630, -0.333781}, [3]float64{0.91113, -0.70477, -0.15204}, [3]float64{0.91113, -0.83886, -0.38582}, [3]float64{196.3762, 0.501209, 0.911132}, [3]float64{213.6923, 0.601698, 0.911132}, [4]uint32{0, 65535, 65535, 65535}, [3]uint8{0, 255, 255}},
57 {Color{1.0, 0.0, 1.0}, [3]float64{300.0, 1.0, 0.50}, [3]float64{300.0, 1.0, 1.0}, "#ff00ff", [3]float64{0.592894, 0.284848, 0.969638}, [3]float64{0.320938, 0.154190, 0.284848}, [3]float64{0.603242, 0.982343, -0.608249}, [3]float64{0.603242, 0.961939, -0.794531}, [3]float64{0.60324, 0.84071, -1.08683}, [3]float64{0.60324, 0.75194, -1.24161}, [3]float64{328.2350, 1.155407, 0.603242}, [3]float64{320.4444, 1.247640, 0.603242}, [4]uint32{65535, 0, 65535, 65535}, [3]uint8{255, 0, 255}},
58 {Color{1.0, 1.0, 0.0}, [3]float64{60.0, 1.0, 0.50}, [3]float64{60.0, 1.0, 1.0}, "#ffff00", [3]float64{0.770033, 0.927825, 0.138526}, [3]float64{0.419320, 0.505246, 0.927825}, [3]float64{0.971393, -0.215537, 0.944780}, [3]float64{0.971393, -0.237800, 0.847398}, [3]float64{0.97139, 0.07706, 1.06787}, [3]float64{0.97139, -0.06590, 0.81862}, [3]float64{102.8512, 0.969054, 0.971393}, [3]float64{105.6754, 0.880131, 0.971393}, [4]uint32{65535, 65535, 0, 65535}, [3]uint8{255, 255, 0}},
59 {Color{0.0, 0.0, 1.0}, [3]float64{240.0, 1.0, 0.50}, [3]float64{240.0, 1.0, 1.0}, "#0000ff", [3]float64{0.180437, 0.072175, 0.950304}, [3]float64{0.150000, 0.060000, 0.072175}, [3]float64{0.322970, 0.791875, -1.078602}, [3]float64{0.322970, 0.778150, -1.263638}, [3]float64{0.32297, -0.09405, -1.30342}, [3]float64{0.32297, -0.14158, -1.38629}, [3]float64{306.2849, 1.338076, 0.322970}, [3]float64{301.6248, 1.484014, 0.322970}, [4]uint32{0, 0, 65535, 65535}, [3]uint8{0, 0, 255}},
60 {Color{0.0, 1.0, 0.0}, [3]float64{120.0, 1.0, 0.50}, [3]float64{120.0, 1.0, 1.0}, "#00ff00", [3]float64{0.357576, 0.715152, 0.119192}, [3]float64{0.300000, 0.600000, 0.715152}, [3]float64{0.877347, -0.861827, 0.831793}, [3]float64{0.877347, -0.879067, 0.739170}, [3]float64{0.87735, -0.83078, 1.07398}, [3]float64{0.87735, -0.95989, 0.84887}, [3]float64{136.0160, 1.197759, 0.877347}, [3]float64{139.9409, 1.148534, 0.877347}, [4]uint32{0, 65535, 0, 65535}, [3]uint8{0, 255, 0}},
61 {Color{1.0, 0.0, 0.0}, [3]float64{0.0, 1.0, 0.50}, [3]float64{0.0, 1.0, 1.0}, "#ff0000", [3]float64{0.412456, 0.212673, 0.019334}, [3]float64{0.640000, 0.330000, 0.212673}, [3]float64{0.532408, 0.800925, 0.672032}, [3]float64{0.532408, 0.782845, 0.621518}, [3]float64{0.53241, 1.75015, 0.37756}, [3]float64{0.53241, 1.67180, 0.24096}, [3]float64{39.9990, 1.045518, 0.532408}, [3]float64{38.4469, 0.999566, 0.532408}, [4]uint32{65535, 0, 0, 65535}, [3]uint8{255, 0, 0}},
62 {Color{0.0, 0.0, 0.0}, [3]float64{0.0, 0.0, 0.00}, [3]float64{0.0, 0.0, 0.0}, "#000000", [3]float64{0.000000, 0.000000, 0.000000}, [3]float64{0.312727, 0.329023, 0.000000}, [3]float64{0.000000, 0.000000, 0.000000}, [3]float64{0.000000, 0.000000, 0.000000}, [3]float64{0.00000, 0.00000, 0.00000}, [3]float64{0.00000, 0.00000, 0.00000}, [3]float64{0.0000, 0.000000, 0.000000}, [3]float64{0.0000, 0.000000, 0.000000}, [4]uint32{0, 0, 0, 65535}, [3]uint8{0, 0, 0}},
63 }
64
65
66
67 var shorthexvals = []struct {
68 c Color
69 hex string
70 }{
71 {Color{1.0, 1.0, 1.0}, "#fff"},
72 {Color{0.6, 1.0, 1.0}, "#9ff"},
73 {Color{1.0, 0.6, 1.0}, "#f9f"},
74 {Color{1.0, 1.0, 0.6}, "#ff9"},
75 {Color{0.6, 0.6, 1.0}, "#99f"},
76 {Color{1.0, 0.6, 0.6}, "#f99"},
77 {Color{0.6, 1.0, 0.6}, "#9f9"},
78 {Color{0.6, 0.6, 0.6}, "#999"},
79 {Color{0.0, 1.0, 1.0}, "#0ff"},
80 {Color{1.0, 0.0, 1.0}, "#f0f"},
81 {Color{1.0, 1.0, 0.0}, "#ff0"},
82 {Color{0.0, 0.0, 1.0}, "#00f"},
83 {Color{0.0, 1.0, 0.0}, "#0f0"},
84 {Color{1.0, 0.0, 0.0}, "#f00"},
85 {Color{0.0, 0.0, 0.0}, "#000"},
86 }
87
88
89
90
91 func TestRGBAConversion(t *testing.T) {
92 for i, tt := range vals {
93 r, g, b, a := tt.c.RGBA()
94 if r != tt.rgba[0] || g != tt.rgba[1] || b != tt.rgba[2] || a != tt.rgba[3] {
95 t.Errorf("%v. %v.RGBA() => (%v), want %v (delta %v)", i, tt.c, []uint32{r, g, b, a}, tt.rgba, delta)
96 }
97 }
98 }
99
100
101
102
103 func TestRGB255Conversion(t *testing.T) {
104 for i, tt := range vals {
105 r, g, b := tt.c.RGB255()
106 if r != tt.rgb255[0] || g != tt.rgb255[1] || b != tt.rgb255[2] {
107 t.Errorf("%v. %v.RGB255() => (%v), want %v (delta %v)", i, tt.c, []uint8{r, g, b}, tt.rgb255, delta)
108 }
109 }
110 }
111
112
113
114
115 func TestHsvCreation(t *testing.T) {
116 for i, tt := range vals {
117 c := Hsv(tt.hsv[0], tt.hsv[1], tt.hsv[2])
118 if !c.AlmostEqualRgb(tt.c) {
119 t.Errorf("%v. Hsv(%v) => (%v), want %v (delta %v)", i, tt.hsv, c, tt.c, delta)
120 }
121 }
122 }
123
124 func TestHsvConversion(t *testing.T) {
125 for i, tt := range vals {
126 h, s, v := tt.c.Hsv()
127 if !almosteq(h, tt.hsv[0]) || !almosteq(s, tt.hsv[1]) || !almosteq(v, tt.hsv[2]) {
128 t.Errorf("%v. %v.Hsv() => (%v), want %v (delta %v)", i, tt.c, []float64{h, s, v}, tt.hsv, delta)
129 }
130 }
131 }
132
133
134
135
136 func TestHslCreation(t *testing.T) {
137 for i, tt := range vals {
138 c := Hsl(tt.hsl[0], tt.hsl[1], tt.hsl[2])
139 if !c.AlmostEqualRgb(tt.c) {
140 t.Errorf("%v. Hsl(%v) => (%v), want %v (delta %v)", i, tt.hsl, c, tt.c, delta)
141 }
142 }
143 }
144
145 func TestHslConversion(t *testing.T) {
146 for i, tt := range vals {
147 h, s, l := tt.c.Hsl()
148 if !almosteq(h, tt.hsl[0]) || !almosteq(s, tt.hsl[1]) || !almosteq(l, tt.hsl[2]) {
149 t.Errorf("%v. %v.Hsl() => (%v), want %v (delta %v)", i, tt.c, []float64{h, s, l}, tt.hsl, delta)
150 }
151 }
152 }
153
154
155
156
157 func TestHexCreation(t *testing.T) {
158 for i, tt := range vals {
159 c, err := Hex(tt.hex)
160 if err != nil || !c.AlmostEqualRgb(tt.c) {
161 t.Errorf("%v. Hex(%v) => (%v), want %v (delta %v)", i, tt.hex, c, tt.c, delta)
162 }
163 }
164 }
165
166 func TestHEXCreation(t *testing.T) {
167 for i, tt := range vals {
168 c, err := Hex(strings.ToUpper(tt.hex))
169 if err != nil || !c.AlmostEqualRgb(tt.c) {
170 t.Errorf("%v. HEX(%v) => (%v), want %v (delta %v)", i, strings.ToUpper(tt.hex), c, tt.c, delta)
171 }
172 }
173 }
174
175 func TestShortHexCreation(t *testing.T) {
176 for i, tt := range shorthexvals {
177 c, err := Hex(tt.hex)
178 if err != nil || !c.AlmostEqualRgb(tt.c) {
179 t.Errorf("%v. Hex(%v) => (%v), want %v (delta %v)", i, tt.hex, c, tt.c, delta)
180 }
181 }
182 }
183
184 func TestShortHEXCreation(t *testing.T) {
185 for i, tt := range shorthexvals {
186 c, err := Hex(strings.ToUpper(tt.hex))
187 if err != nil || !c.AlmostEqualRgb(tt.c) {
188 t.Errorf("%v. Hex(%v) => (%v), want %v (delta %v)", i, strings.ToUpper(tt.hex), c, tt.c, delta)
189 }
190 }
191 }
192
193 func TestHexConversion(t *testing.T) {
194 for i, tt := range vals {
195 hex := tt.c.Hex()
196 if hex != tt.hex {
197 t.Errorf("%v. %v.Hex() => (%v), want %v (delta %v)", i, tt.c, hex, tt.hex, delta)
198 }
199 }
200 }
201
202
203
204
205
206
207 func TestFastLinearRgb(t *testing.T) {
208 const eps = 6.0 / 255.0
209
210 for r := 0.0; r < 256.0; r++ {
211 for g := 0.0; g < 256.0; g++ {
212 for b := 0.0; b < 256.0; b++ {
213 c := Color{r / 255.0, g / 255.0, b / 255.0}
214 r_want, g_want, b_want := c.LinearRgb()
215 r_appr, g_appr, b_appr := c.FastLinearRgb()
216 dr, dg, db := math.Abs(r_want-r_appr), math.Abs(g_want-g_appr), math.Abs(b_want-b_appr)
217 if dr+dg+db > eps {
218 t.Errorf("FastLinearRgb not precise enough for %v: differences are (%v, %v, %v), allowed total difference is %v", c, dr, dg, db, eps)
219 return
220 }
221
222 c_want := LinearRgb(r/255.0, g/255.0, b/255.0)
223 c_appr := FastLinearRgb(r/255.0, g/255.0, b/255.0)
224 dr, dg, db = math.Abs(c_want.R-c_appr.R), math.Abs(c_want.G-c_appr.G), math.Abs(c_want.B-c_appr.B)
225 if dr+dg+db > eps {
226 t.Errorf("FastLinearRgb not precise enough for (%v, %v, %v): differences are (%v, %v, %v), allowed total difference is %v", r, g, b, dr, dg, db, eps)
227 return
228 }
229 }
230 }
231 }
232 }
233
234
235
236
237 func BenchmarkColorToLinear(bench *testing.B) {
238 var r, g, b float64
239 for n := 0; n < bench.N; n++ {
240 r, g, b = Color{rand.Float64(), rand.Float64(), rand.Float64()}.LinearRgb()
241 }
242 bench_result = r + g + b
243 }
244
245 func BenchmarkFastColorToLinear(bench *testing.B) {
246 var r, g, b float64
247 for n := 0; n < bench.N; n++ {
248 r, g, b = Color{rand.Float64(), rand.Float64(), rand.Float64()}.FastLinearRgb()
249 }
250 bench_result = r + g + b
251 }
252
253 func BenchmarkLinearToColor(bench *testing.B) {
254 var c Color
255 for n := 0; n < bench.N; n++ {
256 c = LinearRgb(rand.Float64(), rand.Float64(), rand.Float64())
257 }
258 bench_result = c.R + c.G + c.B
259 }
260
261 func BenchmarkFastLinearToColor(bench *testing.B) {
262 var c Color
263 for n := 0; n < bench.N; n++ {
264 c = FastLinearRgb(rand.Float64(), rand.Float64(), rand.Float64())
265 }
266 bench_result = c.R + c.G + c.B
267 }
268
269
270
271 func TestXyzCreation(t *testing.T) {
272 for i, tt := range vals {
273 c := Xyz(tt.xyz[0], tt.xyz[1], tt.xyz[2])
274 if !c.AlmostEqualRgb(tt.c) {
275 t.Errorf("%v. Xyz(%v) => (%v), want %v (delta %v)", i, tt.xyz, c, tt.c, delta)
276 }
277 }
278 }
279
280 func TestXyzConversion(t *testing.T) {
281 for i, tt := range vals {
282 x, y, z := tt.c.Xyz()
283 if !almosteq(x, tt.xyz[0]) || !almosteq(y, tt.xyz[1]) || !almosteq(z, tt.xyz[2]) {
284 t.Errorf("%v. %v.Xyz() => (%v), want %v (delta %v)", i, tt.c, [3]float64{x, y, z}, tt.xyz, delta)
285 }
286 }
287 }
288
289
290
291 func TestXyyCreation(t *testing.T) {
292 for i, tt := range vals {
293 c := Xyy(tt.xyy[0], tt.xyy[1], tt.xyy[2])
294 if !c.AlmostEqualRgb(tt.c) {
295 t.Errorf("%v. Xyy(%v) => (%v), want %v (delta %v)", i, tt.xyy, c, tt.c, delta)
296 }
297 }
298 }
299
300 func TestXyyConversion(t *testing.T) {
301 for i, tt := range vals {
302 x, y, Y := tt.c.Xyy()
303 if !almosteq(x, tt.xyy[0]) || !almosteq(y, tt.xyy[1]) || !almosteq(Y, tt.xyy[2]) {
304 t.Errorf("%v. %v.Xyy() => (%v), want %v (delta %v)", i, tt.c, [3]float64{x, y, Y}, tt.xyy, delta)
305 }
306 }
307 }
308
309
310
311 func TestLabCreation(t *testing.T) {
312 for i, tt := range vals {
313 c := Lab(tt.lab[0], tt.lab[1], tt.lab[2])
314 if !c.AlmostEqualRgb(tt.c) {
315 t.Errorf("%v. Lab(%v) => (%v), want %v (delta %v)", i, tt.lab, c, tt.c, delta)
316 }
317 }
318 }
319
320 func TestLabConversion(t *testing.T) {
321 for i, tt := range vals {
322 l, a, b := tt.c.Lab()
323 if !almosteq(l, tt.lab[0]) || !almosteq(a, tt.lab[1]) || !almosteq(b, tt.lab[2]) {
324 t.Errorf("%v. %v.Lab() => (%v), want %v (delta %v)", i, tt.c, [3]float64{l, a, b}, tt.lab, delta)
325 }
326 }
327 }
328
329 func TestLabWhiteRefCreation(t *testing.T) {
330 for i, tt := range vals {
331 c := LabWhiteRef(tt.lab50[0], tt.lab50[1], tt.lab50[2], D50)
332 if !c.AlmostEqualRgb(tt.c) {
333 t.Errorf("%v. LabWhiteRef(%v, D50) => (%v), want %v (delta %v)", i, tt.lab50, c, tt.c, delta)
334 }
335 }
336 }
337
338 func TestLabWhiteRefConversion(t *testing.T) {
339 for i, tt := range vals {
340 l, a, b := tt.c.LabWhiteRef(D50)
341 if !almosteq(l, tt.lab50[0]) || !almosteq(a, tt.lab50[1]) || !almosteq(b, tt.lab50[2]) {
342 t.Errorf("%v. %v.LabWhiteRef(D50) => (%v), want %v (delta %v)", i, tt.c, [3]float64{l, a, b}, tt.lab50, delta)
343 }
344 }
345 }
346
347
348
349 func TestLuvCreation(t *testing.T) {
350 for i, tt := range vals {
351 c := Luv(tt.luv[0], tt.luv[1], tt.luv[2])
352 if !c.AlmostEqualRgb(tt.c) {
353 t.Errorf("%v. Luv(%v) => (%v), want %v (delta %v)", i, tt.luv, c, tt.c, delta)
354 }
355 }
356 }
357
358 func TestLuvConversion(t *testing.T) {
359 for i, tt := range vals {
360 l, u, v := tt.c.Luv()
361 if !almosteq(l, tt.luv[0]) || !almosteq(u, tt.luv[1]) || !almosteq(v, tt.luv[2]) {
362 t.Errorf("%v. %v.Luv() => (%v), want %v (delta %v)", i, tt.c, [3]float64{l, u, v}, tt.luv, delta)
363 }
364 }
365 }
366
367 func TestLuvWhiteRefCreation(t *testing.T) {
368 for i, tt := range vals {
369 c := LuvWhiteRef(tt.luv50[0], tt.luv50[1], tt.luv50[2], D50)
370 if !c.AlmostEqualRgb(tt.c) {
371 t.Errorf("%v. LuvWhiteRef(%v, D50) => (%v), want %v (delta %v)", i, tt.luv50, c, tt.c, delta)
372 }
373 }
374 }
375
376 func TestLuvWhiteRefConversion(t *testing.T) {
377 for i, tt := range vals {
378 l, u, v := tt.c.LuvWhiteRef(D50)
379 if !almosteq(l, tt.luv50[0]) || !almosteq(u, tt.luv50[1]) || !almosteq(v, tt.luv50[2]) {
380 t.Errorf("%v. %v.LuvWhiteRef(D50) => (%v), want %v (delta %v)", i, tt.c, [3]float64{l, u, v}, tt.luv50, delta)
381 }
382 }
383 }
384
385
386
387
388 func TestHclCreation(t *testing.T) {
389 for i, tt := range vals {
390 c := Hcl(tt.hcl[0], tt.hcl[1], tt.hcl[2])
391 if !c.AlmostEqualRgb(tt.c) {
392 t.Errorf("%v. Hcl(%v) => (%v), want %v (delta %v)", i, tt.hcl, c, tt.c, delta)
393 }
394 }
395 }
396
397 func TestHclConversion(t *testing.T) {
398 for i, tt := range vals {
399 h, c, l := tt.c.Hcl()
400 if !almosteq(h, tt.hcl[0]) || !almosteq(c, tt.hcl[1]) || !almosteq(l, tt.hcl[2]) {
401 t.Errorf("%v. %v.Hcl() => (%v), want %v (delta %v)", i, tt.c, [3]float64{h, c, l}, tt.hcl, delta)
402 }
403 }
404 }
405
406 func TestHclWhiteRefCreation(t *testing.T) {
407 for i, tt := range vals {
408 c := HclWhiteRef(tt.hcl50[0], tt.hcl50[1], tt.hcl50[2], D50)
409 if !c.AlmostEqualRgb(tt.c) {
410 t.Errorf("%v. HclWhiteRef(%v, D50) => (%v), want %v (delta %v)", i, tt.hcl50, c, tt.c, delta)
411 }
412 }
413 }
414
415 func TestHclWhiteRefConversion(t *testing.T) {
416 for i, tt := range vals {
417 h, c, l := tt.c.HclWhiteRef(D50)
418 if !almosteq(h, tt.hcl50[0]) || !almosteq(c, tt.hcl50[1]) || !almosteq(l, tt.hcl50[2]) {
419 t.Errorf("%v. %v.HclWhiteRef(D50) => (%v), want %v (delta %v)", i, tt.c, [3]float64{h, c, l}, tt.hcl50, delta)
420 }
421 }
422 }
423
424
425
426
427
428 var dists = []struct {
429 c1 Color
430 c2 Color
431 d76 float64
432 d94 float64
433 d00 float64
434 }{
435 {Color{1.0, 1.0, 1.0}, Color{1.0, 1.0, 1.0}, 0.0, 0.0, 0.0},
436 {Color{0.0, 0.0, 0.0}, Color{0.0, 0.0, 0.0}, 0.0, 0.0, 0.0},
437
438
439 {Lab(1.000000, 0.000000, 0.000000), Lab(0.931390, -0.353319, -0.108946), 0.37604638, 0.37604638, 0.23528129},
440 {Lab(0.720892, 0.651673, -0.422133), Lab(0.977637, -0.165795, 0.602017), 1.33531088, 0.65466377, 0.75175896},
441 {Lab(0.590453, 0.332846, -0.637099), Lab(0.681085, 0.483884, 0.228328), 0.88317072, 0.42541075, 0.37688153},
442 {Lab(0.906026, -0.600870, 0.498993), Lab(0.533890, 0.000000, 0.000000), 0.86517280, 0.41038323, 0.39960503},
443 {Lab(0.911132, -0.480875, -0.141312), Lab(0.603242, 0.982343, -0.608249), 1.56647162, 0.87431457, 0.57983482},
444 {Lab(0.971393, -0.215537, 0.944780), Lab(0.322970, 0.791875, -1.078602), 2.35146891, 1.11858192, 1.03426977},
445 {Lab(0.877347, -0.861827, 0.831793), Lab(0.532408, 0.800925, 0.672032), 1.70565338, 0.68800270, 0.86608245},
446 }
447
448 func TestLabDistance(t *testing.T) {
449 for i, tt := range dists {
450 d := tt.c1.DistanceCIE76(tt.c2)
451 if !almosteq(d, tt.d76) {
452 t.Errorf("%v. %v.DistanceCIE76(%v) => (%v), want %v (delta %v)", i, tt.c1, tt.c2, d, tt.d76, delta)
453 }
454 }
455 }
456
457 func TestCIE94Distance(t *testing.T) {
458 for i, tt := range dists {
459 d := tt.c1.DistanceCIE94(tt.c2)
460 if !almosteq(d, tt.d94) {
461 t.Errorf("%v. %v.DistanceCIE94(%v) => (%v), want %v (delta %v)", i, tt.c1, tt.c2, d, tt.d94, delta)
462 }
463 }
464 }
465
466 func TestCIEDE2000Distance(t *testing.T) {
467 for i, tt := range dists {
468 d := tt.c1.DistanceCIEDE2000(tt.c2)
469 if !almosteq(d, tt.d00) {
470 t.Errorf("%v. %v.DistanceCIEDE2000(%v) => (%v), want %v (delta %v)", i, tt.c1, tt.c2, d, tt.d00, delta)
471 }
472 }
473 }
474
475
476
477
478 func TestClamp(t *testing.T) {
479 c_orig := Color{1.1, -0.1, 0.5}
480 c_want := Color{1.0, 0.0, 0.5}
481 if c_orig.Clamped() != c_want {
482 t.Errorf("%v.Clamped() => %v, want %v", c_orig, c_orig.Clamped(), c_want)
483 }
484 }
485
486 func TestMakeColor(t *testing.T) {
487 c_orig_nrgba := color.NRGBA{123, 45, 67, 255}
488 c_ours, ok := MakeColor(c_orig_nrgba)
489 r, g, b := c_ours.RGB255()
490 if r != 123 || g != 45 || b != 67 || !ok {
491 t.Errorf("NRGBA->Colorful->RGB255 error: %v became (%v, %v, %v, %t)", c_orig_nrgba, r, g, b, ok)
492 }
493
494 c_orig_nrgba64 := color.NRGBA64{123 << 8, 45 << 8, 67 << 8, 0xffff}
495 c_ours, ok = MakeColor(c_orig_nrgba64)
496 r, g, b = c_ours.RGB255()
497 if r != 123 || g != 45 || b != 67 || !ok {
498 t.Errorf("NRGBA64->Colorful->RGB255 error: %v became (%v, %v, %v, %t)", c_orig_nrgba64, r, g, b, ok)
499 }
500
501 c_orig_gray := color.Gray{123}
502 c_ours, ok = MakeColor(c_orig_gray)
503 r, g, b = c_ours.RGB255()
504 if r != 123 || g != 123 || b != 123 || !ok {
505 t.Errorf("Gray->Colorful->RGB255 error: %v became (%v, %v, %v, %t)", c_orig_gray, r, g, b, ok)
506 }
507
508 c_orig_gray16 := color.Gray16{123 << 8}
509 c_ours, ok = MakeColor(c_orig_gray16)
510 r, g, b = c_ours.RGB255()
511 if r != 123 || g != 123 || b != 123 || !ok {
512 t.Errorf("Gray16->Colorful->RGB255 error: %v became (%v, %v, %v, %t)", c_orig_gray16, r, g, b, ok)
513 }
514
515 c_orig_rgba := color.RGBA{255, 255, 255, 0}
516 c_ours, ok = MakeColor(c_orig_rgba)
517 r, g, b = c_ours.RGB255()
518 if r != 0 || g != 0 || b != 0 || ok {
519 t.Errorf("RGBA->Colorful->RGB255 error: %v became (%v, %v, %v, %t)", c_orig_rgba, r, g, b, ok)
520 }
521 }
522
523
524
525
526
527 func TestIssue11(t *testing.T) {
528 c1hex := "#1a1a46"
529 c2hex := "#666666"
530
531 c1, _ := Hex(c1hex)
532 c2, _ := Hex(c2hex)
533
534 blend := c1.BlendHsv(c2, 0).Hex()
535 if blend != c1hex {
536 t.Errorf("Issue11: %v --Hsv-> %v = %v, want %v", c1hex, c2hex, blend, c1hex)
537 }
538 blend = c1.BlendHsv(c2, 1).Hex()
539 if blend != c2hex {
540 t.Errorf("Issue11: %v --Hsv-> %v = %v, want %v", c1hex, c2hex, blend, c2hex)
541 }
542
543 blend = c1.BlendLuv(c2, 0).Hex()
544 if blend != c1hex {
545 t.Errorf("Issue11: %v --Luv-> %v = %v, want %v", c1hex, c2hex, blend, c1hex)
546 }
547 blend = c1.BlendLuv(c2, 1).Hex()
548 if blend != c2hex {
549 t.Errorf("Issue11: %v --Luv-> %v = %v, want %v", c1hex, c2hex, blend, c2hex)
550 }
551
552 blend = c1.BlendRgb(c2, 0).Hex()
553 if blend != c1hex {
554 t.Errorf("Issue11: %v --Rgb-> %v = %v, want %v", c1hex, c2hex, blend, c1hex)
555 }
556 blend = c1.BlendRgb(c2, 1).Hex()
557 if blend != c2hex {
558 t.Errorf("Issue11: %v --Rgb-> %v = %v, want %v", c1hex, c2hex, blend, c2hex)
559 }
560
561 blend = c1.BlendLab(c2, 0).Hex()
562 if blend != c1hex {
563 t.Errorf("Issue11: %v --Lab-> %v = %v, want %v", c1hex, c2hex, blend, c1hex)
564 }
565 blend = c1.BlendLab(c2, 1).Hex()
566 if blend != c2hex {
567 t.Errorf("Issue11: %v --Lab-> %v = %v, want %v", c1hex, c2hex, blend, c2hex)
568 }
569
570 blend = c1.BlendHcl(c2, 0).Hex()
571 if blend != c1hex {
572 t.Errorf("Issue11: %v --Hcl-> %v = %v, want %v", c1hex, c2hex, blend, c1hex)
573 }
574 blend = c1.BlendHcl(c2, 1).Hex()
575 if blend != c2hex {
576 t.Errorf("Issue11: %v --Hcl-> %v = %v, want %v", c1hex, c2hex, blend, c2hex)
577 }
578
579 blend = c1.BlendLuvLCh(c2, 0).Hex()
580 if blend != c1hex {
581 t.Errorf("Issue11: %v --LuvLCh-> %v = %v, want %v", c1hex, c2hex, blend, c1hex)
582 }
583 blend = c1.BlendLuvLCh(c2, 1).Hex()
584 if blend != c2hex {
585 t.Errorf("Issue11: %v --LuvLCh-> %v = %v, want %v", c1hex, c2hex, blend, c2hex)
586 }
587 }
588
589
590
591 var anglevals = []struct {
592 a0 float64
593 a1 float64
594 t float64
595 at float64
596 }{
597 {0.0, 1.0, 0.0, 0.0},
598 {0.0, 1.0, 0.25, 0.25},
599 {0.0, 1.0, 0.5, 0.5},
600 {0.0, 1.0, 1.0, 1.0},
601 {0.0, 90.0, 0.0, 0.0},
602 {0.0, 90.0, 0.25, 22.5},
603 {0.0, 90.0, 0.5, 45.0},
604 {0.0, 90.0, 1.0, 90.0},
605 {0.0, 178.0, 0.0, 0.0},
606 {0.0, 178.0, 0.25, 44.5},
607 {0.0, 178.0, 0.5, 89.0},
608 {0.0, 178.0, 1.0, 178.0},
609 {0.0, 182.0, 0.0, 0.0},
610 {0.0, 182.0, 0.25, 315.5},
611 {0.0, 182.0, 0.5, 271.0},
612 {0.0, 182.0, 1.0, 182.0},
613 {0.0, 270.0, 0.0, 0.0},
614 {0.0, 270.0, 0.25, 337.5},
615 {0.0, 270.0, 0.5, 315.0},
616 {0.0, 270.0, 1.0, 270.0},
617 {0.0, 359.0, 0.0, 0.0},
618 {0.0, 359.0, 0.25, 359.75},
619 {0.0, 359.0, 0.5, 359.5},
620 {0.0, 359.0, 1.0, 359.0},
621 }
622
623 func TestInterpolation(t *testing.T) {
624
625 for i, tt := range anglevals {
626 res := interp_angle(tt.a0, tt.a1, tt.t)
627 if !almosteq_eps(res, tt.at, 1e-15) {
628 t.Errorf("%v. interp_angle(%v, %v, %v) => (%v), want %v", i, tt.a0, tt.a1, tt.t, res, tt.at)
629 }
630 }
631
632 for i, tt := range anglevals {
633 res := interp_angle(tt.a1, tt.a0, 1.0-tt.t)
634 if !almosteq_eps(res, tt.at, 1e-15) {
635 t.Errorf("%v. interp_angle(%v, %v, %v) => (%v), want %v", i, tt.a1, tt.a0, 1.0-tt.t, res, tt.at)
636 }
637 }
638 }
639
View as plain text