class Color::HSL
An HSL
colour object. Internally, the hue (h
), saturation (s
), and luminosity/lightness (l
) values are dealt with as fractional values in the range 0..1.
Public Class Methods
Source
# File lib/color/hsl.rb, line 10 def from_fraction(h = 0.0, s = 0.0, l = 0.0, &block) new(h, s, l, 1.0, 1.0, &block) end
Creates an HSL
colour object from fractional values 0..1.
Source
# File lib/color/hsl.rb, line 22 def initialize(h = 0, s = 0, l = 0, radix1 = 360.0, radix2 = 100.0, &block) # :yields self: @h = Color.normalize(h / radix1) @s = Color.normalize(s / radix2) @l = Color.normalize(l / radix2) block.call if block end
Creates an HSL
colour object from the standard values of degrees and percentages (e.g., 145 deg, 30%, 50%).
Public Instance Methods
Source
# File lib/color/hsl.rb, line 97 def brightness @l end
Returns the luminosity (l
) of the colour.
Source
Source
# File lib/color/hsl.rb, line 50 def css_hsl "hsl(%3.2f, %3.2f%%, %3.2f%%)" % [ hue, saturation, luminosity ] end
Present the colour as an HSL
HTML/CSS colour string (e.g., “hsl(180, 25%, 35%)”).
Source
# File lib/color/hsl.rb, line 56 def css_hsla "hsla(%3.2f, %3.2f%%, %3.2f%%, %3.2f)" % [ hue, saturation, luminosity, 1 ] end
Present the colour as an HSLA (with alpha) HTML/CSS colour string (e.g., “hsla(180, 25%, 35%, 1)”).
Source
# File lib/color/hsl.rb, line 37 def css_rgb to_rgb.css_rgb end
Present the colour as an RGB HTML/CSS colour string (e.g., “rgb(0%, 50%, 100%)”). Note that this will perform a to_rgb
operation using the default conversion formula.
Source
# File lib/color/hsl.rb, line 44 def css_rgba(alpha = 1) to_rgb.css_rgba(alpha) end
Present the colour as an RGBA (with alpha) HTML/CSS colour string (e.g., “rgb(0%, 50%, 100%, 1)”). Note that this will perform a to_rgb
operation using the default conversion formula.
Source
# File lib/color/hsl.rb, line 110 def h @h end
Returns the hue of the colour in the range 0.0 .. 1.0.
Source
# File lib/color/hsl.rb, line 124 def h=(hh) @h = Color.normalize(hh) end
Sets the hue of the colour in the range 0.0 .. 1.0.
Source
# File lib/color/hsl.rb, line 30 def html to_rgb.html end
Present the colour as an HTML/CSS colour string.
Source
# File lib/color/hsl.rb, line 106 def hue @h * 360.0 end
Returns the hue of the colour in degrees.
Source
# File lib/color/hsl.rb, line 115 def hue=(hh) hh = hh / 360.0 hh += 1.0 if hh < 0.0 hh -= 1.0 if hh > 1.0 @h = Color.normalize(hh) end
Sets the hue of the colour in degrees. Colour is perceived as a wheel, so values should be set properly even with negative degree values.
Source
# File lib/color/hsl.rb, line 167 def inspect "HSL [%.2f deg, %.2f%%, %.2f%%]" % [ hue, saturation, luminosity ] end
Source
# File lib/color/hsl.rb, line 150 def l @l end
Returns the luminosity of the colour in the range 0.0 .. 1.0.
Source
# File lib/color/hsl.rb, line 159 def l=(ll) @l = Color.normalize(ll) end
Sets the luminosity of the colour in the ragne 0.0 .. 1.0.
Source
# File lib/color/hsl.rb, line 145 def luminosity @l * 100.0 end
Returns the percentage of luminosity of the colour.
Source
# File lib/color/hsl.rb, line 154 def luminosity=(ll) @l = Color.normalize(ll / 100.0) end
Sets the percentage of luminosity of the colour.
Source
# File lib/color/hsl.rb, line 175 def mix_with(color, mix_percent = 0.5) v = to_a.zip(coerce(color).to_a).map { |(x, y)| ((y - x) * mix_percent) + x } self.class.from_fraction(*v) end
Mix the mask colour (which will be converted to an HSL
colour) with the current colour at the stated mix percentage as a decimal value.
- NOTE
-
This differs from
Color::RGB#mix_with
.
Source
# File lib/color/hsl.rb, line 132 def s @s end
Returns the saturation of the colour in the range 0.0 .. 1.0.
Source
# File lib/color/hsl.rb, line 140 def s=(ss) @s = Color.normalize(ss) end
Sets the saturation of the colour in the ragne 0.0 .. 1.0.
Source
# File lib/color/hsl.rb, line 128 def saturation @s * 100.0 end
Returns the percentage of saturation of the colour.
Source
# File lib/color/hsl.rb, line 136 def saturation=(ss) @s = Color.normalize(ss / 100.0) end
Sets the percentage of saturation of the colour.
Source
# File lib/color/hsl.rb, line 92 def to_cmyk to_rgb.to_cmyk end
Converts to RGB then CMYK.
Source
# File lib/color/hsl.rb, line 100 def to_greyscale Color::GrayScale.from_fraction(@l) end
Source
# File lib/color/hsl.rb, line 72 def to_rgb(*) if Color.near_zero_or_less?(l) Color::RGB::Black elsif Color.near_one_or_more?(l) Color::RGB::White elsif Color.near_zero?(s) Color::RGB.from_grayscale_fraction(l) else # Only needed for Ruby 1.8. For Ruby 1.9+, we can do: # Color::RGB.new(*compute_fvd_rgb, 1.0) Color::RGB.new(*(compute_fvd_rgb + [ 1.0 ])) end end
Converting from HSL
to RGB. As with all colour conversions, this is approximate at best. The code here is adapted from fvd and van Dam, originally found at [1] (implemented similarly at [2]).
This simplifies the calculations with the following assumptions:
-
Luminance values <= 0 always translate to Color::RGB::Black.
-
Luminance values >= 1 always translate to Color::RGB::White.
-
Saturation values <= 0 always translate to a shade of gray using luminance as a percentage of gray.
Source
# File lib/color/hsl.rb, line 87 def to_yiq to_rgb.to_yiq end
Converts to RGB then YIQ.
Private Instance Methods
Source
# File lib/color/hsl.rb, line 193 def compute_fvd_rgb t1, t2 = fvd_mix_sat_lum [ h + (1 / 3.0), h, h - (1 / 3.0) ].map { |v| hue_to_rgb(rotate_hue(v), t1, t2) } end
This algorithm calculates based on a mixture of the saturation and luminance, and then takes the RGB values from the hue + 1/3, hue, and hue - 1/3 positions in a circular representation of colour divided into four parts (confusing, I know, but it’s the way that it works). See hue_to_rgb
for more information.
Source
# File lib/color/hsl.rb, line 202 def fvd_mix_sat_lum t = if Color.near_zero_or_less?(l - 0.5) l * (1.0 + s.to_f) else l + s - (l * s.to_f) end [ 2.0 * l - t, t ] end
Mix saturation and luminance for use in hue_to_rgb. The base value is different depending on whether luminance is <= 50% or > 50%.
Source
# File lib/color/hsl.rb, line 228 def hue_to_rgb(h, t1, t2) if Color.near_zero_or_less?((6.0 * h) - 1.0) t1 + ((t2 - t1) * h * 6.0) elsif Color.near_zero_or_less?((2.0 * h) - 1.0) t2 elsif Color.near_zero_or_less?((3.0 * h) - 2.0) t1 + (t2 - t1) * ((2 / 3.0) - h) * 6.0 else t1 end end
We calculate the interaction of the saturation/luminance mix (calculated earlier) based on the position of the hue in the circular colour space divided into quadrants. Our hue range is [0, 1), not [0, 360º).
-
The first quadrant covers the first 60º [0, 60º].
-
The second quadrant covers the next 120º (60º, 180º].
-
The third quadrant covers the next 60º (180º, 240º].
-
The fourth quadrant covers the final 120º (240º, 360º).
Source
# File lib/color/hsl.rb, line 214 def rotate_hue(h) h += 1.0 if Color.near_zero_or_less?(h) h -= 1.0 if Color.near_one_or_more?(h) h end
In HSL
, hues are referenced as degrees in a colour circle. The flow itself is endless; therefore, we can rotate around. The only thing our implementation restricts is that you should not be > 1.0.