class Rustle::Color
Constants
- VALID_HEX_COLOR
The Regex which verifies that a valid hex color code is supplied. It merely checks that a string is 6 characters long and consists of hexadecimal characters.
Attributes
@return [Fixnum] the blue value of the color
@return [Fixnum] the green value of the color
@return [Fixnum] the red value of the color
Public Class Methods
Creates a new color object given a hexadecimal value.
@param [String] hex_value the hexadecimal representation of a color
@return [Color] a new Color
object based on the given hexadecimal value.
@example
# Valid Color.hex('#faa') Color.hex('fa03f2') Color.hex('#fa03f2') # Invalid (will raise) Color.hex('fzx') Color.hex('af3d')
# File lib/rustle/color.rb, line 85 def self.hex(hex_value) # Remove leading hash hex_value = hex_value[1..-1] if hex_value[0] == '#' # Convert f00 to ff0000 if hex_value.length == 3 hex_value = hex_value.split("").map { |s| s+s }.join end # Validate the format raise InvalidHexColorCode unless hex_value =~ VALID_HEX_COLOR self.new *( hex_value.scan(/.{2}/).map(&:hex) ) end
Creates a new Color
object given HSB color values.
@param [Fixnum] hue the color's hue (between 0 and 360) @param [Float] sat the color's saturation (between 0 and 1) @param [Float] bri the color's brightness (between 0 and 1)
@return [Color] a new color object based on the given HSB values.
# File lib/rustle/color.rb, line 107 def self.hsb(hue, sat, bri) hue = fit_within_range(hue, 0, 360) sat = fit_within_range(sat, 0, 1) bri = fit_within_range(bri, 0, 1) if sat == 0 r = g = b = bri else hh = hue % 360 hh /= 60.0 i = hh.to_i f = hh - i p = bri * (1 - sat) q = bri * (1 - sat * f) t = bri * (1 - sat * (1 - f)) case i when 0 r = bri g = t b = p when 1 r = q g = bri b = p when 2 r = p g = bri b = t when 3 r = p g = q b = bri when 4 r = t g = p b = bri else r = bri g = p b = q end end self.new *( [r, g, b].map { |c| (c * 255 + 0.5) } ) end
Creates a new Color
object given RGB values in the range 0..255
. Other values are accepted, but they will be coerced into this range (this is preferable to throwing exceptions, because there's a slim chance that an internal method will have some rounding errors).
@param [Fixnum] r the red value @param [Fixnum] g the green value @param [Fixnum] b the blue value
@return [Color] a new Color
object with the given RGB values.
# File lib/rustle/color.rb, line 27 def initialize(r, g, b) @r = normalize_rgb_param(r) @g = normalize_rgb_param(g) @b = normalize_rgb_param(b) end
Creates a new Color
object given RGB values. Equivalent to {#initialize}.
# File lib/rustle/color.rb, line 34 def self.rgb(r, g, b) self.new(r, g, b) end
Private Class Methods
Coerces `value` into the range given
# File lib/rustle/color.rb, line 221 def self.fit_within_range(value, min_allowed, max_allowed) if (value <= max_allowed) && (value >= min_allowed) value else value > max_allowed ? max_allowed : min_allowed end end
Public Instance Methods
Checks if a color is equal to another color.
@param [Color] other the other Color
object
@example
red_rgb = Rustle::Color.rgb(255, 0, 0) red_hex = Rustle::Color.hex('f00') blue = Rustle::Color.rgb(0, 0, 255) red_rgb.eql? red_hex # => true red_rgb.eql? blue # => false
@return [Boolean] true if the colors are equal, false if they are not.
# File lib/rustle/color.rb, line 66 def eql?(other) [:r, :g, :b].all? { |c| self.send(c) == other.send(c) } end
Serializes a color into a string of chars
. Note that each color is coerced into the range 0..254
, since our end-of-frame code is 255.
@return [String] a string representation of the color.
# File lib/rustle/color.rb, line 49 def serialize to_a.map { |c| self.class.fit_within_range(c, 0, 254).chr }.join end
@return [Array<Fixnum>] the Color's RGB values as an array with the
format +[r, g, b]+
# File lib/rustle/color.rb, line 40 def to_a [@r, @g, @b].map(&:floor) end
Converts the Color
object to an array of HSB values in the format [hue, saturation, brightness].
@return [Array<Fixnum>] the color as an HSB array
# File lib/rustle/color.rb, line 159 def to_hsb r = @r / 255.0 g = @g / 255.0 b = @b / 255.0 max = [r, g, b].max min = [r, g, b].min delta = max - min hue = 0.0 brightness = max saturation = max == 0 ? 0 : (max - min) / max if delta != 0 if r == max hue = (g - b) / delta else if g == max hue = 2 + (b - r) / delta else hue = 4 + (r - g) / delta end end hue *= 60 hue += 360 if hue < 0 end [hue, saturation, brightness] end
Creates an intermediate between the current Color
object and another Color
object. It does so by simple linear RGB transitioning, which seems to work just fine when working with RGB LED strips (even though, in most) cases, HSB transitioning would be better, it is not worth the extra processing time).
@param [Color] other the other Color
object @param [Float] amount the degree to which the color should be transitioned
+(0..1)+.
@return [Color] the new, partially transitioned Color
object
@example
red = Color.new(255, 0, 0) blue = Color.new(0, 0, 255) red.transition_to(blue, 0.5) # => <Color r=127, g=0, b=127>
# File lib/rustle/color.rb, line 204 def transition_to(other, amount) old_col = self.to_a new_col = other.to_a diff = old_col.each_with_index.map { |v, i| (new_col[i] - v) * amount } self.class.rgb *old_col.each_with_index.map { |v, i| v + diff[i] } end
Private Instance Methods
Forces `val` into the range 0..255
# File lib/rustle/color.rb, line 216 def normalize_rgb_param(value) self.class.fit_within_range(value, 0, 255) end