redgreenblue 0.9.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,18 +1,28 @@
1
1
  # Optional support for Philips Hue lights.
2
2
  #
3
3
  # Conforms to Bridge API 1.35 for Philips Hue, published 20-Nov-2019.
4
- # See (regrettably requires registration):
5
- # - https://developers.meethue.com/develop/hue-api/
6
4
 
7
5
  # Automatically load core RGB class before loading options.
8
6
  require 'redgreenblue'
9
7
 
10
8
  class RGB
11
9
 
12
- # 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.
13
11
  #
14
- # When formatted as JSON, this hash can be used directly to set a light's state.
15
- # Only available when optional support for Philips Hue lights is loaded (require 'redgreenblue/opt/philipshue').
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/
19
+ #
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
16
26
  def to_philips_hue_api_hsb_arguments(black_off=true)
17
27
  my_hsb = hsb
18
28
 
@@ -3,7 +3,7 @@ class RGB
3
3
  # On Mac OS, shows the color picker to choose a color for the RGB object.
4
4
  # Not available on other platforms.
5
5
  def pick
6
- result = RGB.mac_choose(rrggbb)
6
+ result = RGB.mac_choose(self)
7
7
  if result
8
8
  self.rrggbb = result
9
9
  end
@@ -14,7 +14,7 @@ class RGB
14
14
  #
15
15
  # If no default color is specified, the picker defaults to a middle grey.
16
16
  def self.pick(default_color=RGB.new)
17
- result = RGB.mac_choose(default_color.rrggbb)
17
+ result = RGB.mac_choose(default_color)
18
18
  if result
19
19
  RGB.rrggbb result
20
20
  else
@@ -32,7 +32,7 @@ class RGB
32
32
  #
33
33
  # Applescript command documented here:
34
34
  # Standard Additions -> User Interaction -> choose color
35
- def self.mac_choose(color)
35
+ def self.mac_choose(default_color)
36
36
 
37
37
  app = case ENV['TERM_PROGRAM']
38
38
  when /iTerm\.app/
@@ -44,7 +44,7 @@ class RGB
44
44
  script = <<~ENDSCRIPT
45
45
  tell application "#{app}"
46
46
  try
47
- return choose color default color { #{color[0]}, #{color[1]}, #{color[2]} }
47
+ return choose color default color #{default_color.applescript}
48
48
  on error
49
49
  return ""
50
50
  end try
@@ -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(round: true)
36
+ [
37
+ color_portion = values.max - values.min,
38
+ white_portion = values.min,
39
+ 1 - color_portion - white_portion
40
+ ].map { |v| round ? v.round(8) : v }
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
@@ -15,16 +15,6 @@ class RGB
15
15
  self.b = ( ( v & 0x001f ) ) << 3
16
16
  end
17
17
 
18
- # Deprecated: this method will be removed in a future version.
19
- # Returns the color in 16-bit RGB565 format as a string of 0's and 1's.
20
- def rgb565_binary
21
- unless defined? @@warned_rgb565_binary_deprecation
22
- warn "Warning: 'rgb565_binary' has been deprecated and will be removed in a future version of redgreenblue."
23
- @@warned_rgb565_binary_deprecation = true
24
- end
25
- rgb565.bytes.reverse.map { |b| "%08b" % b }.join
26
- end
27
-
28
18
  # Creates a new RGB color from 16-bit RGB565 data.
29
19
  def self.rgb565(rgb565_string)
30
20
  c = self.new
@@ -1,7 +1,7 @@
1
1
  class RGB
2
2
 
3
3
  # redgreenblue version.
4
- VERSION = '0.9.0'
4
+ VERSION = '0.14.0'
5
5
 
6
6
  # Returns RGB::VERSION.
7
7
  def self.version
@@ -0,0 +1,34 @@
1
+ class RGB
2
+
3
+ # Prints details for the RGB object, using multiple lines.
4
+ def view
5
+ puts _inspect_view
6
+ end
7
+
8
+ alias v view
9
+
10
+ private
11
+
12
+ def _inspect_view
13
+ o = []
14
+ o << 3.times.map { terminal_background + " \e[0m "}
15
+ o << [ "#{_inspect_hex} ", '%-7.7s ' % color_space, ' ' ]
16
+
17
+ o << components.map { |c| c.terminal_background + " \e[0m " }
18
+ o << %w(R: G: B:)
19
+ o << values.map { |v| '%1.5f ' % v }
20
+ o << rgb.map { |v| '%3d ' % v }
21
+
22
+ o << %w(H: S: L:)
23
+ o << hsl.map { |v| v ? ('%7.3f ' % v) : ' - ' }
24
+ o << %w(H: S: B:)
25
+ o << hsb.map { |v| v ? ('%7.3f ' % v) : ' - ' }
26
+
27
+ o << 3.times.map { (ostwald_color ? ostwald_color.terminal_background + " \e[0m " : ' ') }
28
+ o << %w(C: W: K:)
29
+ o << ostwald_cwk.map { |v| '%1.3f ' % v }
30
+
31
+ o.transpose.map(&:join).join("\n")
32
+ end
33
+
34
+ end
@@ -1,5 +1,60 @@
1
1
  class RGB
2
2
 
3
+ #----------------------------------------------------------------------#
4
+ # Class Methods #
5
+ #----------------------------------------------------------------------#
6
+
7
+ class << self
8
+
9
+ # Returns CSS named colors, as per CSS Color Module Level 4.
10
+ #
11
+ # Optional selector argument can be:
12
+ # - String or Regexp (to select by name)
13
+ # - RGB color (to select by color)
14
+ # - Integer (to select by index).
15
+ # Selection by name (string or regular expression) is case-insensitive by default.
16
+ #
17
+ # @example No Selector
18
+ # # All colors
19
+ # RGB.css
20
+ #
21
+ # # Pastels
22
+ # RGB.css.select { |c| c.ostwald_cwk[1] > 0.6 }
23
+ # @example Select by Name
24
+ # # Exact name
25
+ # RGB.css 'pink'
26
+ #
27
+ # # Regular expression
28
+ # RGB.css /pink|rose/
29
+ #
30
+ # @example Select by RGB color
31
+ # RGB.css RGB.hex('0ff')
32
+ def css(selector=nil)
33
+ @@css ||= load_gpl file: ( File.join File.dirname(__FILE__), 'palettes', 'css.gpl' ), freeze: true
34
+ case selector
35
+ when NilClass
36
+ @@css
37
+ when String
38
+ n = selector.downcase
39
+ @@css.select { |c| c.name == n }.first
40
+ when Regexp
41
+ r = Regexp.new selector.source, Regexp::IGNORECASE
42
+ @@css.select { |c| c.name =~ r }
43
+ when Integer
44
+ @@css[selector]
45
+ when self
46
+ @@css.select { |c| c == selector }
47
+ else
48
+ raise ArgumentError, 'Unsupported selector'
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ #----------------------------------------------------------------------#
55
+ # Instance Methods #
56
+ #----------------------------------------------------------------------#
57
+
3
58
  # Returns the object's RGB value in hexadecimal notation as used in CSS.
4
59
  #
5
60
  # Shortens to 3 digits when possible.
@@ -7,4 +62,48 @@ class RGB
7
62
  "##{hex true}"
8
63
  end
9
64
 
65
+ # Returns the names of CSS named colors identical to this color.
66
+ # @example
67
+ # RGB.hex('f0f').css_names
68
+ def css_names
69
+ RGB.css(self).map &:name
70
+ end
71
+
72
+ # Returns the color's relative luminance, as defined by the Web Content Accessibility Guidelines (WCAG) 2.0.
73
+ #
74
+ # This is different from the Y component of CIE 1931 XYZ.
75
+ #
76
+ # Based on:
77
+ # - https://www.w3.org/TR/WCAG20/#relativeluminancedef
78
+ def wcag20_luminance(round: true)
79
+ if color_space == 'sRGB'
80
+ values.map { |v|
81
+ if v <= 0.03928
82
+ v / 12.92
83
+ else
84
+ ( ( v + 0.055 ) / 1.055 ) ** 2.4
85
+ end
86
+ }.zip( [0.2126, 0.7152, 0.0722] ).map { |c,f|
87
+ c * f
88
+ }.inject(:+).instance_eval { |v| round ? v.round(8) : v }
89
+ else
90
+ raise "can not calculate luminance for color space '#{color_space}'"
91
+ end
92
+ end
93
+
94
+ # Returns the contrast ratio for this color and another color, as defined by the Web Content Accessibility Guidelines (WCAG) 2.0.
95
+ #
96
+ # Based on:
97
+ # - https://www.w3.org/TR/WCAG20/#contrast-ratiodef
98
+ def wcag20_contrast_ratio(another, round: true)
99
+ luminances = [
100
+ wcag20_luminance(round: false),
101
+ another.wcag20_luminance(round: false)
102
+ ].sort.reverse
103
+
104
+ contrast_ratio = ( luminances[0] + 0.05 ) / ( luminances[1] + 0.05 )
105
+
106
+ round ? contrast_ratio.round(8) : contrast_ratio
107
+ end
108
+
10
109
  end