color_conversion 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/.gitignore +20 -0
  2. data/Gemfile +4 -0
  3. data/Guardfile +9 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +67 -0
  6. data/Rakefile +22 -0
  7. data/color_conversion.gemspec +31 -0
  8. data/lib/color_conversion.rb +20 -0
  9. data/lib/color_conversion/color.rb +10 -0
  10. data/lib/color_conversion/color_converter.rb +124 -0
  11. data/lib/color_conversion/converters/cmyk_converter.rb +26 -0
  12. data/lib/color_conversion/converters/hex_converter.rb +26 -0
  13. data/lib/color_conversion/converters/hsl_converter.rb +51 -0
  14. data/lib/color_conversion/converters/hsl_string_converter.rb +24 -0
  15. data/lib/color_conversion/converters/hsv_converter.rb +35 -0
  16. data/lib/color_conversion/converters/name_converter.rb +167 -0
  17. data/lib/color_conversion/converters/null_converter.rb +14 -0
  18. data/lib/color_conversion/converters/rgb_converter.rb +21 -0
  19. data/lib/color_conversion/converters/rgb_string_converter.rb +25 -0
  20. data/lib/color_conversion/errors.rb +4 -0
  21. data/lib/color_conversion/version.rb +3 -0
  22. data/spec/color_converter_spec.rb +63 -0
  23. data/spec/color_spec.rb +94 -0
  24. data/spec/converters/cmyk_converter_spec.rb +31 -0
  25. data/spec/converters/hex_converter_spec.rb +33 -0
  26. data/spec/converters/hsl_converter_spec.rb +41 -0
  27. data/spec/converters/hsl_string_converter_spec.rb +31 -0
  28. data/spec/converters/hsv_converter_spec.rb +36 -0
  29. data/spec/converters/name_converter_spec.rb +26 -0
  30. data/spec/converters/null_converter_spec.rb +19 -0
  31. data/spec/converters/rgb_converter_spec.rb +41 -0
  32. data/spec/converters/rgb_string_converter_spec.rb +45 -0
  33. data/spec/spec_helper.rb +9 -0
  34. data/spec/version_spec.rb +9 -0
  35. metadata +174 -0
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .rvmrc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ .rspec
8
+ Gemfile.lock
9
+ InstalledFiles
10
+ _yardoc
11
+ coverage
12
+ doc/
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
20
+ bin
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in color_parser.gemspec
4
+ gemspec
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec' do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/color_conversion/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
9
+
@@ -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.
@@ -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)
@@ -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,10 @@
1
+ module ColorConversion
2
+ class Color
3
+ extend Forwardable
4
+ def_delegators :@converter, :rgb, :hex, :hsl, :hsv, :hsb, :cymk, :alpha
5
+
6
+ def initialize(color)
7
+ @converter = ColorConverter.factory(color)
8
+ end
9
+ end
10
+ 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