redgreenblue 0.8.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,96 @@
1
+ require 'redgreenblue/hsx_shared'
2
+ require 'redgreenblue/math'
3
+
4
+ class RGB
5
+
6
+ #----------------------------------------------------------------------#
7
+ # Class Methods #
8
+ #----------------------------------------------------------------------#
9
+
10
+ class << self
11
+
12
+ # Creates a new RGB object from HSL values: hue (0..360), saturation (0..1), and lightness (0..1).
13
+ def hsl(*a)
14
+ new hsl_to_values(*a)
15
+ end
16
+
17
+ # Calculates RGB values from HSL.
18
+ # Given hue (0..360), saturation (0..1), and lightness (0..1),
19
+ # returns red, green, and blue as three values between 0 and 1.
20
+ def hsl_to_values(*a)
21
+ hsm_to_values(:hsl, a)
22
+ end
23
+
24
+ end
25
+
26
+ #----------------------------------------------------------------------#
27
+ # Instance Methods #
28
+ #----------------------------------------------------------------------#
29
+
30
+ # Returns color as HSL:
31
+ # hue (0..360), saturation (0..1), lightness (0..1).
32
+ # When saturation is 0, hue is nil.
33
+ def hsl
34
+ hsl_hsv_c[0]
35
+ end
36
+
37
+ # Returns the object's HSL-hue (0..360).
38
+ def hsl_h
39
+ hsl[0]
40
+ end
41
+
42
+ # Returns the object's HSL-saturation (0..1).
43
+ def hsl_s
44
+ hsl[1]
45
+ end
46
+
47
+ # Returns the object's HSL-lightness (0..1).
48
+ def hsl_l
49
+ hsl[2]
50
+ end
51
+
52
+ # Sets red, green, and blue using HSL values: hue (0..360), saturation (0..1), and lightness (0..1).
53
+ def hsl=(*a)
54
+ self.values = RGB.hsl_to_values(*a)
55
+ end
56
+
57
+ # Sets HSL-hue to a number of degrees (0..360) or nil.
58
+ #
59
+ # Adjusts red, green, and blue, leaving saturation and lightness unchanged.
60
+ # When hue is nil, saturation will be 0.
61
+ def hsl_h=(degrees)
62
+ self.hsl = hsl.fill(degrees,0,1)
63
+ end
64
+
65
+ # Sets HSL-saturation to a value between 0 and 1.
66
+ #
67
+ # Adjusts red, green, and blue, leaving hue and lightness unchanged.
68
+ # When saturation is 0, hue will be nil.
69
+ def hsl_s=(value)
70
+ self.hsl = hsl.fill(value ,1,1)
71
+ end
72
+
73
+ # Sets HSL-lightness to a value between 0 and 1.
74
+ #
75
+ # Adjusts red, green, and blue, leaving hue and saturation unchanged.
76
+ # When lightness is 0 or 1, hue will be nil, and saturation will be 0.
77
+ def hsl_l=(value)
78
+ self.hsl = hsl.fill(value ,2,1)
79
+ end
80
+
81
+ # Sets red, green, and blue by rotating the object's HSL-hue a number of degrees.
82
+ def hsl_rotate!(degrees)
83
+ self.hsl = zip_add(hsl, [degrees, 0, 0])
84
+ self
85
+ end
86
+
87
+ # Creates one or more new RGB objects by rotating this object's HSL-hue a number of degrees.
88
+ def hsl_rotate(a_degrees, *b_degrees)
89
+ if a_degrees.class != Array and b_degrees.none?
90
+ RGB.hsl zip_add(hsl, [a_degrees, 0, 0])
91
+ else
92
+ ( [a_degrees] + b_degrees ).flatten.map { |degrees| RGB.hsl zip_add(hsl, [degrees, 0, 0]) }
93
+ end
94
+ end
95
+
96
+ end
@@ -0,0 +1,96 @@
1
+ require 'redgreenblue/hsx_shared'
2
+ require 'redgreenblue/math'
3
+
4
+ class RGB
5
+
6
+ #----------------------------------------------------------------------#
7
+ # Class Methods #
8
+ #----------------------------------------------------------------------#
9
+
10
+ class << self
11
+
12
+ # Creates a new RGB object from HSV values: hue (0..360), saturation (0..1), and value (0..1).
13
+ def hsv(*a)
14
+ new hsv_to_values(*a)
15
+ end
16
+
17
+ # Calculates RGB values from HSV.
18
+ # Given hue (0..360), saturation (0..1), and value (0..1),
19
+ # returns red, green, and blue as three values between 0 and 1.
20
+ def hsv_to_values(*a)
21
+ hsm_to_values(:hsv, a)
22
+ end
23
+
24
+ end
25
+
26
+ #----------------------------------------------------------------------#
27
+ # Instance Methods #
28
+ #----------------------------------------------------------------------#
29
+
30
+ # Returns color as HSV:
31
+ # hue (0..360), saturation (0..1), value (0..1).
32
+ # When saturation is 0, hue is nil.
33
+ def hsv
34
+ hsl_hsv_c[1]
35
+ end
36
+
37
+ # Returns the object's HSV-hue (0..360).
38
+ def hsv_h
39
+ hsv[0]
40
+ end
41
+
42
+ # Returns the object's HSV-saturation (0..1).
43
+ def hsv_s
44
+ hsv[1]
45
+ end
46
+
47
+ # Returns the object's HSV-value (0..1).
48
+ def hsv_v
49
+ hsv[2]
50
+ end
51
+
52
+ # Sets red, green, and blue using HSV values: hue (0..360), saturation (0..1), and value (0..1).
53
+ def hsv=(*a)
54
+ self.values = RGB.hsv_to_values(*a)
55
+ end
56
+
57
+ # Sets HSV-hue to a number of degrees (0..360) or nil.
58
+ #
59
+ # Adjusts red, green, and blue, leaving HSV-saturation and -value unchanged.
60
+ # When hue is nil, saturation will be 0.
61
+ def hsv_h=(degrees)
62
+ self.hsv = hsv.fill(degrees,0,1)
63
+ end
64
+
65
+ # Sets HSV-saturation to a number between 0 and 1.
66
+ #
67
+ # Adjusts red, green, and blue, leaving HSV-hue and -value unchanged.
68
+ # When saturation is 0, hue will be nil.
69
+ def hsv_s=(value)
70
+ self.hsv = hsv.fill(value ,1,1)
71
+ end
72
+
73
+ # Sets HSV-value to a number between 0 and 1.
74
+ #
75
+ # Adjusts red, green, and blue, leaving HSV-hue and -saturation unchanged.
76
+ # When value is 0, hue will be nil, and saturation will be 0.
77
+ def hsv_v=(value)
78
+ self.hsv = hsv.fill(value ,2,1)
79
+ end
80
+
81
+ # Sets red, green, and blue by rotating the object's HSV-hue a number of degrees.
82
+ def hsv_rotate!(degrees)
83
+ self.hsv = zip_add(hsv, [degrees, 0, 0])
84
+ self
85
+ end
86
+
87
+ # Creates one or more new RGB objects by rotating this object's HSV-hue a number of degrees.
88
+ def hsv_rotate(a_degrees, *b_degrees)
89
+ if a_degrees.class != Array and b_degrees.none?
90
+ RGB.hsv zip_add(hsv, [a_degrees, 0, 0])
91
+ else
92
+ ( [a_degrees] + b_degrees ).flatten.map { |degrees| RGB.hsv zip_add(hsv, [degrees, 0, 0]) }
93
+ end
94
+ end
95
+
96
+ end
@@ -0,0 +1,94 @@
1
+ class RGB
2
+
3
+ #----------------------------------------------------------------------#
4
+ # Class Methods #
5
+ #----------------------------------------------------------------------#
6
+
7
+ class << self
8
+
9
+ private
10
+
11
+ # Calculates RGB values from HSL or HSV.
12
+ # With help from:
13
+ # - https://en.wikipedia.org/wiki/HSL_and_HSV
14
+ def hsm_to_values(type, *a)
15
+ raise NotImplementedError unless [:hsl, :hsv].include? type
16
+
17
+ hue, saturation, magnitude = a.flatten
18
+
19
+ if ( saturation == 0 ) or ( ! hue )
20
+ return Array.new(3) { magnitude }
21
+ end
22
+
23
+ hue = hue.modulo 360
24
+
25
+ chroma = case type
26
+ when :hsl
27
+ ( 1 - ( 2 * magnitude - 1 ).abs ) * saturation
28
+ when :hsv
29
+ magnitude * saturation
30
+ end
31
+
32
+ values = [
33
+ chroma,
34
+ ( 1 - ( ( hue / 60.0 ).modulo(2) - 1 ).abs ) * chroma,
35
+ 0
36
+ ]
37
+
38
+ values = case type
39
+ when :hsl
40
+ values.map { |v| ( v + magnitude - chroma / 2.0 ).round(9) }
41
+ when :hsv
42
+ values.map { |v| ( v + magnitude - chroma ).round(9) }
43
+ end
44
+
45
+ # order values according to hue sextant
46
+ [ [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]}
47
+ end
48
+
49
+ end
50
+
51
+ #----------------------------------------------------------------------#
52
+ # Instance Methods #
53
+ #----------------------------------------------------------------------#
54
+
55
+ private
56
+
57
+ # Compute HSL, HSV, and chroma.
58
+ # With help from:
59
+ # - https://en.wikipedia.org/wiki/HSL_and_HSV
60
+ def hsl_hsv_c
61
+ sorted_hash = to_h
62
+ min, max = sorted_hash.values.values_at(2,0)
63
+
64
+ chroma = max - min
65
+
66
+ hue =
67
+ if chroma == 0
68
+ nil
69
+ else
70
+ ( case sorted_hash.keys.first
71
+ when :red
72
+ 60 * ( ( ( green - blue ) / chroma ).modulo 6 )
73
+ when :green
74
+ 60 * ( ( blue - red ) / chroma + 2 )
75
+ when :blue
76
+ 60 * ( ( red - green ) / chroma + 4 )
77
+ end
78
+ ).round(6)
79
+ end
80
+
81
+ lightness = ( min + max ) / 2.0
82
+
83
+ saturation_hsl =
84
+ chroma == 0 ? 0.0 : ( chroma / ( 1 - (2 * lightness - 1).abs ) ).round(9)
85
+
86
+ value = max
87
+
88
+ saturation_hsv =
89
+ value == 0 ? 0.0 : chroma / value
90
+
91
+ [ [hue, saturation_hsl, lightness], [hue, saturation_hsv, value], chroma ]
92
+ end
93
+
94
+ end
@@ -3,34 +3,54 @@ class RGB
3
3
  private
4
4
 
5
5
  def _inspect_default(prefix='RGB')
6
- "#{prefix} ##{hex} (red=%1.5f green=%1.5f blue=%1.5f)" % [red, green, blue]
6
+ "#{prefix} #{_inspect_hex} (red=%1.5f green=%1.5f blue=%1.5f)" % [red, green, blue] + ( name ? ' ' + name : '' )
7
7
  end
8
8
 
9
9
  def _inspect_hex
10
- "##{hex}"
10
+ (self == snap ? '#' : '~') + hex
11
11
  end
12
12
 
13
13
  def _inspect_swatch
14
14
  terminal_background + " \e[0m"
15
15
  end
16
16
 
17
+ def _inspect_short
18
+ "#{_inspect_swatch} #{_inspect_hex}"
19
+ end
20
+
17
21
  def _inspect_simple
18
22
  _inspect_default _inspect_swatch
19
23
  end
20
24
 
25
+ def _inspect_name
26
+ _inspect_swatch + ( name ? ' ' + name : '' )
27
+ end
28
+
21
29
  public
22
30
 
31
+ # Returns a programmer-friendly representation of the object.
32
+ #
33
+ # You can choose among several inspect styles. See the styles, style, and style= class methods.
23
34
  def inspect
24
35
  send "_inspect_#{self.class.style}"
25
36
  end
26
37
 
38
+ # Returns a string representation of the object.
27
39
  def to_s
28
40
  _inspect_default
29
41
  end
30
42
 
31
43
  # Returns the base inspect style, dependent on the COLORTERM environment variable.
32
44
  def self.base_style
33
- ENV['COLORTERM'] == 'truecolor' ? 'simple' : 'default'
45
+ if styles.include? ENV['REDGREENBLUE_STYLE']
46
+ ENV['REDGREENBLUE_STYLE']
47
+ else
48
+ if ENV['COLORTERM'] == 'truecolor'
49
+ 'simple'
50
+ else
51
+ 'default'
52
+ end
53
+ end
34
54
  end
35
55
 
36
56
  # Returns the current inspect style.
@@ -44,6 +64,8 @@ class RGB
44
64
  end
45
65
 
46
66
  # Selects an inspect style.
67
+ #
68
+ # Only the first few characters of your preferred style are required.
47
69
  def self.style=(s)
48
70
  @@style = styles.grep( /^#{s.to_s.downcase}/ ).first || style
49
71
  end
@@ -0,0 +1,22 @@
1
+ class RGB
2
+
3
+ # Returns the color as a 24-bit integer in the range 0..16777215.
4
+ def to_i
5
+ ( r << 16 ) + ( g << 8 ) + b
6
+ end
7
+
8
+ # Creates a new RGB object from a 24-bit integer in the range 0..16777215.
9
+ def self.at(number)
10
+ n = number.to_i
11
+ if (0..16777215) === n
12
+ rgb(
13
+ ( n & 0xff0000 ) >> 16,
14
+ ( n & 0x00ff00 ) >> 8,
15
+ ( n & 0x0000ff )
16
+ )
17
+ else
18
+ raise ArgumentError, "Argument '#{number}' not in range 0..16777215"
19
+ end
20
+ end
21
+
22
+ end
@@ -1,38 +1,73 @@
1
1
  class RGB
2
2
 
3
- # Creates a white RGB object.
4
- def self.white
5
- new(1,1,1)
6
- end
3
+ #----------------------------------------------------------------------#
4
+ # Class Methods #
5
+ #----------------------------------------------------------------------#
7
6
 
8
- # Creates a black RGB object.
9
- def self.black
10
- new(0,0,0)
11
- end
7
+ class << self
12
8
 
13
- # Creates a grey RGB object. Defaults to lightness 0.5, a middle grey. Black equals grey(0), white equals grey(1).
14
- #
15
- # ::gray is an alias for ::grey.
16
- def self.grey(lightness=0.5)
17
- new(lightness, lightness, lightness)
18
- end
9
+ # Creates a white RGB object.
10
+ def white
11
+ new(1,1,1)
12
+ end
19
13
 
20
- # Alias gray for grey.
21
- self.singleton_class.send(:alias_method, :gray, :grey)
14
+ # Creates a black RGB object.
15
+ def black
16
+ new(0,0,0)
17
+ end
22
18
 
23
- # Creates a pure red RGB object.
24
- def self.red
25
- new(1,0,0)
26
- end
19
+ # Creates a grey RGB object. Defaults to lightness 0.5, a middle grey. Black equals grey(0), white equals grey(1).
20
+ #
21
+ # ::gray is an alias for ::grey.
22
+ def grey(lightness=0.5)
23
+ new(lightness, lightness, lightness)
24
+ end
27
25
 
28
- # Creates a pure green RGB object.
29
- def self.green
30
- new(0,1,0)
31
- end
26
+ # Alias gray for grey.
27
+ alias gray grey
28
+
29
+ # Creates a pure red RGB object.
30
+ def red
31
+ new(1,0,0)
32
+ end
33
+
34
+ # Creates a pure green RGB object.
35
+ def green
36
+ new(0,1,0)
37
+ end
38
+
39
+ # Creates a pure blue RGB object.
40
+ def blue
41
+ new(0,0,1)
42
+ end
43
+
44
+ # Creates a yellow RGB object.
45
+ def yellow
46
+ new(1,1,0)
47
+ end
48
+
49
+ # Creates a cyan RGB object.
50
+ def cyan
51
+ new(0,1,1)
52
+ end
53
+
54
+ # Creates a magenta RGB object.
55
+ def magenta
56
+ new(1,0,1)
57
+ end
58
+
59
+ # Returns the 8 corners of the RGB cube.
60
+ def corners
61
+ [ black, red, yellow, green, cyan, blue, magenta, white ]
62
+ end
63
+
64
+ # Returns the centre of the RGB cube.
65
+ def centre
66
+ grey
67
+ end
68
+
69
+ alias center centre
32
70
 
33
- # Creates a pure blue RGB object.
34
- def self.blue
35
- new(0,0,1)
36
71
  end
37
72
 
38
73
  end