class RGB

Constants

VERSION

redgreenblue version.

Public Class Methods

assemble(*a) click to toggle source

Creates a new RGB object from three RGB objects representing the red, green, and blue components.

# File lib/redgreenblue/misc.rb, line 34
def self.assemble(*a)
  v = a.flatten
  RGB.new(v[0].red, v[1].green, v[2].blue)
end
at(number) click to toggle source

Creates a new RGB object from a 24-bit integer in the range 0..16777215.

# File lib/redgreenblue/int.rb, line 9
def self.at(number)
  n = number.to_i
  if (0..16777215) === n
    rgb(
      ( n & 0xff0000 ) >> 16,
      ( n & 0x00ff00 ) >>  8,
      ( n & 0x0000ff )
    )
  else
    raise ArgumentError, "Argument '#{number}' not in range 0..16777215"
  end
end
base_style() click to toggle source

Returns the base inspect style, dependent on the COLORTERM environment variable.

# File lib/redgreenblue/inspect.rb, line 44
def self.base_style
  if styles.include? ENV['REDGREENBLUE_STYLE']
    ENV['REDGREENBLUE_STYLE']
  else
    if ENV['COLORTERM'] == 'truecolor'
      'simple'
    else
      'default'
    end
  end
end
bgr24(bgr) click to toggle source

Creates a new RGB object from BGR24 data (a 3-byte string).

# File lib/redgreenblue/bgr24bit.rb, line 14
def self.bgr24(bgr)
  c = self.new
  c.bgr24 = bgr
  c
end
black() click to toggle source

Creates a black RGB object.

# File lib/redgreenblue/lazy.rb, line 15
def black
  new(0,0,0)
end
blue() click to toggle source

Creates a pure blue RGB object.

# File lib/redgreenblue/lazy.rb, line 40
def blue
  new(0,0,1)
end
center()
Alias for: centre
centre() click to toggle source

Returns the centre of the RGB cube.

# File lib/redgreenblue/lazy.rb, line 65
def centre
  grey
end
Also aliased as: center
corners() click to toggle source

Returns the 8 corners of the RGB cube.

# File lib/redgreenblue/lazy.rb, line 60
def corners
  [ black, red, yellow, green, cyan, blue, magenta, white ]
end
css(selector=nil) click to toggle source

Returns CSS named colors, as per CSS Color Module Level 4.

Optional selector argument can be:

  • String or Regexp (to select by name)

  • RGB color (to select by color)

  • Integer (to select by index).

Selection by name (string or regular expression) is case-insensitive by default.

@example No Selector

# All colors
RGB.css

# Pastels
RGB.css.select { |c| c.ostwald_cwk[1] > 0.6 }

@example Select by Name

# Exact name
RGB.css 'pink'

# Regular expression
RGB.css /pink|rose/

@example Select by RGB color

RGB.css RGB.hex('0ff')
# File lib/redgreenblue/web.rb, line 32
def css(selector=nil)
  @@css ||= load_gpl file: ( File.join File.dirname(__FILE__), 'palettes', 'css.gpl' ), freeze: true
  case selector
    when NilClass
      @@css
    when String
      n = selector.downcase
      @@css.select { |c| c.name == n }.first
    when Regexp
      r = Regexp.new selector.source, Regexp::IGNORECASE
      @@css.select { |c| c.name =~ r }
    when Integer
      @@css[selector]
    when self
      @@css.select { |c| c == selector }
    else
      raise ArgumentError, 'Unsupported selector'
  end
end
cyan() click to toggle source

Creates a cyan RGB object.

# File lib/redgreenblue/lazy.rb, line 50
def cyan
  new(0,1,1)
end
each_24bit_color() { |rgb| ... } click to toggle source

Calls the given block for each 24-bit RGB color (from black to white), passing the color as an RGB object.

Returns the number of iterations.

# File lib/redgreenblue/24bit.rb, line 68
def self.each_24bit_color
  range = 0..255
  range.each do |r|
    range.each do |g|
      range.each do |b|
        yield self.rgb(r,g,b)
      end
    end
  end
  range.size ** 3
end
gpl(line) click to toggle source

Creates a new RGB object from a line of gpl (Gimp color palette) input. Returns nil if not successful.

@example

RGB.gpl "255 153 204\tpink"
# File lib/redgreenblue/gpl.rb, line 13
def gpl(line)
  if line.chomp.match( /^\s*(?<r>\d{1,3})\s+(?<g>\d{1,3})\s+(?<b>\d{1,3})(\s+(?<name>.*))?/ )
    color = RGB.rgb $~[:r].to_i, $~[:g].to_i, $~[:b].to_i
    color.name = $~[:name] if $~[:name]
    color
  else
    nil
  end
end
gpl_header(name=nil, columns: nil) click to toggle source

Returns a header for a .gpl file (Gimp color palette). Includes an optional name and number of columns.

@example

RGB.gpl_header('Spring')

Reverse-engineered from:

# File lib/redgreenblue/gpl.rb, line 74
def gpl_header(name=nil, columns: nil)
  "GIMP Palette\n" +
  ( name    ? "Name: #{name}\n"       : '' ) +
  ( columns ? "Columns: #{columns}\n" : '' )
end
gray(lightness=0.5)

Alias gray for grey.

Alias for: grey
green() click to toggle source

Creates a pure green RGB object.

# File lib/redgreenblue/lazy.rb, line 35
def green
  new(0,1,0)
end
grey(lightness=0.5) click to toggle source

Creates a grey RGB object. Defaults to lightness 0.5, a middle grey. Black equals grey(0), white equals grey(1).

::gray is an alias for ::grey.

# File lib/redgreenblue/lazy.rb, line 22
def grey(lightness=0.5)
  new(lightness, lightness, lightness)
end
Also aliased as: gray
hex(hex_string) click to toggle source

Creates a new object from a 6- or 3-digit hexadecimal string representing red, green, and blue.

The string may include a '#' prefix.

# File lib/redgreenblue/hex.rb, line 32
def self.hex(hex_string)
  if rgb = RGB.hex_to_rgb(hex_string)
    self.rgb rgb
  else
    raise ArgumentError, "'#{hex_string}' is not a usable hexadecimal string"
  end
end
hex_shorthand(hex_string) click to toggle source

Returns a 3-digit shorthand version of a 6-digit hexadecimal string.

If a shorthand version is not possible, returns the original string.

# File lib/redgreenblue/hex.rb, line 43
def self.hex_shorthand(hex_string)
  hex_string.sub( /^(#?)(\h)\2(\h)\3(\h)\4$/, '\1\2\3\4' )
end
hex_to_rgb(hex_string) click to toggle source

Parses a 6- or 3-digit hexadecimal string. Returns three integers in the range 0..255, or nil if not successful.

The string may include a '#' prefix.

# File lib/redgreenblue/hex.rb, line 51
def self.hex_to_rgb(hex_string)
  if hex_string =~ /^(#?)(\h\h)(\h\h)(\h\h)$/
    [$2, $3, $4].map { |h| h.to_i(16) }
  elsif hex_string =~ /^(#?)(\h)(\h)(\h)$/
    [$2, $3, $4].map { |h| (h*2).to_i(16) }
  else
    nil
  end
end
hsb(*a)

Creates a new RGB object from HSB values: hue (0..360), saturation (0..1), and brightness (0..1).

Alias for: hsv
hsl(*a) click to toggle source

Creates a new RGB object from HSL values: hue (0..360), saturation (0..1), and lightness (0..1).

# File lib/redgreenblue/hsl.rb, line 13
def hsl(*a)
  new hsl_to_values(*a)
end
hsl_to_values(*a) click to toggle source

Calculates RGB values from HSL. Given hue (0..360), saturation (0..1), and lightness (0..1), returns red, green, and blue as three values between 0 and 1.

# File lib/redgreenblue/hsl.rb, line 20
def hsl_to_values(*a)
  hsm_to_values(:hsl, a)
end
hsv(*a) click to toggle source

Creates a new RGB object from HSV values: hue (0..360), saturation (0..1), and value (0..1).

# File lib/redgreenblue/hsv.rb, line 13
def hsv(*a)
  new hsv_to_values(*a)
end
Also aliased as: hsb
hsv_to_values(*a) click to toggle source

Calculates RGB values from HSV. Given hue (0..360), saturation (0..1), and value (0..1), returns red, green, and blue as three values between 0 and 1.

# File lib/redgreenblue/hsv.rb, line 20
def hsv_to_values(*a)
  hsm_to_values(:hsv, a)
end
load_gpl(source=nil, file: nil, url: nil, compact: true, freeze: false) click to toggle source

Loads a gpl (Gimp color palette) source and returns an array of RGB objects.

Options:

  • file: Path to a .gpl file to be loaded.

  • url: URL for a .gpl source to be loaded.

  • compact: Defaults to true. If set to false, returns nil for each line that can not be parsed to an RGB color.

  • freeze: Defaults to false. If set to true, returns a frozen array of frozen objects.

@example String

RGB.load_gpl "255 0 0\tred\n255 153 204\tpink\n"

@example File

RGB.load_gpl file: '/path/to/palette.gpl'
RGB.load_gpl file: '/path/to/palette.gpl', compact: false

@example URL

RGB.load_gpl url: 'https://lospec.com/palette-list/yuko-tomita-time.gpl'
# File lib/redgreenblue/gpl.rb, line 38
def load_gpl(source=nil, file: nil, url: nil, compact: true, freeze: false)

  if ! source
    if file
      source = File.open file
    elsif url
      require 'open-uri'
      source = URI.open url
    end
  end

  if source.respond_to? :each_line
    list = source.each_line.map { |line| RGB.gpl(line) }

    if compact
      list.compact!
    end

    if freeze
      list.freeze
      list.each &:freeze
    end

    list
  else
    raise ArgumentError, 'Not a valid source'
  end
end
magenta() click to toggle source

Creates a magenta RGB object.

# File lib/redgreenblue/lazy.rb, line 55
def magenta
  new(1,0,1)
end
new(*a) click to toggle source
# File lib/redgreenblue/base.rb, line 3
def initialize(*a)
  self.values = a.any? ? a : [ 0.5, 0.5, 0.5 ]
end
pick(default_color=RGB.new) click to toggle source

On Mac OS, shows the color picker and creates an RGB object with the chosen color. Not available on other platforms.

If no default color is specified, the picker defaults to a middle grey.

# File lib/redgreenblue/os/mac.rb, line 16
def self.pick(default_color=RGB.new)
  result = RGB.mac_choose(default_color)
  if result
    RGB.rrggbb result
  else
    nil
  end
end
rand() click to toggle source

Creates a new RGB object with random red, green, and blue values.

# File lib/redgreenblue/random.rb, line 21
def self.rand
  new(Kernel::rand, Kernel::rand, Kernel::rand)
end
red() click to toggle source

Creates a pure red RGB object.

# File lib/redgreenblue/lazy.rb, line 30
def red
  new(1,0,0)
end
rgb(*rgb) click to toggle source

Creates a new object from red, green, and blue components as integers in the range 0..255 (three 8-bit values).

# File lib/redgreenblue/24bit.rb, line 48
def self.rgb(*rgb)
  c = self.new
  c.rgb = rgb
  c
end
rgb565(rgb565_string) click to toggle source

Creates a new RGB color from 16-bit RGB565 data.

# File lib/redgreenblue/rgb565.rb, line 19
def self.rgb565(rgb565_string)
  c = self.new
  c.rgb565 = rgb565_string
  c
end
rrggbb(*rrggbb) click to toggle source

Creates a new object from red, green, and blue components as integers in the range 0..65535 (three 16-bit values).

# File lib/redgreenblue/48bit.rb, line 48
def self.rrggbb(*rrggbb)
  c = self.new
  c.rrggbb = rrggbb
  c
end
style() click to toggle source

Returns the current inspect style.

# File lib/redgreenblue/inspect.rb, line 57
def self.style
  @@style ||= base_style
end
style=(s) click to toggle source

Selects an inspect style.

Only the first few characters of your preferred style are required.

# File lib/redgreenblue/inspect.rb, line 69
def self.style=(s)
  @@style = styles.grep( /^#{s.to_s.downcase}/ ).first || style
end
styles() click to toggle source

Returns a list of all available inspect styles.

# File lib/redgreenblue/inspect.rb, line 62
def self.styles
  ( self.instance_methods + self.private_instance_methods ).grep( /^_inspect_(.*)/ ) { $1 }.sort
end
version() click to toggle source

Returns RGB::VERSION.

# File lib/redgreenblue/version.rb, line 7
def self.version
  VERSION
end
white() click to toggle source

Creates a white RGB object.

# File lib/redgreenblue/lazy.rb, line 10
def white
  new(1,1,1)
end
yellow() click to toggle source

Creates a yellow RGB object.

# File lib/redgreenblue/lazy.rb, line 45
def yellow
  new(1,1,0)
end

Private Class Methods

hsm_to_values(type, *a) click to toggle source

Calculates RGB values from HSL or HSV. With help from:

# File lib/redgreenblue/hsx_shared.rb, line 14
def hsm_to_values(type, *a)
  raise NotImplementedError unless [:hsl, :hsv].include? type

  hue, saturation, magnitude = a.flatten

  if ( saturation == 0 ) or ( ! hue )
    return Array.new(3) { magnitude }
  end

  hue = hue.modulo 360

  chroma = case type
    when :hsl
      ( 1 - ( 2 * magnitude - 1 ).abs ) * saturation
    when :hsv
      magnitude * saturation
  end

  values = [
    chroma,
    ( 1 - ( ( hue / 60.0 ).modulo(2) - 1 ).abs ) * chroma,
    0
  ]

  values = case type
    when :hsl
      values.map { |v| ( v + magnitude - chroma / 2.0 ).round(9) }
    when :hsv
      values.map { |v| ( v + magnitude - chroma       ).round(9) }
  end

  # order values according to hue sextant
  [ [0,1,2], [1,0,2], [2,0,1], [2,1,0], [1,2,0], [0,2,1] ][hue.div 60].map { |i| values[i]}
end
mac_choose(default_color) click to toggle source

Uses Applescript to call the color picker on Mac OS.

  • requires a 48-bit RGB triplet [rr, gg, bb] for default choice.

  • Returns nil when <cancel> is clicked or <esc> key hit.

  • Otherwise returns 48-bit RGB triplet [rr, gg, bb].

Applescript command documented here: Standard Additions -> User Interaction -> choose color

# File lib/redgreenblue/os/mac.rb, line 35
  def self.mac_choose(default_color)

    app = case ENV['TERM_PROGRAM']
      when /iTerm\.app/
        'iTerm'
      else
        'Terminal'
      end

    script = <<~ENDSCRIPT
      tell application "#{app}"
        try
          return choose color default color #{default_color.applescript}
        on error
          return ""
        end try
      end tell
    ENDSCRIPT

    result = `osascript -e '#{script}'`.chomp

    if result.empty?
      nil
    else
      (result.split( /,\w*/ )).map { |s| s.to_i }
    end

  end

Public Instance Methods

==(other) click to toggle source

Returns true if this object and another object represent exactly the same color. Otherwise returns false.

# File lib/redgreenblue/base.rb, line 65
def ==(other)
  ( self.class == other.class ) && ( self.values == other.values )
end
achromatic?() click to toggle source

Returns true when this is an achromatic color: red, green, and blue have equal values. Otherwise false.

# File lib/redgreenblue/misc.rb, line 16
def achromatic?
  values.min == values.max
end
applescript() click to toggle source

Returns the color in the format used by AppleScript (a 48-bit RGB triplet).

# File lib/redgreenblue/mac.rb, line 4
def applescript
  "{%i, %i, %i}" % rrggbb
end
b() click to toggle source

Returns the blue component as an integer in the range 0..255 (an 8-bit value).

# File lib/redgreenblue/24bit.rb, line 16
def b
  (blue  * 255).round
end
b=(n) click to toggle source

Sets the blue component using an integer in the range 0..255 (an 8-bit value).

# File lib/redgreenblue/24bit.rb, line 31
def b=(n)
  self.blue  = n / 255.0
end
bb() click to toggle source

Returns the blue component as an integer in the range 0..65535 (a 16-bit value).

# File lib/redgreenblue/48bit.rb, line 16
def bb
  (blue  * 65535).round
end
bb=(n) click to toggle source

Sets the blue component using an integer in the range 0..65535 (a 16-bit value).

# File lib/redgreenblue/48bit.rb, line 31
def bb=(n)
  self.blue  = n / 65535.0
end
bgr24() click to toggle source

Returns a 3-byte string containing the object's color in BGR24 format.

# File lib/redgreenblue/bgr24bit.rb, line 4
def bgr24
  [b, g, r].pack('C3')
end
bgr24=(bgr_string) click to toggle source

Sets red, green, and blue using BGR24 data (a 3-byte string).

# File lib/redgreenblue/bgr24bit.rb, line 9
def bgr24=(bgr_string)
  self.b, self.g, self.r = bgr_string.unpack('C3')
end
blacken(portion=0.5, *portions) click to toggle source

Creates one or more new RGB objects by mixing this object's color with a portion of black.

# File lib/redgreenblue/mix.rb, line 34
def blacken(portion=0.5, *portions)
  if (portion.class != Array) and portions.none?
    mix(RGB.black, portion)
  else
    ( [portion].flatten + portions ).map { |p| mix(RGB.black, p) }
  end
end
blacken!(portion=0.5) click to toggle source

Changes the object's color by mixing it with a portion of black.

# File lib/redgreenblue/mix.rb, line 29
def blacken!(portion=0.5)
  mix!(RGB.black, portion)
end
blue() click to toggle source

Returns the blue component as a value between 0 and 1.

# File lib/redgreenblue/base.rb, line 25
def blue
  @blue
end
blue=(value) click to toggle source

Sets the blue component to a value between 0 and 1.

Values outside the range 0..1 will be clipped.

# File lib/redgreenblue/base.rb, line 46
def blue=(value)
  @blue = limit(value)
end
cie_lab(round: true) click to toggle source

Returns CIE 1976 L*a*b* (CIELAB) values for the RGB object.

# File lib/redgreenblue/cie_1976.rb, line 4
def cie_lab(round: true)
  cie_lab_luv(round: round, type: :lab)
end
Also aliased as: lab
cie_lch_ab() click to toggle source

Returns CIE 1976 LCHab values for the RGB object, derived from L*a*b* (CIELAB).

When C is 0, H is nil.

# File lib/redgreenblue/cie_1976.rb, line 13
def cie_lch_ab
  cie_lch_ab_uv(type: :lab)
end
cie_lch_uv() click to toggle source

Returns CIE 1976 LCHuv values for the RGB object, derived from L*u*v* (CIELUV).

When C is 0, H is nil.

# File lib/redgreenblue/cie_1976.rb, line 27
def cie_lch_uv
  cie_lch_ab_uv(type: :luv)
end
cie_luv(round: true) click to toggle source

Returns CIE 1976 L*u*v* (CIELUV) values for the RGB object.

# File lib/redgreenblue/cie_1976.rb, line 18
def cie_luv(round: true)
  cie_lab_luv(round: round, type: :luv)
end
Also aliased as: luv
cie_xy() click to toggle source

Returns CIE 1931 xy values for the RGB object.

# File lib/redgreenblue/cie_1931.rb, line 45
def cie_xy
  cie_xyy[0..1]
end
Also aliased as: xy
cie_xyy() click to toggle source

Returns CIE 1931 xyY values for the RGB object.

Based on:

# File lib/redgreenblue/cie_1931.rb, line 30
def cie_xyy
  x, y, z = cie_xyz(round: false)

  [

    x / ( x + y + z ),
    y / ( x + y + z ),
    y

  ].map { |v| v.round(8) }
end
Also aliased as: xyy
cie_xyz(round: true) click to toggle source

Returns CIE 1931 XYZ values for the RGB object.

Based on:

sRGB to XYZ matrix for D65 reference white calculated with Javascript by Bruce Lindbloom:

# File lib/redgreenblue/cie_1931.rb, line 10
def cie_xyz(round: true)
  r, g, b = linear_values

  [

    r * 0.4124_5643_9090 + g * 0.3575_7607_7644 + b * 0.1804_3748_3266,
    r * 0.2126_7285_1406 + g * 0.7151_5215_5288 + b * 0.0721_7499_3307,
    r * 0.0193_3389_5582 + g * 0.1191_9202_5881 + b * 0.9503_0407_8536

  ].map { |v| round ? v.round(8) : v }
end
Also aliased as: xyz
color_space() click to toggle source

Returns the color space.

Currently always 'sRGB'.

# File lib/redgreenblue/base.rb, line 10
def color_space
  'sRGB'
end
components() click to toggle source

Returns an array of three RGB objects, for the red, green, and blue components of this object.

# File lib/redgreenblue/misc.rb, line 29
def components
  [ RGB.new(red,0,0), RGB.new(0,green,0), RGB.new(0,0,blue) ]
end
css_hex() click to toggle source

Returns the object's RGB value in hexadecimal notation as used in CSS.

Shortens to 3 digits when possible.

# File lib/redgreenblue/web.rb, line 61
def css_hex
  "##{hex true}"
end
css_names() click to toggle source

Returns the names of CSS named colors identical to this color. @example

RGB.hex('f0f').css_names
# File lib/redgreenblue/web.rb, line 68
def css_names
  RGB.css(self).map &:name
end
cwk(round: true)
Alias for: ostwald_cwk
de76(another)
Alias for: delta_e_cie_1976
delta_e_cie_1976(another) click to toggle source

Returns the difference between this color and another color, according to the CIE 1976 delta E formula.

Based on:

# File lib/redgreenblue/cie_1976.rb, line 36
def delta_e_cie_1976(another)
  l , a , b  =         cie_lab(round: false)
  l2, a2, b2 = another.cie_lab(round: false)

  Math.sqrt( (l - l2) ** 2 + (a - a2) ** 2 + (b - b2) ** 2 ).round(8)
end
Also aliased as: de76
distance(another) click to toggle source

Returns the euclidean distance between this color and another color.

When you imagine a color as a point in a 3-dimensional space, the dimensions being red, green, and blue, this is the distance between two colors.

# File lib/redgreenblue/misc.rb, line 44
def distance(another)
  (
    ( (another.red   - red  ) ** 2) +
    ( (another.green - green) ** 2) +
    ( (another.blue  - blue ) ** 2)
  ) ** (1/2.0)
end
g() click to toggle source

Returns the green component as an integer in the range 0..255 (an 8-bit value).

# File lib/redgreenblue/24bit.rb, line 11
def g
  (green * 255).round
end
g=(n) click to toggle source

Sets the green component using an integer in the range 0..255 (an 8-bit value).

# File lib/redgreenblue/24bit.rb, line 26
def g=(n)
  self.green = n / 255.0
end
gg() click to toggle source

Returns the green component as an integer in the range 0..65535 (a 16-bit value).

# File lib/redgreenblue/48bit.rb, line 11
def gg
  (green * 65535).round
end
gg=(n) click to toggle source

Sets the green component using an integer in the range 0..65535 (a 16-bit value).

# File lib/redgreenblue/48bit.rb, line 26
def gg=(n)
  self.green = n / 65535.0
end
gif_pixel() click to toggle source

Returns a 1-pixel GIF image set to the color.

With help from:

# File lib/redgreenblue/gif.rb, line 7
def gif_pixel
  "GIF89a\1\0\1\0\x90\0\0".b +
  rgb.pack('C3') +
  "\0\0\0,\0\0\0\0\1\0\1\0\0\x02\x02\x04\1\0;".b
end
gif_pixel_write(file_path) click to toggle source

Writes a 1-pixel GIF image to a file.

# File lib/redgreenblue/gif.rb, line 14
def gif_pixel_write(file_path)
  File.binwrite(file_path, gif_pixel)
end
gpl(gpl_name=name) click to toggle source

Returns the color in the format used in .gpl files (Gimp color palettes), including its name (if present).

You can optionally supply a name as argument.

# File lib/redgreenblue/gpl.rb, line 89
def gpl(gpl_name=name)
  ( "%3d %3d %3d" % rgb ) +
  ( gpl_name.to_s.size != 0 ? "\t#{gpl_name}" : '' )
end
green() click to toggle source

Returns the green component as a value between 0 and 1.

# File lib/redgreenblue/base.rb, line 20
def green
  @green
end
green=(value) click to toggle source

Sets the green component to a value between 0 and 1.

Values outside the range 0..1 will be clipped.

# File lib/redgreenblue/base.rb, line 39
def green=(value)
  @green = limit(value)
end
hex(shorthand=false) click to toggle source

Returns a 6-digit hexadecimal string representing the object's red, green, and blue components as 8-bit values.

If shorthand is true, returns 3-digit shorthand if possible.

# File lib/redgreenblue/hex.rb, line 6
def hex(shorthand=false)
  if shorthand
    RGB.hex_shorthand hex6
  else
    hex6
  end
end
hex=(hex_string) click to toggle source

Sets red, green, and blue using a 6- or 3-digit hexadecimal string.

The string may include a '#' prefix.

# File lib/redgreenblue/hex.rb, line 17
def hex=(hex_string)
  if rgb = RGB.hex_to_rgb(hex_string)
    self.rgb = rgb
  else
    raise ArgumentError, "'#{hex_string}' is not a usable hexadecimal string"
  end
end
hsb()

Returns color as HSB: hue (0..360), saturation (0..1), brightness (0..1). When saturation is 0, hue is nil.

Alias for: hsv
hsb=(*a)

Sets red, green, and blue using HSB values: hue (0..360), saturation (0..1), and brightness (0..1).

Alias for: hsv=
hsb_b()

Returns the object's HSB-brightness (0..1).

Alias for: hsv_v
hsb_b=(value)

Sets HSB-brightness to a number between 0 and 1.

Adjusts red, green, and blue, leaving HSB-hue and -saturation unchanged. When brightness is 0, hue will be nil, and saturation will be 0.

Alias for: hsv_v=
hsb_h()

Returns the object's HSB-hue (0..360).

Alias for: hsv_h
hsb_h=(degrees)

Sets HSB-hue to a number of degrees (0..360) or nil.

Adjusts red, green, and blue, leaving HSB-saturation and -brightness unchanged. When hue is nil, saturation will be 0.

Alias for: hsv_h=
hsb_rotate(a_degrees, *b_degrees)

Creates one or more new RGB objects by rotating this object's HSB-hue a number of degrees.

Alias for: hsv_rotate
hsb_rotate!(degrees)

Sets red, green, and blue by rotating the object's HSB-hue a number of degrees.

Alias for: hsv_rotate!
hsb_s()

Returns the object's HSB-saturation (0..1).

Alias for: hsv_s
hsb_s=(value)

Sets HSB-saturation to a number between 0 and 1.

Adjusts red, green, and blue, leaving HSB-hue and -brightness unchanged. When saturation is 0, hue will be nil.

Alias for: hsv_s=
hsl() click to toggle source

Returns color as HSL: hue (0..360), saturation (0..1), lightness (0..1). When saturation is 0, hue is nil.

# File lib/redgreenblue/hsl.rb, line 33
def hsl
  hsl_hsv_c[0]
end
hsl=(*a) click to toggle source

Sets red, green, and blue using HSL values: hue (0..360), saturation (0..1), and lightness (0..1).

# File lib/redgreenblue/hsl.rb, line 53
def hsl=(*a)
  self.values = RGB.hsl_to_values(*a)
end
hsl_h() click to toggle source

Returns the object's HSL-hue (0..360).

# File lib/redgreenblue/hsl.rb, line 38
def hsl_h
  hsl[0]
end
hsl_h=(degrees) click to toggle source

Sets HSL-hue to a number of degrees (0..360) or nil.

Adjusts red, green, and blue, leaving saturation and lightness unchanged. When hue is nil, saturation will be 0.

# File lib/redgreenblue/hsl.rb, line 61
def hsl_h=(degrees)
  self.hsl = hsl.fill(degrees,0,1)
end
hsl_l() click to toggle source

Returns the object's HSL-lightness (0..1).

# File lib/redgreenblue/hsl.rb, line 48
def hsl_l
  hsl[2]
end
hsl_l=(value) click to toggle source

Sets HSL-lightness to a value between 0 and 1.

Adjusts red, green, and blue, leaving hue and saturation unchanged. When lightness is 0 or 1, hue will be nil, and saturation will be 0.

# File lib/redgreenblue/hsl.rb, line 77
def hsl_l=(value)
  self.hsl = hsl.fill(value  ,2,1)
end
hsl_rotate(a_degrees, *b_degrees) click to toggle source

Creates one or more new RGB objects by rotating this object's HSL-hue a number of degrees.

# File lib/redgreenblue/hsl.rb, line 88
def hsl_rotate(a_degrees, *b_degrees)
  if a_degrees.class != Array and b_degrees.none?
    RGB.hsl zip_add(hsl, [a_degrees, 0, 0])
  else
    ( [a_degrees] + b_degrees ).flatten.map { |degrees| RGB.hsl zip_add(hsl, [degrees, 0, 0]) }
  end
end
hsl_rotate!(degrees) click to toggle source

Sets red, green, and blue by rotating the object's HSL-hue a number of degrees.

# File lib/redgreenblue/hsl.rb, line 82
def hsl_rotate!(degrees)
  self.hsl = zip_add(hsl, [degrees, 0, 0])
  self
end
hsl_s() click to toggle source

Returns the object's HSL-saturation (0..1).

# File lib/redgreenblue/hsl.rb, line 43
def hsl_s
  hsl[1]
end
hsl_s=(value) click to toggle source

Sets HSL-saturation to a value between 0 and 1.

Adjusts red, green, and blue, leaving hue and lightness unchanged. When saturation is 0, hue will be nil.

# File lib/redgreenblue/hsl.rb, line 69
def hsl_s=(value)
  self.hsl = hsl.fill(value  ,1,1)
end
hsv() click to toggle source

Returns color as HSV: hue (0..360), saturation (0..1), value (0..1). When saturation is 0, hue is nil.

# File lib/redgreenblue/hsv.rb, line 33
def hsv
  hsl_hsv_c[1]
end
Also aliased as: hsb
hsv=(*a) click to toggle source

Sets red, green, and blue using HSV values: hue (0..360), saturation (0..1), and value (0..1).

# File lib/redgreenblue/hsv.rb, line 53
def hsv=(*a)
  self.values = RGB.hsv_to_values(*a)
end
Also aliased as: hsb=
hsv_h() click to toggle source

Returns the object's HSV-hue (0..360).

# File lib/redgreenblue/hsv.rb, line 38
def hsv_h
  hsv[0]
end
Also aliased as: hsb_h
hsv_h=(degrees) click to toggle source

Sets HSV-hue to a number of degrees (0..360) or nil.

Adjusts red, green, and blue, leaving HSV-saturation and -value unchanged. When hue is nil, saturation will be 0.

# File lib/redgreenblue/hsv.rb, line 61
def hsv_h=(degrees)
  self.hsv = hsv.fill(degrees,0,1)
end
Also aliased as: hsb_h=
hsv_rotate(a_degrees, *b_degrees) click to toggle source

Creates one or more new RGB objects by rotating this object's HSV-hue a number of degrees.

# File lib/redgreenblue/hsv.rb, line 88
def hsv_rotate(a_degrees, *b_degrees)
  if a_degrees.class != Array and b_degrees.none?
    RGB.hsv zip_add(hsv, [a_degrees, 0, 0])
  else
    ( [a_degrees] + b_degrees ).flatten.map { |degrees| RGB.hsv zip_add(hsv, [degrees, 0, 0]) }
  end
end
Also aliased as: hsb_rotate
hsv_rotate!(degrees) click to toggle source

Sets red, green, and blue by rotating the object's HSV-hue a number of degrees.

# File lib/redgreenblue/hsv.rb, line 82
def hsv_rotate!(degrees)
  self.hsv = zip_add(hsv, [degrees, 0, 0])
  self
end
Also aliased as: hsb_rotate!
hsv_s() click to toggle source

Returns the object's HSV-saturation (0..1).

# File lib/redgreenblue/hsv.rb, line 43
def hsv_s
  hsv[1]
end
Also aliased as: hsb_s
hsv_s=(value) click to toggle source

Sets HSV-saturation to a number between 0 and 1.

Adjusts red, green, and blue, leaving HSV-hue and -value unchanged. When saturation is 0, hue will be nil.

# File lib/redgreenblue/hsv.rb, line 69
def hsv_s=(value)
  self.hsv = hsv.fill(value  ,1,1)
end
Also aliased as: hsb_s=
hsv_v() click to toggle source

Returns the object's HSV-value (0..1).

# File lib/redgreenblue/hsv.rb, line 48
def hsv_v
  hsv[2]
end
Also aliased as: hsb_b
hsv_v=(value) click to toggle source

Sets HSV-value to a number between 0 and 1.

Adjusts red, green, and blue, leaving HSV-hue and -saturation unchanged. When value is 0, hue will be nil, and saturation will be 0.

# File lib/redgreenblue/hsv.rb, line 77
def hsv_v=(value)
  self.hsv = hsv.fill(value  ,2,1)
end
Also aliased as: hsb_b=
hwb() click to toggle source

Returns the color's hue (0..360), whiteness (0..1), and blackness (0..1), as defined by the HWB color model.

For achromatic colors, hue is nil.

Based on:

# File lib/redgreenblue/hwb.rb, line 10
def hwb
  [ hsv_h, cwk[1,2] ].flatten
end
inspect() click to toggle source

Returns a programmer-friendly representation of the object.

You can choose among several inspect styles. See the styles, style, and style= class methods.

# File lib/redgreenblue/inspect.rb, line 34
def inspect
  send "_inspect_#{self.class.style}"
end
invert() click to toggle source

Creates a new RGB object with the inverted color of this RGB object.

# File lib/redgreenblue/misc.rb, line 10
def invert
  dup.invert!
end
invert!() click to toggle source

Inverts the object's color.

# File lib/redgreenblue/misc.rb, line 4
def invert!
  self.values = values.map { |v| 1 - v }
  self
end
lab(round: true)
Alias for: cie_lab
linear_values() click to toggle source

Returns gamma-expanded (inverse-companded) RGB values for the object (three values between 0 and 1).

Based on:

# File lib/redgreenblue/gamma.rb, line 9
def linear_values
  if color_space == 'sRGB'
    values.map { |v|
      if v <= 0.04045
        v / 12.92
      else
        ( ( v + 0.055 ) / 1.055 ) ** 2.4
      end
    }
  else
    raise "can not compute gamma for color space '#{color_space}'"
  end
end
linear_values=(*a) click to toggle source

Sets the object's RGB values using three linear RGB values, each between 0 and 1. Linear values will be converted to the object's gamma (gamma-companded).

Based on:

# File lib/redgreenblue/gamma.rb, line 30
def linear_values=(*a)
  if color_space == 'sRGB'
    self.values = a.flatten.map { |v|
      if v <= 0.0031308
        v * 12.92
      else
        1.055 * ( v ** ( 1/2.4 ) ) - 0.055
      end
    }.map { |v| v.round(9) }
  else
    raise "can not compute gamma for color space '#{color_space}'"
  end
end
luv(round: true)
Alias for: cie_luv
match_de76(others) click to toggle source

Matches this color to a set of colors using the CIE 1976 delta E formula.

Returns the given set of colors with their difference from this color, sorted by difference (nearest color first). @example Find the 3 nearest CSS named colors

RGB.hex('f9c').match_de76(RGB.css).first(3)
# File lib/redgreenblue/match.rb, line 17
def match_de76(others)
  others.map { |c| [ c, de76(c) ] }.sort_by { |a| a[1] }
end
match_distance(others) click to toggle source

Matches this color to a set of colors by calculating their euclidean distance.

Returns the given set of colors with their distance from this color, sorted by distance (nearest color first). @example What is nearer: red, grey or white?

RGB.hex('f9c').match_distance [RGB.red, RGB.grey, RGB.white]
# File lib/redgreenblue/match.rb, line 8
def match_distance(others)
  others.map { |c| [ c, distance(c) ] }.sort_by { |a| a[1] }
end
mix(another,portion=0.5) click to toggle source

Creates a new RGB object by mixing this object's color with a portion of another RGB color.

# File lib/redgreenblue/mix.rb, line 10
def mix(another,portion=0.5)
  RGB.new mix_values(another.values, portion)
end
mix!(another,portion=0.5) click to toggle source

Changes the object's color by mixing it with a portion of another RGB color.

# File lib/redgreenblue/mix.rb, line 4
def mix!(another,portion=0.5)
  self.values = mix_values(another.values, portion)
  self
end
name() click to toggle source

Returns the name.

# File lib/redgreenblue/name.rb, line 4
def name
  defined?(@name) ? @name : nil
end
name=(text) click to toggle source

Sets the name (a string or nil).

# File lib/redgreenblue/name.rb, line 9
def name=(text)
  @name = ( text.to_s.size != 0 ) ? text.to_s : nil
end
ostwald_color() click to toggle source

Returns a new RGB object with this color's Ostwald full-color, or nil for achromatic colors (white, greys, and black).

The resulting color contains no white or black, i.e. it has at least one RGB component set to 0, and at least one set to maximum.

This is identical (barring very small rounding errors) to setting HSL-saturation to 1, and -lightness to 0.5

Based on:

# File lib/redgreenblue/ostwald.rb, line 15
def ostwald_color
  white_portion = values.min
  color_portion = values.max - white_portion

  if color_portion == 0
    nil
  else
    RGB.new( values.map { |v| ( ( v - white_portion ) / color_portion ).round(6) } )
  end
end
ostwald_cwk(round: true) click to toggle source

Returns the portions of Ostwald full-color, white, and black, which constitute this color.

The sum of these three numbers equals 1.

cwk is an alias for ostwald_cwk.

Based on:

# File lib/redgreenblue/ostwald.rb, line 35
def ostwald_cwk(round: true)
  [
    color_portion = values.max - values.min,
    white_portion = values.min,
    1 - color_portion - white_portion
  ].map { |v| round ? v.round(8) : v }
end
Also aliased as: cwk
permutation() click to toggle source

Returns an array of RGB objects for all possible ways in which the red, green, and blue values of this object can be exchanged.

Example: RGB.red.permutation returns [ RGB.red, RGB.green, RGB.blue ]. See also: shuffle.

# File lib/redgreenblue/misc.rb, line 24
def permutation
  values.permutation.to_a.uniq.map { |v| RGB.new v }
end
pick() click to toggle source

On Mac OS, shows the color picker to choose a color for the RGB object. Not available on other platforms.

# File lib/redgreenblue/os/mac.rb, line 5
def pick
  result = RGB.mac_choose(self)
  if result
    self.rrggbb = result
  end
end
r() click to toggle source

Returns the red component as an integer in the range 0..255 (an 8-bit value).

# File lib/redgreenblue/24bit.rb, line 6
def r
  (red   * 255).round
end
r=(n) click to toggle source

Sets the red component using an integer in the range 0..255 (an 8-bit value).

# File lib/redgreenblue/24bit.rb, line 21
def r=(n)
  self.red   = n / 255.0
end
randomize!() click to toggle source

Assigns random values to red, green, and blue.

# File lib/redgreenblue/random.rb, line 15
def randomize!
  self.values = Kernel::rand, Kernel::rand, Kernel::rand
  self
end
red() click to toggle source

Returns the red component as a value between 0 and 1.

# File lib/redgreenblue/base.rb, line 15
def red
  @red
end
red=(value) click to toggle source

Sets the red component to a value between 0 and 1.

Values outside the range 0..1 will be clipped.

# File lib/redgreenblue/base.rb, line 32
def red=(value)
  @red = limit(value)
end
rgb() click to toggle source

Returns the red, green, and blue components as integers in the range 0..255 (three 8-bit values).

# File lib/redgreenblue/24bit.rb, line 38
def rgb
  [r,g,b]
end
rgb565() click to toggle source

Returns the color in 16-bit RGB565 format.

# File lib/redgreenblue/rgb565.rb, line 4
def rgb565
  [((r >> 3) << 11) + ((g >> 2) << 5) + (b >> 3)].pack 'S<'
end
rgb565=(rgb565_string) click to toggle source

Sets the color from 16-bit RGB565 data. With help from:

# File lib/redgreenblue/rgb565.rb, line 11
def rgb565=(rgb565_string)
  v = ( rgb565_string.unpack "S<" )[0]
  self.r = ( ( v & 0xf800 ) >> 11 ) << 3
  self.g = ( ( v & 0x07e0 ) >>  5 ) << 2
  self.b = ( ( v & 0x001f )       ) << 3
end
rgb=(*rgb) click to toggle source

Sets the red, green, and blue components using three integers in the range 0..255 (three 8-bit values).

# File lib/redgreenblue/24bit.rb, line 43
def rgb=(*rgb)
  self.r, self.g, self.b = rgb.flatten
end
rr() click to toggle source

Returns the red component as an integer in the range 0..65535 (a 16-bit value).

# File lib/redgreenblue/48bit.rb, line 6
def rr
  (red   * 65535).round
end
rr=(n) click to toggle source

Sets the red component using an integer in the range 0..65535 (a 16-bit value).

# File lib/redgreenblue/48bit.rb, line 21
def rr=(n)
  self.red   = n / 65535.0
end
rrggbb() click to toggle source

Returns the red, green, and blue components as integers in the range 0..65535 (three 16-bit values).

# File lib/redgreenblue/48bit.rb, line 38
def rrggbb
  [rr,gg,bb]
end
rrggbb=(*rrggbb) click to toggle source

Sets the red, green, and blue components using three integers in the range 0..65535 (three 16-bit values).

# File lib/redgreenblue/48bit.rb, line 43
def rrggbb=(*rrggbb)
  self.rr, self.gg, self.bb = rrggbb.flatten
end
shuffle() click to toggle source

Creates a new RGB object with this object's red, green, and blue values shuffled.

# File lib/redgreenblue/random.rb, line 10
def shuffle
  RGB.new values.shuffle
end
shuffle!() click to toggle source

Shuffles the object's red, green, and blue values.

# File lib/redgreenblue/random.rb, line 4
def shuffle!
  self.values = values.shuffle
  self
end
snap() click to toggle source

Creates a new RGB object containing the nearest 24-bit color.

# File lib/redgreenblue/24bit.rb, line 61
def snap
  RGB.rgb rgb
end
snap!() click to toggle source

Sets the red, green, and blue values to those of the nearest 24-bit color.

# File lib/redgreenblue/24bit.rb, line 55
def snap!
  self.rgb = rgb
  self
end
steps(another,step_count=1,include_begin=false) click to toggle source

Returns a set of colors between this color and another. That other color is included.

The resulting colors are spaced evenly in the RGB color space using a straightforward calculation. You will likely experience these colors as not exactly evenly spaced.

# File lib/redgreenblue/mix.rb, line 46
def steps(another,step_count=1,include_begin=false)
  # origin (self, optional)
  ( include_begin ? [self.dup] : [] ) +
  # ...plus intermediate colors
  (1..step_count-1).map { |c| mix(another, c.to_f/step_count) } +
  # ...plus destination color
  [another.dup]
end
terminal_background() click to toggle source

Returns the ANSI escape sequence required to set the background color on a terminal to this color. Only works on terminals that support 24-bit colors, so-called “true color”.

# File lib/redgreenblue/terminal.rb, line 15
def terminal_background
  "\e[48;2;%d;%d;%dm" % rgb
end
terminal_foreground() click to toggle source

Returns the ANSI escape sequence required to set the foreground color on a terminal to this color. Only works on terminals that support 24-bit colors, so-called “true color”.

# File lib/redgreenblue/terminal.rb, line 9
def terminal_foreground
  "\e[38;2;%d;%d;%dm" % rgb
end
to_a()
Alias for: values
to_h() click to toggle source

Returns a sorted hash of 3 key/value pairs for red, green, and blue, sorted in order of decreasing value.

# File lib/redgreenblue/base.rb, line 71
def to_h
  ([:red, :green, :blue].zip values).sort_by {
    |k,v| [-v,[:red, :green, :blue].index(k)]
  }.to_h
end
to_i() click to toggle source

Returns the color as a 24-bit integer in the range 0..16777215.

# File lib/redgreenblue/int.rb, line 4
def to_i
  ( r << 16 ) + ( g << 8 ) + b
end
to_philips_hue_api_hsb_arguments(black_off=true) click to toggle source

Only available when optional support for Philips Hue lights is loaded.

Returns a hash with the arguments required by the Philips Hue API, to set a light to this RGB object's hue, saturation and brightness.

Formatted as JSON, this hash can be sent to a bridge to set a light's state.

See (regrettably requires registration):

@example Load

require 'redgreenblue/opt/philipshue'

@example Use

RGB.magenta.to_philips_hue_api_hsb_arguments
=> {"on"=>true, "bri"=>254, "hue"=>54613, "sat"=>254}

@return [Hash] API arguments

# File lib/redgreenblue/opt/philipshue.rb, line 26
def to_philips_hue_api_hsb_arguments(black_off=true)
  my_hsb = hsb

  # Black means 'off'
  if black_off and ( my_hsb[2] == 0 )
    { 'on'  => false }

  else
    {

      # On/Off state of the light
      'on'  => true,

      # Brightness 1..254
      # Note: a brightness of 1 will not switch the light off
      'bri' => (  my_hsb[2]        * 253 + 1     ).round,

      # Hue 0..65535
      'hue' => (( my_hsb[0] || 0 ) * 65535 / 360 ).round,

      # Saturation 0..254
      'sat' => (  my_hsb[1]        * 254         ).round

    }

  end
end
to_s() click to toggle source

Returns a string representation of the object.

# File lib/redgreenblue/inspect.rb, line 39
def to_s
  _inspect_default
end
v()
Alias for: view
values() click to toggle source

Returns the red, green, and blue components as three values between 0 and 1.

# File lib/redgreenblue/base.rb, line 51
def values
  [ red, green, blue ]
end
Also aliased as: to_a
values=(*a) click to toggle source

Sets the red, green, and blue components using three values between 0 and 1.

Values outside the range 0..1 will be clipped.

# File lib/redgreenblue/base.rb, line 60
def values=(*a)
  self.red, self.green, self.blue = a.flatten
end
view() click to toggle source

Prints details for the RGB object, using multiple lines.

# File lib/redgreenblue/view.rb, line 4
def view
  puts _inspect_view
end
Also aliased as: v
wcag20_contrast_ratio(another, round: true) click to toggle source

Returns the contrast ratio for this color and another color, as defined by the Web Content Accessibility Guidelines (WCAG) 2.0.

Based on:

# File lib/redgreenblue/web.rb, line 98
def wcag20_contrast_ratio(another, round: true)
  luminances = [
    wcag20_luminance(round: false),
    another.wcag20_luminance(round: false)
  ].sort.reverse

  contrast_ratio = ( luminances[0] + 0.05 ) / ( luminances[1] + 0.05 )

  round ? contrast_ratio.round(8) : contrast_ratio
end
wcag20_luminance(round: true) click to toggle source

Returns the color's relative luminance, as defined by the Web Content Accessibility Guidelines (WCAG) 2.0.

This is different from the Y component of CIE 1931 XYZ.

Based on:

# File lib/redgreenblue/web.rb, line 78
def wcag20_luminance(round: true)
  if color_space == 'sRGB'
    values.map { |v|
      if v <= 0.03928
        v / 12.92
      else
        ( ( v + 0.055 ) / 1.055 ) ** 2.4
      end
    }.zip( [0.2126, 0.7152, 0.0722] ).map { |c,f|
      c * f
    }.inject(:+).instance_eval { |v| round ? v.round(8) : v }
  else
    raise "can not calculate luminance for color space '#{color_space}'"
  end
end
whiten(portion=0.5, *portions) click to toggle source

Creates one or more new RGB objects by mixing this object's color with a portion of white.

# File lib/redgreenblue/mix.rb, line 20
def whiten(portion=0.5, *portions)
  if (portion.class != Array) and portions.none?
    mix(RGB.white, portion)
  else
    ( [portion].flatten + portions ).map { |p| mix(RGB.white, p) }
  end
end
whiten!(portion=0.5) click to toggle source

Changes the object's color by mixing it with a portion of white.

# File lib/redgreenblue/mix.rb, line 15
def whiten!(portion=0.5)
  mix!(RGB.white, portion)
end
xy()
Alias for: cie_xy
xyy()
Alias for: cie_xyy
xyz(round: true)
Alias for: cie_xyz

Private Instance Methods

_inspect_default(prefix='RGB') click to toggle source
# File lib/redgreenblue/inspect.rb, line 5
def _inspect_default(prefix='RGB')
  "#{prefix} #{_inspect_hex} (red=%1.5f green=%1.5f blue=%1.5f)" % [red, green, blue] + ( name ? ' ' + name : '' )
end
_inspect_hex() click to toggle source
# File lib/redgreenblue/inspect.rb, line 9
def _inspect_hex
  (self == snap ? '#' : '~') + hex
end
_inspect_name() click to toggle source
# File lib/redgreenblue/inspect.rb, line 25
def _inspect_name
  _inspect_swatch + ( name ? ' ' + name : '' )
end
_inspect_short() click to toggle source
# File lib/redgreenblue/inspect.rb, line 17
def _inspect_short
  "#{_inspect_swatch} #{_inspect_hex}"
end
_inspect_simple() click to toggle source
# File lib/redgreenblue/inspect.rb, line 21
def _inspect_simple
  _inspect_default _inspect_swatch
end
_inspect_swatch() click to toggle source
# File lib/redgreenblue/inspect.rb, line 13
def _inspect_swatch
  terminal_background + "   \e[0m"
end
_inspect_view() click to toggle source
# File lib/redgreenblue/view.rb, line 12
def _inspect_view
  o = []
  o << 3.times.map { terminal_background + "      \e[0m "}
  o << [ "#{_inspect_hex} ", '%-7.7s ' % color_space, '        ' ]

  o << components.map { |c| c.terminal_background + "  \e[0m " }
  o << %w(R: G: B:)
  o << values.map { |v| '%1.5f ' % v }
  o << rgb.map { |v| '%3d ' % v }

  o << %w(H: S: L:)
  o << hsl.map { |v| v ? ('%7.3f ' % v) : '  -     ' }
  o << %w(H: S: B:)
  o << hsb.map { |v| v ? ('%7.3f ' % v) : '  -     ' }

  o << 3.times.map { (ostwald_color ? ostwald_color.terminal_background + "  \e[0m " : '   ') }
  o << %w(C: W: K:)
  o << ostwald_cwk.map { |v| '%1.3f ' % v }

  o.transpose.map(&:join).join("\n")
end
cie_lab_luv(round: true, type: :lab) click to toggle source

Returns either CIE 1976 L*a*b* (CIELAB) or CIE 1976 L*u*v* (CIELUV) values for the RGB object.

L*a*b* formula based on:

With peeking at:

L*u*v* formula based on:

# File lib/redgreenblue/cie_1976.rb, line 58
def cie_lab_luv(round: true, type: :lab)
  x , y , z  =           cie_xyz(round: false)
  xr, yr, zr = RGB.white.cie_xyz(round: false)

  f = [ x / xr, y / yr, z / zr ].map { |v|
    if v > ( 216.0 / 24389 )
      Math.cbrt v
    else
      ( 24389.0 / 27 * v + 16 ) / 116.0
    end
  }

  if type == :luv
    [
      l = 116 * f[1] - 16,
      13 * l * ( ( 4 * x ) / ( x + 15 * y + 3 * z ) - ( 4 * xr ) / ( xr + 15 * yr + 3 * zr ) ),
      13 * l * ( ( 9 * y ) / ( x + 15 * y + 3 * z ) - ( 9 * yr ) / ( xr + 15 * yr + 3 * zr ) )
    ]
  else
    [
      116 *  f[1] - 16,
      500 * (f[0] - f[1]),
      200 * (f[1] - f[2])
    ]
  end.map { |v| v.nan? ? 0.0 : ( round ? v.round(8) : v ) }
end
cie_lch_ab_uv(type: :lab) click to toggle source

Returns either CIE 1976 LCHab or CIE 1976 LCHuv values for the RGB object.

Based on:

# File lib/redgreenblue/cie_1976.rb, line 91
def cie_lch_ab_uv(type: :lab)
  if type == :luv
    l, v1, v2 = cie_luv(round: false)
  else
    l, v1, v2 = cie_lab(round: false)
  end

  [
    l.round(8),
    c = Math.hypot(v1, v2).round(8),
    c == 0 ? nil : ( Math.atan2(v2, v1) * 180.0 / Math::PI ).modulo(360).round(8)
  ]
end
hex6() click to toggle source
# File lib/redgreenblue/hex.rb, line 63
def hex6
  '%02x%02x%02x' % [ r, g, b ]
end
hsl_hsv_c() click to toggle source

Compute HSL, HSV, and chroma. With help from:

# File lib/redgreenblue/hsx_shared.rb, line 60
def hsl_hsv_c
  sorted_hash = to_h
  min, max = sorted_hash.values.values_at(2,0)

  chroma = max - min

  hue =
    if chroma == 0
      nil
    else
      ( case sorted_hash.keys.first
        when :red
          60 * ( ( ( green - blue  ) / chroma ).modulo 6 )
        when :green
          60 * ( (   blue  - red   ) / chroma + 2 )
        when :blue
          60 * ( (   red   - green ) / chroma + 4 )
        end
      ).round(6)
    end

  lightness = ( min + max ) / 2.0

  saturation_hsl =
    chroma == 0 ? 0.0 : ( chroma / ( 1 - (2 * lightness - 1).abs ) ).round(9)

  value = max

  saturation_hsv =
    value == 0 ? 0.0 : chroma / value

  [ [hue, saturation_hsl, lightness], [hue, saturation_hsv, value], chroma ]
end
limit(n) click to toggle source

limits to range 0..1

# File lib/redgreenblue/base.rb, line 80
def limit(n)
  n <= 0 ? 0.0 : n >= 1 ? 1.0 : n
end
mix_values(some_values, portion) click to toggle source
# File lib/redgreenblue/mix.rb, line 57
def mix_values(some_values, portion)
  raise(ArgumentError, "Portion '#{portion}' not in range (0..1)") unless (0..1).include? portion
  [
    ( red   * (1 - portion) ) + ( some_values[0] * portion ),
    ( green * (1 - portion) ) + ( some_values[1] * portion ),
    ( blue  * (1 - portion) ) + ( some_values[2] * portion )
  ]
end
zip_add(a,b) click to toggle source
# File lib/redgreenblue/math.rb, line 5
def zip_add(a,b)
  a.zip(b).map { |ab| ( ab[0] || 0 ) + ab[1] }
end