color_converters 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +199 -190
- data/Rakefile +8 -8
- data/lib/color_converters/base_converter.rb +182 -184
- data/lib/color_converters/color.rb +31 -18
- data/lib/color_converters/converters/cielab_converter.rb +99 -95
- data/lib/color_converters/converters/cielch_converter.rb +65 -61
- data/lib/color_converters/converters/cmyk_converter.rb +63 -59
- data/lib/color_converters/converters/hex_converter.rb +49 -45
- data/lib/color_converters/converters/hsl_converter.rb +72 -68
- data/lib/color_converters/converters/hsl_string_converter.rb +61 -46
- data/lib/color_converters/converters/hsv_converter.rb +64 -60
- data/lib/color_converters/converters/name_converter.rb +69 -67
- data/lib/color_converters/converters/null_converter.rb +23 -19
- data/lib/color_converters/converters/oklab_converter.rb +106 -102
- data/lib/color_converters/converters/oklch_converter.rb +65 -61
- data/lib/color_converters/converters/rgb_converter.rb +113 -109
- data/lib/color_converters/converters/rgb_string_converter.rb +64 -49
- data/lib/color_converters/converters/xyz_converter.rb +114 -110
- data/lib/color_converters/version.rb +1 -1
- metadata +2 -2
@@ -1,184 +1,182 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/object/blank'
|
4
|
-
require 'bigdecimal'
|
5
|
-
require 'bigdecimal/util'
|
6
|
-
|
7
|
-
module ColorConverters
|
8
|
-
class BaseConverter
|
9
|
-
IMPORT_DP = 8
|
10
|
-
OUTPUT_DP = 2
|
11
|
-
|
12
|
-
attr_reader :original_value, :rgba
|
13
|
-
|
14
|
-
# keep track of subclasses for factory
|
15
|
-
class << self
|
16
|
-
attr_reader :converters
|
17
|
-
end
|
18
|
-
|
19
|
-
@converters = []
|
20
|
-
|
21
|
-
def self.inherited(subclass)
|
22
|
-
BaseConverter.converters << subclass
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.factory(
|
26
|
-
converter = BaseConverter.converters.find { |klass| klass.matches?(
|
27
|
-
converter&.new(
|
28
|
-
end
|
29
|
-
|
30
|
-
def initialize(colour_input, limit_override = false)
|
31
|
-
|
32
|
-
|
33
|
-
# self.clamp_input(colour_input) if limit_clamp == true
|
34
|
-
|
35
|
-
validation_errors = self.validate_input(colour_input)
|
36
|
-
if limit_override == false && validation_errors.present?
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
r, g, b, a
|
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
|
-
hsb_hash
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
c, m, y, k
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
x, y, z
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
l, a, b
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
l, c, h
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
l, a, b
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
l, c, h
|
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
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
when self.rgb_max ==
|
144
|
-
h =
|
145
|
-
when self.rgb_max == @
|
146
|
-
h = (@
|
147
|
-
when self.rgb_max == @
|
148
|
-
h =
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
when self.
|
162
|
-
s =
|
163
|
-
|
164
|
-
s = self.rgb_delta / (self.rgb_max
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
end
|
184
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/object/blank'
|
4
|
+
require 'bigdecimal'
|
5
|
+
require 'bigdecimal/util'
|
6
|
+
|
7
|
+
module ColorConverters
|
8
|
+
class BaseConverter
|
9
|
+
IMPORT_DP = 8
|
10
|
+
OUTPUT_DP = 2
|
11
|
+
|
12
|
+
attr_reader :original_value, :rgba
|
13
|
+
|
14
|
+
# keep track of subclasses for factory
|
15
|
+
class << self
|
16
|
+
attr_reader :converters
|
17
|
+
end
|
18
|
+
|
19
|
+
@converters = []
|
20
|
+
|
21
|
+
def self.inherited(subclass)
|
22
|
+
BaseConverter.converters << subclass
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.factory(colour_input, limit_override = false, limit_clamp = false)
|
26
|
+
converter = BaseConverter.converters.find { |klass| klass.matches?(colour_input) }
|
27
|
+
converter&.new(colour_input, limit_override, limit_clamp)
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(colour_input, limit_override = false, limit_clamp = false)
|
31
|
+
colour_input.delete(:space) if colour_input.is_a?(Hash)
|
32
|
+
|
33
|
+
# colour_input = self.clamp_input(colour_input) if limit_clamp == true
|
34
|
+
|
35
|
+
validation_errors = self.validate_input(colour_input) # validation method is defined in each convertor
|
36
|
+
raise InvalidColorError, "Invalid color input: #{validation_errors.join(', ')}" if limit_override == false && validation_errors.present?
|
37
|
+
|
38
|
+
r, g, b, a = self.input_to_rgba(colour_input) # conversion method is defined in each convertor
|
39
|
+
|
40
|
+
@rgba = { r: r.to_f.round(IMPORT_DP), g: g.to_f.round(IMPORT_DP), b: b.to_f.round(IMPORT_DP), a: a.to_f.round(IMPORT_DP) }
|
41
|
+
end
|
42
|
+
|
43
|
+
def rgb
|
44
|
+
{ r: @rgba[:r].to_f.round(OUTPUT_DP), g: @rgba[:g].to_f.round(OUTPUT_DP), b: @rgba[:b].to_f.round(OUTPUT_DP) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def hex
|
48
|
+
HexConverter.rgb_to_hex(self.rgb_array)
|
49
|
+
end
|
50
|
+
|
51
|
+
# not refactored to SubClass methods due to needing so many of the private methods
|
52
|
+
def hsl
|
53
|
+
@r, @g, @b = self.rgb_array_frac
|
54
|
+
|
55
|
+
{ h: self.hue.to_f.round(OUTPUT_DP), s: self.hsl_saturation.to_f.round(OUTPUT_DP), l: self.hsl_lightness.to_f.round(OUTPUT_DP) }
|
56
|
+
end
|
57
|
+
|
58
|
+
# not refactored to SubClass methods due to needing so many of the private methods
|
59
|
+
def hsv
|
60
|
+
@r, @g, @b = self.rgb_array
|
61
|
+
|
62
|
+
{ h: self.hue.to_f.round(OUTPUT_DP), s: self.hsv_saturation.to_f.round(OUTPUT_DP), v: self.hsv_value.to_f.round(OUTPUT_DP) }
|
63
|
+
end
|
64
|
+
|
65
|
+
def hsb
|
66
|
+
hsb_hash = self.hsv
|
67
|
+
hsb_hash[:b] = hsb_hash.delete(:v)
|
68
|
+
hsb_hash
|
69
|
+
end
|
70
|
+
|
71
|
+
def cmyk
|
72
|
+
c, m, y, k = CmykConverter.rgb_to_cmyk(self.rgb_array_frac)
|
73
|
+
|
74
|
+
{ c: c.to_f.round(OUTPUT_DP), m: m.to_f.round(OUTPUT_DP), y: y.to_f.round(OUTPUT_DP), k: k.to_f.round(OUTPUT_DP) }
|
75
|
+
end
|
76
|
+
|
77
|
+
def xyz
|
78
|
+
x, y, z = XyzConverter.rgb_to_xyz(self.rgb_array_frac)
|
79
|
+
|
80
|
+
{ x: x.to_f.round(OUTPUT_DP), y: y.to_f.round(OUTPUT_DP), z: z.to_f.round(OUTPUT_DP) }
|
81
|
+
end
|
82
|
+
|
83
|
+
def cielab
|
84
|
+
l, a, b = CielabConverter.xyz_to_cielab(XyzConverter.rgb_to_xyz(self.rgb_array_frac))
|
85
|
+
|
86
|
+
{ l: l.to_f.round(OUTPUT_DP), a: a.to_f.round(OUTPUT_DP), b: b.to_f.round(OUTPUT_DP) }
|
87
|
+
end
|
88
|
+
|
89
|
+
def cielch
|
90
|
+
l, c, h = CielchConverter.cielab_to_cielch(CielabConverter.xyz_to_cielab(XyzConverter.rgb_to_xyz(self.rgb_array_frac)))
|
91
|
+
|
92
|
+
{ l: l.to_f.round(OUTPUT_DP), c: c.to_f.round(OUTPUT_DP), h: h.to_f.round(OUTPUT_DP) }
|
93
|
+
end
|
94
|
+
|
95
|
+
def oklab
|
96
|
+
l, a, b = OklabConverter.xyz_to_oklab(XyzConverter.rgb_to_xyz(self.rgb_array_frac))
|
97
|
+
|
98
|
+
{ l: l.to_f.round(OUTPUT_DP), a: a.to_f.round(OUTPUT_DP), b: b.to_f.round(OUTPUT_DP) }
|
99
|
+
end
|
100
|
+
|
101
|
+
def oklch
|
102
|
+
l, c, h = OklchConverter.oklab_to_oklch(OklabConverter.xyz_to_oklab(XyzConverter.rgb_to_xyz(self.rgb_array_frac)))
|
103
|
+
|
104
|
+
{ l: l.to_f.round(OUTPUT_DP), c: c.to_f.round(OUTPUT_DP), h: h.to_f.round(OUTPUT_DP) }
|
105
|
+
end
|
106
|
+
|
107
|
+
def alpha
|
108
|
+
@rgba[:a]
|
109
|
+
end
|
110
|
+
|
111
|
+
def name(fuzzy: false)
|
112
|
+
NameConverter.rgb_to_name(self.rgb_array, fuzzy)
|
113
|
+
end
|
114
|
+
|
115
|
+
protected
|
116
|
+
|
117
|
+
def rgb_array
|
118
|
+
[@rgba[:r].to_f, @rgba[:g].to_f, @rgba[:b].to_f]
|
119
|
+
end
|
120
|
+
|
121
|
+
def rgb_array_frac
|
122
|
+
[@rgba[:r] / 255.0, @rgba[:g] / 255.0, @rgba[:b] / 255.0]
|
123
|
+
end
|
124
|
+
|
125
|
+
def rgb_min
|
126
|
+
[@r, @g, @b].min
|
127
|
+
end
|
128
|
+
|
129
|
+
def rgb_max
|
130
|
+
[@r, @g, @b].max
|
131
|
+
end
|
132
|
+
|
133
|
+
def rgb_delta
|
134
|
+
self.rgb_max - self.rgb_min
|
135
|
+
end
|
136
|
+
|
137
|
+
def hue
|
138
|
+
h = 0
|
139
|
+
|
140
|
+
case true
|
141
|
+
when self.rgb_max == self.rgb_min
|
142
|
+
h = 0
|
143
|
+
when self.rgb_max == @r
|
144
|
+
h = (@g - @b) / self.rgb_delta
|
145
|
+
when self.rgb_max == @g
|
146
|
+
h = 2 + (@b - @r) / self.rgb_delta
|
147
|
+
when self.rgb_max == @b
|
148
|
+
h = 4 + (@r - @g) / self.rgb_delta
|
149
|
+
end
|
150
|
+
|
151
|
+
h = [h * 60, 360].min
|
152
|
+
h % 360
|
153
|
+
end
|
154
|
+
|
155
|
+
def hsl_saturation
|
156
|
+
s = 0
|
157
|
+
|
158
|
+
case true
|
159
|
+
when self.rgb_max == self.rgb_min
|
160
|
+
s = 0
|
161
|
+
when (self.hsl_lightness / 100.0) <= 0.5
|
162
|
+
s = self.rgb_delta / (self.rgb_max + self.rgb_min)
|
163
|
+
else
|
164
|
+
s = self.rgb_delta / (2.0 - self.rgb_max - self.rgb_min)
|
165
|
+
end
|
166
|
+
|
167
|
+
s * 100
|
168
|
+
end
|
169
|
+
|
170
|
+
def hsl_lightness
|
171
|
+
(self.rgb_min + self.rgb_max) / 2.0 * 100
|
172
|
+
end
|
173
|
+
|
174
|
+
def hsv_saturation
|
175
|
+
self.rgb_max.zero? ? 0 : ((self.rgb_delta / self.rgb_max * 1000) / 10.0)
|
176
|
+
end
|
177
|
+
|
178
|
+
def hsv_value
|
179
|
+
((self.rgb_max / 255.0) * 1000) / 10.0
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -1,18 +1,31 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ColorConverters
|
4
|
-
class Color
|
5
|
-
extend Forwardable
|
6
|
-
def_delegators :@converter, :rgb, :hex, :hsl, :hsv, :hsb, :cmyk, :xyz, :cielab, :cielch, :oklab, :oklch, :name, :alpha
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ColorConverters
|
4
|
+
class Color
|
5
|
+
extend Forwardable
|
6
|
+
def_delegators :@converter, :rgb, :hex, :hsl, :hsv, :hsb, :cmyk, :xyz, :cielab, :cielch, :oklab, :oklch, :name, :alpha
|
7
|
+
|
8
|
+
# the two arguments mean we can support calling styles of a hash of colour keys, flattened hash, and string
|
9
|
+
# colour_input is nil when key-values are passed and must be pulled from the kwargs hash
|
10
|
+
# colour_input is set when a string is passed and kwargs is a hash of the extra options
|
11
|
+
def initialize(colour_input = nil, **kwargs)
|
12
|
+
if colour_input.nil?
|
13
|
+
colour_input = kwargs.except(:limit_override, :limit_clamp)
|
14
|
+
kwargs = kwargs.slice(:limit_override, :limit_clamp)
|
15
|
+
end
|
16
|
+
|
17
|
+
@original_value = colour_input
|
18
|
+
|
19
|
+
limit_override = kwargs.delete(:limit_override) || false
|
20
|
+
limit_clamp = kwargs.delete(:limit_clamp) || false
|
21
|
+
|
22
|
+
@converter = BaseConverter.factory(colour_input, limit_override, limit_clamp)
|
23
|
+
end
|
24
|
+
|
25
|
+
def ==(other)
|
26
|
+
return false unless other.is_a?(Color)
|
27
|
+
|
28
|
+
rgb == other.rgb && alpha == other.alpha
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,95 +1,99 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ColorConverters
|
4
|
-
class CielabConverter < BaseConverter
|
5
|
-
def self.matches?(colour_input)
|
6
|
-
return false unless colour_input.is_a?(Hash)
|
7
|
-
|
8
|
-
colour_input.keys - [:l, :a, :b, :space] == [] && colour_input[:space].to_s == 'cie'
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.bounds
|
12
|
-
{ l: [0.0, 100.0], a: [-128.0, 127.0], b: [-128.0, 127.0] }
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def
|
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
|
-
x, y, z
|
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
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ColorConverters
|
4
|
+
class CielabConverter < BaseConverter
|
5
|
+
def self.matches?(colour_input)
|
6
|
+
return false unless colour_input.is_a?(Hash)
|
7
|
+
|
8
|
+
colour_input.keys - [:l, :a, :b, :space] == [] && colour_input[:space].to_s == 'cie'
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.bounds
|
12
|
+
{ l: [0.0, 100.0], a: [-128.0, 127.0], b: [-128.0, 127.0] }
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# def clamp_input(colour_input)
|
18
|
+
# colour_input.each { |key, value| colour_input[key] = value.clamp(*CielabConverter.bounds[key]) }
|
19
|
+
# end
|
20
|
+
|
21
|
+
def validate_input(colour_input)
|
22
|
+
CielabConverter.bounds.collect do |key, range|
|
23
|
+
"#{key} must be between #{range[0]} and #{range[1]}" unless colour_input[key].to_f.between?(*range)
|
24
|
+
end.compact
|
25
|
+
end
|
26
|
+
|
27
|
+
def input_to_rgba(colour_input)
|
28
|
+
x, y, z = CielabConverter.cielab_to_xyz(colour_input)
|
29
|
+
r, g, b = XyzConverter.xyz_to_rgb({ x: x, y: y, z: z })
|
30
|
+
|
31
|
+
[r, g, b, 1.0]
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.cielab_to_xyz(colour_input)
|
35
|
+
l = colour_input[:l].to_d
|
36
|
+
a = colour_input[:a].to_d
|
37
|
+
b = colour_input[:b].to_d
|
38
|
+
|
39
|
+
yy = (l + 16.0.to_d) / 116.0.to_d
|
40
|
+
xx = (a / 500.0.to_d) + yy
|
41
|
+
zz = yy - (b / 200.0.to_d)
|
42
|
+
|
43
|
+
e = 216.0.to_d / 24_389.0.to_d
|
44
|
+
|
45
|
+
x, y, z = [xx, yy, zz].map do
|
46
|
+
if _1**3.to_d <= e
|
47
|
+
(3.0.to_d * (6.0.to_d / 29.0.to_d) * (6.0.to_d / 29.0.to_d) * (_1 - (4.0.to_d / 29.0.to_d)))
|
48
|
+
else
|
49
|
+
_1**3.to_d
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
x *= 95.047.to_d
|
54
|
+
y *= 100.0.to_d
|
55
|
+
z *= 108.883.to_d
|
56
|
+
|
57
|
+
[x, y, z]
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.xyz_to_cielab(xyz_array)
|
61
|
+
x, y, z = xyz_array.map(&:to_d)
|
62
|
+
|
63
|
+
# https://www.w3.org/TR/css-color-4/#color-conversion-code
|
64
|
+
# # The D50 & D65 standard illuminant white point
|
65
|
+
# wp_rel = [0.3457 / 0.3585, 1.0, (1.0 - 0.3457 - 0.3585) / 0.3585]
|
66
|
+
wp_rel = [0.3127.to_d / 0.3290.to_d, 1.0.to_d, (1.0.to_d - 0.3127.to_d - 0.3290.to_d) / 0.3290.to_d].map { _1 * 100.0.to_d }
|
67
|
+
|
68
|
+
xr, yr, zr = wp_rel
|
69
|
+
|
70
|
+
# # Calculate the ratio of the XYZ values to the reference white.
|
71
|
+
# # http://www.brucelindbloom.com/index.html?Equations.html
|
72
|
+
rel = [x / xr, y / yr, z / zr]
|
73
|
+
|
74
|
+
e = 216.0.to_d / 24_389.0.to_d
|
75
|
+
k = 841.0.to_d / 108.0.to_d
|
76
|
+
|
77
|
+
# And now transform
|
78
|
+
# http:#en.wikipedia.org/wiki/Lab_color_space#Forward_transformation
|
79
|
+
# There is a brief explanation there as far as the nature of the calculations,
|
80
|
+
# as well as a much nicer looking modeling of the algebra.
|
81
|
+
xx, yy, zz = rel.map do
|
82
|
+
if _1 > e
|
83
|
+
_1**(1.0.to_d / 3.0.to_d)
|
84
|
+
else
|
85
|
+
(k * _1) + (4.0.to_d / 29.0.to_d)
|
86
|
+
# The 4/29 here is for when t = 0 (black). 4/29 * 116 = 16, and 16 -
|
87
|
+
# 16 = 0, which is the correct value for L* with black.
|
88
|
+
# ((1.0/3)*((29.0/6)**2) * t) + (4.0/29)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
l = ((116.0.to_d * yy) - 16.0.to_d)
|
93
|
+
a = (500.0.to_d * (xx - yy))
|
94
|
+
b = (200.0.to_d * (yy - zz))
|
95
|
+
|
96
|
+
[l, a, b]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|