color_calculator 0.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/color_calculator/calculation/delta_e_2000.rb +11 -10
- data/lib/color_calculator/clump.rb +1 -1
- data/lib/color_calculator/clump/{lch_ab.rb → lch.rb} +1 -1
- data/lib/color_calculator/conversion.rb +41 -3
- data/lib/color_calculator/conversion/{lab_to_lch_ab.rb → lab_to_lch.rb} +5 -6
- data/lib/color_calculator/conversion/lab_to_xyz.rb +71 -0
- data/lib/color_calculator/conversion/lch_to_lab.rb +38 -0
- data/lib/color_calculator/conversion/{rgb_to_lch_ab.rb → rgb_to_lch.rb} +3 -3
- data/lib/color_calculator/conversion/xyz_to_lab.rb +4 -7
- data/lib/color_calculator/conversion/xyz_to_rgb.rb +65 -0
- data/lib/color_calculator/shared/constants.rb +15 -0
- data/lib/color_calculator/version.rb +1 -1
- metadata +9 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c07fc4c3003a07a1504d0814fa9d6de586750340
|
4
|
+
data.tar.gz: 7d3f50d42bc4e3e7455b7f568df58311f863f9b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d4388fd40c9f0b7a199a791c30dd090e21c7e2fd287f42f88610e820a00f48f672aaef089a51e0779ecdd877f356b824465f57679ddc3342c7302e1ca430cce
|
7
|
+
data.tar.gz: ed5ff908d20a4b03739dd31fbd8f8add01e3127e6f190290f9b04969227cf5dba2d2e0d07f12d519cc2576f3efb3843b2ebe86b7b362c9b0a0d3345310a16974
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../clump/lab'
|
4
|
+
require_relative '../shared/constants'
|
4
5
|
|
5
6
|
module ColorCalculator
|
6
7
|
module Calculation
|
@@ -11,9 +12,6 @@ module ColorCalculator
|
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
14
|
-
RADIANS_TO_DEGREES = 180.to_f / Math::PI
|
15
|
-
DEGREES_TO_RADIANS = 1.to_f / RADIANS_TO_DEGREES
|
16
|
-
|
17
15
|
K_OF_L = 1
|
18
16
|
K_OF_C = 1
|
19
17
|
K_OF_H = 1
|
@@ -65,7 +63,7 @@ module ColorCalculator
|
|
65
63
|
[
|
66
64
|
2,
|
67
65
|
Math.sqrt(c_prime_reference * c_prime_sample),
|
68
|
-
Math.sin(Rational(delta_little_h_prime, 2) * DEGREES_TO_RADIANS),
|
66
|
+
Math.sin(Rational(delta_little_h_prime, 2) * Constants::DEGREES_TO_RADIANS),
|
69
67
|
].reduce(:*)
|
70
68
|
end
|
71
69
|
|
@@ -74,7 +72,7 @@ module ColorCalculator
|
|
74
72
|
end
|
75
73
|
|
76
74
|
def r_of_t
|
77
|
-
-1 * Math.sin(2 * delta_theta * DEGREES_TO_RADIANS) * r_of_c
|
75
|
+
-1 * Math.sin(2 * delta_theta * Constants::DEGREES_TO_RADIANS) * r_of_c
|
78
76
|
end
|
79
77
|
|
80
78
|
%i[reference sample].each do |lab|
|
@@ -115,7 +113,10 @@ module ColorCalculator
|
|
115
113
|
define_method("little_h_prime_#{lab}") do
|
116
114
|
return 0 if [send(lab).beta, send("a_prime_#{lab}")].all? { |el| el == 0 }
|
117
115
|
|
118
|
-
(
|
116
|
+
(
|
117
|
+
Math.atan2(send(lab).beta, send("a_prime_#{lab}")) *
|
118
|
+
Constants::RADIANS_TO_DEGREES
|
119
|
+
) % 360
|
119
120
|
end
|
120
121
|
end
|
121
122
|
|
@@ -174,10 +175,10 @@ module ColorCalculator
|
|
174
175
|
def big_t
|
175
176
|
[
|
176
177
|
1,
|
177
|
-
-0.17 * Math.cos((little_h_bar_prime - 30) * DEGREES_TO_RADIANS),
|
178
|
-
0.24 * Math.cos(2 * little_h_bar_prime * DEGREES_TO_RADIANS),
|
179
|
-
0.32 * Math.cos((3 * little_h_bar_prime + 6) * DEGREES_TO_RADIANS),
|
180
|
-
-0.2 * Math.cos((4 * little_h_bar_prime - 63) * DEGREES_TO_RADIANS),
|
178
|
+
-0.17 * Math.cos((little_h_bar_prime - 30) * Constants::DEGREES_TO_RADIANS),
|
179
|
+
0.24 * Math.cos(2 * little_h_bar_prime * Constants::DEGREES_TO_RADIANS),
|
180
|
+
0.32 * Math.cos((3 * little_h_bar_prime + 6) * Constants::DEGREES_TO_RADIANS),
|
181
|
+
-0.2 * Math.cos((4 * little_h_bar_prime - 63) * Constants::DEGREES_TO_RADIANS),
|
181
182
|
].reduce(:+)
|
182
183
|
end
|
183
184
|
|
@@ -1,10 +1,48 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'conversion/
|
3
|
+
require_relative 'conversion/lab_to_lch'
|
4
|
+
require_relative 'conversion/lab_to_xyz'
|
5
|
+
require_relative 'conversion/lch_to_lab'
|
6
|
+
require_relative 'conversion/rgb_to_lch'
|
4
7
|
require_relative 'conversion/rgb_to_xyz'
|
5
|
-
require_relative 'conversion/rgb_to_lch_ab'
|
6
8
|
require_relative 'conversion/xyz_to_lab'
|
9
|
+
require_relative 'conversion/xyz_to_rgb'
|
7
10
|
|
8
11
|
module ColorCalculator
|
9
|
-
module Conversion
|
12
|
+
module Conversion
|
13
|
+
NOOP = -> (value) { value }
|
14
|
+
|
15
|
+
# Doesn't seem like it's worth it to build a proper graph for this yet.
|
16
|
+
# This map is fine, even if it is a bit repetitive.
|
17
|
+
MAP = {
|
18
|
+
lab: {
|
19
|
+
lab: NOOP,
|
20
|
+
lch: LabToLch.to_proc,
|
21
|
+
rgb: [LabToXyz, XyzToRgb].map(&:to_proc).reduce(:>>),
|
22
|
+
xyz: LabToXyz.to_proc
|
23
|
+
},
|
24
|
+
lch: {
|
25
|
+
lab: LchToLab.to_proc,
|
26
|
+
lch: NOOP,
|
27
|
+
rgb: [LchToLab, LabToXyz, XyzToRgb].map(&:to_proc).reduce(:>>),
|
28
|
+
xyz: [LchToLab, LabToXyz].map(&:to_proc).reduce(:>>)
|
29
|
+
},
|
30
|
+
rgb: {
|
31
|
+
lab: [RgbToXyz, XyzToLab].map(&:to_proc).reduce(:>>),
|
32
|
+
lch: [RgbToXyz, XyzToLab, LabToLch].map(&:to_proc).reduce(:>>),
|
33
|
+
rgb: NOOP,
|
34
|
+
xyz: RgbToXyz.to_proc
|
35
|
+
},
|
36
|
+
xyz: {
|
37
|
+
lab: XyzToLab.to_proc,
|
38
|
+
lch: [XyzToLab, LabToLch].map(&:to_proc).reduce(:>>),
|
39
|
+
rgb: XyzToRgb.to_proc,
|
40
|
+
xyz: NOOP
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
def self.build(from, to)
|
45
|
+
MAP[from][to]
|
46
|
+
end
|
47
|
+
end
|
10
48
|
end
|
@@ -1,22 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../clump/lab'
|
4
|
-
require_relative '../clump/
|
4
|
+
require_relative '../clump/lch'
|
5
5
|
require_relative '../shared/composable'
|
6
|
+
require_relative '../shared/constants'
|
6
7
|
|
7
8
|
module ColorCalculator
|
8
9
|
module Conversion
|
9
|
-
class
|
10
|
+
class LabToLch
|
10
11
|
extend ColorCalculator::Composable
|
11
12
|
|
12
|
-
RADIANS_TO_DEGREES = 180 / Math::PI
|
13
|
-
|
14
13
|
def initialize(lab)
|
15
14
|
@lab = lab
|
16
15
|
end
|
17
16
|
|
18
17
|
def call
|
19
|
-
ColorCalculator::Clump::
|
18
|
+
ColorCalculator::Clump::Lch.new(lightness, chroma, hue)
|
20
19
|
end
|
21
20
|
|
22
21
|
private
|
@@ -32,7 +31,7 @@ module ColorCalculator
|
|
32
31
|
end
|
33
32
|
|
34
33
|
def hue
|
35
|
-
val = Math.atan2(lab.beta, lab.alpha) * RADIANS_TO_DEGREES
|
34
|
+
val = Math.atan2(lab.beta, lab.alpha) * Constants::RADIANS_TO_DEGREES
|
36
35
|
|
37
36
|
return val if val >= 0
|
38
37
|
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../clump/lab'
|
4
|
+
require_relative '../clump/xyz'
|
5
|
+
require_relative '../shared/composable'
|
6
|
+
|
7
|
+
module ColorCalculator
|
8
|
+
module Conversion
|
9
|
+
class LabToXyz
|
10
|
+
extend ColorCalculator::Composable
|
11
|
+
|
12
|
+
def initialize(lab)
|
13
|
+
@lab = lab
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
Clump::Xyz.new(x, y, z)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :lab
|
23
|
+
|
24
|
+
def x
|
25
|
+
x_of_r * Constants::D50.fetch(:x)
|
26
|
+
end
|
27
|
+
|
28
|
+
def y
|
29
|
+
y_of_r * Constants::D50.fetch(:y)
|
30
|
+
end
|
31
|
+
|
32
|
+
def z
|
33
|
+
z_of_r * Constants::D50.fetch(:z)
|
34
|
+
end
|
35
|
+
|
36
|
+
def f_of_x
|
37
|
+
Rational(lab.alpha, 500) + f_of_y
|
38
|
+
end
|
39
|
+
|
40
|
+
def f_of_y
|
41
|
+
Rational(lab.lightness + 16, 116)
|
42
|
+
end
|
43
|
+
|
44
|
+
def f_of_z
|
45
|
+
f_of_y - Rational(lab.beta, 200)
|
46
|
+
end
|
47
|
+
|
48
|
+
def x_of_r
|
49
|
+
val = f_of_x ** 3
|
50
|
+
return val if val > Constants::EPSILON
|
51
|
+
|
52
|
+
Rational(116 * f_of_x - 16, Constants::KAPPA)
|
53
|
+
end
|
54
|
+
|
55
|
+
def y_of_r
|
56
|
+
if lab.lightness > (Constants::KAPPA * Constants::EPSILON)
|
57
|
+
return Rational(Rational(lab.lightness + 16, 116)) ** 3
|
58
|
+
end
|
59
|
+
|
60
|
+
Rational(lab.lightness, Constants::KAPPA)
|
61
|
+
end
|
62
|
+
|
63
|
+
def z_of_r
|
64
|
+
val = f_of_z ** 3
|
65
|
+
return val if val > Constants::EPSILON
|
66
|
+
|
67
|
+
Rational(116 * f_of_z - 16, Constants::KAPPA)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../clump/lab'
|
4
|
+
require_relative '../clump/lch'
|
5
|
+
require_relative '../shared/composable'
|
6
|
+
require_relative '../shared/constants'
|
7
|
+
|
8
|
+
module ColorCalculator
|
9
|
+
module Conversion
|
10
|
+
class LchToLab
|
11
|
+
extend Composable
|
12
|
+
|
13
|
+
def initialize(lch)
|
14
|
+
@lch = lch
|
15
|
+
end
|
16
|
+
|
17
|
+
def call
|
18
|
+
Clump::Lab.new(lightness, alpha, beta)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :lch
|
24
|
+
|
25
|
+
def lightness
|
26
|
+
lch.lightness
|
27
|
+
end
|
28
|
+
|
29
|
+
def alpha
|
30
|
+
lch.chroma * Math.cos(lch.hue * Constants::DEGREES_TO_RADIANS)
|
31
|
+
end
|
32
|
+
|
33
|
+
def beta
|
34
|
+
lch.chroma * Math.sin(lch.hue * Constants::DEGREES_TO_RADIANS)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -3,11 +3,11 @@
|
|
3
3
|
require_relative '../shared/composable'
|
4
4
|
require_relative '../conversion/rgb_to_xyz'
|
5
5
|
require_relative '../conversion/xyz_to_lab'
|
6
|
-
require_relative '../conversion/
|
6
|
+
require_relative '../conversion/lab_to_lch'
|
7
7
|
|
8
8
|
module ColorCalculator
|
9
9
|
module Conversion
|
10
|
-
class
|
10
|
+
class RgbToLch
|
11
11
|
extend ColorCalculator::Composable
|
12
12
|
|
13
13
|
def initialize(rgb)
|
@@ -30,7 +30,7 @@ module ColorCalculator
|
|
30
30
|
[
|
31
31
|
ColorCalculator::Conversion::RgbToXyz,
|
32
32
|
ColorCalculator::Conversion::XyzToLab,
|
33
|
-
ColorCalculator::Conversion::
|
33
|
+
ColorCalculator::Conversion::LabToLch
|
34
34
|
]
|
35
35
|
end
|
36
36
|
end
|
@@ -3,26 +3,23 @@
|
|
3
3
|
require_relative '../clump/lab'
|
4
4
|
require_relative '../clump/xyz'
|
5
5
|
require_relative '../shared/composable'
|
6
|
+
require_relative '../shared/constants'
|
6
7
|
|
7
8
|
module ColorCalculator
|
8
9
|
module Conversion
|
9
10
|
class XyzToLab
|
10
11
|
extend ColorCalculator::Composable
|
11
12
|
|
12
|
-
D50 = { x: 0.964220, y: 1.000000, z: 0.825210 }
|
13
|
-
EPSILON = 0.008856
|
14
|
-
KAPPA = 903.3
|
15
|
-
|
16
13
|
APPLE = -> (value) do
|
17
14
|
value ** Rational(1, 3)
|
18
15
|
end
|
19
16
|
|
20
17
|
BANANA = -> (value) do
|
21
|
-
((KAPPA * value) + 16) / 116
|
18
|
+
((Constants::KAPPA * value) + 16) / 116
|
22
19
|
end
|
23
20
|
|
24
21
|
FRUIT = -> (value) do
|
25
|
-
(value > EPSILON ? APPLE : BANANA).call(value)
|
22
|
+
(value > Constants::EPSILON ? APPLE : BANANA).call(value)
|
26
23
|
end
|
27
24
|
|
28
25
|
def initialize(xyz)
|
@@ -51,7 +48,7 @@ module ColorCalculator
|
|
51
48
|
|
52
49
|
%i[x y z].each do |symbol|
|
53
50
|
define_method("#{symbol}_scaled") do
|
54
|
-
xyz.public_send(symbol) / D50.fetch(symbol)
|
51
|
+
xyz.public_send(symbol) / Constants::D50.fetch(symbol)
|
55
52
|
end
|
56
53
|
end
|
57
54
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../clump/rgb'
|
4
|
+
require_relative '../clump/xyz'
|
5
|
+
|
6
|
+
require_relative '../shared/composable'
|
7
|
+
require_relative '../shared/constants'
|
8
|
+
|
9
|
+
module ColorCalculator
|
10
|
+
module Conversion
|
11
|
+
class XyzToRgb
|
12
|
+
extend ColorCalculator::Composable
|
13
|
+
|
14
|
+
XYZ_TO_RGB_TRANSFORM_D50 = [
|
15
|
+
[3.1338561, -1.6168667, -0.4906146],
|
16
|
+
[-0.9787684, 1.9161415, 0.0334540],
|
17
|
+
[0.0719453, -0.2289914, 1.4052427]
|
18
|
+
]
|
19
|
+
|
20
|
+
RGB_COMPAND = -> (value) do
|
21
|
+
if value <= 0.0031308
|
22
|
+
12.92 * value
|
23
|
+
else
|
24
|
+
1.055 * (value ** Rational(10, 24)) - 0.055
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(xyz)
|
29
|
+
@xyz = xyz
|
30
|
+
end
|
31
|
+
|
32
|
+
def call
|
33
|
+
Clump::Rgb.new(red, green, blue, normalized: true)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
attr_reader :xyz
|
39
|
+
|
40
|
+
def red
|
41
|
+
RGB_COMPAND.call(linear_rgb.fetch(:red))
|
42
|
+
end
|
43
|
+
|
44
|
+
def green
|
45
|
+
RGB_COMPAND.call(linear_rgb.fetch(:green))
|
46
|
+
end
|
47
|
+
|
48
|
+
def blue
|
49
|
+
RGB_COMPAND.call(linear_rgb.fetch(:blue))
|
50
|
+
end
|
51
|
+
|
52
|
+
def linear_rgb
|
53
|
+
Hash[
|
54
|
+
%i[red green blue].zip(
|
55
|
+
XYZ_TO_RGB_TRANSFORM_D50.map do |row|
|
56
|
+
%i[x y z].map.with_index do |xyz_val, index|
|
57
|
+
row[index] * xyz.public_send(xyz_val)
|
58
|
+
end.sum
|
59
|
+
end
|
60
|
+
)
|
61
|
+
]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ColorCalculator
|
4
|
+
module Constants
|
5
|
+
RADIANS_TO_DEGREES = Rational(180, Math::PI)
|
6
|
+
|
7
|
+
DEGREES_TO_RADIANS = Rational(Math::PI, 180)
|
8
|
+
|
9
|
+
D50 = { x: 0.964220, y: 1.000000, z: 0.825210 }
|
10
|
+
|
11
|
+
EPSILON = 0.008856
|
12
|
+
|
13
|
+
KAPPA = 903.3
|
14
|
+
end
|
15
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: color_calculator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Seither
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-03-
|
11
|
+
date: 2020-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: You can do color math now!
|
14
14
|
email:
|
@@ -25,15 +25,19 @@ files:
|
|
25
25
|
- lib/color_calculator/clump.rb
|
26
26
|
- lib/color_calculator/clump/abstract.rb
|
27
27
|
- lib/color_calculator/clump/lab.rb
|
28
|
-
- lib/color_calculator/clump/
|
28
|
+
- lib/color_calculator/clump/lch.rb
|
29
29
|
- lib/color_calculator/clump/rgb.rb
|
30
30
|
- lib/color_calculator/clump/xyz.rb
|
31
31
|
- lib/color_calculator/conversion.rb
|
32
|
-
- lib/color_calculator/conversion/
|
33
|
-
- lib/color_calculator/conversion/
|
32
|
+
- lib/color_calculator/conversion/lab_to_lch.rb
|
33
|
+
- lib/color_calculator/conversion/lab_to_xyz.rb
|
34
|
+
- lib/color_calculator/conversion/lch_to_lab.rb
|
35
|
+
- lib/color_calculator/conversion/rgb_to_lch.rb
|
34
36
|
- lib/color_calculator/conversion/rgb_to_xyz.rb
|
35
37
|
- lib/color_calculator/conversion/xyz_to_lab.rb
|
38
|
+
- lib/color_calculator/conversion/xyz_to_rgb.rb
|
36
39
|
- lib/color_calculator/shared/composable.rb
|
40
|
+
- lib/color_calculator/shared/constants.rb
|
37
41
|
- lib/color_calculator/version.rb
|
38
42
|
homepage: https://github.com/Supernats/color_calculator
|
39
43
|
licenses:
|