class Milight::Colour

Constants

HUE_OFFSET
VALID_HEX_REGEX

Attributes

blue[R]
green[R]
hue[R]
luminosity[R]
red[R]
saturation[R]

Public Class Methods

new(value) click to toggle source
# File lib/milight/colour.rb, line 11
def initialize(value)
  case value
  when String then from_hex(value)
  when Array  then from_rgb(*value)
  else
    raise invalid_colour_error
  end
end

Public Instance Methods

greyscale?() click to toggle source
# File lib/milight/colour.rb, line 37
def greyscale?
  @red == @green && @red == @blue
end
to_hsl() click to toggle source
# File lib/milight/colour.rb, line 20
def to_hsl
  [@hue, @saturation, @luminosity]
end
to_milight_brightness() click to toggle source
# File lib/milight/colour.rb, line 32
def to_milight_brightness
  percent = [brightness_for_saturation, 100].min
  Milight::Brightness.new(percent).to_milight_brightness
end
to_milight_colour() click to toggle source
# File lib/milight/colour.rb, line 28
def to_milight_colour
  ((256 + HUE_OFFSET - (hue / 360.0 * 255.0)) % 256).to_i
end
to_rgb() click to toggle source
# File lib/milight/colour.rb, line 24
def to_rgb
  [@red, @green, @blue]
end

Private Instance Methods

brightness_for_saturation() click to toggle source
# File lib/milight/colour.rb, line 56
def brightness_for_saturation
  r, g, b = *to_rgb
  (Math.sqrt(r * r + g * g + b * b) / 2.55).round
end
delta(r, g, b) click to toggle source
# File lib/milight/colour.rb, line 98
def delta(r, g, b)
  [r, g, b].minmax.reverse.inject(:-)
end
from_hex(hex) click to toggle source
# File lib/milight/colour.rb, line 50
def from_hex(hex)
  raise invalid_hex_colour_error unless valid_hex_colour? hex
  r, g, b = hex_to_rgb(hex)
  from_rgb(r, g, b)
end
from_rgb(r, g, b) click to toggle source
# File lib/milight/colour.rb, line 43
def from_rgb(r, g, b)
  @red = r
  @green = g
  @blue = b
  @hue, @saturation, @luminosity = rgb_to_hsl(r, g, b)
end
hex_to_rgb(hex) click to toggle source
# File lib/milight/colour.rb, line 61
def hex_to_rgb(hex)
  hex.sub('#', '')
    .chars
    .each_slice(hex.length / 3)
    .map { |val| val.length == 1 ? val * 2 : val }
    .map(&:join)
    .map { |h| h.to_i(16) }
end
invalid_colour_error() click to toggle source
# File lib/milight/colour.rb, line 106
def invalid_colour_error
  ArgumentError.new(
    "Colours must be given as with a hex colour string ( #{self.class}.new('#11A401') )" \
    " or a RGB array ( #{self.class}.new([r,g,b]) )"
  )
end
invalid_hex_colour_error() click to toggle source
# File lib/milight/colour.rb, line 113
def invalid_hex_colour_error
  ArgumentError.new('Hex colours codes must be 3 or 6 0-9 or a-f characters')
end
rgb_to_hsl(r1, g1, b1) click to toggle source
# File lib/milight/colour.rb, line 70
def rgb_to_hsl(r1, g1, b1)
  r, g, b = [r1, g1, b1].map { |c| c / 255.0 }
  h = rgb_to_hue(r, g, b)
  l = rgb_to_luminosity(r, g, b)
  s = rgbl_to_saturation(r, g, b, l)
  [h, s, l]
end
rgb_to_hue(r, g, b) click to toggle source
# File lib/milight/colour.rb, line 78
def rgb_to_hue(r, g, b)
  return 0 if greyscale?
  delta = delta(r, g, b)
  offset = case [r, g, b].max
           when r then ((g - b) / delta)
           when g then ((b - r) / delta) + 2
           when b then ((r - g) / delta) + 4
           end
  60 * offset % 360
end
rgb_to_luminosity(r, g, b) click to toggle source
# File lib/milight/colour.rb, line 89
def rgb_to_luminosity(r, g, b)
  [r, g, b].minmax.inject(:+) / 2
end
rgbl_to_saturation(r, g, b, l) click to toggle source
# File lib/milight/colour.rb, line 93
def rgbl_to_saturation(r, g, b, l)
  return 0 if greyscale?
  (delta(r, g, b) / 1 - (2 * l - 1)).abs
end
valid_hex_colour?(value) click to toggle source
# File lib/milight/colour.rb, line 102
def valid_hex_colour?(value)
  value =~ VALID_HEX_REGEX
end