paleta 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b03ada62d667c325f97922bd22b05801aff9cccd
4
+ data.tar.gz: cb7d2375cfcf0ac8cceb96719d1c9cdb13b5af23
5
+ SHA512:
6
+ metadata.gz: 2a4cd1d750c2f78091b15b904d0d2e599dea95d91922a32b494ecd559bf5fa0eb504cb53e2ca735688efcab05195f573a5944eacaa37cef455d0430282873dbb
7
+ data.tar.gz: 1eeac708731584488a6a1611a14f3ba7417f3de5693f5144602cee107c43fe6d3b48b296c8dbd411a04561b46cead354641d77262f2aa8608f7a0a299292ad57
data/Gemfile CHANGED
@@ -2,6 +2,4 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rspec', '~>2.8.0'
6
- gem 'guard-rspec'
7
- gem 'rmagick'
5
+ gem 'rmagick'
@@ -4,9 +4,9 @@ module Paleta
4
4
  # Represents a color
5
5
  class Color
6
6
  include Math
7
-
7
+
8
8
  attr_reader :red, :green, :blue, :hue, :saturation, :lightness, :hex
9
-
9
+
10
10
  # Initailize a {Color}
11
11
  #
12
12
  # @overload initialize()
@@ -36,7 +36,6 @@ module Paleta
36
36
  #
37
37
  # @return [Color] A new instance of {Color}
38
38
  def initialize(*args)
39
-
40
39
  if args.length == 1 && args[0].is_a?(Color)
41
40
  args[0].instance_variables.each do |key|
42
41
  self.send("#{key[1..key.length]}=".to_sym, args[0].send("#{key[1..key.length]}"))
@@ -59,43 +58,43 @@ module Paleta
59
58
  raise(ArgumentError, "Invalid arguments")
60
59
  end
61
60
  end
62
-
61
+
63
62
  def red=(val)
64
63
  @red = range_validator(val, 0..255)
65
64
  update_hsl
66
65
  update_hex
67
66
  end
68
-
67
+
69
68
  def green=(val)
70
69
  @green = range_validator(val, 0..255)
71
70
  update_hsl
72
71
  update_hex
73
72
  end
74
-
73
+
75
74
  def blue=(val)
76
75
  @blue = range_validator(val, 0..255)
77
76
  update_hsl
78
77
  update_hex
79
78
  end
80
-
79
+
81
80
  def lightness=(val)
82
81
  @lightness = range_validator(val, 0..100)
83
82
  update_rgb
84
83
  update_hex
85
84
  end
86
-
85
+
87
86
  def saturation=(val)
88
87
  @saturation = range_validator(val, 0..100)
89
88
  update_rgb
90
89
  update_hex
91
90
  end
92
-
91
+
93
92
  def hue=(val)
94
93
  @hue = range_validator(val, 0..360)
95
94
  update_rgb
96
95
  update_hex
97
96
  end
98
-
97
+
99
98
  def hex=(val)
100
99
  raise(ArgumentError, "Invalid Hex String") unless val.length == 6 && /^[[:xdigit:]]+$/ === val
101
100
  @hex = val.upcase
@@ -104,23 +103,23 @@ module Paleta
104
103
  @blue = val[4..5].hex
105
104
  update_hsl
106
105
  end
107
-
106
+
108
107
  # Determine the equality of the receiver and another {Color}
109
108
  # @param [Color] color color to compare
110
109
  # @return [Boolean]
111
110
  def ==(color)
112
111
  color.is_a?(Color) ? (self.hex == color.hex) : false
113
112
  end
114
-
113
+
115
114
  # Create a copy of the receiver and lighten it by a percentage
116
115
  # @param [Number] percentage percentage by which to lighten the {Color}
117
116
  # @return [Color] a lightened copy of the receiver
118
117
  def lighten(percentage = 5)
119
- copy = self.class.new(self)
118
+ copy = self.dup
120
119
  copy.lighten!(percentage)
121
120
  copy
122
121
  end
123
-
122
+
124
123
  # Lighten the receiver by a percentage
125
124
  # @param [Number] percentage percentage by which to lighten the {Color}
126
125
  # @return [Color] self
@@ -131,16 +130,16 @@ module Paleta
131
130
  update_hex
132
131
  self
133
132
  end
134
-
133
+
135
134
  # Create a copy of the receiver and darken it by a percentage
136
135
  # @param [Number] percentage percentage by which to darken the {Color}
137
136
  # @return [Color] a darkened copy of the receiver
138
137
  def darken(percentage = 5)
139
- copy = self.class.new(self)
138
+ copy = self.dup
140
139
  copy.darken!(percentage)
141
140
  copy
142
141
  end
143
-
142
+
144
143
  # Darken the receiver by a percentage
145
144
  # @param [Number] percentage percentage by which to darken the {Color}
146
145
  # @return [Color] self
@@ -151,7 +150,7 @@ module Paleta
151
150
  update_hex
152
151
  self
153
152
  end
154
-
153
+
155
154
  # Create a copy of the receiver and invert it
156
155
  # @return [Color] an inverted copy of the receiver
157
156
  def invert
@@ -159,7 +158,7 @@ module Paleta
159
158
  copy.invert!
160
159
  copy
161
160
  end
162
-
161
+
163
162
  # Invert the receiver
164
163
  # @return [Color] self
165
164
  def invert!
@@ -170,7 +169,7 @@ module Paleta
170
169
  update_hex
171
170
  self
172
171
  end
173
-
172
+
174
173
  # Create a copy of the receiver and desaturate it
175
174
  # @return [Color] a desaturated copy of the receiver
176
175
  def desaturate
@@ -187,7 +186,7 @@ module Paleta
187
186
  update_hex
188
187
  self
189
188
  end
190
-
189
+
191
190
  # Create a new {Color} that is the complement of the receiver
192
191
  # @return [Color] a desaturated copy of the receiver
193
192
  def complement
@@ -195,7 +194,7 @@ module Paleta
195
194
  copy.complement!
196
195
  copy
197
196
  end
198
-
197
+
199
198
  # Turn the receiver into it's complement
200
199
  # @return [Color] self
201
200
  def complement!
@@ -204,14 +203,14 @@ module Paleta
204
203
  update_hex
205
204
  self
206
205
  end
207
-
206
+
208
207
  # Calculate the similarity between the receiver and another {Color}
209
208
  # @param [Color] color color to calculate the similarity to
210
209
  # @return [Number] a value in [0..1] with 0 being identical and 1 being as dissimilar as possible
211
210
  def similarity(color)
212
211
  distance({ :r => @red, :g => @green, :b => @blue}, { :r => color.red, :g => color.green, :b => color.blue}) / sqrt(3 * (255 ** 2))
213
212
  end
214
-
213
+
215
214
  # Return an array representation of a {Color} instance,
216
215
  # @param [Symbol] model the color model, should be :rgb or :hsl
217
216
  # @return [Array] an array of component values
@@ -226,25 +225,25 @@ module Paleta
226
225
  end
227
226
  array
228
227
  end
229
-
228
+
230
229
  private
231
-
230
+
232
231
  def rgb_init(red = 0, green = 0, blue = 0)
233
232
  self.red = red
234
233
  self.green = green
235
234
  self.blue = blue
236
235
  end
237
-
236
+
238
237
  def hsl_init(hue = 0, saturation = 0, lightness = 0)
239
238
  self.hue = hue
240
239
  self.saturation = saturation
241
240
  self.lightness = lightness
242
241
  end
243
-
242
+
244
243
  def hex_init(val = "000000")
245
244
  self.hex = val
246
245
  end
247
-
246
+
248
247
  def update_hsl
249
248
  r = @red / 255.0 rescue 0.0
250
249
  g = @green / 255.0 rescue 0.0
@@ -253,10 +252,14 @@ module Paleta
253
252
  min = [r, g, b].min
254
253
  max = [r, g, b].max
255
254
  delta = max - min
256
-
255
+
257
256
  h = 0
258
257
  l = (max + min) / 2.0
259
- s = ((l == 0 || l == 1) ? 0 : (delta / (1 - (2 * l - 1).abs)))
258
+ if ![1, 0].include?(l) && delta / 2.0 == l
259
+ s = 1.0
260
+ else
261
+ s = ((l == 0 || l == 1) ? 0 : (delta / (1 - (2 * l - 1).abs)))
262
+ end
260
263
 
261
264
  if delta != 0
262
265
  case max
@@ -265,15 +268,14 @@ module Paleta
265
268
  when b; h = ((r - g) / delta) + 4
266
269
  end
267
270
  end
268
-
271
+
269
272
  @hue = h * 60
270
273
  @hue += 360 if @hue < 0
271
274
  @saturation = s * 100
272
275
  @lightness = l * 100
273
276
  end
274
-
277
+
275
278
  def update_rgb
276
-
277
279
  h = @hue / 60.0 rescue 0.0
278
280
  s = @saturation / 100.0 rescue 0.0
279
281
  l = @lightness / 100.0 rescue 0.0
@@ -281,7 +283,7 @@ module Paleta
281
283
  d1 = (1 - (2 * l - 1).abs) * s
282
284
  d2 = d1 * (1 - (h % 2 - 1).abs)
283
285
  d3 = l - (d1 / 2.0)
284
-
286
+
285
287
  case h.to_i
286
288
  when 0; @red, @green, @blue = d1, d2, 0
287
289
  when 1; @red, @green, @blue = d2, d1, 0
@@ -291,12 +293,12 @@ module Paleta
291
293
  when 5; @red, @green, @blue = d1, 0, d2
292
294
  else; @red, @green, @blue = 0, 0, 0
293
295
  end
294
-
296
+
295
297
  @red = 255 * (@red + d3)
296
298
  @green = 255 * (@green + d3)
297
299
  @blue = 255 * (@blue + d3)
298
300
  end
299
-
301
+
300
302
  def update_hex
301
303
  r = @red.to_i.to_s(16) rescue "00"
302
304
  g = @green.to_i.to_s(16) rescue "00"
@@ -306,7 +308,7 @@ module Paleta
306
308
  b = "0#{b}" if b.length < 2
307
309
  @hex = "#{r}#{g}#{b}".upcase
308
310
  end
309
-
311
+
310
312
  def range_validator(val, range)
311
313
  range.include?(val) ? val : raise(ArgumentError, "Component range exceeded")
312
314
  end
@@ -8,20 +8,20 @@ module Math
8
8
  a.each_with_index { |v, i| sum += (a[i] - b[i]) ** 2 } if a.is_a?(Array)
9
9
  sqrt(sum)
10
10
  end
11
-
11
+
12
12
  def multiple_regression(dx, dy, dz)
13
13
  regression = {}
14
14
  regression[:slope], regression[:offset] = {}, {}
15
15
  size = dx.size
16
-
16
+
17
17
  raise "arguments not same length!" unless size == dy.size && size == dz.size
18
-
18
+
19
19
  if size == 1
20
20
  regression[:slope] = { :x => dx[0], :y => dy[0], :z => dz[0] }
21
21
  regression[:offset] = { :x => 0, :y => 0, :z => 0 }
22
22
  return regression
23
23
  end
24
-
24
+
25
25
  sxx = syy = szz = sxy = szx = syz = sx = sy = sz = 0
26
26
  dx.zip(dy, dz).each do |x, y, z|
27
27
  sxx += x ** 2
@@ -34,15 +34,15 @@ module Math
34
34
  sy += y
35
35
  sz += z
36
36
  end
37
-
37
+
38
38
  regression[:slope][:x] = ( size * sxy - sx * sz ) / ( size * sxx - sx ** 2 ).to_f
39
39
  regression[:slope][:y] = ( size * syz - sz * sy ) / ( size * syy - sz ** 2 ).to_f
40
40
  regression[:slope][:z] = ( size * syz - sz * sy ) / ( size * szz - sy ** 2 ).to_f
41
-
41
+
42
42
  regression[:offset][:x] = (sz - regression[:slope][:x] * sx) / size
43
43
  regression[:offset][:y] = (sy - regression[:slope][:y] * sz) / size
44
44
  regression[:offset][:z] = (sx - regression[:slope][:z] * sy) / size
45
-
45
+
46
46
  regression
47
47
  end
48
48
  end
@@ -1,24 +1,23 @@
1
1
  require 'paleta/core_ext/math'
2
2
 
3
3
  module Paleta
4
-
5
4
  module MagickDependent
6
5
  def self.included(klass)
7
- require 'RMagick'
6
+ require 'RMagick' unless defined?(Magick)
8
7
  klass.extend(ClassMethods)
9
8
  rescue LoadError
10
9
  puts "You must install RMagick to use Palette.generate(:from => :image, ...)"
11
10
  end
12
-
11
+
13
12
  module ClassMethods
14
13
  def generate_from_image(path, size = 5)
15
14
  include Magick
16
15
  begin
17
16
  image = Magick::ImageList.new(path)
18
-
17
+
19
18
  # quantize image to the nearest power of 2 greater the desired palette size
20
19
  quantized_image = image.quantize((Math.sqrt(size).ceil ** 2), Magick::RGBColorspace)
21
- colors = quantized_image.color_histogram.sort { |a, b| b[1] <=> a[1] }[0..(size - 1)].map do |color|
20
+ colors = quantized_image.color_histogram.sort { |a, b| b[1] <=> a[1] }[0..(size - 1)].map do |color|
22
21
  Paleta::Color.new(color[0].red / 256, color[0].green / 256, color[0].blue / 256)
23
22
  end
24
23
  return Paleta::Palette.new(colors)
@@ -28,15 +27,15 @@ module Paleta
28
27
  end
29
28
  end
30
29
  end
31
-
30
+
32
31
  # Represents a palette, a collection of {Color}s
33
32
  class Palette
34
33
  include Math
35
34
  include Enumerable
36
35
  include MagickDependent
37
-
36
+
38
37
  attr_accessor :colors
39
-
38
+
40
39
  # Initialize a {Palette} from a list of {Color}s
41
40
  # @param [Array] colors a list of {Color}s to include in the {Palette}
42
41
  # @return [Palette] A new instance of {Palette}
@@ -45,7 +44,7 @@ module Paleta
45
44
  colors = (args.length == 1 && args[0].is_a?(Array)) ? args[0] : args
46
45
  colors.each { |color| self << color }
47
46
  end
48
-
47
+
49
48
  # Add a {Color} to the {Palette}
50
49
  # @overload <<(color)
51
50
  # @param [Color] color a {Color} to add to the receiver
@@ -63,7 +62,7 @@ module Paleta
63
62
  end
64
63
  self
65
64
  end
66
-
65
+
67
66
  # Add a {Color} to the {Palette}
68
67
  # @overload push(color)
69
68
  # @param [Color] color a {Color} to add to the receiver
@@ -74,56 +73,56 @@ module Paleta
74
73
  def push(obj)
75
74
  self << obj
76
75
  end
77
-
76
+
78
77
  # Remove the most recently added {Color} from the receiver
79
78
  def pop
80
79
  @colors.pop
81
80
  end
82
-
81
+
83
82
  # Remove a {Color} from the receiver by index
84
83
  # @param [Number] index the index at which to remove a {Color}
85
84
  def delete_at(index = 0)
86
85
  @colors.delete_at(index)
87
86
  end
88
-
87
+
89
88
  # Access a {Color} in the receiver by index
90
89
  # @param [Number] index the index at which to access a {Color}
91
90
  def [](index)
92
91
  @colors[index]
93
92
  end
94
-
93
+
95
94
  # The number of {Color}s in the {Palette}
96
95
  # @return [Number] the number of {Color}s in the receiver
97
96
  def size
98
97
  @colors.size
99
98
  end
100
-
99
+
101
100
  # Iterate through each {Color} in the {Palette}
102
101
  def each
103
102
  @colors.each { |c| yield c }
104
103
  end
105
-
104
+
106
105
  # Create a new instance of {Palette} that is a sorted copy of the receiver
107
106
  # @return [Palette] a new instance of {Palette}
108
107
  def sort(&blk)
109
108
  @colors.sort(&blk)
110
109
  Paleta::Palette.new(@colors)
111
110
  end
112
-
111
+
113
112
  # Sort the {Color}s in the receiver
114
113
  # return [Palette] self
115
114
  def sort!(&blk)
116
115
  @colors.sort!(&blk)
117
116
  self
118
117
  end
119
-
118
+
120
119
  # Test if a {Color} exists in the receiver
121
120
  # @param [Color] color color to test for inclusion in the {Palette}
122
121
  # @return [Boolean]
123
122
  def include?(color)
124
123
  @colors.include?(color)
125
124
  end
126
-
125
+
127
126
  # Lighen each {Color} in the receiver by a percentage
128
127
  # @param [Number] percentage percentage by which to lighten each {Color} in the receiver
129
128
  # @return [Palette] self
@@ -131,7 +130,7 @@ module Paleta
131
130
  @colors.each { |color| color.lighten!(percentage) }
132
131
  self
133
132
  end
134
-
133
+
135
134
  # Lighen each {Color} in the receiver by a percentage
136
135
  # @param [Number] percentage percentage by which to lighten each {Color} in the receiver
137
136
  # @return [Palette] self
@@ -139,40 +138,40 @@ module Paleta
139
138
  @colors.each { |color| color.darken!(percentage) }
140
139
  self
141
140
  end
142
-
141
+
143
142
  # Invert each {Color} in the receiver by a percentage
144
143
  # @return [Palette] self
145
144
  def invert!
146
145
  @colors.each { |color| color.invert! }
147
146
  self
148
147
  end
149
-
148
+
150
149
  # Calculate the similarity between the receiver and another {Palette}
151
150
  # @param [Palette] palette palette to calculate the similarity to
152
151
  # @return [Number] a value in [0..1] with 0 being identical and 1 being as dissimilar as possible
153
152
  def similarity(palette)
154
153
  r, a, b = [], [], []
155
154
  (0..1).each { |i| a[i], b[i] = {}, {} }
156
-
155
+
157
156
  # r[i] is a hash of the multiple regression of the Palette in RGB space
158
157
  r[0] = fit
159
158
  r[1] = palette.fit
160
-
159
+
161
160
  [0, 1].each do |i|
162
161
  [:x, :y, :z].each do |k|
163
162
  a[i][k] = 0 * r[i][:slope][k] + r[i][:offset][k]
164
163
  b[i][k] = 255 * r[i][:slope][k] + r[i][:offset][k]
165
164
  end
166
165
  end
167
-
166
+
168
167
  d_max = sqrt(3 * (65025 ** 2))
169
-
168
+
170
169
  d1 = distance(a[0], a[1]) / d_max
171
170
  d2 = distance(b[0], b[1]) / d_max
172
-
171
+
173
172
  d1 + d2
174
173
  end
175
-
174
+
176
175
  # Generate a {Palette} from a seed {Color}
177
176
  # @param [Hash] opts the options with which to generate a new {Palette}
178
177
  # @option opts [Symbol] :type the type of palette to generate
@@ -182,25 +181,25 @@ module Paleta
182
181
  # @option opts [Number] :size the number of {Color}s to generate for the {Palette}
183
182
  # @return [Palette] A new instance of {Palette}
184
183
  def self.generate(opts = {})
185
-
184
+
186
185
  size = opts[:size] || 5
187
-
186
+
188
187
  if !opts[:type].nil? && opts[:type].to_sym == :random
189
188
  return self.generate_random_from_color(opts[:color], size)
190
189
  end
191
-
190
+
192
191
  unless (opts[:from].to_sym == :color && !opts[:color].nil?) || (opts[:from].to_sym == :image && !opts[:image].nil?)
193
192
  return raise(ArgumentError, 'You must pass :from and it must be either :color or :image, then you must pass :image => "/path/to/img" or :color => color')
194
193
  end
195
-
194
+
196
195
  if opts[:from].to_sym == :image
197
196
  path = opts[:image]
198
197
  return self.generate_from_image(path, size)
199
198
  end
200
-
199
+
201
200
  color = opts[:color]
202
201
  type = opts[:type] || :shades
203
-
202
+
204
203
  case type
205
204
  when :analogous; self.generate_analogous_from_color(color, size)
206
205
  when :complementary; self.generate_complementary_from_color(color, size)
@@ -212,7 +211,7 @@ module Paleta
212
211
  else raise(ArgumentError, "Palette type is not defined. Try :analogous, :monochromatic, :shades, or :random")
213
212
  end
214
213
  end
215
-
214
+
216
215
  # Return an array representation of a {Palette} instance,
217
216
  # @param [Symbol] model the color model, should be :rgb, :hsl, or :hex
218
217
  # @return [Array] an Array of Arrays where each sub-Array is a representation of a {Color} object in a {Palette} instance
@@ -227,9 +226,9 @@ module Paleta
227
226
  end
228
227
  array
229
228
  end
230
-
229
+
231
230
  private
232
-
231
+
233
232
  def self.generate_analogous_from_color(color, size)
234
233
  raise(ArgumentError, "Passed argument is not a Color") unless color.is_a?(Color)
235
234
  palette = self.new(color)
@@ -248,14 +247,14 @@ module Paleta
248
247
  end
249
248
  palette.sort! { |a, b| a.hue <=> b.hue }
250
249
  end
251
-
250
+
252
251
  def self.generate_complementary_from_color(color, size)
253
252
  raise(ArgumentError, "Passed argument is not a Color") unless color.is_a?(Color)
254
253
  complement = color.complement
255
254
  palette = self.new(color, complement)
256
255
  add_monochromatic_in_hues_of_color(palette, color, size)
257
256
  end
258
-
257
+
259
258
  def self.generate_triad_from_color(color, size)
260
259
  raise(ArgumentError, "Passed argument is not a Color") unless color.is_a?(Color)
261
260
  color2 = Paleta::Color.new(:hsl, (color.hue + 120) % 360, color.saturation, color.lightness)
@@ -263,7 +262,7 @@ module Paleta
263
262
  palette = self.new(color, color2, color3)
264
263
  add_monochromatic_in_hues_of_color(palette, color, size)
265
264
  end
266
-
265
+
267
266
  def self.generate_tetrad_from_color(color, size)
268
267
  raise(ArgumentError, "Passed argument is not a Color") unless color.is_a?(Color)
269
268
  color2 = Paleta::Color.new(:hsl, (color.hue + 90) % 360, color.saturation, color.lightness)
@@ -272,7 +271,7 @@ module Paleta
272
271
  palette = self.new(color, color2, color3, color4)
273
272
  add_monochromatic_in_hues_of_color(palette, color, size)
274
273
  end
275
-
274
+
276
275
  def self.generate_monochromatic_from_color(color, size)
277
276
  raise(ArgumentError, "Passed argument is not a Color") unless color.is_a?(Color)
278
277
  palette = self.new(color)
@@ -290,7 +289,7 @@ module Paleta
290
289
  end
291
290
  palette.sort! { |a, b| a.saturation <=> b.saturation }
292
291
  end
293
-
292
+
294
293
  def self.generate_shades_from_color(color, size)
295
294
  raise(ArgumentError, "Passed argument is not a Color") unless color.is_a?(Color)
296
295
  palette = self.new(color)
@@ -298,17 +297,17 @@ module Paleta
298
297
  lightness = color.lightness
299
298
  d = :down
300
299
  until palette.size == size
301
- lightness -= step if d == :down
302
- lightness += step if d == :up
303
- palette << Paleta::Color.new(:hsl, color.hue, color.saturation, lightness)
304
300
  if lightness - step < 0
305
301
  d = :up
306
302
  lightness = color.lightness
307
303
  end
304
+ lightness -= step if d == :down
305
+ lightness += step if d == :up
306
+ palette << Paleta::Color.new(:hsl, color.hue, color.saturation, lightness)
308
307
  end
309
308
  palette.sort! { |a, b| a.lightness <=> b.lightness }
310
309
  end
311
-
310
+
312
311
  def self.generate_split_complement_from_color(color, size)
313
312
  raise(ArgumentError, "Passed argument is not a Color") unless color.is_a?(Color)
314
313
  color2 = Paleta::Color.new(:hsl, (color.hue + 150) % 360, color.saturation, color.lightness)
@@ -316,7 +315,7 @@ module Paleta
316
315
  palette = self.new(color, color2, color3)
317
316
  add_monochromatic_in_hues_of_color(palette, color, size)
318
317
  end
319
-
318
+
320
319
  def self.generate_random_from_color(color = nil, size)
321
320
  palette = color.is_a?(Color) ? self.new(color) : self.new
322
321
  r = Random.new(Time.now.sec)
@@ -325,14 +324,14 @@ module Paleta
325
324
  end
326
325
  palette
327
326
  end
328
-
327
+
329
328
  def self.add_monochromatic_in_hues_of_color(palette, color, size)
330
- raise(ArgumentError, "Second argument is not a Color") unless color.is_a?(Color)
329
+ raise(ArgumentError, "Second argument is not a Color") unless color.is_a?(Color)
331
330
  hues = palette.map { |c| c.hue }
332
331
  step = ugap = dgap = 100 / size
333
332
  i = j = 0
334
333
  saturation = color.saturation
335
- until palette.size == size
334
+ until palette.size == size
336
335
  if color.saturation + ugap < 100
337
336
  saturation = color.saturation + ugap
338
337
  ugap += step
@@ -340,13 +339,13 @@ module Paleta
340
339
  saturation = color.saturation - dgap
341
340
  dgap += step
342
341
  end if j == 3 || j == 1
343
- new_color = Paleta::Color.new(:hsl, hues[i], saturation, color.lightness)
342
+ new_color = Paleta::Color.new(:hsl, hues[i], saturation, color.lightness)
344
343
  palette << new_color unless palette.include?(new_color)
345
344
  i += 1; j += 1; i %= hues.size; j %= (2 * hues.size)
346
345
  end
347
346
  palette.sort! { |a, b| a.saturation <=> b.saturation }
348
347
  end
349
-
348
+
350
349
  def fit
351
350
  # create a 3xn matrix where n = @colors.size to represent the set of colors
352
351
  reds = @colors.map { |c| c.red }
@@ -1,3 +1,3 @@
1
1
  module Paleta
2
- VERSION = '0.2.0'
2
+ VERSION = '0.2.1'
3
3
  end
@@ -14,4 +14,8 @@ Gem::Specification.new do |gem|
14
14
  gem.name = 'paleta'
15
15
  gem.require_paths = ['lib']
16
16
  gem.version = Paleta::VERSION
17
+
18
+ gem.add_development_dependency "rspec", "~> 2.8"
19
+ gem.add_development_dependency "guard-rspec", "~> 1.2"
20
+ gem.add_development_dependency "pry-byebug", "~> 2.0"
17
21
  end
@@ -27,63 +27,82 @@ Paleta allows users to create Color objects. Color objects can be defined by HSL
27
27
  #### Creating Colors
28
28
 
29
29
  Colors can be created using RGB or HSL components, or by using a HEX value by passing in a flag of the desired format as the first parameter. If no format flag is used, RGB is assumed.
30
-
31
- color = Paleta::Color.new(:hsl, 280, 37, 68)
32
- color = Paleta::Color.new(:rgb, 94, 161, 235)
33
- color = Paleta::Color.new(:hex, "5EA1EB")
34
-
35
- # creating a Color with no flag defaults to RGB components
36
- color = Paleta::Color.new(94, 161, 235)
37
-
30
+
31
+ ```ruby
32
+ color = Paleta::Color.new(:hsl, 280, 37, 68)
33
+ color = Paleta::Color.new(:rgb, 94, 161, 235)
34
+ color = Paleta::Color.new(:hex, "5EA1EB")
35
+
36
+ # creating a Color with no flag defaults to RGB components
37
+
38
+ color = Paleta::Color.new(94, 161, 235)
39
+ ```
40
+
38
41
  Individual component values can be accessed by name
39
42
 
40
- color.red # => 94
41
- color.green # => 161
42
- color.blue # => 235
43
- color.hue # => 211.48936170212767
44
- color.saturation # => 77.90055248618782
45
- color.lightness # => 64.50980392156862
46
- color.hex # => "5EA1EB"
47
-
43
+ ```ruby
44
+ color.red # => 94
45
+ color.green # => 161
46
+ color.blue # => 235
47
+ color.hue # => 211.48936170212767
48
+ color.saturation # => 77.90055248618782
49
+ color.lightness # => 64.50980392156862
50
+ color.hex # => "5EA1EB"
51
+ ```
48
52
 
49
53
  Get an array representation of a Color
50
54
 
51
- c = Paleta::Color.new(30, 90, 120)
52
- c.to_array(:rgb) # => [30, 90, 120]
53
-
55
+ ```ruby
56
+ c = Paleta::Color.new(30, 90, 120)
57
+ c.to_array(:rgb) # => [30, 90, 120]
58
+ ```
59
+
54
60
  #### Manipulating Colors
55
61
 
62
+
56
63
  Colors can be lightened or darkened by a percentage
57
64
 
58
- color.lighten!(10)
59
- color.darken!(30)
60
-
65
+ ```ruby
66
+ color.lighten!(10)
67
+ color.darken!(30)
68
+ ```
69
+
61
70
  Colors can be desaturated
62
71
 
63
- color.desaturate!
64
-
72
+ ```ruby
73
+ color.desaturate!
74
+ ```
75
+
65
76
  Colors can be turned into their complement Colors
66
77
 
67
- color.complement!
78
+ ```ruby
79
+ color.complement!
80
+ ```
68
81
 
69
82
  Colors can be inverted
70
83
 
71
- color.invert!
72
-
84
+ ```ruby
85
+ color.invert!
86
+ ```
87
+
73
88
  **Note** all of the previous methods directly manipulate the object on which they were called. If you would like to create a new Color object that is a copy of the original color (but with the desired manipulation), call the desired method without the trailing bang `!`.
74
89
 
75
90
  For example, lets create a new Color that is the complement of a Color we have already defined.
76
91
 
77
- new_color = color.complement
78
-
92
+ ```ruby
93
+ new_color = color.complement
94
+ ```
95
+
79
96
  #### Comparing Colors
80
97
 
81
98
  Colors can calculate their similarity to other Colors. The `similarity` method returns a value between 0 and 1, with 0 being identical and 1 being as dissimilar as possible.
82
99
 
83
- color = Paleta::Color.new(:hsl, 280, 37, 68)
84
- color2 = Paleta::Color.new(237, 172, 33)
85
- color.similarity(color2) # => 0.4100287904421024
86
-
100
+ ```ruby
101
+ color = Paleta::Color.new(:hsl, 280, 37, 68)
102
+ color2 = Paleta::Color.new(237, 172, 33)
103
+ color.similarity(color2) # => 0.4100287904421024
104
+ ```
105
+
87
106
  ### Palette
88
107
 
89
108
  Palettes are collections of Colors, they share many common Array methods such as `push`, `pop`, `sort`, `include?` and `each`. Palettes also allow collections of Colors to be manipulated as a whole and to be compared to each other.
@@ -92,99 +111,127 @@ Palettes are collections of Colors, they share many common Array methods such as
92
111
 
93
112
  Palettes can be created by passing a list of Colors to the Palette constructor, or on the fly with `push` and `<<`.
94
113
 
95
- color1 = Paleta::Color.new(13, 57, 182)
96
- color2 = Paleta::Color.new(94, 161, 235)
97
- color3 = Paleta::Color.new(237, 182, 17)
98
- palette = Paleta::Palette.new(color1, color2)
99
-
100
- palette << color3
101
-
114
+ ```ruby
115
+ color1 = Paleta::Color.new(13, 57, 182)
116
+ color2 = Paleta::Color.new(94, 161, 235)
117
+ color3 = Paleta::Color.new(237, 182, 17)
118
+ palette = Paleta::Palette.new(color1, color2)
119
+
120
+ palette << color3
121
+ ```
122
+
102
123
  #### Retrieving and Removing Colors from Palettes
103
124
 
104
125
  Colors can be accessed and removed by index.
105
126
 
106
- palette[1] # => color2
107
-
108
- palette.delete_at(2)
109
-
127
+ ```ruby
128
+ palette[1] # => color2
129
+
130
+ palette.delete_at(2)
131
+ ```
132
+
110
133
  Get an array representation of a Palette
111
134
 
112
- c1 = Paleta::Color.new(13, 57, 182)
113
- c2 = Paleta::Color.new(94, 161, 235)
114
- palette = Paleta::Palette.new(c1, c2)
135
+ ```ruby
136
+ c1 = Paleta::Color.new(13, 57, 182)
137
+ c2 = Paleta::Color.new(94, 161, 235)
138
+ palette = Paleta::Palette.new(c1, c2)
115
139
 
116
- palette.to_array(:rgb) # => [[13, 57, 182], [94, 161, 235]]
140
+ palette.to_array(:rgb) # => [[13, 57, 182], [94, 161, 235]]
141
+ ```
117
142
 
118
143
  #### Manipulating Palettes
119
144
 
120
145
  Palettes can be lightened, darkened or inverted as a whole.
121
-
122
- palette.lighten!(15)
123
- palette.darken!(20)
124
- palette.invert!
125
-
146
+
147
+ ```ruby
148
+ palette.lighten!(15)
149
+ palette.darken!(20)
150
+ palette.invert!
151
+ ```
152
+
126
153
  #### Comparing Palettes
127
154
 
128
155
  Palettes can calculate their similarity to other Palettes by using the `similarity` method. Just as with `Color#similarity`, this method returns a value between 0 and 1, with 0 being identical and 1 being as dissimilar as possible.
129
156
 
130
- color1 = Paleta::Color.new(13, 57, 182)
131
- color2 = Paleta::Color.new(237, 172, 33)
132
- palette1 = Paleta::Palette.new(color1, color2)
133
-
134
- color3 = Paleta::Color.new(13, 57, 182)
135
- color4 = Paleta::Color.new(94, 161, 235)
136
- palette2 = Paleta::Palette.new(color3, color4)
157
+ ```ruby
158
+ color1 = Paleta::Color.new(13, 57, 182)
159
+ color2 = Paleta::Color.new(237, 172, 33)
160
+ palette1 = Paleta::Palette.new(color1, color2)
161
+
162
+ color3 = Paleta::Color.new(13, 57, 182)
163
+ color4 = Paleta::Color.new(94, 161, 235)
164
+ palette2 = Paleta::Palette.new(color3, color4)
165
+
166
+ palette1.similarity(palette2) # => 0.0046992695975874915
167
+ ```
137
168
 
138
- palette1.similarity(palette2) # => 0.0046992695975874915
139
-
140
169
  #### Generating Palettes
141
170
 
142
171
  Palettes can be generated from a "seed" Color or from an image by using the `generate` method.
143
172
 
144
173
  **Generate a Palette of shades from a Color**
145
174
 
146
- color = Paleta::Color.new(:hex, "ff0000")
147
- palette = Paleta::Palette.generate(:type => :shades, :from => :color, :size => 5)
148
-
175
+ ```ruby
176
+ color = Paleta::Color.new(:hex, "ff0000")
177
+ palette = Paleta::Palette.generate(:type => :shades, :from => :color, :size => 5)
178
+ ```
179
+
149
180
  **Generate a Palette of analogous Colors from a Color**
150
181
 
151
- color = Paleta::Color.new(:hex, "0066cc")
152
- palette = Paleta::Palette.generate(:type => :analogous, :from => :color, :size => 5)
153
-
182
+ ```ruby
183
+ color = Paleta::Color.new(:hex, "0066cc")
184
+ palette = Paleta::Palette.generate(:type => :analogous, :from => :color, :size => 5)
185
+ ```
186
+
154
187
  **Generate a Palette of monochromatic Colors from a Color**
155
188
 
156
- color = Paleta::Color.new(:hex, "336699")
157
- palette = Paleta::Palette.generate(:type => :monochromatic, :from => :color, :size => 5)
158
-
189
+ ```ruby
190
+ color = Paleta::Color.new(:hex, "336699")
191
+ palette = Paleta::Palette.generate(:type => :monochromatic, :from => :color, :size => 5)
192
+ ```
193
+
159
194
  **Generate a Palette of complementary Colors from a Color**
160
195
 
161
- color = Paleta::Color.new(:hex, "0000ff")
162
- palette = Paleta::Palette.generate(:type => :complementary, :from => :color, :size => 5)
196
+ ```ruby
197
+ color = Paleta::Color.new(:hex, "0000ff")
198
+ palette = Paleta::Palette.generate(:type => :complementary, :from => :color, :size => 5)
199
+ ```
163
200
 
164
201
  **Generate a Palette of split-complement Colors from a Color**
165
202
 
166
- color = Paleta::Color.new(:hex, "006699")
167
- palette = Paleta::Palette.generate(:type => :split_complement, :from => :color, :size => 5)
203
+ ```ruby
204
+ color = Paleta::Color.new(:hex, "006699")
205
+ palette = Paleta::Palette.generate(:type => :split_complement, :from => :color, :size => 5)
206
+ ```
168
207
 
169
208
  **Generate a Palette of triad Colors from a Color**
170
209
 
171
- color = Paleta::Color.new(:hex, "006699")
172
- palette = Paleta::Palette.generate(:type => :triad, :from => :color, :size => 5)
210
+ ```ruby
211
+ color = Paleta::Color.new(:hex, "006699")
212
+ palette = Paleta::Palette.generate(:type => :triad, :from => :color, :size => 5)
213
+ ```
173
214
 
174
215
  **Generate a Palette of tetrad Colors from a Color**
175
216
 
176
- color = Paleta::Color.new(:hex, "dd5533")
177
- palette = Paleta::Palette.generate(:type => :tetrad, :from => :color, :size => 5)
178
-
217
+ ```ruby
218
+ color = Paleta::Color.new(:hex, "dd5533")
219
+ palette = Paleta::Palette.generate(:type => :tetrad, :from => :color, :size => 5)
220
+ ```
221
+
179
222
  **Generate a random Palette**
180
223
 
181
- palette = Paleta::Palette.generate(:type => :random, :size => 5)
182
-
224
+ ```ruby
225
+ palette = Paleta::Palette.generate(:type => :random, :size => 5)
226
+ ```
227
+
183
228
  Palettes can also be generated from a seed image
184
229
 
185
230
  **Generate a Palette from an image**
186
231
 
187
- palette = Paleta::Palette.generate(:from => :image, :image => "/path/to/image.jpg", :size => 5)
232
+ ```ruby
233
+ palette = Paleta::Palette.generate(:from => :image, :image => "/path/to/image.jpg", :size => 5)
234
+ ```
188
235
 
189
236
  ***
190
237
 
metadata CHANGED
@@ -1,16 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paleta
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
5
- prerelease:
4
+ version: 0.2.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Jordan Stephens
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-03-13 00:00:00.000000000Z
13
- dependencies: []
11
+ date: 2014-12-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.8'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: guard-rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry-byebug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
14
55
  description: A gem for working with color palettes
15
56
  email:
16
57
  - iam@jordanstephens.net
@@ -18,7 +59,7 @@ executables: []
18
59
  extensions: []
19
60
  extra_rdoc_files: []
20
61
  files:
21
- - .gitignore
62
+ - ".gitignore"
22
63
  - Gemfile
23
64
  - LICENSE
24
65
  - lib/paleta.rb
@@ -34,27 +75,26 @@ files:
34
75
  - spec/spec_helper.rb
35
76
  homepage: http://rubygems.org/gems/paleta
36
77
  licenses: []
78
+ metadata: {}
37
79
  post_install_message:
38
80
  rdoc_options: []
39
81
  require_paths:
40
82
  - lib
41
83
  required_ruby_version: !ruby/object:Gem::Requirement
42
- none: false
43
84
  requirements:
44
- - - ! '>='
85
+ - - ">="
45
86
  - !ruby/object:Gem::Version
46
87
  version: '0'
47
88
  required_rubygems_version: !ruby/object:Gem::Requirement
48
- none: false
49
89
  requirements:
50
- - - ! '>='
90
+ - - ">="
51
91
  - !ruby/object:Gem::Version
52
92
  version: '0'
53
93
  requirements: []
54
94
  rubyforge_project:
55
- rubygems_version: 1.8.10
95
+ rubygems_version: 2.2.2
56
96
  signing_key:
57
- specification_version: 3
97
+ specification_version: 4
58
98
  summary: A little library for creating, manipulating and comparing colors and color
59
99
  palettes
60
100
  test_files:
@@ -62,4 +102,3 @@ test_files:
62
102
  - spec/models/color_spec.rb
63
103
  - spec/models/palette_spec.rb
64
104
  - spec/spec_helper.rb
65
- has_rdoc: