color_conversion 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +20 -0
- data/Gemfile +4 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +67 -0
- data/Rakefile +22 -0
- data/color_conversion.gemspec +31 -0
- data/lib/color_conversion.rb +20 -0
- data/lib/color_conversion/color.rb +10 -0
- data/lib/color_conversion/color_converter.rb +124 -0
- data/lib/color_conversion/converters/cmyk_converter.rb +26 -0
- data/lib/color_conversion/converters/hex_converter.rb +26 -0
- data/lib/color_conversion/converters/hsl_converter.rb +51 -0
- data/lib/color_conversion/converters/hsl_string_converter.rb +24 -0
- data/lib/color_conversion/converters/hsv_converter.rb +35 -0
- data/lib/color_conversion/converters/name_converter.rb +167 -0
- data/lib/color_conversion/converters/null_converter.rb +14 -0
- data/lib/color_conversion/converters/rgb_converter.rb +21 -0
- data/lib/color_conversion/converters/rgb_string_converter.rb +25 -0
- data/lib/color_conversion/errors.rb +4 -0
- data/lib/color_conversion/version.rb +3 -0
- data/spec/color_converter_spec.rb +63 -0
- data/spec/color_spec.rb +94 -0
- data/spec/converters/cmyk_converter_spec.rb +31 -0
- data/spec/converters/hex_converter_spec.rb +33 -0
- data/spec/converters/hsl_converter_spec.rb +41 -0
- data/spec/converters/hsl_string_converter_spec.rb +31 -0
- data/spec/converters/hsv_converter_spec.rb +36 -0
- data/spec/converters/name_converter_spec.rb +26 -0
- data/spec/converters/null_converter_spec.rb +19 -0
- data/spec/converters/rgb_converter_spec.rb +41 -0
- data/spec/converters/rgb_string_converter_spec.rb +45 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/version_spec.rb +9 -0
- metadata +174 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Derek DeVries
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
## Color Conversion
|
2
|
+
|
3
|
+
This gem provides conversions for colors to and from Hex, RGB, and HSL.
|
4
|
+
|
5
|
+
## Examples
|
6
|
+
|
7
|
+
Create a new color:
|
8
|
+
```ruby
|
9
|
+
# from hex
|
10
|
+
color = Color.new("#FFFFFF")
|
11
|
+
color = Color.new("#FFF")
|
12
|
+
|
13
|
+
# from rgb and rgba
|
14
|
+
color = Color.new(r: 255, g: 255, b: 255)
|
15
|
+
color = Color.new(r: 255, g: 255, b: 255, a: 0.5)
|
16
|
+
|
17
|
+
# from hsl and hsla
|
18
|
+
color = Color.new(h: 0, s: 100, l: 100)
|
19
|
+
color = Color.new(h: 0, s: 100, l: 100, a: 0.5)
|
20
|
+
|
21
|
+
# from textual color
|
22
|
+
color = Color.new("white")
|
23
|
+
|
24
|
+
# from a css declaration
|
25
|
+
color = Color.new("rgb(255,255,255)")
|
26
|
+
color = Color.new("hsl(0,100%,100%)")
|
27
|
+
```
|
28
|
+
|
29
|
+
|
30
|
+
Convert to RGB
|
31
|
+
```ruby
|
32
|
+
Color.new("white").rgb
|
33
|
+
=> {:r=>255, :g=>255, :b=>255}
|
34
|
+
```
|
35
|
+
|
36
|
+
Convert to Hex
|
37
|
+
```ruby
|
38
|
+
Color.new("white").hex
|
39
|
+
=> "#FFFFFF"
|
40
|
+
```
|
41
|
+
|
42
|
+
Convert to HSL
|
43
|
+
```ruby
|
44
|
+
Color.new("white").hsl
|
45
|
+
=> {:h=>0, :s=>100, :l=>100}
|
46
|
+
```
|
47
|
+
|
48
|
+
Convert to Name
|
49
|
+
```ruby
|
50
|
+
Color.new("#FFFFFF").name
|
51
|
+
=> "white"
|
52
|
+
```
|
53
|
+
|
54
|
+
|
55
|
+
## Installation
|
56
|
+
|
57
|
+
To install ColorConversion, add the gem to your Gemfile:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
gem "color_conversion", "~> 0.1.0"
|
61
|
+
```
|
62
|
+
|
63
|
+
## LICENSE
|
64
|
+
|
65
|
+
Copyright (c) 2013 Derek DeVries
|
66
|
+
|
67
|
+
Released under the [MIT License](http://www.opensource.org/licenses/MIT)
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new
|
7
|
+
|
8
|
+
namespace :spec do
|
9
|
+
desc 'Run unit specs only'
|
10
|
+
RSpec::Core::RakeTask.new(:unit) do |task|
|
11
|
+
task.pattern = 'spec'
|
12
|
+
task.rspec_opts = '--tag "~live"'
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Run acceptance specs only'
|
16
|
+
RSpec::Core::RakeTask.new(:acceptance) do |task|
|
17
|
+
task.pattern = 'spec'
|
18
|
+
task.rspec_opts = '--tag "live"'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
task :default => :spec
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'color_conversion/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "color_conversion"
|
8
|
+
gem.version = ColorConversion::VERSION
|
9
|
+
gem.summary = %q{Convert colors to hex/rgb/hsv}
|
10
|
+
gem.description = gem.summary
|
11
|
+
|
12
|
+
gem.required_ruby_version = '>= 1.9.3'
|
13
|
+
gem.license = "MIT"
|
14
|
+
|
15
|
+
gem.authors = ["Derek DeVries"]
|
16
|
+
gem.email = ["derek@sportspyder.com"]
|
17
|
+
gem.homepage = "https://github.com/devrieda/color_conversion"
|
18
|
+
|
19
|
+
gem.files = `git ls-files`.split($/)
|
20
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
21
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
22
|
+
gem.require_paths = ["lib"]
|
23
|
+
|
24
|
+
gem.add_development_dependency("rake")
|
25
|
+
gem.add_development_dependency("rspec", "~> 2.9")
|
26
|
+
|
27
|
+
# guard
|
28
|
+
gem.add_development_dependency("guard", "~> 1.7")
|
29
|
+
gem.add_development_dependency("guard-rspec", "~> 2.5")
|
30
|
+
gem.add_development_dependency("rb-fsevent", "~> 0.9")
|
31
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
require 'color_conversion/version'
|
4
|
+
require 'color_conversion/errors'
|
5
|
+
require 'color_conversion/color'
|
6
|
+
require 'color_conversion/color_converter'
|
7
|
+
|
8
|
+
require 'color_conversion/converters/hex_converter'
|
9
|
+
require 'color_conversion/converters/rgb_string_converter'
|
10
|
+
require 'color_conversion/converters/hsl_string_converter'
|
11
|
+
require 'color_conversion/converters/name_converter'
|
12
|
+
|
13
|
+
require 'color_conversion/converters/cmyk_converter'
|
14
|
+
require 'color_conversion/converters/hsl_converter'
|
15
|
+
require 'color_conversion/converters/hsv_converter'
|
16
|
+
require 'color_conversion/converters/rgb_converter'
|
17
|
+
require 'color_conversion/converters/null_converter'
|
18
|
+
|
19
|
+
module ColorConversion
|
20
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module ColorConversion
|
2
|
+
class ColorConverter
|
3
|
+
attr_reader :rgba
|
4
|
+
|
5
|
+
# keep track of subclasses for factory
|
6
|
+
class << self
|
7
|
+
attr_reader :converters
|
8
|
+
end
|
9
|
+
|
10
|
+
@converters = []
|
11
|
+
|
12
|
+
def self.inherited(subclass)
|
13
|
+
ColorConverter.converters << subclass
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.factory(color)
|
17
|
+
converter = ColorConverter.converters.find do |klass|
|
18
|
+
klass.matches?(color)
|
19
|
+
end
|
20
|
+
converter.new(color) if converter
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(color)
|
24
|
+
@rgba = to_rgba(color)
|
25
|
+
end
|
26
|
+
|
27
|
+
def rgb
|
28
|
+
{r: @rgba[:r], g: @rgba[:g], b: @rgba[:b]}
|
29
|
+
end
|
30
|
+
|
31
|
+
def hex
|
32
|
+
"#" + ("%02x" % @rgba[:r] + "%02x" % @rgba[:g] + "%02x" % @rgba[:b])
|
33
|
+
end
|
34
|
+
|
35
|
+
def hsl
|
36
|
+
r = @rgba[:r] / 255.0
|
37
|
+
g = @rgba[:g] / 255.0
|
38
|
+
b = @rgba[:b] / 255.0
|
39
|
+
min = [r, g, b].min
|
40
|
+
max = [r, g, b].max
|
41
|
+
delta = max - min
|
42
|
+
|
43
|
+
h = if max == min
|
44
|
+
0
|
45
|
+
elsif r == max
|
46
|
+
(g - b) / delta
|
47
|
+
elsif g == max
|
48
|
+
2 + (b - r) / delta
|
49
|
+
elsif b == max
|
50
|
+
4 + (r - g) / delta
|
51
|
+
end
|
52
|
+
|
53
|
+
h = [h * 60, 360].min
|
54
|
+
h += 360 if h < 0
|
55
|
+
l = (min + max) / 2.0
|
56
|
+
|
57
|
+
s = if (max == min)
|
58
|
+
0
|
59
|
+
elsif (l <= 0.5)
|
60
|
+
delta / (max + min)
|
61
|
+
else
|
62
|
+
delta / (2.0 - max - min)
|
63
|
+
end
|
64
|
+
|
65
|
+
{h: h.round, s: (s * 100).round, l: (l * 100).round}
|
66
|
+
end
|
67
|
+
|
68
|
+
def hsv
|
69
|
+
r = @rgba[:r].to_f
|
70
|
+
g = @rgba[:g].to_f
|
71
|
+
b = @rgba[:b].to_f
|
72
|
+
min = [r, g, b].min
|
73
|
+
|
74
|
+
max = [r, g, b].max
|
75
|
+
delta = (max - min).to_f
|
76
|
+
|
77
|
+
s = max == 0 ? 0 : (delta / max * 1000) / 10.0
|
78
|
+
|
79
|
+
h = if max == min
|
80
|
+
0
|
81
|
+
elsif r == max
|
82
|
+
(g - b) / delta
|
83
|
+
elsif g == max
|
84
|
+
2 + (b - r) / delta
|
85
|
+
elsif b == max
|
86
|
+
4 + (r - g) / delta
|
87
|
+
end
|
88
|
+
|
89
|
+
h = [h * 60, 360].min
|
90
|
+
h += 360 if h < 0
|
91
|
+
|
92
|
+
v = ((max / 255.0) * 1000) / 10.0
|
93
|
+
|
94
|
+
{h: h.round, s: s.round, v: v.round}
|
95
|
+
end
|
96
|
+
|
97
|
+
def hsb
|
98
|
+
hsb = hsv
|
99
|
+
hsb[:b] = hsb.delete(:v)
|
100
|
+
hsb
|
101
|
+
end
|
102
|
+
|
103
|
+
def cmyk
|
104
|
+
r = @rgba[:r] / 255.0
|
105
|
+
g = @rgba[:g] / 255.0
|
106
|
+
b = @rgba[:b] / 255.0
|
107
|
+
|
108
|
+
k = [1.0 - r, 1.0 - g, 1.0 - b].min
|
109
|
+
c = (1.0 - r - k) / (1.0 - k)
|
110
|
+
m = (1.0 - g - k) / (1.0 - k)
|
111
|
+
y = (1.0 - b - k) / (1.0 - k)
|
112
|
+
|
113
|
+
{c: (c * 100).round,
|
114
|
+
m: (m * 100).round,
|
115
|
+
y: (y * 100).round,
|
116
|
+
k: (k * 100).round}
|
117
|
+
end
|
118
|
+
|
119
|
+
def alpha
|
120
|
+
@rgba[:a]
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ColorConversion
|
2
|
+
class CmykConverter < ColorConverter
|
3
|
+
|
4
|
+
def self.matches?(color)
|
5
|
+
return false unless color.kind_of?(Hash)
|
6
|
+
|
7
|
+
color.include?(:c) && color.include?(:m) &&
|
8
|
+
color.include?(:y) && color.include?(:k)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def to_rgba(cmyk)
|
14
|
+
c = cmyk[:c].to_f / 100.0
|
15
|
+
m = cmyk[:m].to_f / 100.0
|
16
|
+
y = cmyk[:y].to_f / 100.0
|
17
|
+
k = cmyk[:k].to_f / 100.0
|
18
|
+
|
19
|
+
r = (255 * (1.0 - [1.0, c * (1.0 - k) + k].min)).round
|
20
|
+
g = (255 * (1.0 - [1.0, m * (1.0 - k) + k].min)).round
|
21
|
+
b = (255 * (1.0 - [1.0, y * (1.0 - k) + k].min)).round
|
22
|
+
|
23
|
+
{r: r, g: g, b: b, a: 1.0}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ColorConversion
|
2
|
+
class HexConverter < ColorConverter
|
3
|
+
|
4
|
+
def self.matches?(color)
|
5
|
+
return false unless color.kind_of?(String)
|
6
|
+
|
7
|
+
color.include?("#") && [4, 7].include?(color.length)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def to_rgba(hex)
|
13
|
+
hex = normalize_hex(hex)
|
14
|
+
|
15
|
+
{:r => hex[0,2].hex,
|
16
|
+
:g => hex[2,2].hex,
|
17
|
+
:b => hex[4,2].hex,
|
18
|
+
:a => 1.0}
|
19
|
+
end
|
20
|
+
|
21
|
+
def normalize_hex(hex)
|
22
|
+
hex = hex.gsub("#", "")
|
23
|
+
(hex.length == 3 ? hex[0,1]*2 + hex[1,1]*2 + hex[2,1]*2: hex).downcase
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module ColorConversion
|
2
|
+
class HslConverter < ColorConverter
|
3
|
+
|
4
|
+
def self.matches?(color)
|
5
|
+
return false unless color.kind_of?(Hash)
|
6
|
+
|
7
|
+
color.include?(:h) && color.include?(:s) && color.include?(:l)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def to_rgba(hsl)
|
13
|
+
h = hsl[:h].to_s.gsub(/[^0-9\.]/, "").to_f / 360.0
|
14
|
+
s = hsl[:s].to_s.gsub(/[^0-9\.]/, "").to_f / 100.0
|
15
|
+
l = hsl[:l].to_s.gsub(/[^0-9\.]/, "").to_f / 100.0
|
16
|
+
a = hsl[:a] ? hsl[:a].to_s.gsub(/[^0-9\.]/, "").to_f : 1.0
|
17
|
+
|
18
|
+
return [l * 255, l * 255, l * 255] if s == 0
|
19
|
+
|
20
|
+
t2 = if l < 0.5
|
21
|
+
l * (1 + s)
|
22
|
+
else
|
23
|
+
l + s - l * s
|
24
|
+
end
|
25
|
+
|
26
|
+
t1 = 2 * l - t2
|
27
|
+
|
28
|
+
rgb = [0, 0, 0]
|
29
|
+
|
30
|
+
(0..2).each do |i|
|
31
|
+
t3 = h + 1 / 3.0 * - (i - 1)
|
32
|
+
t3 < 0 && t3 += 1
|
33
|
+
t3 > 1 && t3 -= 1
|
34
|
+
|
35
|
+
val = if 6 * t3 < 1
|
36
|
+
t1 + (t2 - t1) * 6 * t3
|
37
|
+
elsif 2 * t3 < 1
|
38
|
+
t2
|
39
|
+
elsif 3 * t3 < 2
|
40
|
+
t1 + (t2 - t1) * (2 / 3.0 - t3) * 6
|
41
|
+
else
|
42
|
+
t1
|
43
|
+
end
|
44
|
+
|
45
|
+
rgb[i] = (val * 255).round
|
46
|
+
end
|
47
|
+
|
48
|
+
{r: rgb[0], g: rgb[1], b: rgb[2], a: a}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|