-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
cie_lab.go
106 lines (94 loc) · 2.86 KB
/
cie_lab.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
//go:build !tinygo
// +build !tinygo
package gfx
import "math"
// CIELab represents a color in CIE-L*ab.
type CIELab struct {
L float64
A float64
B float64
}
// DeltaC calculates Delta C* for two CIE-L*ab colors.
//
// CIE-a*1, CIE-b*1 //Color #1 CIE-L*ab values
// CIE-a*2, CIE-b*2 //Color #2 CIE-L*ab values
//
// Delta C* = sqrt( ( CIE-a*2 ^ 2 ) + ( CIE-b*2 ^ 2 ) )
// - sqrt( ( CIE-a*1 ^ 2 ) + ( CIE-b*1 ^ 2 ) )
func (c1 CIELab) DeltaC(c2 CIELab) float64 {
return math.Sqrt(math.Pow(c2.A, 2)+math.Pow(c2.B, 2)) -
math.Sqrt(math.Pow(c1.A, 2)+math.Pow(c1.B, 2))
}
// DeltaH calculates Delta H* for two CIE-L*ab colors.
//
// CIE-a*1, CIE-b*1 //Color #1 CIE-L*ab values
// CIE-a*2, CIE-b*2 //Color #2 CIE-L*ab values
//
// xDE = sqrt( ( CIE-a*2 ^ 2 ) + ( CIE-b*2 ^ 2 ) )
// - sqrt( ( CIE-a*1 ^ 2 ) + ( CIE-b*1 ^ 2 ) )
//
// Delta H* = sqrt( ( CIE-a*2 - CIE-a*1 ) ^ 2
// - ( CIE-b*2 - CIE-b*1 ) ^ 2 - ( xDE ^ 2 ) )
func (c1 CIELab) DeltaH(c2 CIELab) float64 {
xDE := math.Sqrt(math.Pow(c2.A, 2)+math.Pow(c2.B, 2)) -
math.Sqrt(math.Pow(c1.A, 2)+math.Pow(c1.B, 2))
return math.Sqrt(math.Pow(c2.A-c1.A, 2) +
math.Pow(c2.B-c1.B, 2) - math.Pow(xDE, 2))
}
// DeltaE calculates Delta E* for two CIE-L*ab colors.
//
// CIE-L*1, CIE-a*1, CIE-b*1 //Color #1 CIE-L*ab values
// CIE-L*2, CIE-a*2, CIE-b*2 //Color #2 CIE-L*ab values
//
// Delta E* = sqrt( ( ( CIE-L*1 - CIE-L*2 ) ^ 2 )
// - ( ( CIE-a*1 - CIE-a*2 ) ^ 2 )
// - ( ( CIE-b*1 - CIE-b*2 ) ^ 2 ) )
func (c1 CIELab) DeltaE(c2 CIELab) float64 {
return math.Sqrt(math.Pow(c1.L*1-c2.L*2, 2) +
math.Pow(c1.A*1-c2.A*2, 2) + math.Pow(c1.B*1-c2.B*2, 2),
)
}
// CIELab converts from XYZ to CIE-L*ab.
//
// Reference-X, Y and Z refer to specific illuminants and observers.
// Common reference values are available below in this same page.
//
// var_X = X / Reference-X
// var_Y = Y / Reference-Y
// var_Z = Z / Reference-Z
//
// if ( var_X > 0.008856 ) var_X = var_X ^ ( 1/3 )
// else var_X = ( 7.787 * var_X ) + ( 16 / 116 )
// if ( var_Y > 0.008856 ) var_Y = var_Y ^ ( 1/3 )
// else var_Y = ( 7.787 * var_Y ) + ( 16 / 116 )
// if ( var_Z > 0.008856 ) var_Z = var_Z ^ ( 1/3 )
// else var_Z = ( 7.787 * var_Z ) + ( 16 / 116 )
//
// CIE-L* = ( 116 * var_Y ) - 16
// CIE-a* = 500 * ( var_X - var_Y )
// CIE-b* = 200 * ( var_Y - var_Z )
func (xyz XYZ) CIELab(ref XYZ) CIELab {
X := xyz.X / ref.X
Y := xyz.Y / ref.Y
Z := xyz.Z / ref.Z
if X > 0.008856 {
X = math.Pow(X, (1.0 / 3))
} else {
X = (7.787 * X) + (16.0 / 116)
}
if Y > 0.008856 {
Y = math.Pow(Y, (1.0 / 3))
} else {
Y = (7.787 * Y) + (16.0 / 116)
}
if Z > 0.008856 {
Z = math.Pow(Z, (1.0 / 3))
} else {
Z = (7.787 * Z) + (16.0 / 116)
}
return CIELab{
L: (116.0 * Y) - 16,
A: 500.0 * (X - Y),
B: 200.0 * (Y - Z),
}
}