chroma 0.0.1.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 58cd2ee5df8643fe579d9f3abbb73eb6e5abdd7e
4
+ data.tar.gz: 9f7fc61bf911705268bf1ad174c68106db3e8184
5
+ SHA512:
6
+ metadata.gz: fc91d84ce91dd630d8d8c5371d83e092e11748b44b6158a4281dde2246ced584fc8bd6e30f63f6a5acc12779cde30eb0892c88cb6825b38d05f4da20d55a95e7
7
+ data.tar.gz: e61fd039b71428b30d286d4294bef7c116efad95991dce5174fa1c0ae771da9981119b231756971f0473775d2085957ca83b5347d4e3d98ddf6a9de4a81a458d
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in colortastic.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2015, Jeremy Fairbank <elpapapollo@gmail.com>
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any
4
+ purpose with or without fee is hereby granted, provided that the above
5
+ copyright notice and this permission notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # Chroma
2
+
3
+ Chroma is a color manipulation and palette generation library. It is heavily
4
+ inspired by and a very close Ruby port of the
5
+ [tinycolor.js](https://bgrins.github.io/TinyColor/)
6
+ library. Many thanks to [Brian Grinstead](http://www.briangrinstead.com/blog/)
7
+ for his hard work on that library.
8
+
9
+ Chroma is in alpha stage at the moment. Most of the API methods from tinycolor
10
+ have been ported over with a few exceptions. However, I will be working on
11
+ cleaning up the API where needed, adding docs and examples, and adding tests
12
+ before a first release. Because this is currently in alpha, please be
13
+ prepared for possible API changes or bugs.
14
+
15
+ Please don't hesitate to examine the code and make issues or pull requests
16
+ where you feel it is necessary. Please refer to the
17
+ [Contributing](#contributing) section below.
18
+
19
+ ## Installation
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ ```ruby
24
+ gem 'chroma', '0.0.1.alpha.1'
25
+ ```
26
+
27
+ And then execute:
28
+
29
+ $ bundle
30
+
31
+ Or install it yourself as:
32
+
33
+ $ gem install chroma
34
+
35
+ ## Usage
36
+
37
+ Chroma adds several of the methods available in
38
+ [tinycolor.js](https://github.com/bgrins/TinyColor) but renamed appropriately
39
+ for Ruby conventions (i.e. `isDark` becomes `dark?`).
40
+
41
+ To create a color, just call the `Chroma.paint` method, passing in a string
42
+ that represents a color.
43
+
44
+ ```ruby
45
+ Chroma.paint 'red' # named colors
46
+ Chroma.paint '#00ff00' # 6 character hexadecimal
47
+ Chroma.paint '#00f' # 3 character hexadecimal
48
+ Chroma.paint 'rgb(255, 255, 0)' # rgb
49
+ Chroma.paint 'rgba(255, 255, 0, 0.5)' # rgba
50
+ Chroma.paint 'hsl(60, 100%, 50%)' # hsl with percentages
51
+ Chroma.paint 'hsl(60, 1, 0.5)' # hsl with decimals
52
+ Chroma.paint 'hsv(60, 100%, 50%)' # hsv with percentages
53
+ Chroma.paint 'hsv(60, 1, 0.5)' # hsv with decimals
54
+ ```
55
+
56
+ To work directly from a string you can also use the `String#paint` method:
57
+
58
+ ```ruby
59
+ 'red'.paint
60
+ '#00f'.paint
61
+ 'rgb(255, 255, 0)'.paint
62
+
63
+ # etc...
64
+ ```
65
+
66
+ ## Contributing
67
+
68
+ Please branch from **dev** for all pull requests.
69
+
70
+ 1. Fork it (https://github.com/jfairbank/chroma/fork)
71
+ 2. Checkout dev (`git checkout dev`)
72
+ 3. Create your feature branch (`git checkout -b my-new-feature`)
73
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
74
+ 5. Push to the branch (`git push origin my-new-feature`)
75
+ 6. Create a new pull request against dev
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/chroma.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'chroma/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'chroma'
8
+ spec.version = Chroma::VERSION
9
+ spec.authors = ['Jeremy Fairbank']
10
+ spec.email = ['elpapapollo@gmail.com']
11
+ spec.summary = %q{Color manipulation and palette generation.}
12
+ spec.description = %q{Chroma is a color manipulation and palette generation gem.}
13
+ spec.homepage = 'https://github.com/jfairbank/chroma'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.7'
22
+ spec.add_development_dependency 'rake', '~> 10.0'
23
+ end
data/lib/chroma.rb ADDED
@@ -0,0 +1,63 @@
1
+ # General
2
+ require 'chroma/version'
3
+ require 'yaml'
4
+
5
+ # Modules
6
+ require 'chroma/helpers/bounders'
7
+
8
+ # Color
9
+ require 'chroma/color/attributes'
10
+ require 'chroma/color/serializers'
11
+ require 'chroma/color/modifiers'
12
+ require 'chroma/color'
13
+ require 'chroma/color_modes'
14
+
15
+ # Palettes
16
+ require 'chroma/harmonies'
17
+
18
+ # RGB Generators
19
+ require 'chroma/rgb_generator'
20
+ require 'chroma/rgb_generator/base'
21
+ require 'chroma/rgb_generator/from_string'
22
+ require 'chroma/rgb_generator/from_rgb_values'
23
+ require 'chroma/rgb_generator/from_rgb'
24
+ require 'chroma/rgb_generator/from_hsl_values'
25
+ require 'chroma/rgb_generator/from_hsl'
26
+ require 'chroma/rgb_generator/from_hsv_values'
27
+ require 'chroma/rgb_generator/from_hsv'
28
+ require 'chroma/rgb_generator/from_hex_string_values'
29
+
30
+ # Converters
31
+ require 'chroma/converters/base'
32
+ require 'chroma/converters/rgb_converter'
33
+ require 'chroma/converters/hsl_converter'
34
+ require 'chroma/converters/hsv_converter'
35
+
36
+ # Extensions
37
+ require 'chroma/extensions/string'
38
+
39
+ module Chroma
40
+ class << self
41
+ def paint(input)
42
+ Color.new(input)
43
+ end
44
+
45
+ def hex_from_name(name)
46
+ named_colors_map[name]
47
+ end
48
+
49
+ def name_from_hex(hex)
50
+ hex_named_colors_map[hex]
51
+ end
52
+
53
+ private
54
+
55
+ def hex_named_colors_map
56
+ @hex_named_colors_map ||= named_colors_map.invert
57
+ end
58
+
59
+ def named_colors_map
60
+ @named_colors ||= YAML.load_file(File.expand_path('../support/named_colors.yml', __FILE__))
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,34 @@
1
+ module Chroma
2
+ class Color
3
+ include Attributes
4
+ include Serializers
5
+ include Modifiers
6
+ include Helpers::Bounders
7
+
8
+ def initialize(input, format = nil)
9
+ @input = input
10
+ @rgb, gen_format = generate_rgb_and_format(input)
11
+ @format = format || gen_format
12
+ end
13
+
14
+ def complement
15
+ hsl = to_hsl
16
+ hsl.h = (hsl.h + 180) % 360
17
+ Color.new(hsl)
18
+ end
19
+
20
+ def palette
21
+ Harmonies.new(self)
22
+ end
23
+
24
+ private
25
+
26
+ def to_2char_hex(n)
27
+ n.round.to_s(16).rjust(2, '0')
28
+ end
29
+
30
+ def generate_rgb_and_format(input)
31
+ RgbGenerator.generate_rgb_and_format(input)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,21 @@
1
+ module Chroma
2
+ class Color
3
+ module Attributes
4
+ def dark?
5
+ brightness < 128
6
+ end
7
+
8
+ def light?
9
+ !dark?
10
+ end
11
+
12
+ def alpha
13
+ @rgb.a
14
+ end
15
+
16
+ def brightness
17
+ (@rgb.r * 299 + @rgb.g * 587 + @rgb.b * 114) / 1000.0
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,52 @@
1
+ module Chroma
2
+ class Color
3
+ module Modifiers
4
+ def lighten(amount = 10)
5
+ hsl = to_hsl
6
+ hsl.l = clamp01(hsl.l + amount / 100.0)
7
+ self.class.new(hsl, @format)
8
+ end
9
+
10
+ def brighten(amount = 10)
11
+ # Don't include alpha
12
+ rgb = @rgb.to_a[0..2].map(&:round)
13
+ amount = (255 * (-amount / 100.0)).round
14
+
15
+ rgb.map! do |n|
16
+ [0, [255, n - amount].min].max
17
+ end
18
+
19
+ self.class.new(ColorModes::Rgb.new(*rgb), @format)
20
+ end
21
+
22
+ def darken(amount = 10)
23
+ hsl = to_hsl
24
+ hsl.l = clamp01(hsl.l - amount / 100.0)
25
+ self.class.new(hsl, @format)
26
+ end
27
+
28
+ def desaturate(amount = 10)
29
+ hsl = to_hsl
30
+ hsl.s = clamp01(hsl.s - amount / 100.0)
31
+ self.class.new(hsl, @format)
32
+ end
33
+
34
+ def saturate(amount = 10)
35
+ hsl = to_hsl
36
+ hsl.s = clamp01(hsl.s + amount / 100.0)
37
+ self.class.new(hsl, @format)
38
+ end
39
+
40
+ def greyscale
41
+ desaturate(100)
42
+ end
43
+
44
+ def spin(amount)
45
+ hsl = to_hsl
46
+ hue = (hsl.h.round + amount) % 360
47
+ hsl.h = hue < 0 ? 360 + hue : hue
48
+ self.class.new(hsl, @format)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,113 @@
1
+ module Chroma
2
+ class Color
3
+ module Serializers
4
+ def to_hsv
5
+ Converters::HsvConverter.convert_rgb(@rgb)
6
+ end
7
+
8
+ def to_hsv_s
9
+ to_hs_s(:v)
10
+ end
11
+
12
+ def to_hsl
13
+ Converters::HslConverter.convert_rgb(@rgb)
14
+ end
15
+
16
+ def to_hsl_s
17
+ to_hs_s(:l)
18
+ end
19
+
20
+ def to_hex(allow_3 = false)
21
+ r, g, b = [@rgb.r, @rgb.g, @rgb.b].map do |n|
22
+ to_2char_hex(n)
23
+ end
24
+
25
+ if allow_3 && r[0] == r[1] && g[0] == g[1] && b[0] == b[1]
26
+ return "#{r[0]}#{g[0]}#{b[0]}"
27
+ end
28
+
29
+ [r, g, b].flatten * ''
30
+ end
31
+
32
+ def to_hex_s(allow_3 = false)
33
+ "##{to_hex(allow_3)}"
34
+ end
35
+
36
+ def to_hex8
37
+ [
38
+ to_2char_hex(alpha * 255),
39
+ to_2char_hex(@rgb.r),
40
+ to_2char_hex(@rgb.g),
41
+ to_2char_hex(@rgb.b)
42
+ ].join('')
43
+ end
44
+
45
+ def to_hex8_s
46
+ "##{to_hex8}"
47
+ end
48
+
49
+ def to_rgb
50
+ @rgb
51
+ end
52
+
53
+ def to_rgb_s
54
+ middle = @rgb.to_a[0..2].map(&:round).join(', ')
55
+
56
+ to_alpha_s(:rgb, middle)
57
+ end
58
+
59
+ def to_name
60
+ return 'transparent' if alpha.zero?
61
+
62
+ if alpha < 1 || (name = Chroma.name_from_hex(to_hex(true))).nil?
63
+ '<unknown>'
64
+ else
65
+ name
66
+ end
67
+ end
68
+
69
+ alias_method :to_name_s, :to_name
70
+
71
+ def to_s(format = @format)
72
+ use_alpha = alpha < 1 && alpha >= 0 && /^hex(3|6)?/ =~ format
73
+
74
+ return to_rgb_s if use_alpha
75
+
76
+ case format.to_s
77
+ when 'rgb' then to_rgb_s
78
+ when 'hex', 'hex6' then to_hex_s
79
+ when 'hex3' then to_hex_s(true)
80
+ when 'hex8' then to_hex8_s
81
+ when 'hsl' then to_hsl_s
82
+ when 'hsv' then to_hsv_s
83
+ when 'name' then to_name
84
+ else to_hex_s
85
+ end
86
+ end
87
+
88
+ alias_method :inspect, :to_s
89
+
90
+ private
91
+
92
+ def to_hs_s(third)
93
+ color = send("to_hs#{third}")
94
+
95
+ h = color.h.round
96
+ s = (color.s * 100).round
97
+ lv = (color.send(third) * 100).round
98
+
99
+ middle = "#{h}, #{s}%, #{lv}%"
100
+
101
+ to_alpha_s("hs#{third}", middle)
102
+ end
103
+
104
+ def to_alpha_s(mode, middle)
105
+ if alpha < 1
106
+ "#{mode}a(#{middle}, #{alpha})"
107
+ else
108
+ "#{mode}(#{middle})"
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,29 @@
1
+ module Chroma
2
+ module ColorModes
3
+ class << self
4
+ private
5
+
6
+ def build(*attrs)
7
+ Class.new do
8
+ attr_accessor *(attrs + [:a])
9
+
10
+ class_eval <<-EOS
11
+ def initialize(#{attrs * ', '}, a = 1)
12
+ #{attrs.map{|attr| "@#{attr}"} * ', '}, @a = #{attrs * ', '}, a
13
+ end
14
+
15
+ def to_a
16
+ [#{attrs.map{|attr| "@#{attr}"} * ', '}, @a]
17
+ end
18
+
19
+ alias_method :to_ary, :to_a
20
+ EOS
21
+ end
22
+ end
23
+ end
24
+
25
+ Rgb = build :r, :g, :b
26
+ Hsl = build :h, :s, :l
27
+ Hsv = build :h, :s, :v
28
+ end
29
+ end
@@ -0,0 +1,23 @@
1
+ module Chroma
2
+ module Converters
3
+ class Base
4
+ include Helpers::Bounders
5
+
6
+ def initialize(input)
7
+ @input = input
8
+ end
9
+
10
+ def self.convert_rgb(rgb)
11
+ new(rgb).convert_rgb
12
+ end
13
+
14
+ def self.convert_hsl(hsl)
15
+ new(hsl).convert_hsl
16
+ end
17
+
18
+ def self.convert_hsv(hsv)
19
+ new(hsv).convert_hsv
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,39 @@
1
+ module Chroma
2
+ module Converters
3
+ class HslConverter < Base
4
+ def convert_rgb
5
+ r = bound01(@input.r, 255)
6
+ g = bound01(@input.g, 255)
7
+ b = bound01(@input.b, 255)
8
+
9
+ rgb_array = [r, g, b]
10
+
11
+ max = rgb_array.max
12
+ min = rgb_array.min
13
+ l = (max + min) * 0.5
14
+
15
+ if max == min
16
+ h = s = 0
17
+ else
18
+ d = (max - min).to_f
19
+
20
+ s = if l > 0.5
21
+ d / (2 - max - min)
22
+ else
23
+ d / (max + min)
24
+ end
25
+
26
+ h = case max
27
+ when r then (g - b) / d + (g < b ? 6 : 0)
28
+ when g then (b - r) / d + 2
29
+ when b then (r - g) / d + 4
30
+ end
31
+
32
+ h /= 6.0
33
+ end
34
+
35
+ ColorModes::Hsl.new(h * 360, s, l, @input.a)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,33 @@
1
+ module Chroma
2
+ module Converters
3
+ class HsvConverter < Base
4
+ def convert_rgb
5
+ r = bound01(@input.r, 255)
6
+ g = bound01(@input.g, 255)
7
+ b = bound01(@input.b, 255)
8
+
9
+ rgb_array = [r, g, b]
10
+
11
+ max = rgb_array.max
12
+ min = rgb_array.min
13
+ v = max
14
+ d = (max - min).to_f
15
+ s = max.zero? ? 0 : d / max
16
+
17
+ if max == min
18
+ h = 0
19
+ else
20
+ h = case max
21
+ when r then (g - b) / d + (g < b ? 6 : 0)
22
+ when g then (b - r) / d + 2
23
+ when b then (r - g) / d + 4
24
+ end
25
+
26
+ h /= 6.0
27
+ end
28
+
29
+ ColorModes::Hsv.new(h * 360, s, v, @input.a)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,60 @@
1
+ module Chroma
2
+ module Converters
3
+ class RgbConverter < Base
4
+ def convert_hsl
5
+ h, s, l = @input
6
+
7
+ h = bound01(h, 360)
8
+ s = bound01(s, 100)
9
+ l = bound01(l, 100)
10
+
11
+ if s.zero?
12
+ r = g = b = l * 255
13
+ else
14
+ q = l < 0.5 ? l * (1 + s) : l + s - l * s
15
+ p = 2 * l - q
16
+ r = hue_to_rgb(p, q, h + 1/3.0) * 255
17
+ g = hue_to_rgb(p, q, h) * 255
18
+ b = hue_to_rgb(p, q, h - 1/3.0) * 255
19
+ end
20
+
21
+ ColorModes::Rgb.new(r, g, b)
22
+ end
23
+
24
+ def convert_hsv
25
+ h, s, v = @input
26
+
27
+ h = bound01(h, 360) * 6
28
+ s = bound01(s, 100)
29
+ v = bound01(v, 100)
30
+
31
+ i = h.floor
32
+ f = h - i
33
+ p = v * (1 - s)
34
+ q = v * (1 - f * s)
35
+ t = v * (1 - (1 - f) * s)
36
+ mod = i % 6
37
+
38
+ r = [v, q, p, p, t, v][mod] * 255
39
+ g = [t, v, v, q, p, p][mod] * 255
40
+ b = [p, p, t, v, v, q][mod] * 255
41
+
42
+ ColorModes::Rgb.new(r, g, b)
43
+ end
44
+
45
+ private
46
+
47
+ def hue_to_rgb(p, q, t)
48
+ if t < 0 then t += 1
49
+ elsif t > 1 then t -= 1
50
+ end
51
+
52
+ if t < 1/6.0 then p + (q - p) * 6 * t
53
+ elsif t < 0.5 then q
54
+ elsif t < 2/3.0 then p + (q - p) * (2/3.0 - t) * 6
55
+ else p
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,5 @@
1
+ class String
2
+ def paint
3
+ Chroma.paint(self)
4
+ end
5
+ end
@@ -0,0 +1,55 @@
1
+ module Chroma
2
+ class Harmonies
3
+ def initialize(color)
4
+ @color = color
5
+ end
6
+
7
+ def complement
8
+ [@color, @color.complement]
9
+ end
10
+
11
+ def triad
12
+ hsl_map([0, 120, 240])
13
+ end
14
+
15
+ def tetrad
16
+ hsl_map([0, 90, 180, 270])
17
+ end
18
+
19
+ def split_complement
20
+ hsl_map([0, 72, 216])
21
+ end
22
+
23
+ def analogous(results = 6, slices = 30)
24
+ hsl = @color.to_hsl
25
+ part = 360 / slices
26
+ hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360
27
+
28
+ (results - 1).times.reduce([@color]) do |arr, n|
29
+ hsl.h = (hsl.h + part) % 360
30
+ arr << Color.new(hsl)
31
+ end
32
+ end
33
+
34
+ def monochromatic(results = 6)
35
+ h, s, v = @color.to_hsv
36
+ modification = 1.0 / results
37
+
38
+ results.times.map do
39
+ Color.new(ColorModes::Hsv.new(h, s, v)).tap do
40
+ v = (v + modification) % 1
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def hsl_map(degrees)
48
+ h, s, l = @color.to_hsl
49
+
50
+ degrees.map do |deg|
51
+ Color.new(ColorModes::Hsl.new((h + deg) % 360, s, l))
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,31 @@
1
+ module Chroma
2
+ module Helpers
3
+ module Bounders
4
+ def bound01(n, max)
5
+ is_percent = n.to_s.include? '%'
6
+ n = [max, [0, n.to_f].max].min
7
+ n = (n * max).to_i / 100 if is_percent
8
+
9
+ return 1 if (n - max).abs < 0.000001
10
+
11
+ (n % max) / max.to_f
12
+ end
13
+
14
+ def bound_alpha(a)
15
+ a = a.to_f
16
+ a = 1 if a < 0 || a > 1
17
+ a
18
+ end
19
+
20
+ def clamp01(n)
21
+ [1, [0, n].max].min
22
+ end
23
+
24
+ def to_percentage(n)
25
+ n = n.to_f
26
+ n = "#{n * 100}%" if n <= 1
27
+ n
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,35 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class << self
4
+ def generate_rgb_and_format(input)
5
+ get_generator(input).generate.tap do |(rgb)|
6
+ rgb.r = round(rgb.r)
7
+ rgb.g = round(rgb.g)
8
+ rgb.b = round(rgb.b)
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def get_generator(input)
15
+ klass = case input
16
+ when String then FromString
17
+ when ColorModes::Hsl then FromHsl
18
+ when ColorModes::Hsv then FromHsv
19
+ when ColorModes::Rgb then FromRgb
20
+ end
21
+
22
+ klass.new(input)
23
+ end
24
+
25
+ def round(n)
26
+ if n < 1
27
+ n.round
28
+ else
29
+ #(n * 100).round / 100
30
+ n
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,7 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class Base
4
+ include Helpers::Bounders
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,30 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromHexStringValues < Base
4
+ def initialize(format, r, g, b, a = 'ff')
5
+ @format = format || :hex
6
+ @r, @g, @b, @a = r, g, b, a
7
+ end
8
+
9
+ def generate
10
+ r, g, b = [@r, @g, @b].map { |n| n.to_i(16) }
11
+ a = @a.to_i(16) / 255.0
12
+ [ColorModes::Rgb.new(r, g, b, a), @format]
13
+ end
14
+
15
+ class << self
16
+ def from_hex3(format, r, g, b)
17
+ new(format || :hex3, r * 2, g * 2, b * 2)
18
+ end
19
+
20
+ def from_hex6(format, r, g, b)
21
+ new(format, r, g, b)
22
+ end
23
+
24
+ def from_hex8(format, r, g, b, a)
25
+ new(format || :hex8, r, g, b, a)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,14 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromHsl < Base
4
+ def initialize(format, hsl)
5
+ @format = format || :hsl
6
+ @hsl = hsl
7
+ end
8
+
9
+ def generate
10
+ [Converters::RgbConverter.convert_hsl(@hsl), @format]
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromHslValues < Base
4
+ def initialize(format, h, s, l, a = 1)
5
+ s = to_percentage(s)
6
+ l = to_percentage(l)
7
+
8
+ @format = format
9
+ @hsl = ColorModes::Hsl.new(h, s, l, a)
10
+ end
11
+
12
+ def generate
13
+ FromHsl.new(@format, @hsl).generate
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromHsv < Base
4
+ def initialize(format, hsv)
5
+ @format = format || :hsv
6
+ @hsv = hsv
7
+ end
8
+
9
+ def generate
10
+ [Converters::RgbConverter.convert_hsv(@hsv), @format]
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromHsvValues < Base
4
+ def initialize(format, h, s, v, a = 1)
5
+ s = to_percentage(s)
6
+ v = to_percentage(v)
7
+
8
+ @format = format
9
+ @hsv = ColorModes::Hsv.new(h, s, v, a)
10
+ end
11
+
12
+ def generate
13
+ FromHsv.new(@format, @hsv).generate
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromRgb < Base
4
+ def initialize(format, rgb)
5
+ @format = format || :rgb
6
+ @rgb = rgb
7
+ end
8
+
9
+ def generate
10
+ FromRgbValues.new(@format, @rgb.r, @rgb.g, @rgb.b, @rgb.a).generate
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromRgbValues < Base
4
+ def initialize(format, r, g, b, a = 1)
5
+ @format = format
6
+ @r, @g, @b, @a = r, g, b, a
7
+ end
8
+
9
+ def generate
10
+ r, g, b = [@r, @g, @b].map { |n| bound01(n, 255) * 255 }
11
+ a = bound_alpha(@a)
12
+ [ColorModes::Rgb.new(r, g, b, a), @format]
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,78 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromString < Base
4
+ def self.matchers
5
+ @matchers ||= begin
6
+ # TinyColor.js matchers
7
+ css_int = '[-\\+]?\\d+%?'
8
+ css_num = '[-\\+]?\\d*\\.\\d+%?'
9
+ css_unit = "(?:#{css_num})|(?:#{css_int})"
10
+ permissive_prefix = '[\\s|\\(]+('
11
+ permissive_delim = ')[,|\\s]+('
12
+ permissive_suffix = ')\\s*\\)?'
13
+ permissive_match3 = "#{permissive_prefix}#{[css_unit] * 3 * permissive_delim}#{permissive_suffix}"
14
+ permissive_match4 = "#{permissive_prefix}#{[css_unit] * 4 * permissive_delim}#{permissive_suffix}"
15
+ hex_match = '[0-9a-fA-F]'
16
+
17
+ {
18
+ rgb: { regex: /rgb#{permissive_match3}/, class_name: :FromRgbValues },
19
+ rgba: { regex: /rgba#{permissive_match4}/, class_name: :FromRgbValues },
20
+ hsl: { regex: /hsl#{permissive_match3}/, class_name: :FromHslValues },
21
+ hsla: { regex: /hsla#{permissive_match4}/, class_name: :FromHslValues },
22
+ hsv: { regex: /hsv#{permissive_match3}/, class_name: :FromHsvValues },
23
+ hsva: { regex: /hsva#{permissive_match4}/, class_name: :FromHsvValues },
24
+ hex3: { regex: /^#?#{"(#{hex_match}{1})" * 3}$/, class_name: :FromHexStringValues, builder: :from_hex3 },
25
+ hex6: { regex: /^#?#{"(#{hex_match}{2})" * 3}$/, class_name: :FromHexStringValues, builder: :from_hex6 },
26
+ hex8: { regex: /^#?#{"(#{hex_match}{2})" * 4}$/, class_name: :FromHexStringValues, builder: :from_hex8 }
27
+ }.freeze
28
+ end
29
+ end
30
+
31
+ def initialize(input)
32
+ @input = normalize_input(input)
33
+ end
34
+
35
+ def generate
36
+ get_generator.generate
37
+ end
38
+
39
+ private
40
+
41
+ def get_generator
42
+ if color = Chroma.hex_from_name(@input)
43
+ format = :name
44
+ else
45
+ format = nil
46
+ color = @input
47
+ end
48
+
49
+ match = nil
50
+
51
+ _, hash = matchers.find do |_, h|
52
+ !(match = h[:regex].match(color)).nil?
53
+ end
54
+
55
+ raise 'Unrecognized color' if match.nil?
56
+
57
+ build_generator(match[1..-1], hash[:class_name], hash[:builder], format)
58
+ end
59
+
60
+ def build_generator(args, class_name, builder, format)
61
+ builder ||= :new
62
+ klass = RgbGenerator.const_get(class_name)
63
+ klass.__send__(builder, *([format] + args))
64
+ end
65
+
66
+ def normalize_input(input)
67
+ input.clone.tap do |str|
68
+ str.strip!
69
+ str.downcase!
70
+ end
71
+ end
72
+
73
+ def matchers
74
+ self.class.matchers
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,3 @@
1
+ module Chroma
2
+ VERSION = '0.0.1.alpha.1'
3
+ end
@@ -0,0 +1,149 @@
1
+ aliceblue: 'f0f8ff'
2
+ antiquewhite: 'faebd7'
3
+ aqua: '0ff'
4
+ aquamarine: '7fffd4'
5
+ azure: 'f0ffff'
6
+ beige: 'f5f5dc'
7
+ bisque: 'ffe4c4'
8
+ black: '000'
9
+ blanchedalmond: 'ffebcd'
10
+ blue: '00f'
11
+ blueviolet: '8a2be2'
12
+ brown: 'a52a2a'
13
+ burlywood: 'deb887'
14
+ burntsienna: 'ea7e5d'
15
+ cadetblue: '5f9ea0'
16
+ chartreuse: '7fff00'
17
+ chocolate: 'd2691e'
18
+ coral: 'ff7f50'
19
+ cornflowerblue: '6495ed'
20
+ cornsilk: 'fff8dc'
21
+ crimson: 'dc143c'
22
+ cyan: '0ff'
23
+ darkblue: '00008b'
24
+ darkcyan: '008b8b'
25
+ darkgoldenrod: 'b8860b'
26
+ darkgray: 'a9a9a9'
27
+ darkgreen: '006400'
28
+ darkgrey: 'a9a9a9'
29
+ darkkhaki: 'bdb76b'
30
+ darkmagenta: '8b008b'
31
+ darkolivegreen: '556b2f'
32
+ darkorange: 'ff8c00'
33
+ darkorchid: '9932cc'
34
+ darkred: '8b0000'
35
+ darksalmon: 'e9967a'
36
+ darkseagreen: '8fbc8f'
37
+ darkslateblue: '483d8b'
38
+ darkslategray: '2f4f4f'
39
+ darkslategrey: '2f4f4f'
40
+ darkturquoise: '00ced1'
41
+ darkviolet: '9400d3'
42
+ deeppink: 'ff1493'
43
+ deepskyblue: '00bfff'
44
+ dimgray: '696969'
45
+ dimgrey: '696969'
46
+ dodgerblue: '1e90ff'
47
+ firebrick: 'b22222'
48
+ floralwhite: 'fffaf0'
49
+ forestgreen: '228b22'
50
+ fuchsia: 'f0f'
51
+ gainsboro: 'dcdcdc'
52
+ ghostwhite: 'f8f8ff'
53
+ gold: 'ffd700'
54
+ goldenrod: 'daa520'
55
+ gray: '808080'
56
+ green: '008000'
57
+ greenyellow: 'adff2f'
58
+ grey: '808080'
59
+ honeydew: 'f0fff0'
60
+ hotpink: 'ff69b4'
61
+ indianred: 'cd5c5c'
62
+ indigo: '4b0082'
63
+ ivory: 'fffff0'
64
+ khaki: 'f0e68c'
65
+ lavender: 'e6e6fa'
66
+ lavenderblush: 'fff0f5'
67
+ lawngreen: '7cfc00'
68
+ lemonchiffon: 'fffacd'
69
+ lightblue: 'add8e6'
70
+ lightcoral: 'f08080'
71
+ lightcyan: 'e0ffff'
72
+ lightgoldenrodyellow: 'fafad2'
73
+ lightgray: 'd3d3d3'
74
+ lightgreen: '90ee90'
75
+ lightgrey: 'd3d3d3'
76
+ lightpink: 'ffb6c1'
77
+ lightsalmon: 'ffa07a'
78
+ lightseagreen: '20b2aa'
79
+ lightskyblue: '87cefa'
80
+ lightslategray: '789'
81
+ lightslategrey: '789'
82
+ lightsteelblue: 'b0c4de'
83
+ lightyellow: 'ffffe0'
84
+ lime: '0f0'
85
+ limegreen: '32cd32'
86
+ linen: 'faf0e6'
87
+ magenta: 'f0f'
88
+ maroon: '800000'
89
+ mediumaquamarine: '66cdaa'
90
+ mediumblue: '0000cd'
91
+ mediumorchid: 'ba55d3'
92
+ mediumpurple: '9370db'
93
+ mediumseagreen: '3cb371'
94
+ mediumslateblue: '7b68ee'
95
+ mediumspringgreen: '00fa9a'
96
+ mediumturquoise: '48d1cc'
97
+ mediumvioletred: 'c71585'
98
+ midnightblue: '191970'
99
+ mintcream: 'f5fffa'
100
+ mistyrose: 'ffe4e1'
101
+ moccasin: 'ffe4b5'
102
+ navajowhite: 'ffdead'
103
+ navy: '000080'
104
+ oldlace: 'fdf5e6'
105
+ olive: '808000'
106
+ olivedrab: '6b8e23'
107
+ orange: 'ffa500'
108
+ orangered: 'ff4500'
109
+ orchid: 'da70d6'
110
+ palegoldenrod: 'eee8aa'
111
+ palegreen: '98fb98'
112
+ paleturquoise: 'afeeee'
113
+ palevioletred: 'db7093'
114
+ papayawhip: 'ffefd5'
115
+ peachpuff: 'ffdab9'
116
+ peru: 'cd853f'
117
+ pink: 'ffc0cb'
118
+ plum: 'dda0dd'
119
+ powderblue: 'b0e0e6'
120
+ purple: '800080'
121
+ rebeccapurple: '663399'
122
+ red: 'f00'
123
+ rosybrown: 'bc8f8f'
124
+ royalblue: '4169e1'
125
+ saddlebrown: '8b4513'
126
+ salmon: 'fa8072'
127
+ sandybrown: 'f4a460'
128
+ seagreen: '2e8b57'
129
+ seashell: 'fff5ee'
130
+ sienna: 'a0522d'
131
+ silver: 'c0c0c0'
132
+ skyblue: '87ceeb'
133
+ slateblue: '6a5acd'
134
+ slategray: '708090'
135
+ slategrey: '708090'
136
+ snow: 'fffafa'
137
+ springgreen: '00ff7f'
138
+ steelblue: '4682b4'
139
+ tan: 'd2b48c'
140
+ teal: '008080'
141
+ thistle: 'd8bfd8'
142
+ tomato: 'ff6347'
143
+ turquoise: '40e0d0'
144
+ violet: 'ee82ee'
145
+ wheat: 'f5deb3'
146
+ white: 'fff'
147
+ whitesmoke: 'f5f5f5'
148
+ yellow: 'ff0'
149
+ yellowgreen: '9acd32'
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chroma
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.alpha.1
5
+ platform: ruby
6
+ authors:
7
+ - Jeremy Fairbank
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Chroma is a color manipulation and palette generation gem.
42
+ email:
43
+ - elpapapollo@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - LICENSE
51
+ - README.md
52
+ - Rakefile
53
+ - chroma.gemspec
54
+ - lib/chroma.rb
55
+ - lib/chroma/color.rb
56
+ - lib/chroma/color/attributes.rb
57
+ - lib/chroma/color/modifiers.rb
58
+ - lib/chroma/color/serializers.rb
59
+ - lib/chroma/color_modes.rb
60
+ - lib/chroma/converters/base.rb
61
+ - lib/chroma/converters/hsl_converter.rb
62
+ - lib/chroma/converters/hsv_converter.rb
63
+ - lib/chroma/converters/rgb_converter.rb
64
+ - lib/chroma/extensions/string.rb
65
+ - lib/chroma/harmonies.rb
66
+ - lib/chroma/helpers/bounders.rb
67
+ - lib/chroma/rgb_generator.rb
68
+ - lib/chroma/rgb_generator/base.rb
69
+ - lib/chroma/rgb_generator/from_hex_string_values.rb
70
+ - lib/chroma/rgb_generator/from_hsl.rb
71
+ - lib/chroma/rgb_generator/from_hsl_values.rb
72
+ - lib/chroma/rgb_generator/from_hsv.rb
73
+ - lib/chroma/rgb_generator/from_hsv_values.rb
74
+ - lib/chroma/rgb_generator/from_rgb.rb
75
+ - lib/chroma/rgb_generator/from_rgb_values.rb
76
+ - lib/chroma/rgb_generator/from_string.rb
77
+ - lib/chroma/version.rb
78
+ - lib/support/named_colors.yml
79
+ homepage: https://github.com/jfairbank/chroma
80
+ licenses:
81
+ - MIT
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">"
95
+ - !ruby/object:Gem::Version
96
+ version: 1.3.1
97
+ requirements: []
98
+ rubyforge_project:
99
+ rubygems_version: 2.4.5
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: Color manipulation and palette generation.
103
+ test_files: []