color_converters 0.1.3 → 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 +70 -47
- data/Rakefile +8 -8
- data/lib/color_converters/base_converter.rb +17 -14
- data/lib/color_converters/color.rb +17 -2
- data/lib/color_converters/converters/cielab_converter.rb +19 -12
- data/lib/color_converters/converters/cielch_converter.rb +19 -12
- data/lib/color_converters/converters/cmyk_converter.rb +18 -11
- data/lib/color_converters/converters/hex_converter.rb +29 -12
- data/lib/color_converters/converters/hsl_converter.rb +20 -13
- data/lib/color_converters/converters/hsl_string_converter.rb +46 -12
- data/lib/color_converters/converters/hsv_converter.rb +17 -11
- data/lib/color_converters/converters/name_converter.rb +50 -166
- data/lib/color_converters/converters/null_converter.rb +10 -4
- data/lib/color_converters/converters/oklab_converter.rb +26 -18
- data/lib/color_converters/converters/oklch_converter.rb +19 -12
- data/lib/color_converters/converters/rgb_converter.rb +22 -15
- data/lib/color_converters/converters/rgb_string_converter.rb +48 -16
- data/lib/color_converters/converters/xyz_converter.rb +19 -12
- data/lib/color_converters/version.rb +1 -1
- data/lib/color_converters.rb +31 -30
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bebeb93877646ae484c2432784d6acb4b5a14437024adf5fb4e044f83ccc7de8
|
4
|
+
data.tar.gz: 98c736ac93f9ecbad9a989f0dc53f9a4bc7c6cf699f9cf6f891cfd7df954483a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44b8fa514afa086c085af17f0d112b2e575d77ec44dba6cedb5d6d2c98987c0da3e0db74a06e72e2f708f8ffd16f258a54a8a79effd2692b1675dfd041975be0
|
7
|
+
data.tar.gz: 1b2a7a03dc0e7aec402e5a289ba692d83ba9d475cdda0e34f6d718abc141c8135dcf49f7b376ab7851e647b6c4f10a69fc7683f5d66a7b3af2ffa7d0c166ee00
|
data/README.md
CHANGED
@@ -1,15 +1,18 @@
|
|
1
1
|
# Color Converters
|
2
2
|
|
3
|
-
|
3
|
+
[](https://badge.fury.io/rb/color_converters)
|
4
|
+

|
4
5
|
|
5
|
-
|
6
|
-
Given a color in [Hexadecimal, RGA(A), HSL(A), HSV, HSB, CMYK, XYZ, CIELAB, or OKLCH format](https://github.com/devrieda/color_conversion), it can convert the color to those other spaces.
|
6
|
+
> Give me a colour and I'll convert it.
|
7
7
|
|
8
|
-
|
8
|
+
Color Converters is an ruby gem package for use in ruby or other projects that provides conversions for colours to other colour spaces.
|
9
|
+
Given a colour in [Hexadecimal, RGA(A), HSL(A), HSV, HSB, CMYK, XYZ, CIELAB, or OKLCH format](https://github.com/devrieda/color_conversion), it can convert the colour to those other spaces.
|
10
|
+
|
11
|
+
> Lab and LCH colour spaces are special in that the perceived difference between two colours is proportional to their Euclidean distance in colour space. This special property, called perceptual uniformity, makes them ideal for accurate visual encoding of data. In contrast, the more familiar RGB and HSL colour spaces distort data when used for visualization.
|
9
12
|
|
10
13
|
## Converters
|
11
14
|
|
12
|
-
|
15
|
+
Colours can be converted between the following spaces:
|
13
16
|
|
14
17
|
- hex
|
15
18
|
- rgb(a)
|
@@ -19,8 +22,8 @@ Colors can be converted between the following spaces:
|
|
19
22
|
- xyz
|
20
23
|
- cielab
|
21
24
|
- cielch
|
22
|
-
- oklab (not always reliable)
|
23
|
-
- oklch (not always reliable)
|
25
|
+
- oklab (not always reliable when going from oklab to the source colour)
|
26
|
+
- oklch (not always reliable when going from oklch to the source colour)
|
24
27
|
- name
|
25
28
|
|
26
29
|
## Installation
|
@@ -39,97 +42,98 @@ gem install color_converters
|
|
39
42
|
|
40
43
|
## Usage
|
41
44
|
|
42
|
-
Initialize a
|
45
|
+
Initialize a colour:
|
43
46
|
|
44
47
|
```ruby
|
45
48
|
# from hex
|
46
|
-
|
47
|
-
|
49
|
+
colour = ColorConverters::Color.new("#3366cc")
|
50
|
+
colour = ColorConverters::Color.new("#36c")
|
48
51
|
|
49
52
|
# from rgb(a)
|
50
|
-
|
51
|
-
|
53
|
+
colour = ColorConverters::Color.new(r: 51, g: 102, b: 204)
|
54
|
+
colour = ColorConverters::Color.new(r: 51, g: 102, b: 204, a: 0.5)
|
52
55
|
|
53
56
|
# from hsl(a)
|
54
|
-
|
55
|
-
|
57
|
+
colour = ColorConverters::Color.new(h: 225, s: 73, l: 57)
|
58
|
+
colour = ColorConverters::Color.new(h: 225, s: 73, l: 57, a: 0.5)
|
56
59
|
|
57
60
|
# from hsv/hsb
|
58
|
-
|
59
|
-
|
61
|
+
colour = ColorConverters::Color.new(h: 220, s: 75, v: 80)
|
62
|
+
colour = ColorConverters::Color.new(h: 220, s: 75, b: 80)
|
60
63
|
|
61
64
|
# from cmyk
|
62
|
-
|
65
|
+
colour = ColorConverters::Color.new(c: 74, m: 58, y: 22, k: 3)
|
63
66
|
|
64
67
|
# from xyz
|
65
|
-
|
68
|
+
colour = ColorConverters::Color.new(x: 16, y: 44, z: 32)
|
66
69
|
|
67
70
|
# from cielab
|
68
|
-
|
71
|
+
colour = ColorConverters::Color.new(l: 16, a: 44, b: 32, space: :cie)
|
69
72
|
|
70
73
|
# from cielch
|
71
|
-
|
74
|
+
colour = ColorConverters::Color.new(l: 16, c: 44, h: 32, space: :cie)
|
72
75
|
|
73
76
|
# from oklab
|
74
|
-
|
77
|
+
colour = ColorConverters::Color.new(l: 16, a: 44, b: 32, space: :ok)
|
75
78
|
|
76
79
|
# from oklch
|
77
|
-
|
80
|
+
colour = ColorConverters::Color.new(l: 16, c: 44, h: 32, space: :ok)
|
78
81
|
|
79
|
-
# from textual
|
80
|
-
|
82
|
+
# from textual colour
|
83
|
+
colour = ColorConverters::Color.new("blue")
|
81
84
|
|
82
85
|
# from a css rgb(a) string
|
83
|
-
|
84
|
-
|
86
|
+
colour = ColorConverters::Color.new("rgb(51, 102, 204)")
|
87
|
+
colour = ColorConverters::Color.new("rgba(51, 102, 204, 0.5)")
|
85
88
|
|
86
89
|
# from a css hsl(a) string
|
87
|
-
|
88
|
-
|
90
|
+
colour = ColorConverters::Color.new("hsl(225, 73%, 57%)")
|
91
|
+
colour = ColorConverters::Color.new("hsl(225, 73%, 57%, 0.5)")
|
89
92
|
```
|
90
93
|
|
91
94
|
Converters
|
92
95
|
|
93
96
|
```ruby
|
94
|
-
|
97
|
+
colour = ColorConverters::Color.new("rgba(70, 130, 180, 0.5)")
|
98
|
+
colour = ColorConverters::Color.new(r: 70, g: 130, b: 180, a: 0.5)
|
95
99
|
|
96
|
-
|
100
|
+
colour.alpha
|
97
101
|
=> 0.5
|
98
102
|
|
99
|
-
|
103
|
+
colour.rgb
|
100
104
|
=> {:r=>70, :g=>130, :b=>180}
|
101
105
|
|
102
|
-
|
106
|
+
colour.hsl
|
103
107
|
=> {:h=>207, :s=>44, :l=>49}
|
104
108
|
|
105
|
-
|
109
|
+
colour.hsv
|
106
110
|
=> {:h=>207, :s=>61, :v=>71}
|
107
111
|
|
108
|
-
|
112
|
+
colour.hsb
|
109
113
|
=> {:h=>207, :s=>61, :b=>71}
|
110
114
|
|
111
|
-
|
115
|
+
colour.cmyk
|
112
116
|
=> {:c=>61, :m=>28, :y=>0, :k=>29}
|
113
117
|
|
114
|
-
|
118
|
+
colour.xyz
|
115
119
|
=> {:x=>33, :y=>21, :z=>54}
|
116
120
|
|
117
|
-
|
121
|
+
colour.cielab
|
118
122
|
=> {:l=>52.47, :a=>-4.08, :b=>-32.19}
|
119
123
|
|
120
|
-
|
124
|
+
colour.cielch
|
121
125
|
=> {:l=>52.47, :c=>32.45, :h=>262.78}
|
122
126
|
|
123
|
-
|
127
|
+
colour.oklab # not always accurate
|
124
128
|
=> {:l=>52.47, :a=>-4.08, :b=>-32.19}
|
125
129
|
|
126
|
-
|
130
|
+
colour.oklch # not always accurate
|
127
131
|
=> {:l=>52.47, :c=>32.45, :h=>262.78}
|
128
132
|
|
129
|
-
|
133
|
+
colour.hex
|
130
134
|
=> "#4682b4"
|
131
135
|
|
132
|
-
|
136
|
+
colour.name
|
133
137
|
=> "steelblue"
|
134
138
|
```
|
135
139
|
|
@@ -137,26 +141,45 @@ color.name
|
|
137
141
|
|
138
142
|
### space
|
139
143
|
|
140
|
-
As there are certain
|
144
|
+
As there are certain colour spaces that use the same letter keys, there needed to be a way to different between those space.
|
141
145
|
The space parameter allows that, with examples in the usage code above
|
142
146
|
|
143
147
|
```ruby
|
144
148
|
ColorConverters::Color.new(l: 64, a: 28, b: -15, space: :cie)
|
145
|
-
ColorConverters::Color.new(l: 64, a: 28, b: -15, space: :ok)
|
149
|
+
ColorConverters::Color.new(l: 64, a: 0.28, b: -0.15, space: :ok)
|
146
150
|
```
|
147
151
|
|
148
152
|
### limit_override
|
149
153
|
|
150
|
-
By default all values are checked to be within the expected number ranges, i.e.; rgb between 0-255 each.
|
154
|
+
By default all values are checked to be within the expected number ranges, i.e.; rgb between 0-255 each but there are certain spaces where this is less fixed which this option is purposed for.
|
151
155
|
This parameter allows you to ignore those ranges and submit any values you want.
|
156
|
+
**WARNING: even if you use this, there may be certain conversions that can not handle the large source values; e.g.**
|
152
157
|
|
153
158
|
```ruby
|
154
|
-
ColorConverters::Color.new(r: 270, g: 1300, b: 380, a: 0.5, limit_override: true)
|
159
|
+
ColorConverters::Color.new(r: 270, g: 1300, b: 380, a: 0.5, limit_override: true).rgb
|
160
|
+
=> {r: 270.0, g: 1300.0, b: 380.0}
|
161
|
+
|
162
|
+
ColorConverters::Color.new(x: 174, y: 135, z: 137, limit_override: true).xyz
|
163
|
+
=> {x: 91.58, y: 93.06, z: 107.75}
|
164
|
+
```
|
165
|
+
|
166
|
+
### fuzzy
|
167
|
+
|
168
|
+
Name conversions by default look for exact matches between the hex value of the colour
|
169
|
+
|
170
|
+
```ruby
|
171
|
+
colour = ColorConverters::Color.new(r: 175.8, g: 196.4, b: 222.1)
|
172
|
+
|
173
|
+
colour.name
|
174
|
+
=> nil
|
175
|
+
|
176
|
+
colour.name(fuzzy: true)
|
177
|
+
=> 'lightsteelblue'
|
155
178
|
```
|
156
179
|
|
157
180
|
## Development
|
158
181
|
|
159
|
-
[Converting Colors](https://convertingcolors.com/) and [Colorffy](https://colorffy.com/) can be
|
182
|
+
[Converting Colors](https://convertingcolors.com/) and [Colorffy](https://colorffy.com/) can be used to help verify results. Different calculators use different exponents and standards so there can be discrepency across them (like this calculator for LCH).
|
160
183
|
|
161
184
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
162
185
|
|
data/Rakefile
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'bundler/gem_tasks'
|
4
|
-
require 'rspec/core/rake_task'
|
5
|
-
|
6
|
-
RSpec::Core::RakeTask.new(:spec)
|
7
|
-
|
8
|
-
task default: :spec
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
7
|
+
|
8
|
+
task default: :spec
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/core_ext/object/blank'
|
2
4
|
require 'bigdecimal'
|
3
5
|
require 'bigdecimal/util'
|
4
6
|
|
5
7
|
module ColorConverters
|
6
8
|
class BaseConverter
|
7
|
-
IMPORT_DP =
|
9
|
+
IMPORT_DP = 8
|
8
10
|
OUTPUT_DP = 2
|
9
11
|
|
10
12
|
attr_reader :original_value, :rgba
|
@@ -20,21 +22,20 @@ module ColorConverters
|
|
20
22
|
BaseConverter.converters << subclass
|
21
23
|
end
|
22
24
|
|
23
|
-
def self.factory(
|
24
|
-
converter = BaseConverter.converters.find { |klass| klass.matches?(
|
25
|
-
converter
|
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)
|
26
28
|
end
|
27
29
|
|
28
|
-
def initialize(
|
29
|
-
|
30
|
+
def initialize(colour_input, limit_override = false, limit_clamp = false)
|
31
|
+
colour_input.delete(:space) if colour_input.is_a?(Hash)
|
30
32
|
|
31
|
-
# self.clamp_input(
|
33
|
+
# colour_input = self.clamp_input(colour_input) if limit_clamp == true
|
32
34
|
|
33
|
-
|
34
|
-
|
35
|
-
end
|
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?
|
36
37
|
|
37
|
-
r, g, b, a = self.input_to_rgba(
|
38
|
+
r, g, b, a = self.input_to_rgba(colour_input) # conversion method is defined in each convertor
|
38
39
|
|
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) }
|
40
41
|
end
|
@@ -44,15 +45,17 @@ module ColorConverters
|
|
44
45
|
end
|
45
46
|
|
46
47
|
def hex
|
47
|
-
|
48
|
+
HexConverter.rgb_to_hex(self.rgb_array)
|
48
49
|
end
|
49
50
|
|
51
|
+
# not refactored to SubClass methods due to needing so many of the private methods
|
50
52
|
def hsl
|
51
53
|
@r, @g, @b = self.rgb_array_frac
|
52
54
|
|
53
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) }
|
54
56
|
end
|
55
57
|
|
58
|
+
# not refactored to SubClass methods due to needing so many of the private methods
|
56
59
|
def hsv
|
57
60
|
@r, @g, @b = self.rgb_array
|
58
61
|
|
@@ -105,8 +108,8 @@ module ColorConverters
|
|
105
108
|
@rgba[:a]
|
106
109
|
end
|
107
110
|
|
108
|
-
def name
|
109
|
-
NameConverter.rgb_to_name(self.rgb_array)
|
111
|
+
def name(fuzzy: false)
|
112
|
+
NameConverter.rgb_to_name(self.rgb_array, fuzzy)
|
110
113
|
end
|
111
114
|
|
112
115
|
protected
|
@@ -1,10 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ColorConverters
|
2
4
|
class Color
|
3
5
|
extend Forwardable
|
4
6
|
def_delegators :@converter, :rgb, :hex, :hsl, :hsv, :hsb, :cmyk, :xyz, :cielab, :cielch, :oklab, :oklch, :name, :alpha
|
5
7
|
|
6
|
-
|
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)
|
8
23
|
end
|
9
24
|
|
10
25
|
def ==(other)
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ColorConverters
|
2
4
|
class CielabConverter < BaseConverter
|
3
|
-
def self.matches?(
|
4
|
-
return false unless
|
5
|
+
def self.matches?(colour_input)
|
6
|
+
return false unless colour_input.is_a?(Hash)
|
5
7
|
|
6
|
-
|
8
|
+
colour_input.keys - [:l, :a, :b, :space] == [] && colour_input[:space].to_s == 'cie'
|
7
9
|
end
|
8
10
|
|
9
11
|
def self.bounds
|
@@ -12,22 +14,27 @@ module ColorConverters
|
|
12
14
|
|
13
15
|
private
|
14
16
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
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
|
18
25
|
end
|
19
26
|
|
20
|
-
def input_to_rgba(
|
21
|
-
x, y, z = CielabConverter.cielab_to_xyz(
|
27
|
+
def input_to_rgba(colour_input)
|
28
|
+
x, y, z = CielabConverter.cielab_to_xyz(colour_input)
|
22
29
|
r, g, b = XyzConverter.xyz_to_rgb({ x: x, y: y, z: z })
|
23
30
|
|
24
31
|
[r, g, b, 1.0]
|
25
32
|
end
|
26
33
|
|
27
|
-
def self.cielab_to_xyz(
|
28
|
-
l =
|
29
|
-
a =
|
30
|
-
b =
|
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
|
31
38
|
|
32
39
|
yy = (l + 16.0.to_d) / 116.0.to_d
|
33
40
|
xx = (a / 500.0.to_d) + yy
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ColorConverters
|
2
4
|
class CielchConverter < BaseConverter
|
3
|
-
def self.matches?(
|
4
|
-
return false unless
|
5
|
+
def self.matches?(colour_input)
|
6
|
+
return false unless colour_input.is_a?(Hash)
|
5
7
|
|
6
|
-
|
8
|
+
colour_input.keys - [:l, :c, :h, :space] == [] && colour_input[:space].to_s == 'cie'
|
7
9
|
end
|
8
10
|
|
9
11
|
def self.bounds
|
@@ -12,23 +14,28 @@ module ColorConverters
|
|
12
14
|
|
13
15
|
private
|
14
16
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
17
|
+
# def clamp_input(colour_input)
|
18
|
+
# colour_input.each { |key, value| colour_input[key] = value.clamp(*CielchConverter.bounds[key]) }
|
19
|
+
# end
|
20
|
+
|
21
|
+
def validate_input(colour_input)
|
22
|
+
CielchConverter.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
|
18
25
|
end
|
19
26
|
|
20
|
-
def input_to_rgba(
|
21
|
-
l, a, b = CielchConverter.cielch_to_cielab(
|
27
|
+
def input_to_rgba(colour_input)
|
28
|
+
l, a, b = CielchConverter.cielch_to_cielab(colour_input)
|
22
29
|
x, y, z = CielabConverter.cielab_to_xyz({ l: l, a: a, b: b })
|
23
30
|
r, g, b = XyzConverter.xyz_to_rgb({ x: x, y: y, z: z })
|
24
31
|
|
25
32
|
[r, g, b, 1.0]
|
26
33
|
end
|
27
34
|
|
28
|
-
def self.cielch_to_cielab(
|
29
|
-
l =
|
30
|
-
c =
|
31
|
-
h =
|
35
|
+
def self.cielch_to_cielab(colour_input)
|
36
|
+
l = colour_input[:l].to_d
|
37
|
+
c = colour_input[:c].to_d
|
38
|
+
h = colour_input[:h].to_d
|
32
39
|
|
33
40
|
h_rad = h * (Math::PI.to_d / 180.0.to_d)
|
34
41
|
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ColorConverters
|
2
4
|
class CmykConverter < BaseConverter
|
3
|
-
def self.matches?(
|
4
|
-
return false unless
|
5
|
+
def self.matches?(colour_input)
|
6
|
+
return false unless colour_input.is_a?(Hash)
|
5
7
|
|
6
|
-
|
8
|
+
colour_input.keys - [:c, :m, :y, :k] == []
|
7
9
|
end
|
8
10
|
|
9
11
|
def self.bounds
|
@@ -12,16 +14,21 @@ module ColorConverters
|
|
12
14
|
|
13
15
|
private
|
14
16
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
17
|
+
# def clamp_input(colour_input)
|
18
|
+
# colour_input.each { |key, value| colour_input[key] = value.clamp(*CmykConverter.bounds[key]) }
|
19
|
+
# end
|
20
|
+
|
21
|
+
def validate_input(colour_input)
|
22
|
+
CmykConverter.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
|
18
25
|
end
|
19
26
|
|
20
|
-
def input_to_rgba(
|
21
|
-
c =
|
22
|
-
m =
|
23
|
-
y =
|
24
|
-
k =
|
27
|
+
def input_to_rgba(colour_input)
|
28
|
+
c = colour_input[:c].to_f
|
29
|
+
m = colour_input[:m].to_f
|
30
|
+
y = colour_input[:y].to_f
|
31
|
+
k = colour_input[:k].to_f
|
25
32
|
|
26
33
|
c /= 100.0
|
27
34
|
m /= 100.0
|
@@ -1,31 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ColorConverters
|
2
4
|
class HexConverter < BaseConverter
|
3
|
-
def self.matches?(
|
4
|
-
return false unless
|
5
|
+
def self.matches?(colour)
|
6
|
+
return false unless colour.is_a?(String)
|
5
7
|
|
6
|
-
|
8
|
+
colour.include?('#') && [4, 7, 9].include?(colour.length)
|
7
9
|
end
|
8
10
|
|
9
11
|
private
|
10
12
|
|
11
|
-
def
|
13
|
+
# def clamp_input(colour_input)
|
14
|
+
# colour_input # return it as it was
|
15
|
+
# end
|
16
|
+
|
17
|
+
def validate_input(_colour_input)
|
12
18
|
# TODO
|
13
|
-
|
19
|
+
[] # to return no errors
|
20
|
+
end
|
21
|
+
|
22
|
+
def input_to_rgba(colour_input)
|
23
|
+
HexConverter.hex_to_rgba(colour_input)
|
14
24
|
end
|
15
25
|
|
16
|
-
def
|
17
|
-
|
26
|
+
def self.hex_to_rgba(hex_input)
|
27
|
+
hex_input = self.normalize_hex(hex_input)
|
18
28
|
|
19
|
-
r =
|
20
|
-
g =
|
21
|
-
b =
|
22
|
-
a =
|
29
|
+
r = hex_input[0, 2].hex
|
30
|
+
g = hex_input[2, 2].hex
|
31
|
+
b = hex_input[4, 2].hex
|
32
|
+
a = hex_input.length == 8 ? hex[6, 2].hex : 1.0
|
23
33
|
|
24
34
|
[r, g, b, a]
|
25
35
|
end
|
26
36
|
|
27
|
-
def
|
37
|
+
def self.rgb_to_hex(rgb_array)
|
38
|
+
r, g, b = rgb_array
|
39
|
+
|
40
|
+
format('#%<r>02x%<g>02x%<b>02x', r: r, g: g, b: b)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.normalize_hex(hex_input)
|
28
44
|
hex_input = hex_input.gsub('#', '')
|
45
|
+
|
29
46
|
(hex_input.length == 3 ? hex_input[0, 1] * 2 + hex_input[1, 1] * 2 + hex_input[2, 1] * 2 : hex_input).downcase
|
30
47
|
end
|
31
48
|
end
|
@@ -1,27 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ColorConverters
|
2
4
|
class HslConverter < BaseConverter
|
3
|
-
def self.matches?(
|
4
|
-
return false unless
|
5
|
+
def self.matches?(colour_input)
|
6
|
+
return false unless colour_input.is_a?(Hash)
|
5
7
|
|
6
|
-
|
8
|
+
colour_input.keys - [:h, :s, :l] == [] || colour_input.keys - [:h, :s, :l, :a] == []
|
7
9
|
end
|
8
10
|
|
9
11
|
def self.bounds
|
10
|
-
{ h: [0.0, 360.0], s: [0.0, 100.0], l: [0.0, 100.0] }
|
12
|
+
{ h: [0.0, 360.0], s: [0.0, 100.0], l: [0.0, 100.0], a: [0.0, 1.0] }
|
11
13
|
end
|
12
14
|
|
13
15
|
private
|
14
16
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
17
|
+
# def clamp_input(colour_input)
|
18
|
+
# colour_input.each { |key, value| colour_input[key] = value.clamp(*HslConverter.bounds[key]) }
|
19
|
+
# end
|
20
|
+
|
21
|
+
def validate_input(colour_input)
|
22
|
+
HslConverter.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
|
18
25
|
end
|
19
26
|
|
20
|
-
def input_to_rgba(
|
21
|
-
h =
|
22
|
-
s =
|
23
|
-
l =
|
24
|
-
a =
|
27
|
+
def input_to_rgba(colour_input)
|
28
|
+
h = colour_input[:h].to_s.gsub(/[^0-9.]/, '').to_f / 360.0
|
29
|
+
s = colour_input[:s].to_s.gsub(/[^0-9.]/, '').to_f / 100.0
|
30
|
+
l = colour_input[:l].to_s.gsub(/[^0-9.]/, '').to_f / 100.0
|
31
|
+
a = colour_input[:a] ? colour_input[:a].to_s.gsub(/[^0-9.]/, '').to_f : 1.0
|
25
32
|
|
26
33
|
return greyscale(l, a) if s.zero?
|
27
34
|
|
@@ -37,7 +44,7 @@ module ColorConverters
|
|
37
44
|
|
38
45
|
(0..2).each do |i|
|
39
46
|
t3 = h + 1 / 3.0 * - (i - 1)
|
40
|
-
t3
|
47
|
+
t3.negative? && t3 += 1
|
41
48
|
t3 > 1 && t3 -= 1
|
42
49
|
|
43
50
|
val = if 6 * t3 < 1
|