Module: Inker::Color::Tools

Included in:
Inker::Color
Defined in:
lib/inker/color/tools.rb

Overview

Tools module implements a set of methods useful for color parsing and for getting useful info about color.

Constant Summary collapse

HEX_REGEX =

Regular expression for HEX colors matching

/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/
RGB_REGEX =

Regular expression for RGB colors matching

/^rgb\((\d+,){2}\d+\)$/
RGBA_REGEX =

Regular expression for RGBA colors matching

/^rgba\((\d+,){3}\d+(.\d+)?\)$/
HSL_REGEX =

Regular expression for HSL colors matching

/^hsl\((\d+)(,\d+%|,\d+(.\d+)){2}\)$/
HSLA_REGEX =

Regular expression for HSLA colors matching

/^hsla\((\d+)(,\d+%|,\d+(.\d+)){2},\d+(.\d+)?\)$/

Instance Method Summary collapse

Instance Method Details

#brightness(red, green, blue) ⇒ Integer

Calculate the brightness of a color.

Parameters:

  • red (Integer)

    the value of red component [0-255]

  • green (Integer)

    the value of green component [0-255]

  • blue (Integer)

    the value of blue component [0-255]

Returns:

  • (Integer)

    a value between 0-255 which indicates the brightness of the color



28
29
30
# File 'lib/inker/color/tools.rb', line 28

def brightness(red, green, blue)
  Math.sqrt(0.299 * red**2 + 0.587 * green**2 + 0.114 * blue**2).round
end

#from_custom_string(custom_string, positions: [0, 29, 14, 30, 28, 31]) ⇒ Inker::Color

Use MD5 digest of the string to get hex values from specified positions (by default [0, 29, 14, 30, 28, 31]) in order to obtain a color in HEX format which represents the specified string.

Returns:

  • (Inker::Color)

    a Inker::Color object which represents the color associated to input string



244
245
246
247
# File 'lib/inker/color/tools.rb', line 244

def from_custom_string(custom_string, positions: [0, 29, 14, 30, 28, 31])
  digest = Digest::MD5.hexdigest(custom_string.to_s)
  Inker.color("##{positions.map{|p| digest[p]}.join}")
end

#from_hsl(hue, saturation, lightness) ⇒ Inker::Color

A helper for Inker::Color generation from HSL components.

Parameters:

  • hue (Integer)

    the value of HUE component [0-360]

  • saturation (Float)

    the value of saturation component [0.0-1.0]

  • lightness (Float)

    the value of lightness component [0.0-1.0]

Returns:

  • (Inker::Color)

    a Inker::Color generated from passed HSL values



218
219
220
# File 'lib/inker/color/tools.rb', line 218

def from_hsl(hue, saturation, lightness)
  Inker.color("hsl(#{hue}, #{saturation}, #{lightness})")
end

#from_hsla(hue, saturation, lightness, alpha) ⇒ Inker::Color

A helper for Inker::Color generation from HSLA components.

Parameters:

  • hue (Integer)

    the value of HUE component [0-360]

  • saturation (Float)

    the value of saturation component [0.0-1.0]

  • lightness (Float)

    the value of lightness component [0.0-1.0]

  • alpha (Float)

    the value of alpha component [0.0-1.1]

Returns:

  • (Inker::Color)

    a Inker::Color generated from passed HSLA values



231
232
233
# File 'lib/inker/color/tools.rb', line 231

def from_hsla(hue, saturation, lightness, alpha)
  Inker.color("hsla(#{hue}, #{saturation}, #{lightness}, #{alpha})")
end

#from_rgb(red, green, blue) ⇒ Inker::Color

A helper for Inker::Color generation from RGB components.

Parameters:

  • red (Integer)

    the value of red component [0-255]

  • green (Integer)

    the value of green component [0-255]

  • blue (Integer)

    the value of blue component [0-255]

Returns:

  • (Inker::Color)

    a Inker::Color generated from passed RGB values



193
194
195
# File 'lib/inker/color/tools.rb', line 193

def from_rgb(red, green, blue)
  Inker.color("rgb(#{red}, #{green}, #{blue})")
end

#from_rgba(red, green, blue, alpha) ⇒ Inker::Color

A helper for Inker::Color generation from RGBA components.

Parameters:

  • red (Integer)

    the value of red component [0-255]

  • green (Integer)

    the value of green component [0-255]

  • blue (Integer)

    the value of blue component [0-255]

  • alpha (Float)

    the value of alpha component [0.0-1.1]

Returns:

  • (Inker::Color)

    a Inker::Color generated from passed RGBA values



206
207
208
# File 'lib/inker/color/tools.rb', line 206

def from_rgba(red, green, blue, alpha)
  Inker.color("rgba(#{red}, #{green}, #{blue}, #{alpha})")
end

#hsl_to_rgb(hue, saturation, lightness) ⇒ Hash

Get RGB values from a color in HSL format.

Parameters:

  • hue (Integer)

    the value of HUE component [0-360]

  • saturation (Float)

    the saturation of the color [0.0-1.0]

  • lightness (Float)

    the lightness of the color [0.0-1.0]

Returns:

  • (Hash)

    a Hash which contains the values of RGB components



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/inker/color/tools.rb', line 93

def hsl_to_rgb(hue, saturation, lightness)
  result = nil
  if saturation == 0
    # There's no saturation, so it's a gray scale color, which
    # depends only on brightness
    brightness = (lightness * 255).round

    # All RGB components are equal to brightness
    result = {
      red:   brightness,
      green: brightness,
      blue:  brightness
    }
  else
    q = lightness < 0.5 ? lightness * (1 + saturation) : lightness + saturation - lightness * saturation
    p = 2 * lightness - q
    norm_hue = hue / 360.0

    result = {
      red:   (hue_to_rgb(p, q, norm_hue + 1.0/3.0) * 255).round,
      green: (hue_to_rgb(p, q, norm_hue) * 255).round,
      blue:  (hue_to_rgb(p, q, norm_hue - 1.0/3.0) * 255).round
    }
  end

  return result
end

#hue(red, green, blue) ⇒ Integer

Calculate the HUE value of a color from RGB components.

Parameters:

  • red (Integer)

    the value of red component [0-255]

  • green (Integer)

    the value of green component [0-255]

  • blue (Integer)

    the value of blue component [0-255]

Returns:

  • (Integer)

    a value in range 0-360 which indicates the HUE value of the color



72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/inker/color/tools.rb', line 72

def hue(red, green, blue)
  min, max = [red, green, blue].minmax

  numerator = (max - min).to_f
  return 0 if numerator == 0

  hue = (red == max)   ? (green - blue) / numerator :
        (green == max) ? 2 + (blue - red) / numerator :
                         4 + (red - green) / numerator
  hue = hue * 60
  return (hue < 0 ? hue + 360 : hue).round
end

#is_hex?(color_str) ⇒ Boolean

Returns a Boolean which indicates if color is in HEX format

Parameters:

  • color_str (String)

    a color string

Returns:

  • (Boolean)

    true when color is in HEX format



127
128
129
# File 'lib/inker/color/tools.rb', line 127

def is_hex?(color_str)
  !!(color_str.to_s.downcase.strip =~ HEX_REGEX)
end

#is_hsl?(color_str) ⇒ Boolean

Returns a Boolean which indicates if color is in HSL format

Parameters:

  • color_str (String)

    a color string

Returns:

  • (Boolean)

    true when color is in HSL format



157
158
159
# File 'lib/inker/color/tools.rb', line 157

def is_hsl?(color_str)
  !!(color_str.to_s.downcase.gsub(/\s+/, '') =~ HSL_REGEX)
end

#is_hsla?(color_str) ⇒ Boolean

Returns a Boolean which indicates if color is in HSLA format

Parameters:

  • color_str (String)

    a color string

Returns:

  • (Boolean)

    true when color is in HSLA format



167
168
169
# File 'lib/inker/color/tools.rb', line 167

def is_hsla?(color_str)
  !!(color_str.to_s.downcase.gsub(/\s+/, '') =~ HSLA_REGEX)
end

#is_rgb?(color_str) ⇒ Boolean

Returns a Boolean which indicates if color is in RGB format

Parameters:

  • color_str (String)

    a color string

Returns:

  • (Boolean)

    true when color is in RGB format



137
138
139
# File 'lib/inker/color/tools.rb', line 137

def is_rgb?(color_str)
  !!(color_str.to_s.downcase.gsub(/\s+/, '') =~ RGB_REGEX)
end

#is_rgba?(color_str) ⇒ Boolean

Returns a Boolean which indicates if color is in RGBA format

Parameters:

  • color_str (String)

    a color string

Returns:

  • (Boolean)

    true when color is in RGBA format



147
148
149
# File 'lib/inker/color/tools.rb', line 147

def is_rgba?(color_str)
  !!(color_str.to_s.downcase.gsub(/\s+/, '') =~ RGBA_REGEX)
end

#lightness(red, green, blue) ⇒ Float

Calculate the lightness of a color from RGB components.

Parameters:

  • red (Integer)

    the value of red component [0-255]

  • green (Integer)

    the value of green component [0-255]

  • blue (Integer)

    the value of blue component [0-255]

Returns:

  • (Float)

    a value in range 0.0-1.0 which indicates the ligthness of the color



40
41
42
43
44
# File 'lib/inker/color/tools.rb', line 40

def lightness(red, green, blue)
  min, max = [red, green, blue].minmax

  return (min + max) / (2.0 * 255)
end

#parse_color(color_str) ⇒ Hash

Parse a color string an return it's RGBA components as a hash.

Examples:

Inker::Color.parse_color("#FF005544") # returns {:red=>255, :green=>0, :blue=>85, :alpha=>0.4}

Parameters:

  • color_str (String)

    color string to parse

Returns:

  • (Hash)

    a hash which contains RGBA components of parsed color

Raises:

  • (ArgumentError)


257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/inker/color/tools.rb', line 257

def parse_color(color_str)
  # Normalize input string by stripping white spaces and converting
  # string to downcase
  input = color_str.to_s.strip.downcase

  # By default result is nil
  result = nil

  # Try to guess the format of color string and parse it by
  # using the apropriate algorithm
  if is_hex?(input)
    # Parse the string as HEX color
    result = parse_hex(input)
  elsif is_rgb?(input)
    # Parse the string as RGB color
    result = parse_rgb(input)
  elsif is_rgba?(input)
    # Parse the string as RGBA color
    result = parse_rgb(input, is_rgba: true)
  elsif is_hsl?(input)
    # Parse the string as HSL color
    result = parse_hsl(input)
  elsif is_hsla?(input)
    # Parse the string as HSLA color
    result = parse_hsl(input, is_hsla: true)
  else
    # Check if color is in "named color" format
    named_color = Inker.named_colors[input]
    if named_color
      # If a named color has been matched, use it's HEX value and
      # parse it as HEX color
      result = parse_hex(named_color)
    end
  end

  # If we didn't have any match, throw an ArgumentError error
  raise ArgumentError.new("Unknown color format: #{color_str.to_s.strip.inspect}") if result.nil?

  return result
end

#random(with_alpha: false) ⇒ Inker::Color

Generate a random Inker::Color.

Parameters:

  • with_alpha (Boolean) (defaults to: false)

    when true include alpha channel

Returns:



177
178
179
180
181
182
183
# File 'lib/inker/color/tools.rb', line 177

def random(with_alpha: false)
  prefix = with_alpha ? "rgba" : "rgb"
  values = (1..3).map{ (rand * 255).round }
  values << rand.round(2) if with_alpha

  Inker.color("#{prefix}(#{values.join(",")})")
end

#saturation(red, green, blue) ⇒ Float

Calculate the saturation of a color from RGB components.

Parameters:

  • red (Integer)

    the value of red component [0-255]

  • green (Integer)

    the value of green component [0-255]

  • blue (Integer)

    the value of blue component [0-255]

Returns:

  • (Float)

    a value in range 0.0-1.0 which indicates the saturation of the color



54
55
56
57
58
59
60
61
62
# File 'lib/inker/color/tools.rb', line 54

def saturation(red, green, blue)
  # return 0 for black and white colors
  return 0 if red == green and red == blue and (red == 0 or red == 255)

  lightness = lightness(red, green, blue)
  min, max = [red / 255.0, green / 255.0, blue / 255.0].minmax

  return lightness < 0.5 ? (max - min) / (max + min) : (max - min) / (2.0 - max - min)
end