redgreenblue 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9dea62bd74822100097e661284f2d44164a1be23ee0f81acdc778c182f0939ec
4
- data.tar.gz: baa4c5ab0b3a367841ee18d94131ad4077661d515edb29939ed661175b479ee1
3
+ metadata.gz: 766113ae54ad00c066d264e8bd8d63610f5347e75d95aee3c34bacac0b027a99
4
+ data.tar.gz: a91d7d49e36ebfc29328e32c2aa67df908e4fbc9d36c4ec957e1e6d8ed3220b7
5
5
  SHA512:
6
- metadata.gz: 81808e69a0aadb6ea54cb291fd682c1949e2178df1c31954256167552f12b990ef825561689a958cb533144c25d31852785ebcebe9d07ddb5684b3b0dfcd26ba
7
- data.tar.gz: 62370184d5b291081bd8e7a1f698647d961fd4c98525677821950f59e58e5536473d5f4c0e87da53109866e875caf94fc578fdf14d4de602d50fd0085d4fe6d9
6
+ metadata.gz: 587d547ca6139b84ef36f8064a768aee1cdb3f5618f4f03c9ab606df477ad6ebffe82b00837fe55b06fcf2ba6275a1d85484f758394755567b1aab81351bf1df
7
+ data.tar.gz: e5203156810f3f577bbe20de7d862f96518db292b1f848778dc2c9dc5223b16c9e15e6effc2e08ed4dba655891805873fdf95cda511c5a533f87462200401746
@@ -10,14 +10,18 @@ require 'redgreenblue/48bit'
10
10
  require 'redgreenblue/hex'
11
11
 
12
12
  require 'redgreenblue/hsl_hsv'
13
+ require 'redgreenblue/cie'
13
14
 
15
+ require 'redgreenblue/inspect'
14
16
  require 'redgreenblue/lazy'
15
- require 'redgreenblue/nice'
16
17
 
17
18
  require 'redgreenblue/rgb565'
18
19
  require 'redgreenblue/bgr24bit'
19
20
  require 'redgreenblue/gif'
21
+ require 'redgreenblue/terminal'
22
+ require 'redgreenblue/web'
20
23
 
24
+ require 'redgreenblue/mix'
21
25
  require 'redgreenblue/misc'
22
26
  require 'redgreenblue/random'
23
27
 
@@ -51,4 +51,19 @@ class RGB
51
51
  c
52
52
  end
53
53
 
54
+ # Calls the given block for each 24-bit RGB color (from black to white), passing the color as an RGB object.
55
+ #
56
+ # Returns the number of iterations.
57
+ def self.each_24bit_color
58
+ range = 0..255
59
+ range.each do |r|
60
+ range.each do |g|
61
+ range.each do |b|
62
+ yield self.rgb(r,g,b)
63
+ end
64
+ end
65
+ end
66
+ range.size ** 3
67
+ end
68
+
54
69
  end
@@ -1,41 +1,73 @@
1
1
  class RGB
2
2
 
3
- attr_reader :red, :green, :blue
4
-
5
3
  def initialize(*a)
6
4
  self.values = a.any? ? a : [ 0.5, 0.5, 0.5 ]
7
5
  end
8
6
 
9
- def red=(n)
10
- @red = limit(n)
7
+ # Returns the color space.
8
+ #
9
+ # Currently always 'sRGB'.
10
+ def color_space
11
+ @color_space ||= 'sRGB'
12
+ end
13
+
14
+ # Returns the red component as a value between 0 and 1.
15
+ def red
16
+ @red
17
+ end
18
+
19
+ # Returns the green component as a value between 0 and 1.
20
+ def green
21
+ @green
22
+ end
23
+
24
+ # Returns the blue component as a value between 0 and 1.
25
+ def blue
26
+ @blue
27
+ end
28
+
29
+ # Sets the red component to a value between 0 and 1.
30
+ #
31
+ # Values outside the range 0..1 will be clipped.
32
+ def red=(value)
33
+ @red = limit(value)
11
34
  end
12
35
 
13
- def green=(n)
14
- @green = limit(n)
36
+ # Sets the green component to a value between 0 and 1.
37
+ #
38
+ # Values outside the range 0..1 will be clipped.
39
+ def green=(value)
40
+ @green = limit(value)
15
41
  end
16
42
 
17
- def blue=(n)
18
- @blue = limit(n)
43
+ # Sets the blue component to a value between 0 and 1.
44
+ #
45
+ # Values outside the range 0..1 will be clipped.
46
+ def blue=(value)
47
+ @blue = limit(value)
19
48
  end
20
49
 
50
+ # Returns the red, green, and blue components as three values between 0 and 1.
21
51
  def values
22
52
  [ red, green, blue ]
23
53
  end
24
54
 
25
55
  alias to_a values
26
56
 
57
+ # Sets the red, green, and blue components using three values between 0 and 1.
58
+ #
59
+ # Values outside the range 0..1 will be clipped.
27
60
  def values=(*a)
28
61
  self.red, self.green, self.blue = a.flatten
29
62
  end
30
63
 
31
- # Returns true if this object and an other object represent exactly the same color. Otherwise returns false.
64
+ # Returns true if this object and another object represent exactly the same color. Otherwise returns false.
32
65
  def ==(other)
33
66
  ( self.class == other.class ) && ( self.values == other.values )
34
67
  end
35
68
 
36
- # Returns a sorted hash of 3 key/value pairs
37
- # for red, green and blue,
38
- # sorted in order of decreasing value
69
+ # Returns a sorted hash of 3 key/value pairs for red, green and blue,
70
+ # sorted in order of decreasing value.
39
71
  def to_h
40
72
  ([:red, :green, :blue].zip values).sort_by {
41
73
  |k,v| [-v,[:red, :green, :blue].index(k)]
@@ -44,7 +76,7 @@ class RGB
44
76
 
45
77
  private
46
78
 
47
- # limit to 0..1
79
+ # limits to range 0..1
48
80
  def limit(n)
49
81
  n <= 0 ? 0.0 : n >= 1 ? 1.0 : n
50
82
  end
@@ -1,16 +1,16 @@
1
1
  class RGB
2
2
 
3
- # bgr 24-bit methods (as used by BMP bitmaps)
4
-
3
+ # Returns a 3-byte string containing the object's color in BGR24 format.
5
4
  def bgr24
6
5
  [b, g, r].pack('C3')
7
6
  end
8
7
 
9
- def bgr24=(s)
10
- self.b, self.g, self.r = s.unpack('C3')
8
+ # Sets red, green, and blue using BGR24 data (a 3-byte string).
9
+ def bgr24=(bgr_string)
10
+ self.b, self.g, self.r = bgr_string.unpack('C3')
11
11
  end
12
12
 
13
- # factory method
13
+ # Creates a new RGB object from BGR24 data (a 3-byte string).
14
14
  def self.bgr24(bgr)
15
15
  c = self.new
16
16
  c.bgr24 = bgr
@@ -0,0 +1,62 @@
1
+ class RGB
2
+
3
+ # Returns CIE 1931 XYZ values for the RGB object.
4
+ #
5
+ # Based on:
6
+ # - http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html
7
+ # - https://en.wikipedia.org/wiki/CIE_1931_color_space
8
+ # sRGB to XYZ matrix for D65 reference white by Bruce Lindbloom:
9
+ # - http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
10
+ def cie_xyz
11
+ r, g, b = expanded_srgb_values
12
+ [
13
+ r * 0.4124564 + g * 0.3575761 + b * 0.1804375,
14
+ r * 0.2126729 + g * 0.7151522 + b * 0.0721750,
15
+ r * 0.0193339 + g * 0.1191920 + b * 0.9503041
16
+ ].map { |v| v.round(6) }
17
+ end
18
+
19
+ alias xyz cie_xyz
20
+
21
+ # Returns CIE 1931 xyY values for the RGB object.
22
+ #
23
+ # Based on:
24
+ # - https://en.wikipedia.org/wiki/CIE_1931_color_space
25
+ # - http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_xyY.html
26
+ # - https://ninedegreesbelow.com/photography/xyz-rgb.html
27
+ def cie_xyy
28
+ x, y, z = xyz
29
+ [
30
+ x / ( x + y + z ),
31
+ y / ( x + y + z ),
32
+ y
33
+ ].map { |v| v.round(6) }
34
+ end
35
+
36
+ alias xyy cie_xyy
37
+
38
+ # Returns CIE 1931 xy values for the RGB object.
39
+ def cie_xy
40
+ cie_xyy[0..1]
41
+ end
42
+
43
+ alias xy cie_xy
44
+
45
+ private
46
+
47
+ # Returns gamma-expanded (inverse-companded) RGB values for sRGB.
48
+ #
49
+ # Based on:
50
+ # - https://en.wikipedia.org/wiki/SRGB
51
+ # - http://www.brucelindbloom.com/Eqn_RGB_to_XYZ.html
52
+ def expanded_srgb_values
53
+ values.map { |v|
54
+ if v <= 0.04045
55
+ v / 12.92
56
+ else
57
+ ( ( v + 0.055 ) / 1.055 ) ** 2.4
58
+ end
59
+ }
60
+ end
61
+
62
+ end
@@ -1,35 +1,66 @@
1
1
  class RGB
2
2
 
3
+ # Returns a 6-digit hexadecimal string representing the object's red, green, and blue components as 8-bit values.
4
+ #
5
+ # If shorthand is true, returns 3-digit shorthand if possible.
3
6
  def hex(shorthand=false)
4
7
  if shorthand
5
- RGB.hex_shorthand hexadecimal
8
+ RGB.hex_shorthand hex6
6
9
  else
7
- hexadecimal
10
+ hex6
8
11
  end
9
12
  end
10
13
 
11
- def hex=(s)
12
- if ( s =~ /^(#?)(\h\h)(\h\h)(\h\h)$/ ) # 6-digit hex
13
- self.rgb = [ $2.to_i(16), $3.to_i(16), $4.to_i(16) ]
14
- elsif ( s =~ /^(#?)(\h)(\h)(\h)$/ ) # 3-digit hex
15
- self.rgb = [ ($2*2).to_i(16), ($3*2).to_i(16), ($4*2).to_i(16) ]
14
+ # Sets red, green, and blue using a 6- or 3-digit hexadecimal string.
15
+ #
16
+ # The string may include a '#' prefix.
17
+ def hex=(hex_string)
18
+ if rgb = RGB.hex_to_rgb(hex_string)
19
+ self.rgb = rgb
20
+ else
21
+ raise ArgumentError, "'#{hex_string}' is not a usable hexadecimal string"
22
+ end
23
+ end
24
+
25
+
26
+ # Class methods
27
+
28
+
29
+ # Creates a new object from a 6- or 3-digit hexadecimal string representing red, green, and blue.
30
+ #
31
+ # The string may include a '#' prefix.
32
+ def self.hex(hex_string)
33
+ if rgb = RGB.hex_to_rgb(hex_string)
34
+ self.rgb rgb
35
+ else
36
+ raise ArgumentError, "'#{hex_string}' is not a usable hexadecimal string"
16
37
  end
17
38
  end
18
39
 
19
- # factory method
20
- def self.hex(s)
21
- c = self.new
22
- c.hex = s
23
- c
40
+ # Returns a 3-digit shorthand version of a 6-digit hexadecimal string.
41
+ #
42
+ # If a shorthand version is not possible, returns the original string.
43
+ def self.hex_shorthand(hex_string)
44
+ hex_string.sub( /^(#?)(\h)\2(\h)\3(\h)\4$/, '\1\2\3\4' )
24
45
  end
25
46
 
26
- def self.hex_shorthand(h)
27
- h.sub( /^(#?)(\h)\2(\h)\3(\h)\4$/, '\1\2\3\4' )
47
+ # Parses a 6- or 3-digit hexadecimal string.
48
+ # Returns three integers in the range 0..255, or nil if not successful.
49
+ #
50
+ # The string may include a '#' prefix.
51
+ def self.hex_to_rgb(hex_string)
52
+ if hex_string =~ /^(#?)(\h\h)(\h\h)(\h\h)$/
53
+ [$2, $3, $4].map { |h| h.to_i(16) }
54
+ elsif hex_string =~ /^(#?)(\h)(\h)(\h)$/
55
+ [$2, $3, $4].map { |h| (h*2).to_i(16) }
56
+ else
57
+ nil
58
+ end
28
59
  end
29
60
 
30
61
  private
31
62
 
32
- def hexadecimal
63
+ def hex6
33
64
  '%02x%02x%02x' % [ r, g, b ]
34
65
  end
35
66
 
@@ -0,0 +1,51 @@
1
+ class RGB
2
+
3
+ private
4
+
5
+ def _inspect_default(prefix='RGB')
6
+ "#{prefix} ##{hex} (red=%1.5f green=%1.5f blue=%1.5f)" % [red, green, blue]
7
+ end
8
+
9
+ def _inspect_hex
10
+ "##{hex}"
11
+ end
12
+
13
+ def _inspect_swatch
14
+ terminal_background + " \e[0m"
15
+ end
16
+
17
+ def _inspect_simple
18
+ _inspect_default _inspect_swatch
19
+ end
20
+
21
+ public
22
+
23
+ def inspect
24
+ send "_inspect_#{self.class.style}"
25
+ end
26
+
27
+ def to_s
28
+ _inspect_default
29
+ end
30
+
31
+ # Returns the base inspect style, dependent on the COLORTERM environment variable.
32
+ def self.base_style
33
+ ENV['COLORTERM'] == 'truecolor' ? 'simple' : 'default'
34
+ end
35
+
36
+ # Returns the current inspect style.
37
+ def self.style
38
+ @@style ||= base_style
39
+ end
40
+
41
+ # Returns a list of all available inspect styles.
42
+ def self.styles
43
+ ( self.instance_methods + self.private_instance_methods ).grep( /^_inspect_(.*)/ ) { $1 }.sort
44
+ end
45
+
46
+ # Selects an inspect style.
47
+ def self.style=(s)
48
+ @@style = styles.grep( /^#{s.to_s.downcase}/ ).first || style
49
+ end
50
+
51
+ end
@@ -1,60 +1,27 @@
1
1
  class RGB
2
2
 
3
- # Mix
4
-
5
- # Mix with second RGB color.
6
- # p denotes portion of the mixed-in color to be used.
7
- # p=0 delivers pure original color (no change),
8
- # p=1 delivers pure mixed-in color.
9
-
10
- def mix!(color,p=0.5)
11
- self.values = mix_values(color.values, p)
12
- self
13
- end
14
-
15
- def mix(color,p=0.5)
16
- RGB.new mix_values(color.values, p)
17
- end
18
-
19
- # Invert
20
-
3
+ # Inverts the object's color.
21
4
  def invert!
22
- self.values = values.map { |v| 1-v }
5
+ self.values = values.map { |v| 1 - v }
23
6
  self
24
7
  end
25
8
 
9
+ # Creates a new RGB object with the inverted color of this RGB object.
26
10
  def invert
27
11
  dup.invert!
28
12
  end
29
13
 
30
- # Mix with white
31
-
32
- def whiten!(p)
33
- mix!(RGB.white, p)
34
- end
35
-
36
- def whiten(p)
37
- mix(RGB.white, p)
38
- end
39
-
40
- # Mix with black
41
-
42
- def blacken!(p)
43
- mix!(RGB.black, p)
14
+ # Returns an array of RGB objects for all possible ways in which the red, green, and blue values of this object can be exchanged.
15
+ #
16
+ # Example: RGB.red.permutation returns [ RGB.red, RGB.green, RGB.blue ]
17
+ # See also: shuffle
18
+ def permutation
19
+ values.permutation.to_a.uniq.map { |v| RGB.new v }
44
20
  end
45
21
 
46
- def blacken(p)
47
- mix(RGB.black, p)
22
+ # Returns an array of three RGB objects, for the red, green, and blue components of this object.
23
+ def components
24
+ [ RGB.new(red,0,0), RGB.new(0,green,0), RGB.new(0,0,blue) ]
48
25
  end
49
26
 
50
- private
51
-
52
- def mix_values(v, p)
53
- raise(ArgumentError, "Portion '#{p}' not in range (0..1)") unless (0..1).include? p
54
- [
55
- ( red * (1-p) ) + ( v[0] * p ),
56
- ( green * (1-p) ) + ( v[1] * p ),
57
- ( blue * (1-p) ) + ( v[2] * p )
58
- ]
59
- end
60
27
  end
@@ -0,0 +1,44 @@
1
+ class RGB
2
+
3
+ # Changes the object's color by mixing it with a portion of another RGB color.
4
+ def mix!(another,portion=0.5)
5
+ self.values = mix_values(another.values, portion)
6
+ self
7
+ end
8
+
9
+ # Creates a new RGB object by mixing this object's color with a portion of another RGB color.
10
+ def mix(another,portion=0.5)
11
+ RGB.new mix_values(another.values, portion)
12
+ end
13
+
14
+ # Changes the object's color by mixing it with a portion of white.
15
+ def whiten!(portion=0.5)
16
+ mix!(RGB.white, portion)
17
+ end
18
+
19
+ # Creates a new RGB object by mixing this object's color with a portion of white.
20
+ def whiten(portion=0.5)
21
+ mix(RGB.white, portion)
22
+ end
23
+
24
+ # Changes the object's color by mixing it with a portion of black.
25
+ def blacken!(portion=0.5)
26
+ mix!(RGB.black, portion)
27
+ end
28
+
29
+ # Creates a new RGB object by mixing this object's color with a portion of black.
30
+ def blacken(portion=0.5)
31
+ mix(RGB.black, portion)
32
+ end
33
+
34
+ private
35
+
36
+ def mix_values(some_values, portion)
37
+ raise(ArgumentError, "Portion '#{portion}' not in range (0..1)") unless (0..1).include? portion
38
+ [
39
+ ( red * (1 - portion) ) + ( some_values[0] * portion ),
40
+ ( green * (1 - portion) ) + ( some_values[1] * portion ),
41
+ ( blue * (1 - portion) ) + ( some_values[2] * portion )
42
+ ]
43
+ end
44
+ end
@@ -1,9 +1,13 @@
1
+ # Optional support for Philips Hue lights.
2
+
3
+ # Automatically load core RGB class before loading options.
4
+ require 'redgreenblue'
5
+
1
6
  class RGB
2
7
 
3
8
  # Returns the arguments required by the Philips Hue API to set a light to this RGB object's hue, saturation and brightness (HSB).
4
9
  #
5
- # When formatted as JSON, this hash can be used
6
- # directly to set a light's state.
10
+ # When formatted as JSON, this hash can be used directly to set a light's state.
7
11
  def to_philips_hue_api_hsb_arguments(black_off=true)
8
12
  my_hsb = hsb
9
13
 
@@ -31,8 +31,15 @@ class RGB
31
31
  # Standard Additions -> User Interaction -> choose color
32
32
  def self.mac_choose(color)
33
33
 
34
+ app = case ENV['TERM_PROGRAM']
35
+ when /iTerm\.app/
36
+ 'iTerm'
37
+ else
38
+ 'Terminal'
39
+ end
40
+
34
41
  script = <<~ENDSCRIPT
35
- tell application "Terminal"
42
+ tell application "#{app}"
36
43
  try
37
44
  return choose color default color { #{color[0]}, #{color[1]}, #{color[2]} }
38
45
  on error
@@ -6,6 +6,11 @@ class RGB
6
6
  self
7
7
  end
8
8
 
9
+ # Creates a new RGB object with this object's red, green, and blue values shuffled.
10
+ def shuffle
11
+ RGB.new values.shuffle
12
+ end
13
+
9
14
  # Assigns random values to red, green, and blue.
10
15
  def randomize!
11
16
  self.values = Kernel::rand, Kernel::rand, Kernel::rand
@@ -0,0 +1,19 @@
1
+ class RGB
2
+
3
+ # With help from:
4
+ # - https://gist.github.com/XVilka/8346728
5
+ # - https://unix.stackexchange.com/questions/404414
6
+
7
+ # Returns the ANSI escape sequence required to set the foreground color on a terminal to this color.
8
+ # Only works on terminals that support 24-bit colors, so-called "true color".
9
+ def terminal_foreground
10
+ "\e[38;2;%d;%d;%dm" % rgb
11
+ end
12
+
13
+ # Returns the ANSI escape sequence required to set the background color on a terminal to this color.
14
+ # Only works on terminals that support 24-bit colors, so-called "true color".
15
+ def terminal_background
16
+ "\e[48;2;%d;%d;%dm" % rgb
17
+ end
18
+
19
+ end
@@ -1,3 +1,3 @@
1
1
  class RGB
2
- VERSION = '0.7.0'
2
+ VERSION = '0.8.0'
3
3
  end
@@ -0,0 +1,10 @@
1
+ class RGB
2
+
3
+ # Returns the object's RGB value in hexadecimal notation as used in CSS.
4
+ #
5
+ # Shortens to 3 digits when possible.
6
+ def css_hex
7
+ "##{hex true}"
8
+ end
9
+
10
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redgreenblue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - lllist.eu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-11 00:00:00.000000000 Z
11
+ date: 2019-12-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -21,18 +21,22 @@ files:
21
21
  - lib/redgreenblue/48bit.rb
22
22
  - lib/redgreenblue/base.rb
23
23
  - lib/redgreenblue/bgr24bit.rb
24
+ - lib/redgreenblue/cie.rb
24
25
  - lib/redgreenblue/gif.rb
25
26
  - lib/redgreenblue/hex.rb
26
27
  - lib/redgreenblue/hsl_hsv.rb
28
+ - lib/redgreenblue/inspect.rb
27
29
  - lib/redgreenblue/lazy.rb
28
30
  - lib/redgreenblue/misc.rb
29
- - lib/redgreenblue/nice.rb
31
+ - lib/redgreenblue/mix.rb
30
32
  - lib/redgreenblue/opt/philipshue.rb
31
33
  - lib/redgreenblue/os.rb
32
34
  - lib/redgreenblue/os/mac.rb
33
35
  - lib/redgreenblue/random.rb
34
36
  - lib/redgreenblue/rgb565.rb
37
+ - lib/redgreenblue/terminal.rb
35
38
  - lib/redgreenblue/version.rb
39
+ - lib/redgreenblue/web.rb
36
40
  homepage: https://github.com/lllisteu/redgreenblue
37
41
  licenses:
38
42
  - MIT
@@ -52,8 +56,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
52
56
  - !ruby/object:Gem::Version
53
57
  version: '0'
54
58
  requirements: []
55
- rubygems_version: 3.0.3
59
+ rubygems_version: 3.0.6
56
60
  signing_key:
57
61
  specification_version: 4
58
- summary: A simple Ruby library for handling RGB colors
62
+ summary: A simple Ruby library for handling RGB colors.
59
63
  test_files: []
@@ -1,9 +0,0 @@
1
- class RGB
2
-
3
- def inspect
4
- "RGB ##{hex} (red=%1.5f green=%1.5f blue=%1.5f)" % [red, green, blue]
5
- end
6
-
7
- alias to_s inspect
8
-
9
- end