pigment 0.2.3 → 0.3.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 +5 -5
- data/CHANGELOG.md +6 -0
- data/LICENSE.md +22 -0
- data/README.md +176 -20
- data/lib/pigment.rb +3 -306
- data/lib/pigment/color.rb +195 -0
- data/lib/pigment/color/hsl.rb +154 -0
- data/lib/pigment/color/invalid_color_format_error.rb +10 -0
- data/lib/pigment/color/rgb.rb +279 -0
- data/lib/pigment/default_rgb_palette.rb +891 -0
- data/lib/pigment/float_snap.rb +14 -0
- data/lib/pigment/palette.rb +99 -0
- data/lib/pigment/version.rb +3 -0
- metadata +97 -22
- data/lib/colors.rb +0 -756
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: dda5e6ade89b5949326fcb411e9aa8d99065fa511d3baeebb08e1cfb6199e84e
|
4
|
+
data.tar.gz: '058d8b2c5e47edfe74d716688ab99e33b99b51c46773dd0600c43c4755010b2e'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 409765f525e55b3b63fd2ce3fe1e54af1fb070600c4f049a7992d984bd20b0b7f08bbdedb08f5702d6a9f53b50f035c4e25cff4013d741175f5615f889b1febd
|
7
|
+
data.tar.gz: ab38122e3bbd72c5af6f78a451ae885b52673ec3583a05d346af1bd9c81bd8d844d0dea757fb8e5a5eb7a111452815a192cfebd079304707128a35b45ced28d6
|
data/CHANGELOG.md
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright © 2020 Pedro Miranda
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
'Software'), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -6,29 +6,185 @@ To install:
|
|
6
6
|
gem install pigment
|
7
7
|
```
|
8
8
|
|
9
|
-
|
9
|
+
## Usage
|
10
|
+
### RGB Color Format
|
11
|
+
The RGB color format is represented with four components between 0.0 and 1.0, representing 0 to 255
|
12
|
+
- `@red`
|
13
|
+
- `@green`
|
14
|
+
- `@blue`
|
15
|
+
- `@alpha`
|
10
16
|
|
11
|
-
|
17
|
+
```ruby
|
18
|
+
require 'pigment/color/rgb'
|
12
19
|
|
13
|
-
(
|
20
|
+
red = Pigment::Color::RGB.new(1.0, 0.0, 0.0)
|
21
|
+
# RGB Color(red: 1.0, green: 0.0, blue: 0.0, alpha: 0.0)
|
14
22
|
|
15
|
-
|
23
|
+
red.to_a
|
24
|
+
# [1.0, 0.0, 0.0, 1.0]
|
16
25
|
|
17
|
-
|
18
|
-
|
19
|
-
'Software'), to deal in the Software without restriction, including
|
20
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
21
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
22
|
-
permit persons to whom the Software is furnished to do so, subject to
|
23
|
-
the following conditions:
|
26
|
+
semitransparent_red = Pigment::Color::RGB.new(1.0, 0.0, 0.0, 0.5)
|
27
|
+
# RGB Color(red: 1.0, green: 0.0, blue: 0.0, alpha: 0.5)
|
24
28
|
|
25
|
-
|
26
|
-
|
29
|
+
red + semitransparent_red
|
30
|
+
# RGB Color(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
|
27
31
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
semitransparent_red + red
|
33
|
+
# RGB Color(red: 1.0, green: 0.0, blue: 0.0, alpha: 0.5)
|
34
|
+
|
35
|
+
red - semitransparent_red
|
36
|
+
# RGB Color(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)
|
37
|
+
|
38
|
+
half_red = red / 2
|
39
|
+
# RGB Color(red: 0.5, green: 0.0, blue: 0.0, alpha: 1.0)
|
40
|
+
|
41
|
+
half_red * 2 == red
|
42
|
+
# true
|
43
|
+
|
44
|
+
gray50 = Pigment::Color::RGB.new(1.0, 0.5, 0.0).grayscale
|
45
|
+
# RGB Color(red: 0.5, green: 0.5, blue: 0.5, alpha: 1.0)
|
46
|
+
|
47
|
+
gray50.grayscale?
|
48
|
+
# true
|
49
|
+
|
50
|
+
cyan = red.inverse
|
51
|
+
# RGB Color(red: 0.0, green: 1.0, blue: 1.0, alpha: 1.0)
|
52
|
+
|
53
|
+
green, blue = red.triadic
|
54
|
+
# [RGB Color(red: 0.0, green: 1.0, blue: 0.0, alpha: 1.0), RGB Color(red: 0.0, green: 0.0, blue: 1.0, alpha: 1.0)]
|
55
|
+
|
56
|
+
red.to_hex
|
57
|
+
# '0xff0000ff'
|
58
|
+
|
59
|
+
red.to_hex(with_alpha: false)
|
60
|
+
# '0xff0000'
|
61
|
+
|
62
|
+
Pigment::Color::RGB.convert(Pigment::Color::HSL.new(0.0, 1, 0.5))
|
63
|
+
# RGB Color(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
|
64
|
+
```
|
65
|
+
|
66
|
+
### HSL Color Format
|
67
|
+
|
68
|
+
The HSL color format is represented with
|
69
|
+
|
70
|
+
- `@hue` - a value from 0.0 to 1.0, representing 0 to 360 degrees
|
71
|
+
- `@saturation` - a value from 0.0 to 1.0
|
72
|
+
- `@lightness` - a value from 0.0 to 1.0
|
73
|
+
- `@alpha` - a value from 0.0 to 1.0
|
74
|
+
|
75
|
+
This format is useful to calculate related colors:
|
76
|
+
|
77
|
+
- triadic
|
78
|
+
- split
|
79
|
+
- analogous
|
80
|
+
- tetradic
|
81
|
+
- rectangular
|
82
|
+
- tertiary
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
require 'pigment/color/hsl'
|
86
|
+
|
87
|
+
hsl_red = Pigment::Color::HSL.convert(red)
|
88
|
+
# HSL Color(hue: 0.0, saturation: 1.0, lightness: 0.5, alpha: 1.0)
|
89
|
+
|
90
|
+
hsl_red == Pigment::Color::HSL(0.0, 1, 0.5)
|
91
|
+
# HSL Color(hue: 0.0, saturation: 1.0, lightness: 0.5, alpha: 1.0)
|
92
|
+
|
93
|
+
hsl_red.triadic
|
94
|
+
hsl_red.split
|
95
|
+
hsl_red.analogous
|
96
|
+
hsl_red.tetradic
|
97
|
+
hsl_red.rectangular
|
98
|
+
hsl_red.tertiary
|
99
|
+
|
100
|
+
```
|
101
|
+
|
102
|
+
### Color Module
|
103
|
+
|
104
|
+
The color module works as the base for any possible color format, implementing common methods
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
red.to_html
|
108
|
+
# '#ff0000'
|
109
|
+
|
110
|
+
red.into(Pigment::HSL)
|
111
|
+
# HSL Color(hue: 0.0, saturation: 1.0, lightness: 0.5, alpha: 1.0)
|
112
|
+
|
113
|
+
red.inverse?(cyan)
|
114
|
+
# true
|
115
|
+
|
116
|
+
red.triadic_of?(blue)
|
117
|
+
# true
|
118
|
+
|
119
|
+
red.triadic_include?(green, blue)
|
120
|
+
# true
|
121
|
+
|
122
|
+
red.split_of?
|
123
|
+
red.split_include?
|
124
|
+
red.analogous_of?
|
125
|
+
red.analogous_include?
|
126
|
+
red.tetradic_of?
|
127
|
+
red.tetradic_include?
|
128
|
+
red.rectangular_of?
|
129
|
+
red.rectangular_include?
|
130
|
+
red.tertiary_of?
|
131
|
+
red.tertiary_include?
|
132
|
+
# of -> checks if self is included in argument result
|
133
|
+
# include -> checks if arguments are included in self result
|
134
|
+
```
|
135
|
+
|
136
|
+
### Color Palette
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
require 'pigment/palette'
|
140
|
+
|
141
|
+
pallete = Pigment::Palette.new(
|
142
|
+
red: red,
|
143
|
+
blue: blue,
|
144
|
+
)
|
145
|
+
|
146
|
+
pallete[:red]
|
147
|
+
# RGB Color(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
|
148
|
+
|
149
|
+
pallete[:green] = green
|
150
|
+
# RGB Color(red: 0.0, green: 1.0, blue: 0.0, alpha: 1.0)
|
151
|
+
|
152
|
+
# Pigment::Palette is enumerable
|
153
|
+
|
154
|
+
palette.map.to_a
|
155
|
+
# [RGB Color(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0), RGB Color(red: 0.0, green: 0.0, blue: 1.0, alpha: 1.0), RGB Color(red: 0.0, green: 1.0, blue: 0.0, alpha: 1.0)]
|
156
|
+
```
|
157
|
+
|
158
|
+
### Default Color Palette
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
require 'pigment/default_rgb_palette'
|
162
|
+
|
163
|
+
Pigment::Palette::RGB::DEFAULT[:Red]
|
164
|
+
# RGB Color(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
|
165
|
+
|
166
|
+
|
167
|
+
Pigment::Palette::RGB::Green
|
168
|
+
# RGB Color(red: 0.0, green: 1.0, blue: 0.0, alpha: 1.0)
|
169
|
+
|
170
|
+
Pigment::Palette::RGB.Blue
|
171
|
+
# RGB Color(red: 0.0, green: 0.0, blue: 1.0, alpha: 1.0)
|
172
|
+
```
|
173
|
+
|
174
|
+
## Changes
|
175
|
+
See [Changelog](CHANGELOG.md)
|
176
|
+
|
177
|
+
|
178
|
+
## Future Work
|
179
|
+
- [ ] new color formats:
|
180
|
+
- [ ] Y'CbCr
|
181
|
+
- [ ] RYB
|
182
|
+
- [ ] CMYK
|
183
|
+
- [ ] redesign of Base Color module to support Additive color formats
|
184
|
+
- [ ] Palette Loader to load palette files
|
185
|
+
|
186
|
+
## License
|
187
|
+
See [License](LICENSE.md)
|
188
|
+
|
189
|
+
## Related interests
|
190
|
+
- [color-names](https://github.com/meodai/color-names): javascript collection of 25586 color names
|
data/lib/pigment.rb
CHANGED
@@ -1,306 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
class Color
|
5
|
-
|
6
|
-
@named_colors = {}
|
7
|
-
attr_reader :color, :hsl
|
8
|
-
|
9
|
-
# Pigment uses sRGB or sRGBA as the default color system
|
10
|
-
# color can be a hexadecimal code preceded by a '#' like '#FF4CB2' or a array of floats (1.0, 0.3, 0.7)
|
11
|
-
# or an array of integers between 0 and 255 (153, 255, 31)
|
12
|
-
# @param [String, Array] color
|
13
|
-
def initialize(*color)
|
14
|
-
@color = case
|
15
|
-
when color[0] =~ /^#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})?$/
|
16
|
-
[$1, $2, $3, $4 || 'ff'].map { |v| v.to_i(16) / 255.0 }
|
17
|
-
when color.is_a?(Array) && (color.all? { |c| (0.0..1.0).include? c }) && color.length == 3
|
18
|
-
[color, 1.0].flatten!
|
19
|
-
when color.is_a?(Array) && (color.all? { |c| (0..255).include? c && c.is_a?(Integer) } ) && color.length == 3
|
20
|
-
[color.map { |c| c / 255.0 }, 1.0].flatten!
|
21
|
-
when color.is_a?(Array) && (color.all? { |c| (0.0..1.0).include? c }) && color.length == 4
|
22
|
-
color
|
23
|
-
when color.is_a?(Array) && (color.all? { |c| (0..255).include? c && c.is_a?(Integer) } ) && color.length == 4
|
24
|
-
color.map { |c| c / 255.0 }
|
25
|
-
else
|
26
|
-
raise ArgumentError, "Expected String or Array with length 3 or 4. Given #{color.class} with length = #{color.length}"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# Getters and Setters.
|
31
|
-
%w'r g b a'.each_with_index do |m, i|
|
32
|
-
define_method("#{m}", ->() { @color[i] })
|
33
|
-
define_method("#{m}=", ->(value) { @color[i] = value if value.is_a?(Float) && (0.0..1.0).include?(value) })
|
34
|
-
end
|
35
|
-
|
36
|
-
%w'h s l'.each_with_index do |m, i|
|
37
|
-
define_method("#{m}", ->() { hsl[i] })
|
38
|
-
end
|
39
|
-
|
40
|
-
def method_missing(method, *args)
|
41
|
-
# Returns an array with the respective rgba components
|
42
|
-
# @return [Array]
|
43
|
-
super unless method =~ /(a|b|g|r)+/ && args.empty?
|
44
|
-
method.size.times.map{ |i| send(method[i]) }
|
45
|
-
end
|
46
|
-
|
47
|
-
# Return specified color by its name from the named_colors hash.
|
48
|
-
# @param [Symbol] name
|
49
|
-
# @return [Array]
|
50
|
-
def self.[](*colors)
|
51
|
-
colors.size > 1 ? colors.map { |color| @named_colors[color] } : @named_colors[colors[0]]
|
52
|
-
end
|
53
|
-
|
54
|
-
# Add name to a color , add it to the named_colors hash and defines a constant.
|
55
|
-
# @param [Array of Strings] names
|
56
|
-
# @param [Color] color
|
57
|
-
def self.[]=(*names, color)
|
58
|
-
color = new(color) unless color.is_a? Color
|
59
|
-
names.each do |name|
|
60
|
-
@named_colors[name.downcase] = color
|
61
|
-
const_set("#{name}".to_sym, color)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
# Return all the named_colors as an array.
|
66
|
-
def self.named_colors
|
67
|
-
@named_colors.keys
|
68
|
-
end
|
69
|
-
|
70
|
-
# Return all the named_colors as a sorted array.
|
71
|
-
def self.named_colors_sorted
|
72
|
-
named_colors.sort
|
73
|
-
end
|
74
|
-
|
75
|
-
# Suppress an array of floats by dividing by the greatest color component.
|
76
|
-
# @param [Array] color
|
77
|
-
# @return [Array]
|
78
|
-
def self.suppress(color)
|
79
|
-
color.map! { |c| c / color.max } unless (0.0..1.0).include?(color.max)
|
80
|
-
color
|
81
|
-
end
|
82
|
-
|
83
|
-
# Creates a Color form the HSL color System. It's mostly used to calculate harmonic colors.
|
84
|
-
# @param [Float] h
|
85
|
-
# @param [Float] s
|
86
|
-
# @param [Float] l
|
87
|
-
# @return [Color]
|
88
|
-
def self.from_hsl(h, s, l)
|
89
|
-
return new(l, l, l) if s == 0
|
90
|
-
v2 = l < 0.5 ? l * (1 + s) : (l + s) - (s * l)
|
91
|
-
v1 = 2 * l - v2
|
92
|
-
color = [h + (1 / 3.0), h, h - (1 / 3.0)].map do |hv|
|
93
|
-
case
|
94
|
-
when hv < 0 then hv += 1
|
95
|
-
when hv > 1 then hv -= 1
|
96
|
-
when 6 * hv < 1 then v1 +(v2 - v1) * 6 * hv
|
97
|
-
when 2 * hv < 1 then v2
|
98
|
-
when 3 * hv < 2 then v1 + (v2 - v1) * ((2 / 3.0)- hv) * 6
|
99
|
-
else v1
|
100
|
-
end
|
101
|
-
end
|
102
|
-
new(*color)
|
103
|
-
end
|
104
|
-
|
105
|
-
# Same as inverse.
|
106
|
-
def -@
|
107
|
-
inv
|
108
|
-
end
|
109
|
-
|
110
|
-
# Sums all the two colors components. If any component gets out of the 0 to 1.0 range its suppressed.
|
111
|
-
# @param [Numeric] color
|
112
|
-
# @return [Color]
|
113
|
-
def +(color)
|
114
|
-
case color
|
115
|
-
when Color
|
116
|
-
self.class.new(*self.class.suppress([color.rgb, rgb].transpose.map! { |c, d| c + d }))
|
117
|
-
else
|
118
|
-
raise ArgumentError, "Expecting Color. Given #{color.class}"
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
# Subtracts all the two color components. If any component gets out of the 0 to 1.0 range its suppressed.
|
123
|
-
# If tone component gets lower than 0 it acts like its dealing with the inverse component -> 1 - component
|
124
|
-
# @param [Numeric] color
|
125
|
-
# @return [Color]
|
126
|
-
def -(color)
|
127
|
-
case color
|
128
|
-
when Color
|
129
|
-
self.class.new(*self.class.suppress([rgb, color.rgb].transpose.map! do |c, d|
|
130
|
-
e = c - d
|
131
|
-
e >= 0 ? e : e = 1 + e
|
132
|
-
e
|
133
|
-
end))
|
134
|
-
else
|
135
|
-
raise ArgumentError, "Expecting color. Given #{color.class}"
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
# Multiplies all the color components by n. If any component gets out of the 0 to 1.0 range its suppressed.
|
140
|
-
# @param [Numeric] n
|
141
|
-
# @return [Color]
|
142
|
-
def *(n)
|
143
|
-
case n
|
144
|
-
when Numeric
|
145
|
-
n = rgb.map { |c| c * n.to_f }
|
146
|
-
self.class.new(*self.class.suppress(n))
|
147
|
-
else
|
148
|
-
raise ArgumentError, "Expecting Numeric. Given #{n.class}"
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
# Divides all the color components by n. If any component gets out of the 0 to 1.0 range its suppressed.
|
153
|
-
# @param [Numeric] n
|
154
|
-
# @return [Color]
|
155
|
-
def /(n)
|
156
|
-
case n
|
157
|
-
when Numeric
|
158
|
-
n = rgb.map { |c| c * n.to_f }
|
159
|
-
self.class.new(*self.class.suppress(n))
|
160
|
-
else
|
161
|
-
raise ArgumentError, "Expecting Numeric. Given #{n.class}"
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
# Test if two colors are equal
|
166
|
-
# @param [Color] color
|
167
|
-
# @return [Boolean]
|
168
|
-
def ==(color)
|
169
|
-
color.is_a?(Color) && color.rgba == rgba
|
170
|
-
end
|
171
|
-
|
172
|
-
# @return [Color]
|
173
|
-
def dup
|
174
|
-
self.class.new(*@color)
|
175
|
-
end
|
176
|
-
|
177
|
-
# Converts a color to its grayscale correspondent
|
178
|
-
# @return [Color]
|
179
|
-
def grayscale
|
180
|
-
r = g = b = (self.r + self.g + self.b)/3
|
181
|
-
self.class.new(r, g, b)
|
182
|
-
end
|
183
|
-
|
184
|
-
# Calculates the harmonic colors. Type can be :triadic, :split, :analogous, :complement or :complementary
|
185
|
-
# @param [Symbol] type
|
186
|
-
# @return [Color, Array of Colors]
|
187
|
-
def harmonize(type = :triadic)
|
188
|
-
color.to_hsl unless @hsl
|
189
|
-
case type
|
190
|
-
when :triadic
|
191
|
-
[self.class.from_hsl(h - 5 / 12.0, s, l), self.class.from_hsl(h + 1 / 3.0, s, l)]
|
192
|
-
when :split
|
193
|
-
[self.class.from_hsl(h - 5 / 12.0, s, l), self.class.from_hsl(h + 5 / 12.0, s, l)]
|
194
|
-
when :analogous
|
195
|
-
[self.class.from_hsl(h - 1 / 12.0, s, l), self.class.from_hsl(h + 1 / 12.0, s, l)]
|
196
|
-
when :complement, :complementary
|
197
|
-
inv
|
198
|
-
else
|
199
|
-
raise ArgumentError, "Expected :triadic, :split, :analogous, :complement or :complementary. Given #{type}"
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
# Interpolates two colors. Amount must be an float between -1.0 and 1.0
|
204
|
-
# @param [Color] color
|
205
|
-
# @param [Float] amount
|
206
|
-
def interpolate(color, amount = 0.5)
|
207
|
-
if color.is_a?(Color) && (-1.0..1.0).include?(amount)
|
208
|
-
n = [rgb, color.rgb].transpose.map! { |c, d| c + amount * (d - c) }
|
209
|
-
self.class.new(*self.class.suppress(n))
|
210
|
-
else
|
211
|
-
raise ArgumentError
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
# Returns the Invert color
|
216
|
-
# @return [Color]
|
217
|
-
def inverse
|
218
|
-
self.class.new(*rgb.map { |c| 1.0 - c })
|
219
|
-
end
|
220
|
-
|
221
|
-
# Returns a new Color without the given channels
|
222
|
-
# @param [Array of Symbols] channels
|
223
|
-
# @return [Color]
|
224
|
-
def remove_channels(*channels)
|
225
|
-
color = self.class.new(r, g, b, a)
|
226
|
-
%w'r g b a'.each do |attr|
|
227
|
-
color.send("#{attr}=", 0) if channels.include? attr.to_sym
|
228
|
-
end
|
229
|
-
color
|
230
|
-
end
|
231
|
-
|
232
|
-
# Creates an instance variable to keep the HSL values of a RGB color.
|
233
|
-
# @return [Array]
|
234
|
-
def to_hsl
|
235
|
-
min = rgb.min
|
236
|
-
max = rgb.max
|
237
|
-
delta = (max - min)
|
238
|
-
l = (max + min) / 2.0
|
239
|
-
|
240
|
-
s = if delta == 0.0 # close to 0.0, so it's a grey
|
241
|
-
h = 0
|
242
|
-
0
|
243
|
-
elsif l < 0.5
|
244
|
-
delta / (max + min)
|
245
|
-
else
|
246
|
-
delta / (2.0 - max - min)
|
247
|
-
end
|
248
|
-
|
249
|
-
h = if r == max
|
250
|
-
h = ((g - b) / delta) / 6.0
|
251
|
-
h += 1.0 if g < b
|
252
|
-
h
|
253
|
-
elsif g == max
|
254
|
-
((b - r) / delta) / 6.0 + (1.0 / 3.0)
|
255
|
-
elsif b == max
|
256
|
-
((r - g) / delta) / 6.0 + (2.0 / 3.0)
|
257
|
-
end
|
258
|
-
|
259
|
-
h += 1 if h < 0
|
260
|
-
h -= 1 if h > 1
|
261
|
-
@hsl = [h, s, l]
|
262
|
-
self
|
263
|
-
end
|
264
|
-
|
265
|
-
# Returns an array of the color components. Alpha value is passed as well if with_alpha is set to true.
|
266
|
-
# @param [Boolean] with_alpha
|
267
|
-
# @return [Array]
|
268
|
-
def to_floats(with_alpha = true)
|
269
|
-
with_alpha ? @color.dup : rgb
|
270
|
-
end
|
271
|
-
|
272
|
-
# Returns an array of the color components. Alpha value is passed as well if with_alpha is set to true.
|
273
|
-
# @param [Boolean] with_alpha
|
274
|
-
# @return [Array]
|
275
|
-
def to_ints(with_alpha = true)
|
276
|
-
to_floats(with_alpha).map { |v| Integer(v * 255) }
|
277
|
-
end
|
278
|
-
|
279
|
-
# Returns an array of the color components. Alpha value is passed as well if with_alpha is set to true.
|
280
|
-
# @param [Boolean] with_alpha
|
281
|
-
# @return [Array]
|
282
|
-
def to_hex(with_alpha = true)
|
283
|
-
to_ints(with_alpha).map { |v| '%02x' % v }.join
|
284
|
-
end
|
285
|
-
|
286
|
-
def to_s
|
287
|
-
"Color(r=#{r}, g=#{g}, b=#{b}, a=#{a}#{", [h=#{h}, s=#{s}, l=#{l}]" if @hsl})"
|
288
|
-
end
|
289
|
-
|
290
|
-
alias_method :alpha=, :a=
|
291
|
-
alias_method :inv, :inverse
|
292
|
-
alias_method :invert, :inverse
|
293
|
-
alias_method :complementary, :inverse
|
294
|
-
alias_method :mix, :interpolate
|
295
|
-
alias_method :red, :r
|
296
|
-
alias_method :green, :g
|
297
|
-
alias_method :blue, :b
|
298
|
-
alias_method :alpha, :a
|
299
|
-
alias_method :to_a, :to_floats
|
300
|
-
alias_method :to_ary, :to_floats
|
301
|
-
alias_method :to_f, :to_floats
|
302
|
-
alias_method :to_hsl, :hsl
|
303
|
-
end
|
304
|
-
end
|
305
|
-
|
306
|
-
require_relative 'colors.rb'
|
1
|
+
require_relative 'pigment/version'
|
2
|
+
require_relative 'pigment/float_snap'
|
3
|
+
require_relative 'pigment/color/invalid_color_format_error'
|