colorable 0.0.1
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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +59 -0
- data/Rakefile +1 -0
- data/colorable.gemspec +21 -0
- data/lib/colorable.rb +12 -0
- data/lib/colorable/color.rb +51 -0
- data/lib/colorable/colorset.rb +74 -0
- data/lib/colorable/converter.rb +101 -0
- data/lib/colorable/system_extension.rb +24 -0
- data/lib/colorable/version.rb +3 -0
- data/spec/color_spec.rb +60 -0
- data/spec/colorset_spec.rb +66 -0
- data/spec/converter_spec.rb +127 -0
- data/spec/spec_helper.rb +2 -0
- metadata +84 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 kyoendo
|
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,59 @@
|
|
1
|
+
# Colorable
|
2
|
+
|
3
|
+
A simple color handler which provide a conversion between colorname, RGB, HSB and HEX. It also provides a colorset which can be sorted by above color units.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'colorable'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install colorable
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Create a color object:
|
22
|
+
|
23
|
+
require "colorable"
|
24
|
+
|
25
|
+
# Accept X11 color names
|
26
|
+
c = Colorable::Color.new(:green)
|
27
|
+
c # => rgb(0,255,0)
|
28
|
+
c.name # => "Green"
|
29
|
+
c.hsb # => [120, 100, 100]
|
30
|
+
c.hex # => "#00FF00"
|
31
|
+
|
32
|
+
# or RGB
|
33
|
+
c2 = Colorable::Color.new([240, 248, 255])
|
34
|
+
c2 # => rgb(240,248,255)
|
35
|
+
c2.name # => "Alice Blue"
|
36
|
+
c2.rgb # => [240, 248, 255]
|
37
|
+
c2.hsb # => [208, 6, 100]
|
38
|
+
c2.hex # => "#F0F8FF"
|
39
|
+
|
40
|
+
Create a colorset object:
|
41
|
+
|
42
|
+
# Default colorset sequence is by its color name order.
|
43
|
+
cs = Colorable::Colorset.new
|
44
|
+
cs.at # => rgb(240,248,255)
|
45
|
+
10.times.map { cs.next.name } # => ["Antique White", "Aqua", "Aquamarine", "Azure", "Beige", "Bisque", "Black", "Blanched Almond", "Blue", "Blue Violet"]
|
46
|
+
|
47
|
+
# Using Colorset#[], the order of the sequence is specified.
|
48
|
+
cs2 = Colorable::Colorset[:hsb]
|
49
|
+
cs2.at # => rgb(0,0,0)
|
50
|
+
10.times.map { cs2.next.hsb } # => [[0, 0, 41], [0, 0, 50], [0, 0, 66], [0, 0, 75], [0, 0, 75], [0, 0, 83], [0, 0, 86], [0, 0, 96], [0, 0, 100], [0, 2, 100]]
|
51
|
+
|
52
|
+
|
53
|
+
## Contributing
|
54
|
+
|
55
|
+
1. Fork it
|
56
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
57
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
58
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
59
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/colorable.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'colorable/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "colorable"
|
8
|
+
gem.version = Colorable::VERSION
|
9
|
+
gem.authors = ["kyoendo"]
|
10
|
+
gem.email = ["postagie@gmail.com"]
|
11
|
+
gem.description = %q{A simple color handler which provide a conversion between colorname, RGB, HSB and HEX}
|
12
|
+
gem.summary = %q{A simple color handler which provide a conversion between colorname, RGB, HSB and HEX}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
gem.required_ruby_version = '>=1.9.3'
|
20
|
+
gem.add_development_dependency 'rspec'
|
21
|
+
end
|
data/lib/colorable.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "colorable/version"
|
2
|
+
%w(system_extension converter color colorset).each { |lib| require_relative "colorable/" + lib }
|
3
|
+
|
4
|
+
module Colorable
|
5
|
+
|
6
|
+
# Based on X11 color names - Wikipedia, the free encyclopedia
|
7
|
+
# http://en.wikipedia.org/wiki/X11_color_names
|
8
|
+
# When W3C color conflict with X11, a name of the color is appended with '2'.
|
9
|
+
COLORNAMES = [["Alice Blue", [240, 248, 255]], ["Antique White", [250, 235, 215]], ["Aqua", [0, 255, 255]], ["Aquamarine", [127, 255, 212]], ["Azure", [240, 255, 255]], ["Beige", [245, 245, 220]], ["Bisque", [255, 228, 196]], ["Black", [0, 0, 0]], ["Blanched Almond", [255, 235, 205]], ["Blue", [0, 0, 255]], ["Blue Violet", [138, 43, 226]], ["Brown", [165, 42, 42]], ["Burlywood", [222, 184, 135]], ["Cadet Blue", [95, 158, 160]], ["Chartreuse", [127, 255, 0]], ["Chocolate", [210, 105, 30]], ["Coral", [255, 127, 80]], ["Cornflower", [100, 149, 237]], ["Cornsilk", [255, 248, 220]], ["Crimson", [220, 20, 60]], ["Cyan", [0, 255, 255]], ["Dark Blue", [0, 0, 139]], ["Dark Cyan", [0, 139, 139]], ["Dark Goldenrod", [184, 134, 11]], ["Dark Gray", [169, 169, 169]], ["Dark Green", [0, 100, 0]], ["Dark Khaki", [189, 183, 107]], ["Dark Magenta", [139, 0, 139]], ["Dark Olive Green", [85, 107, 47]], ["Dark Orange", [255, 140, 0]], ["Dark Orchid", [153, 50, 204]], ["Dark Red", [139, 0, 0]], ["Dark Salmon", [233, 150, 122]], ["Dark Sea Green", [143, 188, 143]], ["Dark Slate Blue", [72, 61, 139]], ["Dark Slate Gray", [47, 79, 79]], ["Dark Turquoise", [0, 206, 209]], ["Dark Violet", [148, 0, 211]], ["Deep Pink", [255, 20, 147]], ["Deep Sky Blue", [0, 191, 255]], ["Dim Gray", [105, 105, 105]], ["Dodger Blue", [30, 144, 255]], ["Firebrick", [178, 34, 34]], ["Floral White", [255, 250, 240]], ["Forest Green", [34, 139, 34]], ["Fuchsia", [255, 0, 255]], ["Gainsboro", [220, 220, 220]], ["Ghost White", [248, 248, 255]], ["Gold", [255, 215, 0]], ["Goldenrod", [218, 165, 32]], ["Gray", [190, 190, 190]], ["Gray2", [128, 128, 128]], ["Green", [0, 255, 0]], ["Green Yellow", [173, 255, 47]], ["Green2", [0, 128, 0]], ["Honeydew", [240, 255, 240]], ["Hot Pink", [255, 105, 180]], ["Indian Red", [205, 92, 92]], ["Indigo", [75, 0, 130]], ["Ivory", [255, 255, 240]], ["Khaki", [240, 230, 140]], ["Lavender", [230, 230, 250]], ["Lavender Blush", [255, 240, 245]], ["Lawn Green", [124, 252, 0]], ["Lemon Chiffon", [255, 250, 205]], ["Light Blue", [173, 216, 230]], ["Light Coral", [240, 128, 128]], ["Light Cyan", [224, 255, 255]], ["Light Goldenrod", [250, 250, 210]], ["Light Gray", [211, 211, 211]], ["Light Green", [144, 238, 144]], ["Light Pink", [255, 182, 193]], ["Light Salmon", [255, 160, 122]], ["Light Sea Green", [32, 178, 170]], ["Light Sky Blue", [135, 206, 250]], ["Light Slate Gray", [119, 136, 153]], ["Light Steel Blue", [176, 196, 222]], ["Light Yellow", [255, 255, 224]], ["Lime", [0, 255, 0]], ["Lime Green", [50, 205, 50]], ["Linen", [250, 240, 230]], ["Magenta", [255, 0, 255]], ["Maroon", [176, 48, 96]], ["Maroon2", [127, 0, 0]], ["Medium Aquamarine", [102, 205, 170]], ["Medium Blue", [0, 0, 205]], ["Medium Orchid", [186, 85, 211]], ["Medium Purple", [147, 112, 219]], ["Medium Sea Green", [60, 179, 113]], ["Medium Slate Blue", [123, 104, 238]], ["Medium Spring Green", [0, 250, 154]], ["Medium Turquoise", [72, 209, 204]], ["Medium Violet Red", [199, 21, 133]], ["Midnight Blue", [25, 25, 112]], ["Mint Cream", [245, 255, 250]], ["Misty Rose", [255, 228, 225]], ["Moccasin", [255, 228, 181]], ["Navajo White", [255, 222, 173]], ["Navy", [0, 0, 128]], ["Old Lace", [253, 245, 230]], ["Olive", [128, 128, 0]], ["Olive Drab", [107, 142, 35]], ["Orange", [255, 165, 0]], ["Orange Red", [255, 69, 0]], ["Orchid", [218, 112, 214]], ["Pale Goldenrod", [238, 232, 170]], ["Pale Green", [152, 251, 152]], ["Pale Turquoise", [175, 238, 238]], ["Pale Violet Red", [219, 112, 147]], ["Papaya Whip", [255, 239, 213]], ["Peach Puff", [255, 218, 185]], ["Peru", [205, 133, 63]], ["Pink", [255, 192, 203]], ["Plum", [221, 160, 221]], ["Powder Blue", [176, 224, 230]], ["Purple", [160, 32, 240]], ["Purple2", [127, 0, 127]], ["Red", [255, 0, 0]], ["Rosy Brown", [188, 143, 143]], ["Royal Blue", [65, 105, 225]], ["Saddle Brown", [139, 69, 19]], ["Salmon", [250, 128, 114]], ["Sandy Brown", [244, 164, 96]], ["Sea Green", [46, 139, 87]], ["Seashell", [255, 245, 238]], ["Sienna", [160, 82, 45]], ["Silver", [192, 192, 192]], ["Sky Blue", [135, 206, 235]], ["Slate Blue", [106, 90, 205]], ["Slate Gray", [112, 128, 144]], ["Snow", [255, 250, 250]], ["Spring Green", [0, 255, 127]], ["Steel Blue", [70, 130, 180]], ["Tan", [210, 180, 140]], ["Teal", [0, 128, 128]], ["Thistle", [216, 191, 216]], ["Tomato", [255, 99, 71]], ["Turquoise", [64, 224, 208]], ["Violet", [238, 130, 238]], ["Wheat", [245, 222, 179]], ["White", [255, 255, 255]], ["White Smoke", [245, 245, 245]], ["Yellow", [255, 255, 0]], ["Yellow Green", [154, 205, 50]]]
|
10
|
+
|
11
|
+
end
|
12
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Colorable
|
2
|
+
class Color
|
3
|
+
class ColorNameError < StandardError; end
|
4
|
+
include Colorable::Converter
|
5
|
+
attr_reader :name, :rgb
|
6
|
+
|
7
|
+
def initialize(name_or_rgb)
|
8
|
+
@name, @rgb, @hex, @hsb, @esc = nil
|
9
|
+
case name_or_rgb
|
10
|
+
when String, Symbol
|
11
|
+
@name = varidate_name(name_or_rgb)
|
12
|
+
@rgb = name2rgb(@name)
|
13
|
+
when Array
|
14
|
+
@rgb = validate_rgb(name_or_rgb)
|
15
|
+
@name = rgb2name(@rgb)
|
16
|
+
else
|
17
|
+
raise ArgumentError, "'#{name_or_rgb}' is wrong argument. Only colorname and RGB value are acceptable"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"rgb(%i,%i,%i)" % rgb
|
23
|
+
end
|
24
|
+
|
25
|
+
def hex
|
26
|
+
@hex ||= rgb2hex(rgb)
|
27
|
+
end
|
28
|
+
|
29
|
+
def hsb
|
30
|
+
@hsb ||= rgb2hsb(rgb)
|
31
|
+
end
|
32
|
+
|
33
|
+
%w(red green blue).each_with_index do |c, i|
|
34
|
+
define_method(c) { rgb[i] }
|
35
|
+
end
|
36
|
+
|
37
|
+
%w(hue sat bright).each_with_index do |n, i|
|
38
|
+
define_method(n) { hsb[i] }
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def varidate_name(name)
|
43
|
+
COLORNAMES.detect do |label, _|
|
44
|
+
[label, name].same? { |str| "#{str}".gsub(/[_\s]/,'').downcase }
|
45
|
+
end.tap do |res, _|
|
46
|
+
raise ColorNameError, "'#{name}' is not a valid colorname" unless res
|
47
|
+
break res
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Colorable
|
2
|
+
class Colorset
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize(colorset=nil)
|
6
|
+
@pos = 0
|
7
|
+
@colorset =
|
8
|
+
colorset || COLORNAMES.map { |name, rgb| Colorable::Color.new(name) }
|
9
|
+
end
|
10
|
+
|
11
|
+
# +Colorset[:order]+ create a ordered colorset by passing a order key.
|
12
|
+
def self.[](order, dir=:+)
|
13
|
+
rgb = [:red, :green, :blue]
|
14
|
+
hsb = [:hue, :sat, :bright]
|
15
|
+
blk =
|
16
|
+
case order
|
17
|
+
when :red, :blue, :green
|
18
|
+
->color{ color.rgb.move_to_top rgb.index(order) }
|
19
|
+
when :hue, :sat, :bright
|
20
|
+
->color{ color.hsb.move_to_top hsb.index(order) }
|
21
|
+
else
|
22
|
+
->color{ color.send order }
|
23
|
+
end
|
24
|
+
|
25
|
+
case dir
|
26
|
+
when :+
|
27
|
+
new.sort_by(&blk)
|
28
|
+
when :-
|
29
|
+
new.sort_by(&blk).reverse
|
30
|
+
else
|
31
|
+
raise ArgumentError, "it must ':+' or ':-'"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def each(&blk)
|
36
|
+
@colorset.each(&blk)
|
37
|
+
end
|
38
|
+
|
39
|
+
def at(pos=0)
|
40
|
+
@colorset[pos]
|
41
|
+
end
|
42
|
+
|
43
|
+
def next(n=1)
|
44
|
+
@pos += n
|
45
|
+
at @pos
|
46
|
+
end
|
47
|
+
|
48
|
+
def prev(n=1)
|
49
|
+
@pos -= n
|
50
|
+
at @pos
|
51
|
+
end
|
52
|
+
|
53
|
+
def rewind
|
54
|
+
@pos = 0
|
55
|
+
at @pos
|
56
|
+
end
|
57
|
+
|
58
|
+
def last(n=1)
|
59
|
+
@colorset.last(n)
|
60
|
+
end
|
61
|
+
|
62
|
+
def first(n=1)
|
63
|
+
@colorset.first(n)
|
64
|
+
end
|
65
|
+
|
66
|
+
def sort_by(&blk)
|
67
|
+
self.class.new @colorset.sort_by(&blk)
|
68
|
+
end
|
69
|
+
|
70
|
+
def reverse
|
71
|
+
self.class.new @colorset.reverse
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module Colorable
|
2
|
+
module Converter
|
3
|
+
class NoNameError < StandardError; end
|
4
|
+
|
5
|
+
def name2rgb(name)
|
6
|
+
COLORNAMES.assoc(name)[1]
|
7
|
+
rescue
|
8
|
+
raise NoNameError, "'#{name}' not exist"
|
9
|
+
end
|
10
|
+
|
11
|
+
def rgb2name(rgb)
|
12
|
+
validate_rgb(rgb)
|
13
|
+
COLORNAMES.rassoc(rgb).tap { |c, _| break c if c }
|
14
|
+
end
|
15
|
+
|
16
|
+
def rgb2hsb(rgb)
|
17
|
+
validate_rgb(rgb)
|
18
|
+
r, g, b = rgb.map(&:to_f)
|
19
|
+
hue = Math.atan2(Math.sqrt(3)*(g-b), 2*r-g-b).to_degree
|
20
|
+
|
21
|
+
min, max = [r, g, b].minmax
|
22
|
+
sat = [min, max].all?(&:zero?) ? 0.0 : ((max - min) / max * 100)
|
23
|
+
|
24
|
+
bright = max / 2.55
|
25
|
+
[hue, sat, bright].map(&:round)
|
26
|
+
end
|
27
|
+
alias :rgb2hsv :rgb2hsb
|
28
|
+
|
29
|
+
class NotImplemented < StandardError; end
|
30
|
+
def rgb2hsl(rgb)
|
31
|
+
validate_rgb(rgb)
|
32
|
+
raise NotImplemented, 'Not Implemented Yet'
|
33
|
+
r, g, b = rgb.map(&:to_f)
|
34
|
+
hue = Math.atan2(Math.sqrt(3)*(g-b), 2*r-g-b).to_degree
|
35
|
+
|
36
|
+
min, max = [r, g, b].minmax
|
37
|
+
sat = [min, max].all?(&:zero?) ? 0.0 : ((max - min) / (1-(max+min-1).abs) * 100)
|
38
|
+
|
39
|
+
lum = 0.298912*r + 0.586611*g + 0.114478*b
|
40
|
+
[hue, sat, lum].map(&:round)
|
41
|
+
end
|
42
|
+
|
43
|
+
def hsb2rgb(hsb)
|
44
|
+
validate_hsb(hsb)
|
45
|
+
hue, sat, bright = hsb
|
46
|
+
norm = ->range{ hue.norm(range, 0..255) }
|
47
|
+
rgb_h =
|
48
|
+
case hue
|
49
|
+
when 0..60 then [255, norm[0..60], 0]
|
50
|
+
when 60..120 then [255-norm[60..120], 255, 0]
|
51
|
+
when 120..180 then [0, 255, norm[120..180]]
|
52
|
+
when 180..240 then [0, 255-norm[180..240], 255]
|
53
|
+
when 240..300 then [norm[240..300], 0, 255]
|
54
|
+
when 300..360 then [255, 0, 255-norm[300.360]]
|
55
|
+
end
|
56
|
+
rgb_s = rgb_h.map { |val| val + (255-val) * (1-sat/100.0) }
|
57
|
+
rgb_s.map { |val| (val * bright/100.0).round }
|
58
|
+
end
|
59
|
+
alias :hsv2rgb :hsb2rgb
|
60
|
+
|
61
|
+
def rgb2hex(rgb)
|
62
|
+
validate_rgb(rgb)
|
63
|
+
hex = rgb.map do |val|
|
64
|
+
val.to_s(16).tap { |h| break "0#{h}" if h.size==1 }
|
65
|
+
end
|
66
|
+
'#' + hex.join.upcase
|
67
|
+
end
|
68
|
+
|
69
|
+
def hex2rgb(hex)
|
70
|
+
validate_hex(hex)
|
71
|
+
_, *hex = hex.unpack('A1A2A2A2')
|
72
|
+
hex.map { |val| val.to_i(16) }
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def validate_rgb(rgb)
|
77
|
+
if rgb.all? { |val| val.between?(0, 255) }
|
78
|
+
rgb
|
79
|
+
else
|
80
|
+
raise ArgumentError, "'#{rgb}' is invalid for a RGB value"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def validate_hsb(hsb)
|
85
|
+
h, *sb = hsb
|
86
|
+
if h.between?(0, 360) && sb.all? { |val| val.between?(0, 100) }
|
87
|
+
hsb
|
88
|
+
else
|
89
|
+
raise ArgumentError, "'#{hsb}' is invalid for a HSB value"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def validate_hex(hex)
|
94
|
+
if hex.match(/^#[0-9A-F]{6}$/i)
|
95
|
+
hex.upcase
|
96
|
+
else
|
97
|
+
raise ArgumentError, "'#{hex}' is invalid for a HEX value"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Float
|
2
|
+
def to_degree
|
3
|
+
res = self * (180 / Math::PI)
|
4
|
+
res < 0 ? res + 360 : res
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class Numeric
|
9
|
+
def norm(range, tgr=0.0..1.0)
|
10
|
+
unit = (self - range.min) / (range.max - range.min).to_f
|
11
|
+
unit * (tgr.max - tgr.min) + tgr.min
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Array
|
16
|
+
def same?(&blk)
|
17
|
+
self.uniq(&blk).size==1
|
18
|
+
end
|
19
|
+
|
20
|
+
def move_to_top(idx)
|
21
|
+
arr = self.dup
|
22
|
+
arr.insert 0, arr.delete_at(idx)
|
23
|
+
end
|
24
|
+
end
|
data/spec/color_spec.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe Colorable::Color do
|
4
|
+
let(:color) { Colorable::Color }
|
5
|
+
describe ".new" do
|
6
|
+
context "with a string" do
|
7
|
+
context "of valid colorname" do
|
8
|
+
it { color.new("Alice Blue").name.should eql "Alice Blue" }
|
9
|
+
it { color.new("Khaki").name.should eql "Khaki" }
|
10
|
+
it { color.new("Mint Cream").name.should eql "Mint Cream" }
|
11
|
+
it { color.new("Thistle").name.should eql "Thistle" }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "of valid name variations" do
|
15
|
+
it { color.new("AliceBlue").name.should eql "Alice Blue" }
|
16
|
+
it { color.new("aliceblue").name.should eql "Alice Blue" }
|
17
|
+
it { color.new("aliceblue").name.should eql "Alice Blue" }
|
18
|
+
it { color.new(:AliceBlue).name.should eql "Alice Blue" }
|
19
|
+
it { color.new(:aliceblue).name.should eql "Alice Blue" }
|
20
|
+
it { color.new(:alice_blue).name.should eql "Alice Blue" }
|
21
|
+
end
|
22
|
+
|
23
|
+
context "of invalid name" do
|
24
|
+
it "raise an error" do
|
25
|
+
expect { color.new("Alice-Blue") }.to raise_error color::ColorNameError
|
26
|
+
expect { color.new("Alice") }.to raise_error color::ColorNameError
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with an array" do
|
32
|
+
context "of valid RGB value" do
|
33
|
+
it { color.new([240, 248, 255]).rgb.should eql [240, 248, 255] }
|
34
|
+
it { color.new([240, 230, 140]).rgb.should eql [240, 230, 140] }
|
35
|
+
it { color.new([245, 255, 250]).rgb.should eql [245, 255, 250] }
|
36
|
+
it { color.new([216, 191, 216]).rgb.should eql [216, 191, 216] }
|
37
|
+
end
|
38
|
+
|
39
|
+
context "of invalid RGB value" do
|
40
|
+
it "raise an error" do
|
41
|
+
expect { color.new([200, 100, 260]) }.to raise_error ArgumentError
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "#hex" do
|
48
|
+
it { color.new("Alice Blue").hex.should eql "#F0F8FF" }
|
49
|
+
it { color.new("Khaki").hex.should eql "#F0E68C" }
|
50
|
+
it { color.new("Mint Cream").hex.should eql "#F5FFFA" }
|
51
|
+
it { color.new("Thistle").hex.should eql "#D8BFD8" }
|
52
|
+
end
|
53
|
+
|
54
|
+
context "#hsb" do
|
55
|
+
it { color.new("Alice Blue").hsb.should eql [208, 6, 100] }
|
56
|
+
it { color.new("Khaki").hsb.should eql [55, 42, 94] }
|
57
|
+
it { color.new("Mint Cream").hsb.should eql [150, 4, 100] }
|
58
|
+
it { color.new("Thistle").hsb.should eql [300, 12, 85] }
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe Colorable::Colorset do
|
4
|
+
let(:colorset) { Colorable::Colorset }
|
5
|
+
let(:color) { Colorable::Color }
|
6
|
+
describe ".new" do
|
7
|
+
it "returns a colorset object" do
|
8
|
+
colorset.new.should be_a_instance_of colorset
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe ".[](order)" do
|
13
|
+
context "when :rgb passed" do
|
14
|
+
before(:all) { @cs = colorset[:rgb] }
|
15
|
+
it { @cs.take(3).to_s.should eql '[rgb(0,0,0), rgb(0,0,128), rgb(0,0,139)]' }
|
16
|
+
it { @cs.last.to_s.should eql '[rgb(255,255,255)]' }
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when :red" do
|
20
|
+
before(:all) { @cs = colorset[:red] }
|
21
|
+
it { @cs.take(3).to_s.should eql '[rgb(0,0,0), rgb(0,0,128), rgb(0,0,139)]' }
|
22
|
+
it { @cs.last.to_s.should eql '[rgb(255,255,255)]' }
|
23
|
+
end
|
24
|
+
|
25
|
+
context "when :green in descent order" do
|
26
|
+
before(:all) { @cs = colorset[:green, :-] }
|
27
|
+
it { @cs.take(3).to_s.should eql '[rgb(255,255,255), rgb(255,255,240), rgb(255,255,224)]' }
|
28
|
+
it { @cs.last(3).to_s.should eql '[rgb(0,0,139), rgb(0,0,128), rgb(0,0,0)]' }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#at" do
|
33
|
+
context "when colorset is ordered RGB" do
|
34
|
+
before(:all) { @cs = colorset.new }
|
35
|
+
it { @cs.at.to_s.should eql 'rgb(240,248,255)' }
|
36
|
+
it { @cs.at(1).to_s.should eql 'rgb(250,235,215)' }
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when colorset is ordered RGB" do
|
40
|
+
before(:all) { @cs = colorset[:green] }
|
41
|
+
it { @cs.at.to_s.should eql 'rgb(0,0,0)' }
|
42
|
+
it { @cs.at(1).to_s.should eql 'rgb(0,0,128)' }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#next" do
|
47
|
+
before(:all) { @cs = colorset.new }
|
48
|
+
it { @cs.next.should eql @cs.at(1) }
|
49
|
+
it { @cs.next.should eql @cs.at(2) }
|
50
|
+
it { @cs.next.should eql @cs.at(3) }
|
51
|
+
it { @cs.next(2).should eql @cs.at(5) }
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#prev" do
|
55
|
+
before(:all) { @cs = colorset[:hsb] }
|
56
|
+
it { @cs.prev.should eql @cs.at(-1) }
|
57
|
+
it { @cs.prev.should eql @cs.at(-2) }
|
58
|
+
it { @cs.prev.should eql @cs.at(-3) }
|
59
|
+
it { @cs.prev(2).should eql @cs.at(-5) }
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#rewind" do
|
63
|
+
before(:all) { @cs = colorset.new }
|
64
|
+
it { @cs.next(10); @cs.rewind.should eql @cs.at }
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
include Colorable::Converter
|
4
|
+
describe Colorable::Converter do
|
5
|
+
let(:conv) { Colorable::Converter }
|
6
|
+
describe "#name2rgb" do
|
7
|
+
context "when name exsist" do
|
8
|
+
it "return a RGB value" do
|
9
|
+
name2rgb("Alice Blue").should eql [240, 248, 255]
|
10
|
+
name2rgb("Khaki").should eql [240, 230, 140]
|
11
|
+
name2rgb("Mint Cream").should eql [245, 255, 250]
|
12
|
+
name2rgb("Thistle").should eql [216, 191, 216]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when name not exist" do
|
17
|
+
it "raise NoNameError" do
|
18
|
+
expect { name2rgb("Hello Yellow") }.to raise_error conv::NoNameError
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#rgb2name" do
|
24
|
+
context "when name exist" do
|
25
|
+
it "returns a name" do
|
26
|
+
rgb2name([240, 248, 255]).should eql "Alice Blue"
|
27
|
+
rgb2name([216, 191, 216]).should eql "Thistle"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when name not exist" do
|
32
|
+
it "returns nil" do
|
33
|
+
rgb2name([240, 240, 240]).should be_nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when invalid rgb" do
|
38
|
+
it "raise ArgumentError" do
|
39
|
+
expect { rgb2name([0, 260, 0]) }.to raise_error ArgumentError
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#rgb2hsb" do
|
45
|
+
context "when a valid rgb" do
|
46
|
+
it "returns a HSB value" do
|
47
|
+
rgb2hsb([240, 248, 255]).should eql [208, 6, 100]
|
48
|
+
rgb2hsb([216, 191, 216]).should eql [300, 12, 85]
|
49
|
+
rgb2hsb([240, 230, 140]).should eql [55, 42, 94]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when a invalid rgb" do
|
54
|
+
it "raise ArgumentError" do
|
55
|
+
expect { rgb2hsb([100, 100, -10]) }.to raise_error ArgumentError
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "#hsb2rgb" do
|
61
|
+
context "when a valid hsb" do
|
62
|
+
it "returns a RGB value" do
|
63
|
+
hsb2rgb([208, 6, 100]).should eql [240, 248, 255]
|
64
|
+
hsb2rgb([300, 12, 85]).should eql [217, 191, 217] # hava a margin of error
|
65
|
+
hsb2rgb([55, 42, 94]).should eql [240, 231, 139] # hava a margin of error
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "when a invalid hsb" do
|
70
|
+
it "raise ArgumentError" do
|
71
|
+
expect { hsb2rgb([-100, 50, 50]) }.to raise_error ArgumentError
|
72
|
+
expect { hsb2rgb([350, 101, 50]) }.to raise_error ArgumentError
|
73
|
+
expect { hsb2rgb([0, 50, -50]) }.to raise_error ArgumentError
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#rgb2hex" do
|
79
|
+
context "when a valid rgb" do
|
80
|
+
it "returns a HEX value" do
|
81
|
+
rgb2hex([240, 248, 255]).should eql '#F0F8FF'
|
82
|
+
rgb2hex([216, 191, 216]).should eql '#D8BFD8'
|
83
|
+
rgb2hex([240, 230, 140]).should eql '#F0E68C'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "when a invalid rgb" do
|
88
|
+
it "raise ArgumentError" do
|
89
|
+
expect { rgb2hex([100, 100, -10]) }.to raise_error ArgumentError
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#hex2rgb" do
|
95
|
+
context "when a valid hex" do
|
96
|
+
it "returns a RGB value" do
|
97
|
+
hex2rgb('#F0F8FF').should eql [240, 248, 255]
|
98
|
+
hex2rgb('#D8BFD8').should eql [216, 191, 216]
|
99
|
+
hex2rgb('#f0e68c').should eql [240, 230, 140]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "when a invalid hex" do
|
104
|
+
it "raise ArgumentError" do
|
105
|
+
expect { hex2rgb('#FFFFFG') }.to raise_error ArgumentError
|
106
|
+
expect { hex2rgb('$FFFFFG') }.to raise_error ArgumentError
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "#rgb2hsl" do
|
112
|
+
context "when a valid rgb" do
|
113
|
+
it "returns a HSL value" do
|
114
|
+
expect { rgb2hsl([240, 248, 255]) }.to raise_error NotImplemented
|
115
|
+
# rgb2hsl([240, 248, 255]).should eql [208, 100, 97]
|
116
|
+
# rgb2hsl([216, 191, 216]).should eql [300, 24, 80]
|
117
|
+
# rgb2hsl([240, 230, 140]).should eql [55, 77, 75]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "when a invalid rgb" do
|
122
|
+
it "raise ArgumentError" do
|
123
|
+
expect { rgb2hsb([100, 100, -10]) }.to raise_error ArgumentError
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: colorable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- kyoendo
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-05 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: A simple color handler which provide a conversion between colorname,
|
31
|
+
RGB, HSB and HEX
|
32
|
+
email:
|
33
|
+
- postagie@gmail.com
|
34
|
+
executables: []
|
35
|
+
extensions: []
|
36
|
+
extra_rdoc_files: []
|
37
|
+
files:
|
38
|
+
- .gitignore
|
39
|
+
- Gemfile
|
40
|
+
- LICENSE.txt
|
41
|
+
- README.md
|
42
|
+
- Rakefile
|
43
|
+
- colorable.gemspec
|
44
|
+
- lib/colorable.rb
|
45
|
+
- lib/colorable/color.rb
|
46
|
+
- lib/colorable/colorset.rb
|
47
|
+
- lib/colorable/converter.rb
|
48
|
+
- lib/colorable/system_extension.rb
|
49
|
+
- lib/colorable/version.rb
|
50
|
+
- spec/color_spec.rb
|
51
|
+
- spec/colorset_spec.rb
|
52
|
+
- spec/converter_spec.rb
|
53
|
+
- spec/spec_helper.rb
|
54
|
+
homepage: ''
|
55
|
+
licenses: []
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.9.3
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 1.8.24
|
75
|
+
signing_key:
|
76
|
+
specification_version: 3
|
77
|
+
summary: A simple color handler which provide a conversion between colorname, RGB,
|
78
|
+
HSB and HEX
|
79
|
+
test_files:
|
80
|
+
- spec/color_spec.rb
|
81
|
+
- spec/colorset_spec.rb
|
82
|
+
- spec/converter_spec.rb
|
83
|
+
- spec/spec_helper.rb
|
84
|
+
has_rdoc:
|