Class: Colorist::Color

Inherits:
Object
  • Object
show all
Defined in:
lib/colorist/color.rb

Overview

Color is the general class for storing and manipulating a color with the Colorist gem. It provides methods to add, subtract, and calculate aspects of the color based on W3C and other standards.

Constant Summary collapse

CSS_COLOR_NAMES =
{  "maroon"  => 0x800000,
"red"     => 0xff0000,
"orange"  => 0xffa500,
"yellow"  => 0xffff00,
"olive"   => 0x808000,
"purple"  => 0x800080,
"fuchsia" => 0xff00ff,
"white"   => 0xffffff,
"lime"    => 0x00ff00,
"green"   => 0x008000,
"navy"    => 0x000080,
"blue"    => 0x0000ff,
"aqua"    => 0x00ffff,
"teal"    => 0x008080,
"black"   => 0x000000,
"silver"  => 0xc0c0c0,
"gray"    => 0x808080  }

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(color = 0x000000) ⇒ Color

Creates a new color with the hex color provided as a number (i.e. 0x112233)



27
28
29
30
31
32
# File 'lib/colorist/color.rb', line 27

def initialize(color=0x000000)
  string = "%.6x" % color
  @r = string[0..1].hex
  @g = string[2..3].hex
  @b = string[4..5].hex
end

Instance Attribute Details

#bObject

Returns the value of attribute b.



6
7
8
# File 'lib/colorist/color.rb', line 6

def b
  @b
end

#gObject

Returns the value of attribute g.



6
7
8
# File 'lib/colorist/color.rb', line 6

def g
  @g
end

#rObject

Returns the value of attribute r.



6
7
8
# File 'lib/colorist/color.rb', line 6

def r
  @r
end

Class Method Details

.from(some_entity) ⇒ Object

Create a new color from the provided object. Duplicates Color objects and attempts to call to_color on other objects. Will raise an ArgumentError if it is unable to coerce the color.



96
97
98
99
100
101
102
103
104
# File 'lib/colorist/color.rb', line 96

def self.from(some_entity)
  case some_entity
    when Colorist::Color
      some_entity.dup
    else
      raise ArgumentError, "#{some_entity.class.to_s} cannot be coerced into a color.", caller unless some_entity.respond_to?(:to_color)
      some_entity.to_color
  end
end

.from_hsv(hue, saturation, value) ⇒ Object

Initialize a colour based on HSV/HSB values. Hue should be between 0 and 360 (inclusive), while saturation and value should be from 0.0 to 1.0.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/colorist/color.rb', line 50

def self.from_hsv(hue, saturation, value)
  saturation = 1 if saturation > 1
  value = 1 if saturation > 1

  # Conversion formula taken from wikipedia

  f = (hue / 60.0) - (hue / 60).floor

  p = value * (1 - saturation)
  q = value * (1 - (saturation * f))
  t = value * (1 - (saturation * (1 - f)))

  r, g, b = case (hue / 60).floor % 6
            when 0 then [ value, t, p ]
            when 1 then [ q, value, p ]
            when 2 then [ p, value, t ]
            when 3 then [ p, q, value ]
            when 4 then [ t, p, value ]
            when 5 then [ value, p, q ]
            end

  from_rgb(r, g, b, :percent => true)
end

.from_rgb(r, g, b, options = {}) ⇒ Object

Initialize a color based on RGB values. By default, the values should be between 0 and 255. If you use the option :percent => true, the values should then be between 0.0 and 1.0.



37
38
39
40
41
42
43
44
45
46
# File 'lib/colorist/color.rb', line 37

def self.from_rgb(r,g,b,options={})
  color = new
  # convert from 0.0 to 1.0 to 0 to 255 if the :percent option is used
  if options[:percent]
    color.r, color.g, color.b = (r * 255).round, (g * 255).round, (b * 255).round
  else
    color.r, color.g, color.b = r, g, b
  end
  color
end

.from_string(some_string) ⇒ Object

Converts a CSS hex string into a color. Works both with the full form (i.e. #ffffff) and the abbreviated form (#fff). Can also take any of the 16 named CSS colors.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/colorist/color.rb', line 77

def self.from_string(some_string)
  if matched = some_string.match(/\A#([0-9a-f]{3})\z/i)
    color = from_rgb(*matched[1].split(//).collect{|v| "#{v}#{v}".hex })
  elsif matched = some_string.match(/\A#([0-9a-f]{6})\z/i)
    color = new
    color.r = matched[1][0..1].hex
    color.g = matched[1][2..3].hex
    color.b = matched[1][4..5].hex
  elsif CSS_COLOR_NAMES.key?(some_string)
    color = new(CSS_COLOR_NAMES[some_string])
  else
    raise ArgumentError, "Must provide a valid CSS hex color or color name.", caller
  end
  color
end

Instance Method Details

#+(other_color) ⇒ Object

Add the individual RGB values of two colors together. You may also use an equivalent numeric or string color representation.

Examples:

gray = Colorist::Color.new(0x333333)
gray + "#300"   # => <Color #663333>
gray + 0x000000 # => <Color #333333>
white = "white".to_color
gray + white    # => <Color #ffffff>


121
122
123
124
125
126
127
128
# File 'lib/colorist/color.rb', line 121

def +(other_color)
  other_color = self.class.from(other_color)
  color = self.dup
  color.r += other_color.r
  color.g += other_color.g
  color.b += other_color.b
  color
end

#-(other_color) ⇒ Object

Subtract the individual RGB values of the two colors together. You may also use an equivalent numeric or string color representation.



132
133
134
135
136
137
138
139
# File 'lib/colorist/color.rb', line 132

def -(other_color)
  other_color = self.class.from(other_color)
  color = self.dup
  color.r -= other_color.r
  color.g -= other_color.g
  color.b -= other_color.b
  color
end

#<(other_color) ⇒ Object

Compares colors based on brightness.



148
149
150
151
# File 'lib/colorist/color.rb', line 148

def < (other_color)
  other_color = self.class.from(other_color)
  brightness < other_color.brightness
end

#<=>(other_color) ⇒ Object

Compares colors based on brightness.



142
143
144
145
# File 'lib/colorist/color.rb', line 142

def <=>(other_color)
  other_color = self.class.from(other_color)
  brightness <=> other_color.brightness
end

#==(other_color) ⇒ Object

Equal if the red, green, and blue values are identical.



160
161
162
163
# File 'lib/colorist/color.rb', line 160

def ==(other_color)
  other_color = self.class.from(other_color)
  other_color.r == self.r && other_color.g == self.g && other_color.b == self.b
end

#===(other_color) ⇒ Object

Equal if the brightnesses of the two colors are identical.



166
167
168
169
# File 'lib/colorist/color.rb', line 166

def ===(other_color)
  other_color = self.class.from(other_color)
  other_color.brightness == brightness
end

#>(other_color) ⇒ Object

Compares colors based on brightness.



154
155
156
157
# File 'lib/colorist/color.rb', line 154

def > (other_color)
  other_color = self.class.from(other_color)
  brightness > other_color.brightness
end

#adjust(opts = {}) ⇒ Object

Adjusts any of H, S, V values with relative values: opts[:h], opts[:s], opts[:v] and returns adjusted value.



296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/colorist/color.rb', line 296

def adjust(opts = {})
  unless [:h, :s, :v].any? { |part| opts.include? part }
    raise ArgumentError, "please specify at least one of :h, :s, or :v options"
  end

  h, s, v = *self.to_hsv

  h = _within(0, h + opts[:h], 359) if opts[:h]
  s = _within(0, s + opts[:s], 1)   if opts[:s]
  v = _within(0, v + opts[:v], 1)   if opts[:v]

  self.class.from_hsv(h, s, v)
end

#brightness(formula = :w3c) ⇒ Object

Returns the perceived brightness of the provided color on a scale of 0.0 to 1.0 based on the formula provided. The formulas available are:

  • :w3c - ((r * 299 + g * 587 + b * 114) / 1000 / 255

  • :standard - sqrt(0.241 * r^2 + 0.691 * g^2 + 0.068 * b^2) / 255



227
228
229
230
231
232
233
234
# File 'lib/colorist/color.rb', line 227

def brightness(formula=:w3c)
  case formula
    when :standard
      Math.sqrt(0.241 * r**2 + 0.691 * g**2 + 0.068 * b**2) / 255
    when :w3c
      ((r * 299 + g * 587 + b * 114) / 255000.0)
  end
end

#contrast_with(other_color, formula = :w3c) ⇒ Object

Contrast this color with another color using the provided formula. The available formulas are:

  • :w3c - (max(r1 r2) - min(r1 r2)) + (max(g1 g2) - min(g1 g2)) + (max(b1 b2) - min(b1 b2))



240
241
242
243
244
245
246
247
248
# File 'lib/colorist/color.rb', line 240

def contrast_with(other_color, formula=:w3c)
  other_color = self.class.from(other_color)
  case formula
    when :w3c
      (([self.r, other_color.r].max - [self.r, other_color.r].min) +
      ([self.g, other_color.g].max - [self.g, other_color.g].min) +
      ([self.b, other_color.b].max - [self.b, other_color.b].min)) / 765.0
  end
end

#dupObject

Create a duplicate of this color.



107
108
109
# File 'lib/colorist/color.rb', line 107

def dup
  self.class.from_rgb(@r,@g,@b)
end

#gradient_to(color, steps = 10) ⇒ Object

Uses a naive formula to generate a gradient between this color and the given color. Returns the array of colors that make the gradient, including this color and the target color. By default will return 10 colors, but this can be changed by supplying an optional steps parameter.



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/colorist/color.rb', line 261

def gradient_to(color, steps = 10)
  color_to = self.class.from(color)
  red = color_to.r - r
  green = color_to.g - g
  blue = color_to.b - b

  result = (1..(steps - 3)).to_a.collect do |step|
    percentage = step.to_f / (steps - 1)
    self.class.from_rgb(r + (red * percentage), g + (green * percentage), b + (blue * percentage))
  end

  # Add first and last colors to result, avoiding uneccessary calculation and rounding errors

  result.unshift(self.dup)
  result.push(color.dup)
  result
end

#inspectObject



217
218
219
# File 'lib/colorist/color.rb', line 217

def inspect
  "#<Color #{to_s(:css)}>"
end

#invertObject Also known as: opposite

Returns the opposite of the current color.



251
252
253
# File 'lib/colorist/color.rb', line 251

def invert
  self.class.from_rgb(255 - r, 255 - g, 255 - b)
end

#text_color(threshold = 0.6, formula = :standard) ⇒ Object

Returns an appropriate text color (either black or white) based on the brightness of this color. The threshold specifies the brightness cutoff point.



290
291
292
# File 'lib/colorist/color.rb', line 290

def text_color(threshold=0.6, formula=:standard)
  brightness(formula) > threshold ? self.class.new(0x000000) : self.class.new(0xffffff)
end

#to_grayscale(formula = :w3c) ⇒ Object

Converts the current color to grayscale using the brightness formula provided. See #brightness for a description of the available formulas.



282
283
284
285
# File 'lib/colorist/color.rb', line 282

def to_grayscale(formula=:w3c)
  b = brightness(formula)
  self.class.from_rgb(255 * b, 255 * b, 255 * b)
end

#to_hsvObject

Returns an array of the hue, saturation and value of the color. Hue will range from 0-359, hue and saturation will be between 0 and 1.



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/colorist/color.rb', line 198

def to_hsv
  red, green, blue = *[r, g, b].collect {|x| x / 255.0}
  max = [red, green, blue].max
  min = [red, green, blue].min

  if min == max
    hue = 0
  elsif max == red
    hue = 60 * ((green - blue) / (max - min))
  elsif max == green
    hue = 60 * ((blue - red) / (max - min)) + 120
  elsif max == blue
    hue = 60 * ((red - green) / (max - min)) + 240
  end

  saturation = (max == 0) ? 0 : (max - min) / max
  [hue % 360, saturation, max]
end

#to_s(format = :css) ⇒ Object

Outputs a string representation of the color in the desired format. The available formats are:

  • :css - As a CSS hex string (i.e. #ffffff) (default)

  • :css_rgb - As a CSS RGB value string (i.e. rgb(255,255,255))

  • :rgb - As an RGB triplet (i.e. 1.0, 1.0, 1.0)



184
185
186
187
188
189
190
191
192
193
# File 'lib/colorist/color.rb', line 184

def to_s(format=:css)
  case format
    when :css
      "#%.2x%.2x%.2x" % [r, g, b]
    when :css_rgb
      "rgb(%.2f,%.2f,%.2f)" % [r, g, b]
    when :rgb
      "%.3f, %.3f, %.3f" % [r / 255, g / 255, b / 255]
  end
end