Module: Colir::HSLRGB

Defined in:
lib/colir/hslrgb.rb

Overview

The module provides methods for RGB to HSL and HSL to RGB conversions. I just ported it from a C implementation.

See Also:

Since:

  • 0.0.1

Defined Under Namespace

Modules: HSL, RGB

Constant Summary collapse

RGB_ORDER_CODES =

The cached array of arrays, which contains order codes for the model from ‘::hsl_to_rgb`. The model is an array, where the needed for conversion values are calculated only once. The order codes allows to refer to the calculated model array values via indices. Hopefully, it saves some CPU cycles.

Since:

  • 0.0.1

[
  [0, 1, 2], # [0, 60)
  [1, 0, 2], # [60, 120)
  [2, 0, 1], # [120, 180)
  [2, 1, 0], # [180, 240)
  [1, 2, 0], # [240, 300)
  [0, 2, 1], # [300, 360)
]
RGB_DEFAULT_CODE =

The code returned for 0 or 360 degrees.

Since:

  • 0.0.1

[2, 2, 2]

Class Method Summary collapse

Class Method Details

.hsl_to_rgb(hue, saturation, lightness) ⇒ Array<Integer>

Converts an HSL colour to its RGB counterpart. The algorithm is correct, but sometimes you’ll notice little laxity (because of rounding problems).

Examples:

HSLRGB.hsl_to_rgb(180, 1, 0.55) #=> [26, 255, 255]

Parameters:

  • hue (Integer)

    Possible values: 0..360

  • saturation (BigDecimal)

    Possible values: 0..1

  • lightness (BigDecimal)

    Possible values: 0..1

Returns:

  • (Array<Integer>)

    the converted RGB representation of a HSL colour

Raises:

  • (RangeError)

    if one of the parameters doesn’t lie within the accepted range

See Also:

  • rgb_to_hsl

Since:

  • 0.0.1



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/colir/hslrgb.rb', line 170

def self.hsl_to_rgb(hue, saturation, lightness)
  validate_hsl!([hue, saturation, lightness])

  chroma = (1 - (2 * lightness - 1).abs) * saturation
  a = 1 * (lightness - 0.5 * chroma)
  b = chroma * (1 - ((hue / BigDecimal('60.0')).modulo(2) - 1).abs)

  degrees = Array.new(7) { |idx| idx * 60 }.each
  model = [chroma+a, a+b, a]

  RGB_ORDER_CODES.find(->{RGB_DEFAULT_CODE}) {
    (degrees.next...degrees.peek) === hue
  }.map { |id|
    (model[id] * 255).round
  }
end

.rgb_to_hsl(red, green, blue) ⇒ Array<Integer,BigDecimal>

Converts an RGB colour to its HSL counterpart.

Examples:

rgb = 'c0c0c0'.scan(/../).map { |b| b.to_i(16) } #=> [192, 192, 192]
HSLRGB.rgb_to_hsl(192, 192, 192) #=> [0, 0.0, 0.75]

Parameters:

  • red (Integer)

    Possible values: 0..255

  • green (Integer)

    Possible values: 0..255

  • blue (Integer)

    Possible values: 0..255

Returns:

  • (Array<Integer,BigDecimal>)

    the converted HSL representation of an RGB colour

Raises:

  • (RangeError)

    if one of the parameters doesn’t lie within the accepted range

See Also:

Since:

  • 0.0.1



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/colir/hslrgb.rb', line 118

def self.rgb_to_hsl(red, green, blue)
  validate_rgb!([red, green, blue])

  red, green, blue = [red, green, blue].map { |b| b / BigDecimal('255.0') }
  min, max = [red, green, blue].minmax
  chroma = max - min

  lightness = (min + max) * BigDecimal('0.5')

  hue = 0
  saturation = BigDecimal('0.0')

  if chroma.nonzero?
    hue = case max
          when red   then (green - blue) / chroma % 6
          when green then (blue - red) / chroma + 2
          else            (red - green) / chroma + 4
          end
    hue = (hue * 60).round
    saturation = chroma / (1 - (2 * lightness - 1).abs)
  end

  [hue, saturation, lightness]
end