redgreenblue 0.8.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/redgreenblue.rb +20 -18
- data/lib/redgreenblue/24bit.rb +11 -0
- data/lib/redgreenblue/base.rb +2 -2
- data/lib/redgreenblue/cie_1931.rb +51 -0
- data/lib/redgreenblue/cie_1976.rb +105 -0
- data/lib/redgreenblue/gamma.rb +44 -0
- data/lib/redgreenblue/gpl.rb +91 -0
- data/lib/redgreenblue/hsb.rb +61 -0
- data/lib/redgreenblue/hsl.rb +96 -0
- data/lib/redgreenblue/hsv.rb +96 -0
- data/lib/redgreenblue/hsx_shared.rb +94 -0
- data/lib/redgreenblue/inspect.rb +25 -3
- data/lib/redgreenblue/int.rb +22 -0
- data/lib/redgreenblue/lazy.rb +62 -27
- data/lib/redgreenblue/mac.rb +8 -0
- data/lib/redgreenblue/match.rb +21 -0
- data/lib/redgreenblue/math.rb +9 -0
- data/lib/redgreenblue/misc.rb +27 -2
- data/lib/redgreenblue/mix.rb +27 -6
- data/lib/redgreenblue/name.rb +13 -0
- data/lib/redgreenblue/opt/philipshue.rb +17 -2
- data/lib/redgreenblue/os/mac.rb +9 -6
- data/lib/redgreenblue/ostwald.rb +45 -0
- data/lib/redgreenblue/palettes/css.gpl +164 -0
- data/lib/redgreenblue/rgb565.rb +0 -5
- data/lib/redgreenblue/version.rb +9 -1
- data/lib/redgreenblue/view.rb +34 -0
- data/lib/redgreenblue/web.rb +55 -0
- metadata +23 -6
- data/lib/redgreenblue/cie.rb +0 -62
- data/lib/redgreenblue/hsl_hsv.rb +0 -59
@@ -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
|
data/lib/redgreenblue/inspect.rb
CHANGED
@@ -3,34 +3,54 @@ class RGB
|
|
3
3
|
private
|
4
4
|
|
5
5
|
def _inspect_default(prefix='RGB')
|
6
|
-
"#{prefix}
|
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
|
-
|
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['
|
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
|
data/lib/redgreenblue/lazy.rb
CHANGED
@@ -1,38 +1,73 @@
|
|
1
1
|
class RGB
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
end
|
3
|
+
#----------------------------------------------------------------------#
|
4
|
+
# Class Methods #
|
5
|
+
#----------------------------------------------------------------------#
|
7
6
|
|
8
|
-
|
9
|
-
def self.black
|
10
|
-
new(0,0,0)
|
11
|
-
end
|
7
|
+
class << self
|
12
8
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
21
|
-
|
14
|
+
# Creates a black RGB object.
|
15
|
+
def black
|
16
|
+
new(0,0,0)
|
17
|
+
end
|
22
18
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|