class Color::RGB

An RGB colour object.

Constants

PDF_FORMAT_STR

The format of a DeviceRGB colour for PDF. In color-tools 2.0 this will be removed from this package and added back as a modification by the PDF::Writer package.

Public Class Methods

by_css(name_or_hex, &block) click to toggle source

Return a colour as identified by the colour name, or by hex.

# File lib/color/rgb.rb, line 648
def by_css(name_or_hex, &block)
  by_name(name_or_hex) { by_hex(name_or_hex, &block) }
end
by_hex(hex, &block) click to toggle source

Find or create a colour by an HTML hex code. This differs from the from_html method in that if the colour code matches a named colour, the existing colour will be returned.

Color::RGB.by_hex('ff0000').name # => 'red'
Color::RGB.by_hex('ff0001').name # => nil

If a block is provided, the value that is returned by the block will be returned instead of the exception caused by an error in providing a correct hex format.

# File lib/color/rgb.rb, line 632
def by_hex(hex, &block)
  __by_hex.fetch(html_hexify(hex)) { from_html(hex) }
rescue
  if block
    block.call
  else
    raise
  end
end
by_name(name, &block) click to toggle source

Return a colour as identified by the colour name.

# File lib/color/rgb.rb, line 643
def by_name(name, &block)
  __by_name.fetch(name.to_s.downcase, &block)
end
extract_colors(text, mode = :both) click to toggle source

Extract named or hex colours from the provided text.

# File lib/color/rgb.rb, line 653
def extract_colors(text, mode = :both)
  text  = text.downcase
  regex = case mode
          when :name
            Regexp.union(__by_name.keys)
          when :hex
            Regexp.union(__by_hex.keys)
          when :both
            Regexp.union(__by_hex.keys + __by_name.keys)
          end

  text.scan(regex).map { |match|
    case mode
    when :name
      by_name(match)
    when :hex
      by_hex(match)
    when :both
      by_css(match)
    end
  }
end
from_fraction(r = 0.0, g = 0.0, b = 0.0, &block) click to toggle source

Creates an RGB colour object from fractional values 0..1.

Color::RGB.from_fraction(.3, .2, .1)
# File lib/color/rgb.rb, line 592
def from_fraction(r = 0.0, g = 0.0, b = 0.0, &block)
  new(r, g, b, 1.0, &block)
end
from_grayscale_fraction(l = 0.0, &block) click to toggle source

Creates an RGB colour object from a grayscale fractional value 0..1.

# File lib/color/rgb.rb, line 597
def from_grayscale_fraction(l = 0.0, &block)
  new(l, l, l, 1.0, &block)
end
Also aliased as: from_greyscale_fraction
from_greyscale_fraction(l = 0.0, &block)
from_html(html_colour, &block) click to toggle source

Creates an RGB colour object from an HTML colour descriptor (e.g., "fed" or "#cabbed;".

Color::RGB.from_html("fed")
Color::RGB.from_html("#fed")
Color::RGB.from_html("#cabbed")
Color::RGB.from_html("cabbed")
# File lib/color/rgb.rb, line 609
def from_html(html_colour, &block)
  # When we can move to 1.9+ only, this will be \h
  h = html_colour.scan(/[0-9a-f]/i)
  case h.size
  when 3
    new(*h.map { |v| (v * 2).to_i(16) }, &block)
  when 6
    new(*h.each_slice(2).map { |v| v.join.to_i(16) }, &block)
  else
    raise ArgumentError, "Not a supported HTML colour type."
  end
end
from_percentage(r = 0, g = 0, b = 0, &block) click to toggle source

Creates an RGB colour object from percentages 0..100.

Color::RGB.from_percentage(10, 20, 30)
# File lib/color/rgb.rb, line 585
def from_percentage(r = 0, g = 0, b = 0, &block)
  new(r, g, b, 100.0, &block)
end
new(r = 0, g = 0, b = 0, radix = 255.0, &block) click to toggle source

Creates an RGB colour object from the standard range 0..255.

Color::RGB.new(32, 64, 128)
Color::RGB.new(0x20, 0x40, 0x80)
# File lib/color/rgb.rb, line 19
def initialize(r = 0, g = 0, b = 0, radix = 255.0, &block) # :yields self:
  @r, @g, @b = [ r, g, b ].map { |v| Color.normalize(v / radix) }
  block.call(self) if block
end

Private Class Methods

__by_hex() click to toggle source
# File lib/color/rgb.rb, line 694
def __by_hex
  @__by_hex ||= {}
end
__by_name() click to toggle source
# File lib/color/rgb.rb, line 698
def __by_name
  @__by_name ||= {}
end
__named_color(mod, rgb, *names) click to toggle source
# File lib/color/rgb.rb, line 680
def __named_color(mod, rgb, *names)
  used = names - mod.constants.map(&:to_sym)
  if used.length < names.length
    raise ArgumentError, "#{names.join(', ')} already defined in #{mod}"
  end

  names.each { |n| mod.const_set(n, rgb) }

  rgb.names = names
  rgb.names.each { |n| __by_name[n] = rgb }
  __by_hex[rgb.hex] = rgb
  rgb.freeze
end
html_hexify(hex) click to toggle source
# File lib/color/rgb.rb, line 702
def html_hexify(hex)
  # When we can move to 1.9+ only, this will be \h
  h = hex.to_s.downcase.scan(/[0-9a-f]/)
  case h.size
  when 3
    h.map { |v| (v * 2) }.join
  when 6
    h.join
  else
    raise ArgumentError, "Not a supported HTML colour type."
  end
end
metallic(rgb, *names) click to toggle source
# File lib/color/rgb/metallic.rb, line 9
def metallic(rgb, *names)
  __named_color(Metallic, new(*rgb), *names)
end
named(rgb, *names) click to toggle source
# File lib/color/rgb/colors.rb, line 4
def named(rgb, *names)
  __named_color(self, new(*rgb), *names)
end

Public Instance Methods

+(other) click to toggle source

Adds another colour to the current colour. The other colour will be converted to RGB before addition. This conversion depends upon a to_rgb method on the other colour.

The addition is done using the RGB Accessor methods to ensure a valid colour in the result.

# File lib/color/rgb.rb, line 532
def +(other)
  self.class.from_fraction(r + other.r, g + other.g, b + other.b)
end
-(other) click to toggle source

Subtracts another colour to the current colour. The other colour will be converted to RGB before subtraction. This conversion depends upon a to_rgb method on the other colour.

The subtraction is done using the RGB Accessor methods to ensure a valid colour in the result.

# File lib/color/rgb.rb, line 542
def -(other)
  self + (-other)
end
-@() click to toggle source

Numerically negate the color. This results in a color that is only usable for subtraction.

# File lib/color/rgb.rb, line 563
def -@
  rgb = self.dup
  rgb.instance_variable_set(:@r, -rgb.r)
  rgb.instance_variable_set(:@g, -rgb.g)
  rgb.instance_variable_set(:@b, -rgb.b)
  rgb
end
adjust_brightness(percent) click to toggle source

Returns a new colour with the brightness adjusted by the specified percentage. Negative percentages will darken the colour; positive percentages will brighten the colour.

Color::RGB::DarkBlue.adjust_brightness(10)
Color::RGB::DarkBlue.adjust_brightness(-10)
# File lib/color/rgb.rb, line 301
def adjust_brightness(percent)
  percent = normalize_percent(percent)
  hsl      = to_hsl
  hsl.l   *= percent
  hsl.to_rgb
end
adjust_hue(percent) click to toggle source

Returns a new colour with the hue adjusted by the specified percentage. Negative percentages will reduce the hue; positive percentages will increase the hue.

Color::RGB::DarkBlue.adjust_hue(10)
Color::RGB::DarkBlue.adjust_hue(-10)
# File lib/color/rgb.rb, line 327
def adjust_hue(percent)
  percent = normalize_percent(percent)
  hsl      = to_hsl
  hsl.h   *= percent
  hsl.to_rgb
end
adjust_saturation(percent) click to toggle source

Returns a new colour with the saturation adjusted by the specified percentage. Negative percentages will reduce the saturation; positive percentages will increase the saturation.

Color::RGB::DarkBlue.adjust_saturation(10)
Color::RGB::DarkBlue.adjust_saturation(-10)
# File lib/color/rgb.rb, line 314
def adjust_saturation(percent)
  percent = normalize_percent(percent)
  hsl      = to_hsl
  hsl.s   *= percent
  hsl.to_rgb
end
b() click to toggle source

Returns the blue component of the colour as a fraction in the range 0.0 .. 1.0.

# File lib/color/rgb.rb, line 509
def b
  @b
end
b=(bb) click to toggle source

Sets the blue component of the colour as a fraction in the range 0.0 .. 1.0.

# File lib/color/rgb.rb, line 522
def b=(bb)
  @b = Color.normalize(bb)
end
blue() click to toggle source

Returns the blue component of the colour in the normal 0 .. 255 range.

# File lib/color/rgb.rb, line 500
def blue
  @b * 255.0
end
blue=(bb) click to toggle source

Sets the blue component of the colour in the normal 0 .. 255 range.

# File lib/color/rgb.rb, line 513
def blue=(bb)
  @b = Color.normalize(bb / 255.0)
end
blue_p() click to toggle source

Returns the blue component of the colour as a percentage.

# File lib/color/rgb.rb, line 504
def blue_p
  @b * 100.0
end
blue_p=(bb) click to toggle source

Sets the blue component of the colour as a percentage.

# File lib/color/rgb.rb, line 517
def blue_p=(bb)
  @b = Color.normalize(bb / 100.0)
end
brightness() click to toggle source

Returns the brightness value for a colour, a number between 0..1. Based on the Y value of YIQ encoding, representing luminosity, or perceived brightness.

This may be modified in a future version of color-tools to use the luminosity value of HSL.

# File lib/color/rgb.rb, line 286
def brightness
  to_yiq.y
end
closest_match(color_list, threshold_distance = 1000.0) click to toggle source

Calculates and returns the closest match to this colour from a list of provided colours. Returns nil if color_list is empty or if there is no colour within the threshold_distance.

threshold_distance is used to determine the minimum colour distance permitted. Uses the CIE Delta E 1994 algorithm (CIE94) to find near matches based on perceived visual colour. The default value (1000.0) is an arbitrarily large number. The values :jnd and :just_noticeable may be passed as the threshold_distance to use the value 2.3.

# File lib/color/rgb.rb, line 347
def closest_match(color_list, threshold_distance = 1000.0)
  color_list = [ color_list ].flatten(1)
  return nil if color_list.empty?

  threshold_distance = case threshold_distance
                       when :jnd, :just_noticeable
                         2.3
                       else
                         threshold_distance.to_f
                       end
  lab = to_lab
  closest_distance = threshold_distance
  best_match = nil

  color_list.each do |c|
    distance = delta_e94(lab, c.to_lab)
    if (distance < closest_distance)
      closest_distance = distance
      best_match = c
    end
  end
  best_match
end
coerce(other) click to toggle source

Coerces the other Color object into RGB.

# File lib/color/rgb.rb, line 11
def coerce(other)
  other.to_rgb
end
contrast(other) click to toggle source

Outputs how much contrast this color has with another RGB color. Computes the same regardless of which one is considered foreground. If the other color does not have a to_rgb method, this will throw an exception. Anything over about 0.22 should have a high likelihood of being legible, but the larger the difference, the more contrast. Otherwise, to be safe go with something > 0.3

# File lib/color/rgb/contrast.rb, line 9
def contrast(other)
  other = coerce(other)

  # The following numbers have been set with some care.
  ((diff_brightness(other) * 0.65) +
   (diff_hue(other)        * 0.20) +
   (diff_luminosity(other) * 0.15))
end
css_hsl() click to toggle source

Present the colour as an HSL HTML/CSS colour string (e.g., “hsl(180, 25%, 35%)”). Note that this will perform a to_hsl operation using the default conversion formula.

# File lib/color/rgb.rb, line 77
def css_hsl
  to_hsl.css_hsl
end
css_hsla() click to toggle source

Present the colour as an HSLA (with alpha) HTML/CSS colour string (e.g., “hsla(180, 25%, 35%, 1)”). Note that this will perform a to_hsl operation using the default conversion formula.

# File lib/color/rgb.rb, line 84
def css_hsla
  to_hsl.css_hsla
end
css_rgb() click to toggle source

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.

# File lib/color/rgb.rb, line 58
def css_rgb
  "rgb(%3.2f%%, %3.2f%%, %3.2f%%)" % [ red_p, green_p, blue_p ]
end
css_rgba(alpha = 1) click to toggle source

Present the colour as an RGBA (with an optional alpha that defaults to 1) 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.

Color::RGB.by_hex('ff0000').css_rgba
=> 'rgba(100.00%, 0.00%, 0.00%, 1.00)'
Color::RGB.by_hex('ff0000').css_rgba(0.2)
=> 'rgba(100.00%, 0.00%, 0.00%, 0.20)'
# File lib/color/rgb.rb, line 70
def css_rgba(alpha = 1)
  "rgba(%3.2f%%, %3.2f%%, %3.2f%%, %3.2f)" % [ red_p, green_p, blue_p, alpha ]
end
darken_by(percent) click to toggle source

Mix the RGB hue with Black so that the RGB hue is the specified percentage of the resulting colour. Strictly speaking, this isn’t a darken_by operation.

# File lib/color/rgb.rb, line 263
def darken_by(percent)
  mix_with(Black, percent)
end
delta_e94(color_1, color_2, weighting_type = :graphic_arts) click to toggle source

The Delta E (CIE94) algorithm en.wikipedia.org/wiki/Color_difference#CIE94

There is a newer version, CIEDE2000, that uses slightly more complicated math, but addresses “the perceptual uniformity issue” left lingering by the CIE94 algorithm. color_1 and color_2 are both L*a*b* hashes, rendered by to_lab.

Since our source is treated as sRGB, we use the “graphic arts” presets for k_L, k_1, and k_2

The calculations go through LCH(ab). (?)

See also www.brucelindbloom.com/index.html?Eqn_DeltaE_CIE94.html

NOTE: This should be moved to Color::Lab.

# File lib/color/rgb.rb, line 387
def delta_e94(color_1, color_2, weighting_type = :graphic_arts)
  case weighting_type
  when :graphic_arts
    k_1 = 0.045
    k_2 = 0.015
    k_L = 1
  when :textiles
    k_1 = 0.048
    k_2 = 0.014
    k_L = 2
  else
    raise ArgumentError, "Unsupported weighting type #{weighting_type}."
  end

  # delta_E = Math.sqrt(
  #   ((delta_L / (k_L * s_L)) ** 2) +
  #   ((delta_C / (k_C * s_C)) ** 2) +
  #   ((delta_H / (k_H * s_H)) ** 2)
  # )
  #
  # Under some circumstances in real computers, delta_H could be an
  # imaginary number (it's a square root value), so we're going to treat
  # this as:
  #
  # delta_E = Math.sqrt(
  #   ((delta_L / (k_L * s_L)) ** 2) +
  #   ((delta_C / (k_C * s_C)) ** 2) +
  #   (delta_H2 / ((k_H * s_H) ** 2)))
  # )
  #
  # And not perform the square root when calculating delta_H2.

  k_C = k_H = 1

  l_1, a_1, b_1 = color_1.values_at(:L, :a, :b)
  l_2, a_2, b_2 = color_2.values_at(:L, :a, :b)

  delta_a = a_1 - a_2
  delta_b = b_1 - b_2

  c_1 = Math.sqrt((a_1 ** 2) + (b_1 ** 2))
  c_2 = Math.sqrt((a_2 ** 2) + (b_2 ** 2))

  delta_L = color_1[:L] - color_2[:L]
  delta_C = c_1 - c_2

  delta_H2 = (delta_a ** 2) + (delta_b ** 2) - (delta_C ** 2)

  s_L = 1
  s_C = 1 + k_1 * c_1
  s_H = 1 + k_2 * c_1

  composite_L = (delta_L / (k_L * s_L)) ** 2
  composite_C = (delta_C / (k_C * s_C)) ** 2
  composite_H = delta_H2 / ((k_H * s_H) ** 2)
  Math.sqrt(composite_L + composite_C + composite_H)
end
g() click to toggle source

Returns the green component of the colour as a fraction in the range 0.0 .. 1.0.

# File lib/color/rgb.rb, line 482
def g
  @g
end
g=(gg) click to toggle source

Sets the green component of the colour as a fraction in the range 0.0 .. 1.0.

# File lib/color/rgb.rb, line 495
def g=(gg)
  @g = Color.normalize(gg)
end
green() click to toggle source

Returns the green component of the colour in the normal 0 .. 255 range.

# File lib/color/rgb.rb, line 473
def green
  @g * 255.0
end
green=(gg) click to toggle source

Sets the green component of the colour in the normal 0 .. 255 range.

# File lib/color/rgb.rb, line 486
def green=(gg)
  @g = Color.normalize(gg / 255.0)
end
green_p() click to toggle source

Returns the green component of the colour as a percentage.

# File lib/color/rgb.rb, line 477
def green_p
  @g * 100.0
end
green_p=(gg) click to toggle source

Sets the green component of the colour as a percentage.

# File lib/color/rgb.rb, line 490
def green_p=(gg)
  @g = Color.normalize(gg / 100.0)
end
hex() click to toggle source

Present the colour as an RGB hex triplet.

# File lib/color/rgb.rb, line 37
def hex
  r = (@r * 255).round
  r = 255 if r > 255

  g = (@g * 255).round
  g = 255 if g > 255

  b = (@b * 255).round
  b = 255 if b > 255

  "%02x%02x%02x" % [ r, g, b ]
end
html() click to toggle source

Present the colour as an HTML/CSS colour string.

# File lib/color/rgb.rb, line 51
def html
  "##{hex}"
end
inspect() click to toggle source
# File lib/color/rgb.rb, line 553
def inspect
  "RGB [#{html}]"
end
lighten_by(percent) click to toggle source

Mix the RGB hue with White so that the RGB hue is the specified percentage of the resulting colour. Strictly speaking, this isn’t a darken_by operation.

# File lib/color/rgb.rb, line 256
def lighten_by(percent)
  mix_with(White, percent)
end
max_rgb_as_grayscale() click to toggle source

Retrieve the maxmum RGB value from the current colour as a GrayScale colour

# File lib/color/rgb.rb, line 548
def max_rgb_as_grayscale
  Color::GrayScale.from_fraction([@r, @g, @b].max)
end
Also aliased as: max_rgb_as_greyscale
max_rgb_as_greyscale()
mix_with(mask, opacity) click to toggle source

Mix the mask colour (which must be an RGB object) with the current colour at the stated opacity percentage (0..100).

# File lib/color/rgb.rb, line 269
def mix_with(mask, opacity)
  opacity /= 100.0
  rgb = self.dup

  rgb.r = (@r * opacity) + (mask.r * (1 - opacity))
  rgb.g = (@g * opacity) + (mask.g * (1 - opacity))
  rgb.b = (@b * opacity) + (mask.b * (1 - opacity))

  rgb
end
pdf_fill() click to toggle source

Present the colour as a DeviceRGB fill colour string for PDF. This will be removed from the default package in color-tools 2.0.

# File lib/color/rgb.rb, line 26
def pdf_fill
  PDF_FORMAT_STR % [ @r, @g, @b, "rg" ]
end
pdf_stroke() click to toggle source

Present the colour as a DeviceRGB stroke colour string for PDF. This will be removed from the default package in color-tools 2.0.

# File lib/color/rgb.rb, line 32
def pdf_stroke
  PDF_FORMAT_STR % [ @r, @g, @b, "RG" ]
end
r() click to toggle source

Returns the red component of the colour as a fraction in the range 0.0 .. 1.0.

# File lib/color/rgb.rb, line 455
def r
  @r
end
r=(rr) click to toggle source

Sets the red component of the colour as a fraction in the range 0.0 .. 1.0.

# File lib/color/rgb.rb, line 468
def r=(rr)
  @r = Color.normalize(rr)
end
red() click to toggle source

Returns the red component of the colour in the normal 0 .. 255 range.

# File lib/color/rgb.rb, line 446
def red
  @r * 255.0
end
red=(rr) click to toggle source

Sets the red component of the colour in the normal 0 .. 255 range.

# File lib/color/rgb.rb, line 459
def red=(rr)
  @r = Color.normalize(rr / 255.0)
end
red_p() click to toggle source

Returns the red component of the colour as a percentage.

# File lib/color/rgb.rb, line 450
def red_p
  @r * 100.0
end
red_p=(rr) click to toggle source

Sets the red component of the colour as a percentage.

# File lib/color/rgb.rb, line 463
def red_p=(rr)
  @r = Color.normalize(rr / 100.0)
end
to_a() click to toggle source
# File lib/color/rgb.rb, line 557
def to_a
  [ r, g, b ]
end
to_cmyk() click to toggle source

Converts the RGB colour to CMYK. Most colour experts strongly suggest that this is not a good idea (some even suggesting that it’s a very bad idea). CMYK represents additive percentages of inks on white paper, whereas RGB represents mixed colour intensities on a black screen.

However, the colour conversion can be done. The basic method is multi-step:

  1. Convert the R, G, and B components to C, M, and Y components.

    c = 1.0 - r
    m = 1.0 - g
    y = 1.0 - b
    
  2. Compute the minimum amount of black (K) required to smooth the colour in inks.

    k = min(c, m, y)
    
  3. Perform undercolour removal on the C, M, and Y components of the colours because less of each colour is needed for each bit of black. Also, regenerate the black (K) based on the undercolour removal so that the colour is more accurately represented in ink.

    c = min(1.0, max(0.0, c - UCR(k)))
    m = min(1.0, max(0.0, m - UCR(k)))
    y = min(1.0, max(0.0, y - UCR(k)))
    k = min(1.0, max(0.0, BG(k)))
    

The undercolour removal function and the black generation functions return a value based on the brightness of the RGB colour.

# File lib/color/rgb.rb, line 114
def to_cmyk
  c = 1.0 - @r.to_f
  m = 1.0 - @g.to_f
  y = 1.0 - @b.to_f

  k = [c, m, y].min
  k = k - (k * brightness)

  c = [1.0, [0.0, c - k].max].min
  m = [1.0, [0.0, m - k].max].min
  y = [1.0, [0.0, y - k].max].min
  k = [1.0, [0.0, k].max].min

  Color::CMYK.from_fraction(c, m, y, k)
end
to_grayscale() click to toggle source

Convert to grayscale.

# File lib/color/rgb.rb, line 290
def to_grayscale
  Color::GrayScale.from_fraction(to_hsl.l)
end
Also aliased as: to_greyscale
to_greyscale()
Alias for: to_grayscale
to_hsl() click to toggle source

Returns the HSL colour encoding of the RGB value. The conversions here are based on forumlas from www.easyrgb.com/math.php and elsewhere.

# File lib/color/rgb.rb, line 145
def to_hsl
  min   = [ @r, @g, @b ].min
  max   = [ @r, @g, @b ].max
  delta = (max - min).to_f

  lum   = (max + min) / 2.0

  if Color.near_zero?(delta) # close to 0.0, so it's a grey
    hue = 0
    sat = 0
  else
    if Color.near_zero_or_less?(lum - 0.5)
      sat = delta / (max + min).to_f
    else
      sat = delta / (2 - max - min).to_f
    end

    # This is based on the conversion algorithm from
    # http://en.wikipedia.org/wiki/HSV_color_space#Conversion_from_RGB_to_HSL_or_HSV
    # Contributed by Adam Johnson
    sixth = 1 / 6.0
    if @r == max # Color.near_zero_or_less?(@r - max)
      hue = (sixth * ((@g - @b) / delta))
      hue += 1.0 if @g < @b
    elsif @g == max # Color.near_zero_or_less(@g - max)
      hue = (sixth * ((@b - @r) / delta)) + (1.0 / 3.0)
    elsif @b == max # Color.near_zero_or_less?(@b - max)
      hue = (sixth * ((@r - @g) / delta)) + (2.0 / 3.0)
    end

    hue += 1 if hue < 0
    hue -= 1 if hue > 1
  end
  Color::HSL.from_fraction(hue, sat, lum)
end
to_lab(color_space = :sRGB, reference_white = [ 95.047, 100.00, 108.883 ]) click to toggle source

Returns the L*a*b* colour encoding of the value via the XYZ colour encoding. Based on the XYZ to Lab formula presented by Bruce Lindbloom.

Currently only the sRGB colour space is supported and defaults to using a D65 reference white.

# File lib/color/rgb.rb, line 217
  def to_lab(color_space = :sRGB, reference_white = [ 95.047, 100.00, 108.883 ])
    xyz = to_xyz

    # Calculate the ratio of the XYZ values to the reference white.
    # http://www.brucelindbloom.com/index.html?Equations.html
    xr = xyz[:x] / reference_white[0]
    yr = xyz[:y] / reference_white[1]
    zr = xyz[:z] / reference_white[2]

    # NOTE: This should be using Rational instead of floating point values,
    # otherwise there will be discontinuities.
    # http://www.brucelindbloom.com/LContinuity.html
    epsilon = (216 / 24389.0)
    kappa   = (24389 / 27.0)

    # And now transform
    # http://en.wikipedia.org/wiki/Lab_color_space#Forward_transformation
    # There is a brief explanation there as far as the nature of the calculations,
    # as well as a much nicer looking modeling of the algebra.
    fx, fy, fz = [ xr, yr, zr ].map { |t|
      if (t > (epsilon))
        t ** (1.0 / 3)
      else # t <= epsilon
        ((kappa * t) + 16) / 116.0
        # The 4/29 here is for when t = 0 (black). 4/29 * 116 = 16, and 16 -
        # 16 = 0, which is the correct value for L* with black.
#       ((1.0/3)*((29.0/6)**2) * t) + (4.0/29)
      end
    }
    {
      :L => ((116 * fy) - 16),
      :a => (500 * (fx - fy)),
      :b => (200 * (fy - fz))
    }
  end
to_rgb(ignored = nil) click to toggle source
# File lib/color/rgb.rb, line 130
def to_rgb(ignored = nil)
  self
end
to_xyz(color_space = :sRGB) click to toggle source

Returns the XYZ colour encoding of the value. Based on the RGB to XYZ formula presented by Bruce Lindbloom.

Currently only the sRGB colour space is supported.

# File lib/color/rgb.rb, line 186
def to_xyz(color_space = :sRGB)
  unless color_space.to_s.downcase == 'srgb'
    raise ArgumentError, "Unsupported colour space #{color_space}."
  end

  # Inverse sRGB companding. Linearizes RGB channels with respect to
  # energy.
  r, g, b = [ @r, @g, @b ].map { |v|
    if (v > 0.04045)
      (((v + 0.055) / 1.055) ** 2.4) * 100
    else
      (v / 12.92) * 100
    end
  }

  # Convert using the RGB/XYZ matrix at:
  # http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html#WSMatrices
  {
    :x => (r * 0.4124564 + g * 0.3575761 + b * 0.1804375),
    :y => (r * 0.2126729 + g * 0.7151522 + b * 0.0721750),
    :z => (r * 0.0193339 + g * 0.1191920 + b * 0.9503041)
  }
end
to_yiq() click to toggle source

Returns the YIQ (NTSC) colour encoding of the RGB value.

# File lib/color/rgb.rb, line 135
def to_yiq
  y = (@r * 0.299) + (@g *  0.587) + (@b *  0.114)
  i = (@r * 0.596) + (@g * -0.275) + (@b * -0.321)
  q = (@r * 0.212) + (@g * -0.523) + (@b *  0.311)
  Color::YIQ.from_fraction(y, i, q)
end

Private Instance Methods

diff_brightness(other) click to toggle source

Provides the brightness difference.

# File lib/color/rgb/contrast.rb, line 34
def diff_brightness(other)
  other = other.to_rgb
  br1 = (299 * other.r + 587 * other.g + 114 * other.b)
  br2 = (299 * self.r + 587 * self.g + 114 * self.b)
  (br1 - br2).abs / 1000.0;
end
diff_euclidean(other) click to toggle source

Provides the euclidean distance between the two color values

# File lib/color/rgb/contrast.rb, line 42
def diff_euclidean(other)
  other = other.to_rgb
  ((((other.r - self.r) ** 2) +
    ((other.g - self.g) ** 2) +
    ((other.b - self.b) ** 2)) ** 0.5) / 1.7320508075688772
end
diff_hue(other) click to toggle source

Difference in the two colors’ hue

# File lib/color/rgb/contrast.rb, line 50
def diff_hue(other)
  other = other.to_rgb
  ((self.r - other.r).abs +
   (self.g - other.g).abs +
   (self.b - other.b).abs) / 3
end
diff_luminosity(other) click to toggle source

Provides the luminosity difference between two rbg vals

# File lib/color/rgb/contrast.rb, line 20
def diff_luminosity(other)
  other = coerce(other)
  l1 = (0.2126 * (other.r) ** 2.2) +
       (0.7152 * (other.b) ** 2.2) +
       (0.0722 * (other.g) ** 2.2);

  l2 = (0.2126 * (self.r) ** 2.2) +
       (0.7152 * (self.b) ** 2.2) +
       (0.0722 * (self.g) ** 2.2);

  ((([l1, l2].max) + 0.05) / ( ([l1, l2].min) + 0.05 ) - 1) / 20.0
end
normalize_percent(percent) click to toggle source
# File lib/color/rgb.rb, line 572
def normalize_percent(percent)
  percent /= 100.0
  percent += 1.0
  percent  = [ percent, 2.0 ].min
  percent  = [ 0.0, percent ].max
  percent
end