paleta 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/paleta/color.rb +90 -48
- data/lib/paleta/palette.rb +99 -2
- data/lib/paleta/version.rb +1 -1
- data/readme.markdown +41 -15
- data/spec/models/color_spec.rb +102 -18
- data/spec/models/palette_spec.rb +53 -2
- metadata +2 -2
data/lib/paleta/color.rb
CHANGED
@@ -8,11 +8,21 @@ module Paleta
|
|
8
8
|
|
9
9
|
def initialize(*args)
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
if args.length == 1 && args[0].is_a?(Color)
|
12
|
+
# TODO: refactor this, find out how to call a method name by the value of a variable
|
13
|
+
# something like args[0].instance_variables.each { |k, v| self.(k) = v }
|
14
|
+
@red = args[0].red
|
15
|
+
@green = args[0].green
|
16
|
+
@blue = args[0].blue
|
17
|
+
@hue = args[0].hue
|
18
|
+
@saturation = args[0].saturation
|
19
|
+
@lightness = args[0].lightness
|
20
|
+
@hex = args[0].hex
|
21
|
+
elsif args.length == 2 && args[0] == :hex && args[1].is_a?(String)
|
22
|
+
# example: new(:hex, "336699")
|
13
23
|
hex_init(args[1])
|
14
|
-
# example: new(235, 129, 74)
|
15
24
|
elsif args.length == 3 && args[0].is_a?(Numeric) && args[1].is_a?(Numeric) && args[2].is_a?(Numeric)
|
25
|
+
# example: new(235, 129, 74)
|
16
26
|
rgb_init(args[0], args[1], args[2])
|
17
27
|
elsif args.length == 4 && [:rgb, :hsl].include?(args[0]) && args[1].is_a?(Numeric) && args[2].is_a?(Numeric) && args[3].is_a?(Numeric)
|
18
28
|
# example: new(:hsl, 320, 96, 74)
|
@@ -80,9 +90,7 @@ module Paleta
|
|
80
90
|
end
|
81
91
|
|
82
92
|
def hex=(val)
|
83
|
-
unless val.length == 6 && /^[[:xdigit:]]+$/ === val
|
84
|
-
raise(ArgumentError, "Invalid Hex String")
|
85
|
-
end
|
93
|
+
raise(ArgumentError, "Invalid Hex String") unless val.length == 6 && /^[[:xdigit:]]+$/ === val
|
86
94
|
@hex = val.upcase
|
87
95
|
@red = val[0..1].hex
|
88
96
|
@green = val[2..3].hex
|
@@ -90,6 +98,12 @@ module Paleta
|
|
90
98
|
update_hsl
|
91
99
|
end
|
92
100
|
|
101
|
+
def lighten(percent = 5)
|
102
|
+
copy = self.class.new(self)
|
103
|
+
copy.lighten!(percent)
|
104
|
+
return copy
|
105
|
+
end
|
106
|
+
|
93
107
|
def lighten!(percent = 5)
|
94
108
|
@lightness += percent
|
95
109
|
@lightness = 100 if @lightness > 100
|
@@ -97,6 +111,12 @@ module Paleta
|
|
97
111
|
update_hex
|
98
112
|
end
|
99
113
|
|
114
|
+
def darken(percent = 5)
|
115
|
+
copy = self.class.new(self)
|
116
|
+
copy.darken!(percent)
|
117
|
+
return copy
|
118
|
+
end
|
119
|
+
|
100
120
|
def darken!(percent = 5)
|
101
121
|
@lightness -= percent
|
102
122
|
@lightness = 0 if @lightness < 0
|
@@ -104,6 +124,12 @@ module Paleta
|
|
104
124
|
update_hex
|
105
125
|
end
|
106
126
|
|
127
|
+
def invert
|
128
|
+
copy = self.class.new(self)
|
129
|
+
copy.invert!
|
130
|
+
return copy
|
131
|
+
end
|
132
|
+
|
107
133
|
def invert!
|
108
134
|
@red = 255 - @red
|
109
135
|
@green = 255 - @green
|
@@ -112,6 +138,30 @@ module Paleta
|
|
112
138
|
update_hex
|
113
139
|
end
|
114
140
|
|
141
|
+
def desaturate
|
142
|
+
copy = self.class.new(self)
|
143
|
+
copy.desaturate!
|
144
|
+
return copy
|
145
|
+
end
|
146
|
+
|
147
|
+
def desaturate!
|
148
|
+
@saturation = 0
|
149
|
+
update_rgb
|
150
|
+
update_hex
|
151
|
+
end
|
152
|
+
|
153
|
+
def complement
|
154
|
+
copy = self.class.new(self)
|
155
|
+
copy.complement!
|
156
|
+
return copy
|
157
|
+
end
|
158
|
+
|
159
|
+
def complement!
|
160
|
+
@hue = (@hue + 180) % 360
|
161
|
+
update_rgb
|
162
|
+
update_hex
|
163
|
+
end
|
164
|
+
|
115
165
|
def similarity(color)
|
116
166
|
distance({ :r => @red, :g => @green, :b => @blue}, { :r => color.red, :g => color.green, :b => color.blue}) / sqrt(3 * (255 ** 2))
|
117
167
|
end
|
@@ -122,22 +172,23 @@ module Paleta
|
|
122
172
|
r = @red / 255.0 rescue 0.0
|
123
173
|
g = @green / 255.0 rescue 0.0
|
124
174
|
b = @blue / 255.0 rescue 0.0
|
125
|
-
|
175
|
+
|
126
176
|
min = [r, g, b].min
|
127
177
|
max = [r, g, b].max
|
128
178
|
delta = max - min
|
129
179
|
|
130
|
-
h =
|
180
|
+
h = 0
|
131
181
|
l = (max + min) / 2.0
|
132
|
-
|
182
|
+
s = ((l == 0 || l == 1) ? 0 : (delta / (1 - (2 * l - 1).abs)))
|
183
|
+
|
133
184
|
if delta != 0
|
134
|
-
s = (l < 0.5) ? delta / (max + min) : delta / (2.0 - max - min)
|
135
185
|
case max
|
136
|
-
when r; h = (g - b) / delta
|
137
|
-
when g; h =
|
138
|
-
when b; h =
|
186
|
+
when r; h = ((g - b) / delta) % 6
|
187
|
+
when g; h = ((b - r) / delta) + 2
|
188
|
+
when b; h = ((r - g) / delta) + 4
|
139
189
|
end
|
140
190
|
end
|
191
|
+
|
141
192
|
@hue = h * 60
|
142
193
|
@hue += 360 if @hue < 0
|
143
194
|
@saturation = s * 100
|
@@ -145,49 +196,40 @@ module Paleta
|
|
145
196
|
end
|
146
197
|
|
147
198
|
def update_rgb
|
199
|
+
|
200
|
+
h = @hue / 60.0 rescue 0.0
|
201
|
+
s = @saturation / 100.0 rescue 0.0
|
202
|
+
l = @lightness / 100.0 rescue 0.0
|
203
|
+
|
204
|
+
d1 = (1 - (2 * l - 1).abs) * s
|
205
|
+
d2 = d1 * (1 - (h % 2 - 1).abs)
|
206
|
+
d3 = l - (d1 / 2.0)
|
148
207
|
|
149
|
-
h
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
t2 = l < 0.5 ? l * (s + 1) : (l + s) - (l * s)
|
158
|
-
t1 = 2 * l - t2
|
159
|
-
|
160
|
-
r = h + (1.0 / 3.0)
|
161
|
-
g = h
|
162
|
-
b = h - (1.0 / 3.0)
|
163
|
-
|
164
|
-
r = hue_calc(r, t1, t2)
|
165
|
-
g = hue_calc(g, t1, t2)
|
166
|
-
b = hue_calc(b, t1, t2)
|
167
|
-
|
168
|
-
@red = r * 255.0
|
169
|
-
@green = g * 255.0
|
170
|
-
@blue = b * 255.0
|
208
|
+
case h.to_i
|
209
|
+
when 0; @red, @green, @blue = d1, d2, 0
|
210
|
+
when 1; @red, @green, @blue = d2, d1, 0
|
211
|
+
when 2; @red, @green, @blue = 0, d1, d2
|
212
|
+
when 3; @red, @green, @blue = 0, d2, d1
|
213
|
+
when 4; @red, @green, @blue = d2, 0, d1
|
214
|
+
when 5; @red, @green, @blue = d1, 0, d2
|
215
|
+
else; @red, @green, @blue = 0, 0, 0
|
171
216
|
end
|
217
|
+
|
218
|
+
@red = 255 * (@red + d3)
|
219
|
+
@green = 255 * (@green + d3)
|
220
|
+
@blue = 255 * (@blue + d3)
|
172
221
|
end
|
173
222
|
|
174
223
|
def update_hex
|
175
|
-
r = @red.to_s(16) rescue "00"
|
176
|
-
g = @green.to_s(16) rescue "00"
|
177
|
-
b = @blue.to_s(16) rescue "00"
|
178
|
-
|
224
|
+
r = @red.to_i.to_s(16) rescue "00"
|
225
|
+
g = @green.to_i.to_s(16) rescue "00"
|
226
|
+
b = @blue.to_i.to_s(16) rescue "00"
|
227
|
+
r = "0#{r}" if r.length < 2
|
228
|
+
g = "0#{g}" if g.length < 2
|
229
|
+
b = "0#{b}" if b.length < 2
|
179
230
|
@hex = "#{r}#{g}#{b}".upcase
|
180
231
|
end
|
181
232
|
|
182
|
-
def hue_calc(value, t1, t2)
|
183
|
-
value += 1 if value < 0
|
184
|
-
value -= 1 if value > 1
|
185
|
-
return (t1 + (t2 - t1) * 6 * value) if 6 * value < 1
|
186
|
-
return t2 if 2 * value < 1
|
187
|
-
return (t1 + (t2 - t1) * (2.0 / 3.0 - value) * 6) if 3 * value < 2
|
188
|
-
return t1;
|
189
|
-
end
|
190
|
-
|
191
233
|
def range_validator(val, range)
|
192
234
|
range.include?(val) ? val : raise(ArgumentError, "Component range exceeded")
|
193
235
|
end
|
data/lib/paleta/palette.rb
CHANGED
@@ -3,11 +3,13 @@ require 'paleta/core_ext/math'
|
|
3
3
|
module Paleta
|
4
4
|
class Palette
|
5
5
|
include Math
|
6
|
+
include Enumerable
|
6
7
|
|
7
8
|
attr_accessor :colors
|
8
9
|
|
9
|
-
def initialize(*
|
10
|
+
def initialize(*args)
|
10
11
|
@colors = []
|
12
|
+
colors = (args.length == 1 && args[0].is_a?(Array)) ? args[0] : args
|
11
13
|
colors.each do |color|
|
12
14
|
self << color
|
13
15
|
end
|
@@ -15,6 +17,7 @@ module Paleta
|
|
15
17
|
|
16
18
|
def <<(color)
|
17
19
|
color.is_a?(Color) ? @colors << color : raise(ArgumentError, "Passed argument is not a Color")
|
20
|
+
self
|
18
21
|
end
|
19
22
|
|
20
23
|
def push(color)
|
@@ -37,6 +40,20 @@ module Paleta
|
|
37
40
|
@colors.size
|
38
41
|
end
|
39
42
|
|
43
|
+
def each
|
44
|
+
@colors.each { |c| yield c }
|
45
|
+
end
|
46
|
+
|
47
|
+
def sort &blk
|
48
|
+
@colors.sort &blk
|
49
|
+
Paleta::Palette.new(@colors)
|
50
|
+
end
|
51
|
+
|
52
|
+
def sort! &blk
|
53
|
+
@colors.sort! &blk
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
40
57
|
def include?(color)
|
41
58
|
@colors.include?(color)
|
42
59
|
end
|
@@ -81,7 +98,87 @@ module Paleta
|
|
81
98
|
|
82
99
|
d1 + d2
|
83
100
|
end
|
84
|
-
|
101
|
+
|
102
|
+
def self.generate(opts = {})
|
103
|
+
raise(ArgumentError, "Pass a Color using :from, generate( :from => Color )") if opts.empty?
|
104
|
+
color = opts[:from]
|
105
|
+
type = opts[:type] || :shades
|
106
|
+
size = opts[:size] || 5
|
107
|
+
case type
|
108
|
+
when :analogous; self.generate_analogous_palette_from_color(color, size)
|
109
|
+
when :monochromatic; self.generate_monochromatic_palette_from_color(color, size)
|
110
|
+
when :shades; self.generate_shades_palette_from_color(color, size)
|
111
|
+
when :random; self.generate_random_palette_from_color(color, size)
|
112
|
+
else raise(ArgumentError, "Palette type is not defined. Try :analogous, :monochromatic, :shades, or :random")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def self.generate_analogous_palette_from_color(color, n)
|
119
|
+
raise(ArgumentError, "Passed argument is not a Color") unless color.is_a?(Color)
|
120
|
+
palette = self.new(color)
|
121
|
+
step = 20
|
122
|
+
below = (n / 2)
|
123
|
+
above = (n % 2 == 0) ? (n / 2) - 1: (n / 2)
|
124
|
+
below.times do |i|
|
125
|
+
hue = color.hue - ((i + 1) * step)
|
126
|
+
hue += 360 if hue < 0
|
127
|
+
palette << Paleta::Color.new(:hsl, hue, color.saturation, color.lightness)
|
128
|
+
end
|
129
|
+
above.times do |i|
|
130
|
+
hue = color.hue + ((i + 1) * step)
|
131
|
+
hue -= 360 if hue > 360
|
132
|
+
palette << Paleta::Color.new(:hsl, hue, color.saturation, color.lightness)
|
133
|
+
end
|
134
|
+
palette.sort! { |a, b| a.hue <=> b.hue }
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.generate_monochromatic_palette_from_color(color, n)
|
138
|
+
raise(ArgumentError, "Passed argument is not a Color") unless color.is_a?(Color)
|
139
|
+
palette = self.new(color)
|
140
|
+
step = (100 / n)
|
141
|
+
saturation = color.saturation
|
142
|
+
d = :down
|
143
|
+
until palette.size == n
|
144
|
+
saturation -= step if d == :down
|
145
|
+
saturation += step if d == :up
|
146
|
+
palette << Paleta::Color.new(:hsl, color.hue, saturation, color.lightness)
|
147
|
+
if saturation - step < 0
|
148
|
+
d = :up
|
149
|
+
saturation = color.saturation
|
150
|
+
end
|
151
|
+
end
|
152
|
+
palette.sort! { |a, b| a.saturation <=> b.saturation }
|
153
|
+
end
|
154
|
+
|
155
|
+
def self.generate_shades_palette_from_color(color, n)
|
156
|
+
raise(ArgumentError, "Passed argument is not a Color") unless color.is_a?(Color)
|
157
|
+
palette = self.new(color)
|
158
|
+
step = (100 / n)
|
159
|
+
lightness = color.lightness
|
160
|
+
d = :down
|
161
|
+
until palette.size == n
|
162
|
+
lightness -= step if d == :down
|
163
|
+
lightness += step if d == :up
|
164
|
+
palette << Paleta::Color.new(:hsl, color.hue, color.saturation, lightness)
|
165
|
+
if lightness - step < 0
|
166
|
+
d = :up
|
167
|
+
lightness = color.lightness
|
168
|
+
end
|
169
|
+
end
|
170
|
+
palette.sort! { |a, b| a.lightness <=> b.lightness }
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.generate_random_palette_from_color(color = nil, n)
|
174
|
+
palette = color.is_a?(Color) ? self.new(color) : self.new
|
175
|
+
r = Random.new(Time.now.sec)
|
176
|
+
until palette.size == n
|
177
|
+
palette << Paleta::Color.new(r.rand(0..255), r.rand(0..255), r.rand(0..255))
|
178
|
+
end
|
179
|
+
palette
|
180
|
+
end
|
181
|
+
|
85
182
|
def fit
|
86
183
|
# create a 3xn matrix where n = @colors.size to represent the set of colors
|
87
184
|
reds = @colors.map { |c| c.red }
|
data/lib/paleta/version.rb
CHANGED
data/readme.markdown
CHANGED
@@ -22,16 +22,16 @@ and run
|
|
22
22
|
|
23
23
|
### Color
|
24
24
|
|
25
|
-
# create a
|
25
|
+
# create a Color with HSL components
|
26
26
|
color = Paleta::Color.new(:hsl, 280, 37, 68)
|
27
27
|
|
28
|
-
# create a
|
28
|
+
# create a Color with RGB components
|
29
29
|
color = Paleta::Color.new(:rgb, 94, 161, 235)
|
30
30
|
|
31
|
-
# create a
|
31
|
+
# create a Color with a HEX value
|
32
32
|
color = Paleta::Color.new(:hex, "5EA1EB")
|
33
33
|
|
34
|
-
# creating a
|
34
|
+
# creating a Color with no flag defaults to RGB components
|
35
35
|
color = Paleta::Color.new(94, 161, 235)
|
36
36
|
|
37
37
|
# access component values
|
@@ -53,11 +53,17 @@ and run
|
|
53
53
|
# darken by a percentage
|
54
54
|
color.darken!(10)
|
55
55
|
|
56
|
-
#
|
56
|
+
# desaturate a Color
|
57
|
+
color.desaturate!
|
58
|
+
|
59
|
+
# convert a Color into its complement
|
60
|
+
color.complement!
|
61
|
+
|
62
|
+
# invert a Color
|
57
63
|
color.invert!
|
58
64
|
|
59
65
|
# calculate similarity between Colors
|
60
|
-
# Color#similarity calculates the similarity between two
|
66
|
+
# Color#similarity calculates the similarity between two Colors and returns a
|
61
67
|
# value in 0..1, with 0 being identical and 1 being as dissimilar as possible
|
62
68
|
color2 = Paleta::Color.new(237, 172, 33)
|
63
69
|
color.similarity(color2) # => 0.5609077061558945
|
@@ -68,8 +74,11 @@ and run
|
|
68
74
|
color1 = Paleta::Color.new(13, 57, 182)
|
69
75
|
color2 = Paleta::Color.new(94, 161, 235)
|
70
76
|
color3 = Paleta::Color.new(237, 182, 17)
|
71
|
-
palette = Paleta::Palette.new(color1, color2
|
72
|
-
|
77
|
+
palette = Paleta::Palette.new(color1, color2)
|
78
|
+
|
79
|
+
# add Colors to a Palette
|
80
|
+
palette << color3
|
81
|
+
|
73
82
|
# retreive a Color from a Palette
|
74
83
|
palette[1] # => color2
|
75
84
|
|
@@ -84,16 +93,33 @@ and run
|
|
84
93
|
palette.invert!
|
85
94
|
|
86
95
|
# calculate similarity of two Palettes
|
87
|
-
|
88
|
-
|
89
|
-
palette1 = Paleta::Palette.new(
|
96
|
+
color1 = Paleta::Color.new(13, 57, 182)
|
97
|
+
color2 = Paleta::Color.new(237, 172, 33)
|
98
|
+
palette1 = Paleta::Palette.new(color1, color2)
|
90
99
|
|
91
|
-
|
92
|
-
|
93
|
-
palette2 = Paleta::Palette.new(
|
94
|
-
|
100
|
+
color3 = Paleta::Color.new(13, 57, 182)
|
101
|
+
color4 = Paleta::Color.new(94, 161, 235)
|
102
|
+
palette2 = Paleta::Palette.new(color3, color4)
|
103
|
+
|
104
|
+
# Palette#similarity calculates the similarity between two Palettes and returns a
|
105
|
+
# value in 0..1, with 0 being identical and 1 being as dissimilar as possible
|
95
106
|
palette1.similarity(palette2) # => 0.0046992695975874915
|
96
107
|
|
108
|
+
# generate random Palette
|
109
|
+
palette = Paleta::Palette.generate(:type => :random, :size = 5)
|
110
|
+
|
111
|
+
# generate a Palette of shades from a Color
|
112
|
+
color = Paleta::Color.new(:hex, "ff0000")
|
113
|
+
palette = Paleta::Palette.generate(:type => :shades, :from => color, :size => 5)
|
114
|
+
|
115
|
+
# generate a Palette of Colors analogous to the seed Color
|
116
|
+
color = Paleta::Color.new(:hex, "0066cc")
|
117
|
+
palette = Paleta::Palette.generate(:type => :analogous, :from => color, :size => 5)
|
118
|
+
|
119
|
+
# generate a Palette of Colors monochromatic to the seed Color
|
120
|
+
color = Paleta::Color.new(:hex, "336699")
|
121
|
+
palette = Paleta::Palette.generate(:type => :monochromatic, :from => color, :size => 5)
|
122
|
+
|
97
123
|
See the [documentation](http://rubydoc.info/gems/paleta/ "Documentation").
|
98
124
|
|
99
125
|
|
data/spec/models/color_spec.rb
CHANGED
@@ -16,10 +16,14 @@ describe Paleta::Color do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should initialize with the :hsl flag, hue in 0..360, and saturation and lightness in 0..100" do
|
19
|
-
color = Paleta::Color.new(:hsl,
|
20
|
-
color.hue.should ==
|
21
|
-
color.saturation.should ==
|
22
|
-
color.lightness.should ==
|
19
|
+
color = Paleta::Color.new(:hsl, 0, 0, 100)
|
20
|
+
color.hue.should == 0
|
21
|
+
color.saturation.should == 0
|
22
|
+
color.lightness.should == 100
|
23
|
+
color.red.should == 255
|
24
|
+
color.green.should == 255
|
25
|
+
color.blue.should == 255
|
26
|
+
color.hex.should == "FFFFFF"
|
23
27
|
end
|
24
28
|
|
25
29
|
it "should initialize with the :rgb flag with RGB components in 0..255" do
|
@@ -29,8 +33,28 @@ describe Paleta::Color do
|
|
29
33
|
color.blue.should == 235
|
30
34
|
end
|
31
35
|
|
32
|
-
it "should
|
33
|
-
expect{ Paleta::Color.new(
|
36
|
+
it "should raise an error on an invalid format flag" do
|
37
|
+
expect{ Paleta::Color.new(:something, 50, 50, 50) }.to raise_error(ArgumentError)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should raise an error on an invalid hex string" do
|
41
|
+
expect{ Paleta::Color.new(:hex, "xkfjs") }.to raise_error(ArgumentError)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should raise an error on RGB components not in 0..255" do
|
45
|
+
expect{ Paleta::Color.new(-74, 333, 4321) }.to raise_error(ArgumentError)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should raise an error on hue not in 0..360" do
|
49
|
+
expect{ Paleta::Color.new(:hsl, 400, 50, 50) }.to raise_error(ArgumentError)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should raise an error on saturation not in 0..100" do
|
53
|
+
expect{ Paleta::Color.new(:hsl, 200, 150, 50) }.to raise_error(ArgumentError)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should raise an error on lightness not in 0..100" do
|
57
|
+
expect{ Paleta::Color.new(:hsl, 200, 50, 150) }.to raise_error(ArgumentError)
|
34
58
|
end
|
35
59
|
|
36
60
|
it "should calculate its HSL value on itialization" do
|
@@ -50,9 +74,9 @@ describe Paleta::Color do
|
|
50
74
|
|
51
75
|
color.green = 123
|
52
76
|
color.hue.to_i.should == 136
|
53
|
-
color.saturation.to_i.should ==
|
77
|
+
color.saturation.to_i.should == 99
|
54
78
|
color.lightness.to_i.should == 24
|
55
|
-
|
79
|
+
|
56
80
|
color.blue = 241
|
57
81
|
color.hue.to_i.should == 209
|
58
82
|
color.saturation.to_i.should == 100
|
@@ -61,24 +85,23 @@ describe Paleta::Color do
|
|
61
85
|
|
62
86
|
it "should update its RGB value when its HSL value is updated" do
|
63
87
|
color = Paleta::Color.new(0, 0, 255)
|
64
|
-
|
65
88
|
color.hue = 120
|
66
|
-
color.red.to_i.should ==
|
67
|
-
color.green.to_i.should ==
|
89
|
+
color.red.to_i.should == 0
|
90
|
+
color.green.to_i.should == 255
|
68
91
|
color.blue.to_i.should == 0
|
69
92
|
|
70
93
|
color.saturation = 50
|
71
|
-
color.red.to_i.should ==
|
72
|
-
color.green.to_i.should ==
|
94
|
+
color.red.to_i.should == 63
|
95
|
+
color.green.to_i.should == 191
|
73
96
|
color.blue.to_i.should == 63
|
74
|
-
|
97
|
+
|
75
98
|
color.lightness = 80
|
76
|
-
color.red.to_i.should ==
|
77
|
-
color.green.to_i.should ==
|
99
|
+
color.red.to_i.should == 178
|
100
|
+
color.green.to_i.should == 229
|
78
101
|
color.blue.to_i.should == 178
|
79
102
|
end
|
80
103
|
|
81
|
-
it "should lighten by a percentage
|
104
|
+
it "should lighten itself by a percentage" do
|
82
105
|
color = Paleta::Color.new(94, 161, 235)
|
83
106
|
lightness = color.lightness
|
84
107
|
color.lighten!
|
@@ -88,6 +111,14 @@ describe Paleta::Color do
|
|
88
111
|
color.lightness.should == lightness + 20
|
89
112
|
end
|
90
113
|
|
114
|
+
it "should return a copy of itself, lightened by a percentage" do
|
115
|
+
color = Paleta::Color.new(94, 161, 235)
|
116
|
+
lightness = color.lightness
|
117
|
+
copy = color.lighten(20)
|
118
|
+
copy.lightness.should == lightness + 20
|
119
|
+
color.lightness.should == lightness
|
120
|
+
end
|
121
|
+
|
91
122
|
it "should quietly maintain a maximum of 100 when lightening" do
|
92
123
|
color = Paleta::Color.new(94, 161, 235)
|
93
124
|
color.lighten!(300)
|
@@ -104,6 +135,14 @@ describe Paleta::Color do
|
|
104
135
|
color.lightness.should == lightness - 20
|
105
136
|
end
|
106
137
|
|
138
|
+
it "should return a copy of itself, darkened by a percentage" do
|
139
|
+
color = Paleta::Color.new(94, 161, 235)
|
140
|
+
lightness = color.lightness
|
141
|
+
copy = color.darken(20)
|
142
|
+
copy.lightness.should == lightness - 20
|
143
|
+
color.lightness.should == lightness
|
144
|
+
end
|
145
|
+
|
107
146
|
it "should quietly maintain a minimum of 0 when darkening" do
|
108
147
|
color = Paleta::Color.new(94, 161, 235)
|
109
148
|
color.darken!(300)
|
@@ -118,6 +157,51 @@ describe Paleta::Color do
|
|
118
157
|
color.blue.should == 20
|
119
158
|
end
|
120
159
|
|
160
|
+
it "should return an inverted copy of itself" do
|
161
|
+
color = Paleta::Color.new(94, 161, 235)
|
162
|
+
copy = color.invert
|
163
|
+
copy.red.should == 161
|
164
|
+
copy.green.should == 94
|
165
|
+
copy.blue.should == 20
|
166
|
+
color.red.should == 94
|
167
|
+
color.green.should == 161
|
168
|
+
color.blue.should == 235
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should desaturate" do
|
172
|
+
color = Paleta::Color.new(94, 161, 235)
|
173
|
+
color.desaturate!
|
174
|
+
color.saturation.should == 0
|
175
|
+
color.red.to_i.should == 164
|
176
|
+
color.green.to_i.should == 164
|
177
|
+
color.blue.to_i.should == 164
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should return a desaturated copy of itself" do
|
181
|
+
color = Paleta::Color.new(94, 161, 235)
|
182
|
+
copy = color.desaturate
|
183
|
+
copy.saturation.should == 0
|
184
|
+
copy.red.to_i.should == 164
|
185
|
+
copy.green.to_i.should == 164
|
186
|
+
copy.blue.to_i.should == 164
|
187
|
+
color.saturation.to_i.should == 77
|
188
|
+
color.red.should == 94
|
189
|
+
color.green.should == 161
|
190
|
+
color.blue.should == 235
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should become its complement" do
|
194
|
+
color = Paleta::Color.new(:hsl, 90, 50, 50)
|
195
|
+
color.complement!
|
196
|
+
color.hue.should == 270
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should return its complement Color" do
|
200
|
+
color = Paleta::Color.new(:hsl, 90, 50, 50)
|
201
|
+
complement = color.complement
|
202
|
+
complement.hue.should == 270
|
203
|
+
end
|
204
|
+
|
121
205
|
it "should calculate its similarity to another Color" do
|
122
206
|
color1 = Paleta::Color.new(94, 161, 235)
|
123
207
|
color2 = Paleta::Color.new(237, 172, 33)
|
@@ -138,7 +222,7 @@ describe Paleta::Color do
|
|
138
222
|
end
|
139
223
|
|
140
224
|
it "should update its HSB and RGB components when its HEX value is updated" do
|
141
|
-
color = Paleta::Color.new
|
225
|
+
color = Paleta::Color.new(100, 100, 100)
|
142
226
|
color.hex = "ffffff"
|
143
227
|
color.red.should == 255
|
144
228
|
color.green.should == 255
|
data/spec/models/palette_spec.rb
CHANGED
@@ -11,14 +11,15 @@ describe Paleta::Palette do
|
|
11
11
|
it "should not initialize if an object in the set is not a Color" do
|
12
12
|
c1 = Paleta::Color.new(13, 57, 182)
|
13
13
|
c2 = 13
|
14
|
-
expect{ Paleta::Palette.new(c1, c2) }.to raise_error
|
14
|
+
expect{ Paleta::Palette.new(c1, c2) }.to raise_error(ArgumentError)
|
15
15
|
end
|
16
16
|
|
17
17
|
it "should add Colors" do
|
18
18
|
c1 = Paleta::Color.new(13, 57, 182)
|
19
19
|
c2 = Paleta::Color.new(94, 161, 235)
|
20
|
+
c3 = Paleta::Color.new(0, 0, 0)
|
20
21
|
palette = Paleta::Palette.new(c1)
|
21
|
-
palette << c2
|
22
|
+
palette << c2 << c3
|
22
23
|
palette.include?(c2).should be_true
|
23
24
|
end
|
24
25
|
|
@@ -92,6 +93,7 @@ describe Paleta::Palette do
|
|
92
93
|
end
|
93
94
|
|
94
95
|
it "should calculate a multiple regression over each Color in the Palette in RGB space" do
|
96
|
+
Paleta::Palette.send(:public, :fit)
|
95
97
|
c1 = Paleta::Color.new(13, 57, 182)
|
96
98
|
c2 = Paleta::Color.new(94, 161, 235)
|
97
99
|
c3 = Paleta::Color.new(237, 172, 33)
|
@@ -132,4 +134,53 @@ describe Paleta::Palette do
|
|
132
134
|
p6 = Paleta::Palette.new(c9, c10)
|
133
135
|
p5.similarity(p6).round(5).should == 0.0047
|
134
136
|
end
|
137
|
+
|
138
|
+
it "should generate a new Palette of shades of a single Color" do
|
139
|
+
color = Paleta::Color.new(:hex, "ff0000")
|
140
|
+
palette = Paleta::Palette.generate(:from => color, :size => 5)
|
141
|
+
palette.each do |p|
|
142
|
+
p.hue.should == color.hue
|
143
|
+
p.saturation.should == color.saturation
|
144
|
+
end
|
145
|
+
|
146
|
+
palette[0].lightness.should == 10
|
147
|
+
palette[1].lightness.should == 30
|
148
|
+
palette[2].lightness.should == 50
|
149
|
+
palette[3].lightness.should == 70
|
150
|
+
palette[4].lightness.should == 90
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should generate a new Palette of Colors analogous to the seed Color" do
|
154
|
+
color = Paleta::Color.new(:hex, "0066cc")
|
155
|
+
palette = Paleta::Palette.generate(:type => :analogous, :from => color, :size => 5)
|
156
|
+
palette.each do |p|
|
157
|
+
p.lightness.should == color.lightness
|
158
|
+
p.saturation.should == color.saturation
|
159
|
+
end
|
160
|
+
palette[0].hue.should == 170
|
161
|
+
palette[1].hue.should == 190
|
162
|
+
palette[2].hue.should == 210
|
163
|
+
palette[3].hue.should == 230
|
164
|
+
palette[4].hue.should == 250
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should generate a new Palette of Colors monochromatic to the seed Color" do
|
168
|
+
color = Paleta::Color.new(:hex, "0066cc")
|
169
|
+
palette = Paleta::Palette.generate(:type => :monochromatic, :from => color, :size => 5)
|
170
|
+
palette.each do |p|
|
171
|
+
p.hue.should == color.hue
|
172
|
+
p.lightness.should == color.lightness
|
173
|
+
end
|
174
|
+
palette[0].saturation.should == 20
|
175
|
+
palette[1].saturation.should == 40
|
176
|
+
palette[2].saturation.should == 60
|
177
|
+
palette[3].saturation.should == 80
|
178
|
+
palette[4].saturation.should == 100
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should generate a new Palette of random Colors" do
|
183
|
+
palette = Paleta::Palette.generate(:type => :random, :size => 5)
|
184
|
+
palette.size.should == 5
|
185
|
+
end
|
135
186
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paleta
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-01-
|
12
|
+
date: 2012-01-11 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
14
|
description: A gem for working with color palettes
|
15
15
|
email:
|