Skip to content

Instantly share code, notes, and snippets.

@metaskills
Created February 28, 2012 14:33
Show Gist options
  • Save metaskills/1932866 to your computer and use it in GitHub Desktop.
Save metaskills/1932866 to your computer and use it in GitHub Desktop.
Sass Color Extensions For HSV
class Sass::Script::Color < Sass::Script::Literal
class << self
def new_hsv_float(hue, saturation, value)
zero_to_threesixty = lambda { |x| x < 0 ? 0 : (x > 360 ? 360 : x) }
zero_to_onehundred = lambda { |x| x < 0 ? 0 : (x > 100 ? 100 : x) }
hue = zero_to_threesixty.call((hue * 360.0).round)
saturation = zero_to_onehundred.call((saturation * 100.0).round)
value = zero_to_onehundred.call((value * 100.0).round)
new_hsv(hue, saturation, value)
end
def new_hsv(hue, saturation, value)
new(hsv_to_rgb(hue, saturation, value))
end
def rgb_to_hsv(red, green, blue)
r = red / 255.0
g = green / 255.0
b = blue / 255.0
max = [r, g, b].max
min = [r, g, b].min
delta = max - min
v = max * 100
if (max != 0.0)
s = delta / max *100
else
s = 0.0
end
if (s == 0.0)
h = 0.0
else
if (r == max)
h = (g - b) / delta
elsif (g == max)
h = 2 + (b - r) / delta
elsif (b == max)
h = 4 + (r - g) / delta
end
h *= 60.0
if (h < 0)
h += 360.0
end
end
[h.round, s.round, v.round]
end
def hsv_to_rgb(hue, saturation, value)
max = lambda { |m,v| m > v ? m : v }
min = lambda { |m,v| m < v ? m : v }
h = max.call(0, min.call(360, hue)).to_f
s = max.call(0, min.call(100, saturation)).to_f
v = max.call(0, min.call(100, value)).to_f
s = s / 100.0
v = v / 100.0
if s == 0.0
r = g = b = v
return [(r * 255).round, (g * 255).round, (b * 255).round]
end
h = h / 60.0
i = h.floor.to_f
f = h - i
p = v * (1 - s)
q = v * (1 - s * f)
t = v * (1 - s * (1 - f))
case i
when 0.0
r, g, b = v, t, p
when 1.0
r, g, b = q, v, p
when 2.0
r, g, b = p, v, t
when 3.0
r, g, b = p, q, v
when 4.0
r, g, b = t, p, v
else
r, g, b = v, p, q
end
[(r * 255).round, (g * 255).round, (b * 255).round];
end
def multiply_hsv(color, hd, sd, vd)
h = color.hsv_h
s = color.hsv_s
v = color.hsv_v
h = h * hd
s = s * sd
v = v * vd
new_hsv(h, s, v)
end
end
def hsv_h
rgb_to_hsv!
@attrs[:hsv_h]
end
def hsv_s
rgb_to_hsv!
@attrs[:hsv_s]
end
def hsv_v
rgb_to_hsv!
@attrs[:hsv_v]
end
private
def rgb_to_hsv!
return if @attrs[:hsv_h] && @attrs[:hsv_s] && @attrs[:hsv_v]
@attrs[:hsv_h], @attrs[:hsv_s], @attrs[:hsv_v] = self.class.rgb_to_hsv(red, green, blue)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment