1
+ function RGB ( r , g , b , name ) {
2
+ this . r = r ;
3
+ this . g = g ;
4
+ this . b = b ;
5
+ if ( name ) this . name = name ;
6
+ this . css = 'rgb(' + r + ',' + g + ',' + b + ')' ;
7
+ }
8
+
9
+ RGB . prototype . toXYZ = function ( ) {
10
+ var var_R = this . r / 255 ; //R from 0 to 255
11
+ var var_G = this . g / 255 ; //G from 0 to 255
12
+ var var_B = this . b / 255 ; //B from 0 to 255
13
+
14
+ if ( var_R > 0.04045 ) var_R = Math . pow ( ( ( var_R + 0.055 ) / 1.055 ) , 2.4 ) ;
15
+ else var_R = var_R / 12.92 ;
16
+ if ( var_G > 0.04045 ) var_G = Math . pow ( ( ( var_G + 0.055 ) / 1.055 ) , 2.4 ) ;
17
+ else var_G = var_G / 12.92 ;
18
+ if ( var_B > 0.04045 ) var_B = Math . pow ( ( ( var_B + 0.055 ) / 1.055 ) , 2.4 ) ;
19
+ else var_B = var_B / 12.92 ;
20
+
21
+ var_R = var_R * 100 ;
22
+ var_G = var_G * 100 ;
23
+ var_B = var_B * 100 ;
24
+
25
+ //Observer. = 2°, Illuminant = D65
26
+ var X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805 ;
27
+ var Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722 ;
28
+ var Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505 ;
29
+
30
+ return new XYZ ( X , Y , Z ) ;
31
+ }
32
+
33
+ RGB . prototype . toLAB = function ( ) {
34
+ return this . toXYZ ( ) . toLAB ( ) ;
35
+ }
36
+
37
+ RGB . prototype . closest = function ( ) {
38
+ return this . toLAB ( ) . closest ( ) ;
39
+ }
40
+
41
+ function XYZ ( x , y , z ) {
42
+ this . x = x ;
43
+ this . y = y ;
44
+ this . z = z ;
45
+ }
46
+
47
+ var ref_X = 95.047 ; //Observer= 2°, Illuminant= D65
48
+ var ref_Y = 100.000 ;
49
+ var ref_Z = 108.883 ;
50
+ var const1 = 1.00 / 3 ;
51
+ var const2 = 16.00 / 116 ;
52
+
53
+ XYZ . prototype . toLAB = function ( ) {
54
+ var var_X = this . x / ref_X ;
55
+ var var_Y = this . y / ref_Y ;
56
+ var var_Z = this . z / ref_Z ;
57
+
58
+ if ( var_X > 0.008856 ) var_X = Math . pow ( var_X , const1 ) ;
59
+ else var_X = ( 7.787 * var_X ) + const2 ;
60
+ if ( var_Y > 0.008856 ) var_Y = Math . pow ( var_Y , const1 ) ;
61
+ else var_Y = ( 7.787 * var_Y ) + const2 ;
62
+ if ( var_Z > 0.008856 ) var_Z = Math . pow ( var_Z , const1 ) ;
63
+ else var_Z = ( 7.787 * var_Z ) + const2 ;
64
+
65
+ var L = ( 116 * var_Y ) - 16 ;
66
+ var A = 500 * ( var_X - var_Y ) ;
67
+ var B = 200 * ( var_Y - var_Z ) ;
68
+ return new LAB ( L , A , B ) ;
69
+
70
+ }
71
+
72
+ function LAB ( l , a , b ) {
73
+ this . l = l ;
74
+ this . a = a ;
75
+ this . b = b ;
76
+ }
77
+
78
+ LAB . prototype . delta = function ( lab2 ) {
79
+ return ColorUtils . calculateDeltaE ( this . l , this . a , this . b , lab2 . l , lab2 . a , lab2 . b ) ;
80
+ }
81
+
82
+ LAB . prototype . closest = function ( ) {
83
+ var closest = - 1 ;
84
+ var minDiff = 999999999 ;
85
+ for ( var i = 0 ; i < ColorUtils . COLORS_LAB . length ; ++ i ) {
86
+ var diff = this . delta ( ColorUtils . COLORS_LAB [ i ] ) ;
87
+ if ( diff < minDiff ) {
88
+ minDiff = diff ;
89
+ closest = i ;
90
+ }
91
+ }
92
+ return ColorUtils . COLORS [ closest ] ;
93
+ }
94
+
95
+ var ColorUtils = {
96
+ COLORS : [
97
+ new RGB ( 0 , 0 , 0 , "black" ) ,
98
+ new RGB ( 255 , 0 , 0 , "red" ) ,
99
+ new RGB ( 255 , 127 , 0 , "orange" ) ,
100
+ new RGB ( 255 , 255 , 0 , "yellow" ) ,
101
+ new RGB ( 0 , 255 , 0 , "green" ) ,
102
+ new RGB ( 0 , 255 , 0 , "blue" ) ,
103
+ new RGB ( 75 , 0 , 130 , "indigo" ) ,
104
+ new RGB ( 143 , 0 , 255 , "violet" ) ,
105
+ new RGB ( 255 , 255 , 255 , "white" )
106
+ ] ,
107
+
108
+ COLORS_LAB : [
109
+ new RGB ( 0 , 0 , 0 , "black" ) . toLAB ( ) ,
110
+ new RGB ( 255 , 0 , 0 , "red" ) . toLAB ( ) ,
111
+ new RGB ( 255 , 127 , 0 , "orange" ) . toLAB ( ) ,
112
+ new RGB ( 255 , 255 , 0 , "yellow" ) . toLAB ( ) ,
113
+ new RGB ( 0 , 255 , 0 , "green" ) . toLAB ( ) ,
114
+ new RGB ( 0 , 255 , 0 , "blue" ) . toLAB ( ) ,
115
+ new RGB ( 75 , 0 , 130 , "indigo" ) . toLAB ( ) ,
116
+ new RGB ( 143 , 0 , 255 , "violet" ) . toLAB ( ) ,
117
+ new RGB ( 255 , 255 , 255 , "white" ) . toLAB ( )
118
+ ] ,
119
+
120
+ averageColor : function ( imgData ) {
121
+ var totalRed = 0 ;
122
+ var totalGreen = 0 ;
123
+ var totalBlue = 0 ;
124
+ var data = imgData . data ;
125
+ var bytes = data . length ;
126
+ for ( var i = 0 ; i < bytes ; i += 4 ) {
127
+ totalRed += data [ i ] ;
128
+ totalGreen += data [ i + 1 ] ;
129
+ totalBlue += data [ i + 2 ] ;
130
+ }
131
+ var len = bytes / 4 ;
132
+ return new RGB ( Math . round ( totalRed / len ) , Math . round ( totalGreen / len ) , Math . round ( totalBlue / len ) ) ;
133
+ } ,
134
+
135
+ calculateDeltaE : function ( L1 , a1 , b1 , L2 , a2 , b2 ) {
136
+ var Lmean = ( L1 + L2 ) / 2.0 ;
137
+ var C1 = Math . sqrt ( a1 * a1 + b1 * b1 ) ;
138
+ var C2 = Math . sqrt ( a2 * a2 + b2 * b2 ) ;
139
+ var Cmean = ( C1 + C2 ) / 2.0 ;
140
+
141
+ var G = ( 1 - Math . sqrt ( Math . pow ( Cmean , 7 ) / ( Math . pow ( Cmean , 7 ) + Math . pow ( 25 , 7 ) ) ) ) / 2 ;
142
+ var a1prime = a1 * ( 1 + G ) ;
143
+ var a2prime = a2 * ( 1 + G ) ;
144
+
145
+ var C1prime = Math . sqrt ( a1prime * a1prime + b1 * b1 ) ;
146
+ var C2prime = Math . sqrt ( a2prime * a2prime + b2 * b2 ) ;
147
+ var Cmeanprime = ( C1prime + C2prime ) / 2 ;
148
+
149
+ var h1prime = Math . atan2 ( b1 , a1prime ) + 2 * Math . PI * ( Math . atan2 ( b1 , a1prime ) < 0 ? 1 : 0 ) ;
150
+ var h2prime = Math . atan2 ( b2 , a2prime ) + 2 * Math . PI * ( Math . atan2 ( b2 , a2prime ) < 0 ? 1 : 0 ) ;
151
+ var Hmeanprime = ( ( Math . abs ( h1prime - h2prime ) > Math . PI ) ? ( h1prime + h2prime + 2 * Math . PI ) / 2 : ( h1prime + h2prime ) / 2 ) ;
152
+
153
+ var T = 1.0 - 0.17 * Math . cos ( Hmeanprime - Math . PI / 6.0 ) + 0.24 * Math . cos ( 2 * Hmeanprime ) + 0.32 * Math . cos ( 3 * Hmeanprime + Math . PI / 30 ) - 0.2 * Math . cos ( 4 * Hmeanprime - 21 * Math . PI / 60 ) ; //ok
154
+
155
+ var deltahprime = ( ( Math . abs ( h1prime - h2prime ) <= Math . PI ) ? h2prime - h1prime : ( h2prime <= h1prime ) ? h2prime - h1prime + 2 * Math . PI : h2prime - h1prime - 2 * Math . PI ) ;
156
+
157
+ var deltaLprime = L2 - L1 ;
158
+ var deltaCprime = C2prime - C1prime ;
159
+ var deltaHprime = 2.0 * Math . sqrt ( C1prime * C2prime ) * Math . sin ( deltahprime / 2.0 ) ;
160
+ var SL = 1.0 + ( ( 0.015 * ( Lmean - 50 ) * ( Lmean - 50 ) ) / ( Math . sqrt ( 20 + ( Lmean - 50 ) * ( Lmean - 50 ) ) ) ) ;
161
+ var SC = 1.0 + 0.045 * Cmeanprime ;
162
+ var SH = 1.0 + 0.015 * Cmeanprime * T ;
163
+
164
+ var deltaTheta = ( 30 * Math . PI / 180 ) * Math . exp ( - ( ( 180 / Math . PI * Hmeanprime - 275 ) / 25 ) * ( ( 180 / Math . PI * Hmeanprime - 275 ) / 25 ) ) ;
165
+ var RC = ( 2 * Math . sqrt ( Math . pow ( Cmeanprime , 7 ) / ( Math . pow ( Cmeanprime , 7 ) + Math . pow ( 25 , 7 ) ) ) ) ;
166
+ var RT = ( - RC * Math . sin ( 2 * deltaTheta ) ) ;
167
+
168
+ var KL = 1 ;
169
+ var KC = 1 ;
170
+ var KH = 1 ;
171
+
172
+ var deltaE = Math . sqrt (
173
+ ( ( deltaLprime / ( KL * SL ) ) * ( deltaLprime / ( KL * SL ) ) ) +
174
+ ( ( deltaCprime / ( KC * SC ) ) * ( deltaCprime / ( KC * SC ) ) ) +
175
+ ( ( deltaHprime / ( KH * SH ) ) * ( deltaHprime / ( KH * SH ) ) ) +
176
+ ( RT * ( deltaCprime / ( KC * SC ) ) * ( deltaHprime / ( KH * SH ) ) )
177
+ ) ;
178
+
179
+ return deltaE ;
180
+ }
181
+
182
+ } ;
0 commit comments