redgreenblue 0.7.0 → 0.12.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.
@@ -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
@@ -35,4 +35,19 @@ class RGB
35
35
  new(0,0,1)
36
36
  end
37
37
 
38
+ # Creates a yellow RGB object.
39
+ def self.yellow
40
+ new(1,1,0)
41
+ end
42
+
43
+ # Creates a cyan RGB object.
44
+ def self.cyan
45
+ new(0,1,1)
46
+ end
47
+
48
+ # Creates a magenta RGB object.
49
+ def self.magenta
50
+ new(1,0,1)
51
+ end
52
+
38
53
  end
@@ -0,0 +1,9 @@
1
+ class RGB
2
+
3
+ private
4
+
5
+ def zip_add(a,b)
6
+ a.zip(b).map { |ab| ( ab[0] || 0 ) + ab[1] }
7
+ end
8
+
9
+ end
@@ -1,60 +1,52 @@
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)
14
+ # Returns true when this is an achromatic color: red, green, and blue have equal values.
15
+ # Otherwise false.
16
+ def achromatic?
17
+ values.min == values.max
34
18
  end
35
19
 
36
- def whiten(p)
37
- mix(RGB.white, p)
20
+ # Returns an array of RGB objects for all possible ways in which the red, green, and blue values of this object can be exchanged.
21
+ #
22
+ # Example: RGB.red.permutation returns [ RGB.red, RGB.green, RGB.blue ].
23
+ # See also: shuffle.
24
+ def permutation
25
+ values.permutation.to_a.uniq.map { |v| RGB.new v }
38
26
  end
39
27
 
40
- # Mix with black
41
-
42
- def blacken!(p)
43
- mix!(RGB.black, p)
28
+ # Returns an array of three RGB objects, for the red, green, and blue components of this object.
29
+ def components
30
+ [ RGB.new(red,0,0), RGB.new(0,green,0), RGB.new(0,0,blue) ]
44
31
  end
45
32
 
46
- def blacken(p)
47
- mix(RGB.black, p)
33
+ # Creates a new RGB object from three RGB objects representing the red, green, and blue components.
34
+ def self.assemble(*a)
35
+ v = a.flatten
36
+ RGB.new(v[0].red, v[1].green, v[2].blue)
48
37
  end
49
38
 
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
- ]
39
+ # Returns the euclidean distance between this color and another color.
40
+ #
41
+ # When you imagine a color as a point in a 3-dimensional space,
42
+ # the dimensions being red, green, and blue,
43
+ # this is the distance between two colors.
44
+ def distance(another)
45
+ (
46
+ ( (another.red - red ) ** 2) +
47
+ ( (another.green - green) ** 2) +
48
+ ( (another.blue - blue ) ** 2)
49
+ ) ** (1/2.0)
59
50
  end
51
+
60
52
  end
@@ -0,0 +1,65 @@
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 one or more new RGB objects by mixing this object's color with a portion of white.
20
+ def whiten(portion=0.5, *portions)
21
+ if (portion.class != Array) and portions.none?
22
+ mix(RGB.white, portion)
23
+ else
24
+ ( [portion].flatten + portions ).map { |p| mix(RGB.white, p) }
25
+ end
26
+ end
27
+
28
+ # Changes the object's color by mixing it with a portion of black.
29
+ def blacken!(portion=0.5)
30
+ mix!(RGB.black, portion)
31
+ end
32
+
33
+ # Creates one or more new RGB objects by mixing this object's color with a portion of black.
34
+ def blacken(portion=0.5, *portions)
35
+ if (portion.class != Array) and portions.none?
36
+ mix(RGB.black, portion)
37
+ else
38
+ ( [portion].flatten + portions ).map { |p| mix(RGB.black, p) }
39
+ end
40
+ end
41
+
42
+ # Returns a set of colors between this color and another. That other color is included.
43
+ #
44
+ # The resulting colors are spaced evenly in the RGB color space using a straightforward calculation.
45
+ # You will likely experience these colors as not exactly evenly spaced.
46
+ def steps(another,step_count=1,include_begin=false)
47
+ # origin (self, optional)
48
+ ( include_begin ? [self.dup] : [] ) +
49
+ # ...plus intermediate colors
50
+ (1..step_count-1).map { |c| mix(another, c.to_f/step_count) } +
51
+ # ...plus destination color
52
+ [another.dup]
53
+ end
54
+
55
+ private
56
+
57
+ def mix_values(some_values, portion)
58
+ raise(ArgumentError, "Portion '#{portion}' not in range (0..1)") unless (0..1).include? portion
59
+ [
60
+ ( red * (1 - portion) ) + ( some_values[0] * portion ),
61
+ ( green * (1 - portion) ) + ( some_values[1] * portion ),
62
+ ( blue * (1 - portion) ) + ( some_values[2] * portion )
63
+ ]
64
+ end
65
+ end
@@ -0,0 +1,13 @@
1
+ class RGB
2
+
3
+ # Returns the name.
4
+ def name
5
+ defined?(@name) ? @name : nil
6
+ end
7
+
8
+ # Sets the name (a string or nil).
9
+ def name=(text)
10
+ @name = ( text.to_s.size != 0 ) ? text.to_s : nil
11
+ end
12
+
13
+ end
@@ -1,9 +1,28 @@
1
+ # Optional support for Philips Hue lights.
2
+ #
3
+ # Conforms to Bridge API 1.35 for Philips Hue, published 20-Nov-2019.
4
+
5
+ # Automatically load core RGB class before loading options.
6
+ require 'redgreenblue'
7
+
1
8
  class RGB
2
9
 
3
- # Returns the arguments required by the Philips Hue API to set a light to this RGB object's hue, saturation and brightness (HSB).
10
+ # Only available when optional support for Philips Hue lights is loaded.
11
+ #
12
+ # Returns a hash with the arguments required by the Philips Hue API,
13
+ # to set a light to this RGB object's hue, saturation and brightness.
14
+ #
15
+ # Formatted as JSON, this hash can be sent to a bridge to set a light's state.
16
+ #
17
+ # See (regrettably requires registration):
18
+ # - https://developers.meethue.com/develop/hue-api/
4
19
  #
5
- # When formatted as JSON, this hash can be used
6
- # directly to set a light's state.
20
+ # @example Load
21
+ # require 'redgreenblue/opt/philipshue'
22
+ # @example Use
23
+ # RGB.magenta.to_philips_hue_api_hsb_arguments
24
+ # => {"on"=>true, "bri"=>254, "hue"=>54613, "sat"=>254}
25
+ # @return [Hash] API arguments
7
26
  def to_philips_hue_api_hsb_arguments(black_off=true)
8
27
  my_hsb = hsb
9
28
 
@@ -1,6 +1,7 @@
1
1
  class RGB
2
2
 
3
- # Shows the Mac OS color picker to choose a color for the RGB object.
3
+ # On Mac OS, shows the color picker to choose a color for the RGB object.
4
+ # Not available on other platforms.
4
5
  def pick
5
6
  result = RGB.mac_choose(rrggbb)
6
7
  if result
@@ -8,7 +9,9 @@ class RGB
8
9
  end
9
10
  end
10
11
 
11
- # Shows the Mac OS color picker and creates an RGB object with the chosen color.
12
+ # On Mac OS, shows the color picker and creates an RGB object with the chosen color.
13
+ # Not available on other platforms.
14
+ #
12
15
  # If no default color is specified, the picker defaults to a middle grey.
13
16
  def self.pick(default_color=RGB.new)
14
17
  result = RGB.mac_choose(default_color.rrggbb)
@@ -31,8 +34,15 @@ class RGB
31
34
  # Standard Additions -> User Interaction -> choose color
32
35
  def self.mac_choose(color)
33
36
 
37
+ app = case ENV['TERM_PROGRAM']
38
+ when /iTerm\.app/
39
+ 'iTerm'
40
+ else
41
+ 'Terminal'
42
+ end
43
+
34
44
  script = <<~ENDSCRIPT
35
- tell application "Terminal"
45
+ tell application "#{app}"
36
46
  try
37
47
  return choose color default color { #{color[0]}, #{color[1]}, #{color[2]} }
38
48
  on error
@@ -0,0 +1,45 @@
1
+ class RGB
2
+
3
+ # Returns a new RGB object with this color's Ostwald full-color,
4
+ # or nil for achromatic colors (white, greys, and black).
5
+ #
6
+ # The resulting color contains no white or black,
7
+ # i.e. it has at least one RGB component set to 0, and at least one set to maximum.
8
+ #
9
+ # This is identical (barring very small rounding errors)
10
+ # to setting HSL-saturation to 1, and -lightness to 0.5
11
+ #
12
+ # Based on:
13
+ # - Color for the Sciences, pp. 575–591
14
+ # - https://lirias.kuleuven.be/retrieve/306124 (PDF)
15
+ def ostwald_color
16
+ white_portion = values.min
17
+ color_portion = values.max - white_portion
18
+
19
+ if color_portion == 0
20
+ nil
21
+ else
22
+ RGB.new( values.map { |v| ( ( v - white_portion ) / color_portion ).round(6) } )
23
+ end
24
+ end
25
+
26
+ # Returns the portions of Ostwald full-color, white, and black, which constitute this color.
27
+ #
28
+ # The sum of these three numbers equals 1.
29
+ #
30
+ # #cwk is an alias for #ostwald_cwk.
31
+ #
32
+ # Based on:
33
+ # - Color for the Sciences, pp. 575–591
34
+ # - https://lirias.kuleuven.be/retrieve/306124 (PDF)
35
+ def ostwald_cwk
36
+ [
37
+ color_portion = values.max - values.min,
38
+ white_portion = values.min,
39
+ 1 - color_portion - white_portion
40
+ ]
41
+ end
42
+
43
+ alias cwk ostwald_cwk
44
+
45
+ end
@@ -0,0 +1,164 @@
1
+ GIMP Palette
2
+ Name: CSS Named Colors
3
+ #
4
+ # As per CSS Color Module Level 4, Editor's Draft, 19 August 2020.
5
+ # - source: https://drafts.csswg.org/css-color/#named-colors
6
+ #
7
+ # Notes:
8
+ # "Don't cite this document other than as work in progress."
9
+ #
10
+ # "CSS defines a large set of named colors, so that
11
+ # common colors can be written and read more easily."
12
+ #
13
+ # "[...] all of these keywords are ASCII case-insensitive."
14
+ #
15
+ # "The names resolve to colors in sRGB."
16
+ #
17
+ 240 248 255 aliceblue
18
+ 250 235 215 antiquewhite
19
+ 0 255 255 aqua
20
+ 127 255 212 aquamarine
21
+ 240 255 255 azure
22
+ 245 245 220 beige
23
+ 255 228 196 bisque
24
+ 0 0 0 black
25
+ 255 235 205 blanchedalmond
26
+ 0 0 255 blue
27
+ 138 43 226 blueviolet
28
+ 165 42 42 brown
29
+ 222 184 135 burlywood
30
+ 95 158 160 cadetblue
31
+ 127 255 0 chartreuse
32
+ 210 105 30 chocolate
33
+ 255 127 80 coral
34
+ 100 149 237 cornflowerblue
35
+ 255 248 220 cornsilk
36
+ 220 20 60 crimson
37
+ 0 255 255 cyan
38
+ 0 0 139 darkblue
39
+ 0 139 139 darkcyan
40
+ 184 134 11 darkgoldenrod
41
+ 169 169 169 darkgray
42
+ 0 100 0 darkgreen
43
+ 169 169 169 darkgrey
44
+ 189 183 107 darkkhaki
45
+ 139 0 139 darkmagenta
46
+ 85 107 47 darkolivegreen
47
+ 255 140 0 darkorange
48
+ 153 50 204 darkorchid
49
+ 139 0 0 darkred
50
+ 233 150 122 darksalmon
51
+ 143 188 143 darkseagreen
52
+ 72 61 139 darkslateblue
53
+ 47 79 79 darkslategray
54
+ 47 79 79 darkslategrey
55
+ 0 206 209 darkturquoise
56
+ 148 0 211 darkviolet
57
+ 255 20 147 deeppink
58
+ 0 191 255 deepskyblue
59
+ 105 105 105 dimgray
60
+ 105 105 105 dimgrey
61
+ 30 144 255 dodgerblue
62
+ 178 34 34 firebrick
63
+ 255 250 240 floralwhite
64
+ 34 139 34 forestgreen
65
+ 255 0 255 fuchsia
66
+ 220 220 220 gainsboro
67
+ 248 248 255 ghostwhite
68
+ 255 215 0 gold
69
+ 218 165 32 goldenrod
70
+ 128 128 128 gray
71
+ 0 128 0 green
72
+ 173 255 47 greenyellow
73
+ 128 128 128 grey
74
+ 240 255 240 honeydew
75
+ 255 105 180 hotpink
76
+ 205 92 92 indianred
77
+ 75 0 130 indigo
78
+ 255 255 240 ivory
79
+ 240 230 140 khaki
80
+ 230 230 250 lavender
81
+ 255 240 245 lavenderblush
82
+ 124 252 0 lawngreen
83
+ 255 250 205 lemonchiffon
84
+ 173 216 230 lightblue
85
+ 240 128 128 lightcoral
86
+ 224 255 255 lightcyan
87
+ 250 250 210 lightgoldenrodyellow
88
+ 211 211 211 lightgray
89
+ 144 238 144 lightgreen
90
+ 211 211 211 lightgrey
91
+ 255 182 193 lightpink
92
+ 255 160 122 lightsalmon
93
+ 32 178 170 lightseagreen
94
+ 135 206 250 lightskyblue
95
+ 119 136 153 lightslategray
96
+ 119 136 153 lightslategrey
97
+ 176 196 222 lightsteelblue
98
+ 255 255 224 lightyellow
99
+ 0 255 0 lime
100
+ 50 205 50 limegreen
101
+ 250 240 230 linen
102
+ 255 0 255 magenta
103
+ 128 0 0 maroon
104
+ 102 205 170 mediumaquamarine
105
+ 0 0 205 mediumblue
106
+ 186 85 211 mediumorchid
107
+ 147 112 219 mediumpurple
108
+ 60 179 113 mediumseagreen
109
+ 123 104 238 mediumslateblue
110
+ 0 250 154 mediumspringgreen
111
+ 72 209 204 mediumturquoise
112
+ 199 21 133 mediumvioletred
113
+ 25 25 112 midnightblue
114
+ 245 255 250 mintcream
115
+ 255 228 225 mistyrose
116
+ 255 228 181 moccasin
117
+ 255 222 173 navajowhite
118
+ 0 0 128 navy
119
+ 253 245 230 oldlace
120
+ 128 128 0 olive
121
+ 107 142 35 olivedrab
122
+ 255 165 0 orange
123
+ 255 69 0 orangered
124
+ 218 112 214 orchid
125
+ 238 232 170 palegoldenrod
126
+ 152 251 152 palegreen
127
+ 175 238 238 paleturquoise
128
+ 219 112 147 palevioletred
129
+ 255 239 213 papayawhip
130
+ 255 218 185 peachpuff
131
+ 205 133 63 peru
132
+ 255 192 203 pink
133
+ 221 160 221 plum
134
+ 176 224 230 powderblue
135
+ 128 0 128 purple
136
+ 102 51 153 rebeccapurple
137
+ 255 0 0 red
138
+ 188 143 143 rosybrown
139
+ 65 105 225 royalblue
140
+ 139 69 19 saddlebrown
141
+ 250 128 114 salmon
142
+ 244 164 96 sandybrown
143
+ 46 139 87 seagreen
144
+ 255 245 238 seashell
145
+ 160 82 45 sienna
146
+ 192 192 192 silver
147
+ 135 206 235 skyblue
148
+ 106 90 205 slateblue
149
+ 112 128 144 slategray
150
+ 112 128 144 slategrey
151
+ 255 250 250 snow
152
+ 0 255 127 springgreen
153
+ 70 130 180 steelblue
154
+ 210 180 140 tan
155
+ 0 128 128 teal
156
+ 216 191 216 thistle
157
+ 255 99 71 tomato
158
+ 64 224 208 turquoise
159
+ 238 130 238 violet
160
+ 245 222 179 wheat
161
+ 255 255 255 white
162
+ 245 245 245 whitesmoke
163
+ 255 255 0 yellow
164
+ 154 205 50 yellowgreen