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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5cff79bc695fab4e8041206a798421948d03eb04933b77274a802f90a0010999
4
- data.tar.gz: 1edc8b8811b32ca6ac4d7b9f8347151ab772fa58d52d90ba4cd8f48ab60d889e
3
+ metadata.gz: bebeb93877646ae484c2432784d6acb4b5a14437024adf5fb4e044f83ccc7de8
4
+ data.tar.gz: 98c736ac93f9ecbad9a989f0dc53f9a4bc7c6cf699f9cf6f891cfd7df954483a
5
5
  SHA512:
6
- metadata.gz: a5fe55d89679198c41e0e166dbdae882b11f9396d58710b004707358652c6187e53889d88dd21efbeeee99b7738484a7cd3d71f7cc35496445881a9558fa9543
7
- data.tar.gz: 507da4fe02639e97285b5df4ed0e6e5e69fd78f793aa8bc772b2702d72e029f227ce50abf2987ac087fe1b050a06562262ed9660ca8395d6833e528412900852
6
+ metadata.gz: 44b8fa514afa086c085af17f0d112b2e575d77ec44dba6cedb5d6d2c98987c0da3e0db74a06e72e2f708f8ffd16f258a54a8a79effd2692b1675dfd041975be0
7
+ data.tar.gz: 1b2a7a03dc0e7aec402e5a289ba692d83ba9d475cdda0e34f6d718abc141c8135dcf49f7b376ab7851e647b6c4f10a69fc7683f5d66a7b3af2ffa7d0c166ee00
data/README.md CHANGED
@@ -1,15 +1,18 @@
1
1
  # Color Converters
2
2
 
3
- > Give me a color and I'll convert it.
3
+ [![Gem Version](https://badge.fury.io/rb/color_converters.svg)](https://badge.fury.io/rb/color_converters)
4
+ ![Static Badge](https://img.shields.io/badge/RubyGems-red?link=https%3A%2F%2Frubygems.org%2Fgems%color_converters)
4
5
 
5
- Color Converters is an ruby gem package for use in ruby or other projects that provides conversions for colors to other color spaces.
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
- > Lab and LCH color spaces are special in that the perceived difference between two colors is proportional to their Euclidean distance in color space. This special property, called perceptual uniformity, makes them ideal for accurate visual encoding of data. In contrast, the more familiar RGB and HSL color spaces distort data when used for visualization.
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
- Colors can be converted between the following spaces:
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 color:
45
+ Initialize a colour:
43
46
 
44
47
  ```ruby
45
48
  # from hex
46
- color = ColorConverters::Color.new("#3366cc")
47
- color = ColorConverters::Color.new("#36c")
49
+ colour = ColorConverters::Color.new("#3366cc")
50
+ colour = ColorConverters::Color.new("#36c")
48
51
 
49
52
  # from rgb(a)
50
- color = ColorConverters::Color.new(r: 51, g: 102, b: 204)
51
- color = ColorConverters::Color.new(r: 51, g: 102, b: 204, a: 0.5)
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
- color = ColorConverters::Color.new(h: 225, s: 73, l: 57)
55
- color = ColorConverters::Color.new(h: 225, s: 73, l: 57, a: 0.5)
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
- color = ColorConverters::Color.new(h: 220, s: 75, v: 80)
59
- color = ColorConverters::Color.new(h: 220, s: 75, b: 80)
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
- color = ColorConverters::Color.new(c: 74, m: 58, y: 22, k: 3)
65
+ colour = ColorConverters::Color.new(c: 74, m: 58, y: 22, k: 3)
63
66
 
64
67
  # from xyz
65
- color = ColorConverters::Color.new(x: 16, y: 44, z: 32)
68
+ colour = ColorConverters::Color.new(x: 16, y: 44, z: 32)
66
69
 
67
70
  # from cielab
68
- color = ColorConverters::Color.new(l: 16, a: 44, b: 32, space: :cie)
71
+ colour = ColorConverters::Color.new(l: 16, a: 44, b: 32, space: :cie)
69
72
 
70
73
  # from cielch
71
- color = ColorConverters::Color.new(l: 16, c: 44, h: 32, space: :cie)
74
+ colour = ColorConverters::Color.new(l: 16, c: 44, h: 32, space: :cie)
72
75
 
73
76
  # from oklab
74
- color = ColorConverters::Color.new(l: 16, a: 44, b: 32, space: :ok)
77
+ colour = ColorConverters::Color.new(l: 16, a: 44, b: 32, space: :ok)
75
78
 
76
79
  # from oklch
77
- color = ColorConverters::Color.new(l: 16, c: 44, h: 32, space: :ok)
80
+ colour = ColorConverters::Color.new(l: 16, c: 44, h: 32, space: :ok)
78
81
 
79
- # from textual color
80
- color = ColorConverters::Color.new("blue")
82
+ # from textual colour
83
+ colour = ColorConverters::Color.new("blue")
81
84
 
82
85
  # from a css rgb(a) string
83
- color = ColorConverters::Color.new("rgb(51, 102, 204)")
84
- color = ColorConverters::Color.new("rgba(51, 102, 204, 0.5)")
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
- color = ColorConverters::Color.new("hsl(225, 73%, 57%)")
88
- color = ColorConverters::Color.new("hsl(225, 73%, 57%, 0.5)")
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
- color = ColorConverters::Color.new(r: 70, g: 130, b: 180, a: 0.5)
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
- color.alpha
100
+ colour.alpha
97
101
  => 0.5
98
102
 
99
- color.rgb
103
+ colour.rgb
100
104
  => {:r=>70, :g=>130, :b=>180}
101
105
 
102
- color.hsl
106
+ colour.hsl
103
107
  => {:h=>207, :s=>44, :l=>49}
104
108
 
105
- color.hsv
109
+ colour.hsv
106
110
  => {:h=>207, :s=>61, :v=>71}
107
111
 
108
- color.hsb
112
+ colour.hsb
109
113
  => {:h=>207, :s=>61, :b=>71}
110
114
 
111
- color.cmyk
115
+ colour.cmyk
112
116
  => {:c=>61, :m=>28, :y=>0, :k=>29}
113
117
 
114
- color.xyz
118
+ colour.xyz
115
119
  => {:x=>33, :y=>21, :z=>54}
116
120
 
117
- color.cielab
121
+ colour.cielab
118
122
  => {:l=>52.47, :a=>-4.08, :b=>-32.19}
119
123
 
120
- color.cielch
124
+ colour.cielch
121
125
  => {:l=>52.47, :c=>32.45, :h=>262.78}
122
126
 
123
- color.oklab # not always accurate
127
+ colour.oklab # not always accurate
124
128
  => {:l=>52.47, :a=>-4.08, :b=>-32.19}
125
129
 
126
- color.oklch # not always accurate
130
+ colour.oklch # not always accurate
127
131
  => {:l=>52.47, :c=>32.45, :h=>262.78}
128
132
 
129
- color.hex
133
+ colour.hex
130
134
  => "#4682b4"
131
135
 
132
- color.name
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 color spaces that use the same letter keys, there needed to be a way to different between those space.
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 usef to help verify results. Different calculators use different exponents and standards so there can be discrepency across them (like this calculator for LCH).
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 = 2
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(color)
24
- converter = BaseConverter.converters.find { |klass| klass.matches?(color) }
25
- converter.new(color) if 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(color_input, limit_override = false)
29
- @original_value = color_input
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(color_input) if limit_clamp == true
33
+ # colour_input = self.clamp_input(colour_input) if limit_clamp == true
32
34
 
33
- if limit_override == false && !self.validate_input(color_input)
34
- raise InvalidColorError # validation method is defined in each convertor
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(color_input) # conversion method is defined in each convertor
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
- "##{'%02x' % @rgba[:r] + '%02x' % @rgba[:g] + '%02x' % @rgba[:b]}"
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
- def initialize(color)
7
- @converter = BaseConverter.factory(color)
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?(color_input)
4
- return false unless color_input.is_a?(Hash)
5
+ def self.matches?(colour_input)
6
+ return false unless colour_input.is_a?(Hash)
5
7
 
6
- color_input.keys - [:l, :a, :b, :space] == [] && color_input[:space].to_s == 'cie'
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 validate_input(color_input)
16
- bounds = CielabConverter.bounds
17
- color_input[:l].to_f.between?(*bounds[:l]) && color_input[:a].to_f.between?(*bounds[:a]) && color_input[:b].to_f.between?(*bounds[:b])
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(color_input)
21
- x, y, z = CielabConverter.cielab_to_xyz(color_input)
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(color_input)
28
- l = color_input[:l].to_d
29
- a = color_input[:a].to_d
30
- b = color_input[:b].to_d
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?(color_input)
4
- return false unless color_input.is_a?(Hash)
5
+ def self.matches?(colour_input)
6
+ return false unless colour_input.is_a?(Hash)
5
7
 
6
- color_input.keys - [:l, :c, :h, :space] == [] && color_input[:space].to_s == 'cie'
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 validate_input(color_input)
16
- bounds = CielchConverter.bounds
17
- color_input[:l].to_f.between?(*bounds[:l]) && color_input[:c].to_f.between?(*bounds[:c]) && color_input[:h].to_f.between?(*bounds[:h])
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(color_input)
21
- l, a, b = CielchConverter.cielch_to_cielab(color_input)
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(color_input)
29
- l = color_input[:l].to_d
30
- c = color_input[:c].to_d
31
- h = color_input[:h].to_d
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?(color_input)
4
- return false unless color_input.is_a?(Hash)
5
+ def self.matches?(colour_input)
6
+ return false unless colour_input.is_a?(Hash)
5
7
 
6
- color_input.keys - [:c, :m, :y, :k] == []
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 validate_input(color_input)
16
- bounds = CmykConverter.bounds
17
- color_input[:c].to_f.between?(*bounds[:c]) && color_input[:m].to_f.between?(*bounds[:m]) && color_input[:y].to_f.between?(*bounds[:y]) && color_input[:k].to_f.between?(*bounds[:k])
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(color_input)
21
- c = color_input[:c].to_f
22
- m = color_input[:m].to_f
23
- y = color_input[:y].to_f
24
- k = color_input[:k].to_f
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?(color)
4
- return false unless color.is_a?(String)
5
+ def self.matches?(colour)
6
+ return false unless colour.is_a?(String)
5
7
 
6
- color.include?('#') && [4, 7, 9].include?(color.length)
8
+ colour.include?('#') && [4, 7, 9].include?(colour.length)
7
9
  end
8
10
 
9
11
  private
10
12
 
11
- def validate_input(_color_input)
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
- true
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 input_to_rgba(color_input)
17
- color_input = self.normalize_hex(color_input)
26
+ def self.hex_to_rgba(hex_input)
27
+ hex_input = self.normalize_hex(hex_input)
18
28
 
19
- r = color_input[0, 2].hex
20
- g = color_input[2, 2].hex
21
- b = color_input[4, 2].hex
22
- a = color_input.length == 8 ? hex[6, 2].hex : 1.0
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 normalize_hex(hex_input)
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?(color_input)
4
- return false unless color_input.is_a?(Hash)
5
+ def self.matches?(colour_input)
6
+ return false unless colour_input.is_a?(Hash)
5
7
 
6
- color_input.keys - [:h, :s, :l] == [] || color_input.keys - [:h, :s, :l, :a] == []
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 validate_input(color_input)
16
- bounds = HslConverter.bounds
17
- color_input[:h].to_f.between?(*bounds[:h]) && color_input[:s].to_f.between?(*bounds[:s]) && color_input[:l].to_f.between?(*bounds[:l])
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(color_input)
21
- h = color_input[:h].to_s.gsub(/[^0-9.]/, '').to_f / 360.0
22
- s = color_input[:s].to_s.gsub(/[^0-9.]/, '').to_f / 100.0
23
- l = color_input[:l].to_s.gsub(/[^0-9.]/, '').to_f / 100.0
24
- a = color_input[:a] ? color_input[:a].to_s.gsub(/[^0-9.]/, '').to_f : 1.0
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 < 0 && t3 += 1
47
+ t3.negative? && t3 += 1
41
48
  t3 > 1 && t3 -= 1
42
49
 
43
50
  val = if 6 * t3 < 1