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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65191c26a6dcae9a6bb52abe182d376e0975b79672686120185c9a2b3d49e4e9
|
4
|
+
data.tar.gz: 3fb9dc542660f5edaec8283a2e74ec0687e369e05475bf6840344ca5cca0304f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c0d6a47aa611822dba62189c14ebf38c0ef6315f08ac9b5eb9efe04b28487d2c95105c0e86536cb52fdc9ce36df445d060623a14e99f2dbab34df5e0d10e515
|
7
|
+
data.tar.gz: 756bdaa8c6859c685e51342ee8a6d34e7340ea0580bd79b4487443d97b04629ed1b7c8f1631bf3ac26a5570e6c243aba7f7b931243ea967f07d8437fa223d495
|
data/lib/redgreenblue.rb
CHANGED
@@ -1,28 +1,30 @@
|
|
1
1
|
class RGB
|
2
2
|
end
|
3
3
|
|
4
|
-
|
4
|
+
%w(
|
5
5
|
|
6
|
-
|
6
|
+
version
|
7
7
|
|
8
|
-
|
9
|
-
require 'redgreenblue/48bit'
|
10
|
-
require 'redgreenblue/hex'
|
8
|
+
base
|
11
9
|
|
12
|
-
|
13
|
-
require 'redgreenblue/cie'
|
10
|
+
24bit 48bit hex int
|
14
11
|
|
15
|
-
|
16
|
-
require 'redgreenblue/lazy'
|
12
|
+
hsl hsv hsb
|
17
13
|
|
18
|
-
|
19
|
-
require 'redgreenblue/bgr24bit'
|
20
|
-
require 'redgreenblue/gif'
|
21
|
-
require 'redgreenblue/terminal'
|
22
|
-
require 'redgreenblue/web'
|
14
|
+
ostwald
|
23
15
|
|
24
|
-
|
25
|
-
require 'redgreenblue/misc'
|
26
|
-
require 'redgreenblue/random'
|
16
|
+
gamma
|
27
17
|
|
28
|
-
|
18
|
+
cie_1931 cie_1976
|
19
|
+
|
20
|
+
name
|
21
|
+
|
22
|
+
inspect view lazy
|
23
|
+
|
24
|
+
rgb565 bgr24bit gif terminal web gpl mac
|
25
|
+
|
26
|
+
match mix misc random
|
27
|
+
|
28
|
+
os
|
29
|
+
|
30
|
+
).each { |m| require "redgreenblue/#{m}" }
|
data/lib/redgreenblue/24bit.rb
CHANGED
@@ -51,6 +51,17 @@ class RGB
|
|
51
51
|
c
|
52
52
|
end
|
53
53
|
|
54
|
+
# Sets the red, green, and blue values to those of the nearest 24-bit color.
|
55
|
+
def snap!
|
56
|
+
self.rgb = rgb
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
# Creates a new RGB object containing the nearest 24-bit color.
|
61
|
+
def snap
|
62
|
+
RGB.rgb rgb
|
63
|
+
end
|
64
|
+
|
54
65
|
# Calls the given block for each 24-bit RGB color (from black to white), passing the color as an RGB object.
|
55
66
|
#
|
56
67
|
# Returns the number of iterations.
|
data/lib/redgreenblue/base.rb
CHANGED
@@ -8,7 +8,7 @@ class RGB
|
|
8
8
|
#
|
9
9
|
# Currently always 'sRGB'.
|
10
10
|
def color_space
|
11
|
-
|
11
|
+
'sRGB'
|
12
12
|
end
|
13
13
|
|
14
14
|
# Returns the red component as a value between 0 and 1.
|
@@ -66,7 +66,7 @@ class RGB
|
|
66
66
|
( self.class == other.class ) && ( self.values == other.values )
|
67
67
|
end
|
68
68
|
|
69
|
-
# Returns a sorted hash of 3 key/value pairs for red, green and blue,
|
69
|
+
# Returns a sorted hash of 3 key/value pairs for red, green, and blue,
|
70
70
|
# sorted in order of decreasing value.
|
71
71
|
def to_h
|
72
72
|
([:red, :green, :blue].zip values).sort_by {
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class RGB
|
2
|
+
|
3
|
+
# Returns CIE 1931 XYZ values for the RGB object.
|
4
|
+
#
|
5
|
+
# Based on:
|
6
|
+
# - http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html
|
7
|
+
# - https://en.wikipedia.org/wiki/CIE_1931_color_space
|
8
|
+
# sRGB to XYZ matrix for D65 reference white calculated with Javascript by Bruce Lindbloom:
|
9
|
+
# - http://www.brucelindbloom.com/ColorCalculator.html
|
10
|
+
def cie_xyz(round: true)
|
11
|
+
r, g, b = linear_values
|
12
|
+
|
13
|
+
[
|
14
|
+
|
15
|
+
r * 0.4124_5643_9090 + g * 0.3575_7607_7644 + b * 0.1804_3748_3266,
|
16
|
+
r * 0.2126_7285_1406 + g * 0.7151_5215_5288 + b * 0.0721_7499_3307,
|
17
|
+
r * 0.0193_3389_5582 + g * 0.1191_9202_5881 + b * 0.9503_0407_8536
|
18
|
+
|
19
|
+
].map { |v| round ? v.round(8) : v }
|
20
|
+
end
|
21
|
+
|
22
|
+
alias xyz cie_xyz
|
23
|
+
|
24
|
+
# Returns CIE 1931 xyY values for the RGB object.
|
25
|
+
#
|
26
|
+
# Based on:
|
27
|
+
# - https://en.wikipedia.org/wiki/CIE_1931_color_space
|
28
|
+
# - http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_xyY.html
|
29
|
+
# - https://ninedegreesbelow.com/photography/xyz-rgb.html
|
30
|
+
def cie_xyy
|
31
|
+
x, y, z = cie_xyz(round: false)
|
32
|
+
|
33
|
+
[
|
34
|
+
|
35
|
+
x / ( x + y + z ),
|
36
|
+
y / ( x + y + z ),
|
37
|
+
y
|
38
|
+
|
39
|
+
].map { |v| v.round(8) }
|
40
|
+
end
|
41
|
+
|
42
|
+
alias xyy cie_xyy
|
43
|
+
|
44
|
+
# Returns CIE 1931 xy values for the RGB object.
|
45
|
+
def cie_xy
|
46
|
+
cie_xyy[0..1]
|
47
|
+
end
|
48
|
+
|
49
|
+
alias xy cie_xy
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
class RGB
|
2
|
+
|
3
|
+
# Returns CIE 1976 L*a*b* (CIELAB) values for the RGB object.
|
4
|
+
def cie_lab(round: true)
|
5
|
+
cie_lab_luv(round: round, type: :lab)
|
6
|
+
end
|
7
|
+
|
8
|
+
alias lab cie_lab
|
9
|
+
|
10
|
+
# Returns CIE 1976 LCHab values for the RGB object, derived from L*a*b* (CIELAB).
|
11
|
+
#
|
12
|
+
# When C is 0, H is nil.
|
13
|
+
def cie_lch_ab
|
14
|
+
cie_lch_ab_uv(type: :lab)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns CIE 1976 L*u*v* (CIELUV) values for the RGB object.
|
18
|
+
def cie_luv(round: true)
|
19
|
+
cie_lab_luv(round: round, type: :luv)
|
20
|
+
end
|
21
|
+
|
22
|
+
alias luv cie_luv
|
23
|
+
|
24
|
+
# Returns CIE 1976 LCHuv values for the RGB object, derived from L*u*v* (CIELUV).
|
25
|
+
#
|
26
|
+
# When C is 0, H is nil.
|
27
|
+
def cie_lch_uv
|
28
|
+
cie_lch_ab_uv(type: :luv)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the difference between this color and another color, according to the CIE 1976 delta E formula.
|
32
|
+
#
|
33
|
+
# Based on:
|
34
|
+
# - http://www.brucelindbloom.com/Eqn_DeltaE_CIE76.html
|
35
|
+
# - https://en.wikipedia.org/wiki/Color_difference
|
36
|
+
def delta_e_cie_1976(another)
|
37
|
+
l , a , b = cie_lab(round: false)
|
38
|
+
l2, a2, b2 = another.cie_lab(round: false)
|
39
|
+
|
40
|
+
Math.sqrt( (l - l2) ** 2 + (a - a2) ** 2 + (b - b2) ** 2 ).round(8)
|
41
|
+
end
|
42
|
+
|
43
|
+
alias de76 delta_e_cie_1976
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# Returns either CIE 1976 L*a*b* (CIELAB) or CIE 1976 L*u*v* (CIELUV) values for the RGB object.
|
48
|
+
#
|
49
|
+
# L*a*b* formula based on:
|
50
|
+
# - http://www.brucelindbloom.com/Eqn_XYZ_to_Lab.html
|
51
|
+
# - https://en.wikipedia.org/wiki/CIELAB_color_space
|
52
|
+
# With peeking at:
|
53
|
+
# - https://github.com/halostatue/color/blob/master/lib/color/rgb.rb
|
54
|
+
#
|
55
|
+
# L*u*v* formula based on:
|
56
|
+
# - http://www.brucelindbloom.com/Eqn_XYZ_to_Luv.html
|
57
|
+
# - https://en.wikipedia.org/wiki/CIELUV
|
58
|
+
def cie_lab_luv(round: true, type: :lab)
|
59
|
+
x , y , z = cie_xyz(round: false)
|
60
|
+
xr, yr, zr = RGB.white.cie_xyz(round: false)
|
61
|
+
|
62
|
+
f = [ x / xr, y / yr, z / zr ].map { |v|
|
63
|
+
if v > ( 216.0 / 24389 )
|
64
|
+
Math.cbrt v
|
65
|
+
else
|
66
|
+
( 24389.0 / 27 * v + 16 ) / 116.0
|
67
|
+
end
|
68
|
+
}
|
69
|
+
|
70
|
+
if type == :luv
|
71
|
+
[
|
72
|
+
l = 116 * f[1] - 16,
|
73
|
+
13 * l * ( ( 4 * x ) / ( x + 15 * y + 3 * z ) - ( 4 * xr ) / ( xr + 15 * yr + 3 * zr ) ),
|
74
|
+
13 * l * ( ( 9 * y ) / ( x + 15 * y + 3 * z ) - ( 9 * yr ) / ( xr + 15 * yr + 3 * zr ) )
|
75
|
+
]
|
76
|
+
else
|
77
|
+
[
|
78
|
+
116 * f[1] - 16,
|
79
|
+
500 * (f[0] - f[1]),
|
80
|
+
200 * (f[1] - f[2])
|
81
|
+
]
|
82
|
+
end.map { |v| v.nan? ? 0.0 : ( round ? v.round(8) : v ) }
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns either CIE 1976 LCHab or CIE 1976 LCHuv values for the RGB object.
|
86
|
+
#
|
87
|
+
# Based on:
|
88
|
+
# - http://www.brucelindbloom.com/Eqn_Lab_to_LCH.html
|
89
|
+
# - http://www.brucelindbloom.com/Eqn_Luv_to_LCH.html
|
90
|
+
# - https://en.wikipedia.org/wiki/CIELAB_color_space
|
91
|
+
def cie_lch_ab_uv(type: :lab)
|
92
|
+
if type == :luv
|
93
|
+
l, v1, v2 = cie_luv(round: false)
|
94
|
+
else
|
95
|
+
l, v1, v2 = cie_lab(round: false)
|
96
|
+
end
|
97
|
+
|
98
|
+
[
|
99
|
+
l.round(8),
|
100
|
+
c = Math.hypot(v1, v2).round(8),
|
101
|
+
c == 0 ? nil : ( Math.atan2(v2, v1) * 180.0 / Math::PI ).modulo(360).round(8)
|
102
|
+
]
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class RGB
|
2
|
+
|
3
|
+
# Returns gamma-expanded (inverse-companded) RGB values for the object (three values between 0 and 1).
|
4
|
+
#
|
5
|
+
# Based on:
|
6
|
+
# - https://en.wikipedia.org/wiki/SRGB
|
7
|
+
# - http://www.brucelindbloom.com/Eqn_RGB_to_XYZ.html
|
8
|
+
# - https://entropymine.com/imageworsener/srgbformula/
|
9
|
+
def linear_values
|
10
|
+
if color_space == 'sRGB'
|
11
|
+
values.map { |v|
|
12
|
+
if v <= 0.04045
|
13
|
+
v / 12.92
|
14
|
+
else
|
15
|
+
( ( v + 0.055 ) / 1.055 ) ** 2.4
|
16
|
+
end
|
17
|
+
}
|
18
|
+
else
|
19
|
+
raise "can not compute gamma for color space '#{color_space}'"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Sets the object's RGB values using three linear RGB values, each between 0 and 1.
|
24
|
+
# Linear values will be converted to the object's gamma (gamma-companded).
|
25
|
+
#
|
26
|
+
# Based on:
|
27
|
+
# - https://en.wikipedia.org/wiki/SRGB
|
28
|
+
# - http://www.brucelindbloom.com/Eqn_XYZ_to_RGB.html
|
29
|
+
# - https://entropymine.com/imageworsener/srgbformula/
|
30
|
+
def linear_values=(*a)
|
31
|
+
if color_space == 'sRGB'
|
32
|
+
self.values = a.flatten.map { |v|
|
33
|
+
if v <= 0.0031308
|
34
|
+
v * 12.92
|
35
|
+
else
|
36
|
+
1.055 * ( v ** ( 1/2.4 ) ) - 0.055
|
37
|
+
end
|
38
|
+
}.map { |v| v.round(9) }
|
39
|
+
else
|
40
|
+
raise "can not compute gamma for color space '#{color_space}'"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
class RGB
|
2
|
+
|
3
|
+
#----------------------------------------------------------------------#
|
4
|
+
# Class Methods #
|
5
|
+
#----------------------------------------------------------------------#
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
# Creates a new RGB object from a line of gpl (Gimp color palette) input. Returns nil if not successful.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# RGB.gpl "255 153 204\tpink"
|
13
|
+
def gpl(line)
|
14
|
+
if line.chomp.match( /^\s*(?<r>\d{1,3})\s+(?<g>\d{1,3})\s+(?<b>\d{1,3})(\s+(?<name>.*))?/ )
|
15
|
+
color = RGB.rgb $~[:r].to_i, $~[:g].to_i, $~[:b].to_i
|
16
|
+
color.name = $~[:name] if $~[:name]
|
17
|
+
color
|
18
|
+
else
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Loads a gpl (Gimp color palette) source and returns an array of RGB objects.
|
24
|
+
#
|
25
|
+
# Options:
|
26
|
+
# - file: Path to a .gpl file to be loaded.
|
27
|
+
# - url: URL for a .gpl source to be loaded.
|
28
|
+
# - compact: Defaults to true. If set to false, returns nil for each line that can not be parsed to an RGB color.
|
29
|
+
# - freeze: Defaults to false. If set to true, returns a frozen array of frozen objects.
|
30
|
+
#
|
31
|
+
# @example String
|
32
|
+
# RGB.load_gpl "255 0 0\tred\n255 153 204\tpink\n"
|
33
|
+
# @example File
|
34
|
+
# RGB.load_gpl file: '/path/to/palette.gpl'
|
35
|
+
# RGB.load_gpl file: '/path/to/palette.gpl', compact: false
|
36
|
+
# @example URL
|
37
|
+
# RGB.load_gpl url: 'https://lospec.com/palette-list/yuko-tomita-time.gpl'
|
38
|
+
def load_gpl(source=nil, file: nil, url: nil, compact: true, freeze: false)
|
39
|
+
|
40
|
+
if ! source
|
41
|
+
if file
|
42
|
+
source = File.open file
|
43
|
+
elsif url
|
44
|
+
require 'open-uri'
|
45
|
+
source = URI.open url
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
if source.respond_to? :each_line
|
50
|
+
list = source.each_line.map { |line| RGB.gpl(line) }
|
51
|
+
|
52
|
+
if compact
|
53
|
+
list.compact!
|
54
|
+
end
|
55
|
+
|
56
|
+
if freeze
|
57
|
+
list.freeze
|
58
|
+
list.each &:freeze
|
59
|
+
end
|
60
|
+
|
61
|
+
list
|
62
|
+
else
|
63
|
+
raise ArgumentError, 'Not a valid source'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# Reverse-engineered from:
|
70
|
+
# - https://github.com/GNOME/gimp/blob/5d79fba8238a27b8691556489898d33b3fa0dda0/app/core/gimppalette-load.c
|
71
|
+
def gpl_header(name, columns=nil)
|
72
|
+
"GIMP Palette\n" +
|
73
|
+
"Name: #{name}\n" +
|
74
|
+
( columns ? "Columns: #{columns}\n" : '' )
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
#----------------------------------------------------------------------#
|
80
|
+
# Instance Methods #
|
81
|
+
#----------------------------------------------------------------------#
|
82
|
+
|
83
|
+
# Returns the color in the format used in .gpl files (Gimp color palettes), including its name (if present).
|
84
|
+
#
|
85
|
+
# You can optionally supply a name as argument.
|
86
|
+
def gpl(gpl_name=name)
|
87
|
+
( "%3d %3d %3d" % rgb ) +
|
88
|
+
( gpl_name.to_s.size != 0 ? "\t#{gpl_name}" : '' )
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'redgreenblue/hsv'
|
2
|
+
|
3
|
+
class RGB
|
4
|
+
|
5
|
+
#----------------------------------------------------------------------#
|
6
|
+
# Class Methods #
|
7
|
+
#----------------------------------------------------------------------#
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
# Creates a new RGB object from HSB values: hue (0..360), saturation (0..1), and brightness (0..1).
|
12
|
+
alias hsb hsv
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
#----------------------------------------------------------------------#
|
17
|
+
# Instance Methods #
|
18
|
+
#----------------------------------------------------------------------#
|
19
|
+
|
20
|
+
# Returns color as HSB:
|
21
|
+
# hue (0..360), saturation (0..1), brightness (0..1).
|
22
|
+
# When saturation is 0, hue is nil.
|
23
|
+
alias hsb hsv
|
24
|
+
|
25
|
+
# Returns the object's HSB-hue (0..360).
|
26
|
+
alias hsb_h hsv_h
|
27
|
+
|
28
|
+
# Returns the object's HSB-saturation (0..1).
|
29
|
+
alias hsb_s hsv_s
|
30
|
+
|
31
|
+
# Returns the object's HSB-brightness (0..1).
|
32
|
+
alias hsb_b hsv_v
|
33
|
+
|
34
|
+
# Sets red, green, and blue using HSB values: hue (0..360), saturation (0..1), and brightness (0..1).
|
35
|
+
alias hsb= hsv=
|
36
|
+
|
37
|
+
# Sets HSB-hue to a number of degrees (0..360) or nil.
|
38
|
+
#
|
39
|
+
# Adjusts red, green, and blue, leaving HSB-saturation and -brightness unchanged.
|
40
|
+
# When hue is nil, saturation will be 0.
|
41
|
+
alias hsb_h= hsv_h=
|
42
|
+
|
43
|
+
# Sets HSB-saturation to a number between 0 and 1.
|
44
|
+
#
|
45
|
+
# Adjusts red, green, and blue, leaving HSB-hue and -brightness unchanged.
|
46
|
+
# When saturation is 0, hue will be nil.
|
47
|
+
alias hsb_s= hsv_s=
|
48
|
+
|
49
|
+
# Sets HSB-brightness to a number between 0 and 1.
|
50
|
+
#
|
51
|
+
# Adjusts red, green, and blue, leaving HSB-hue and -saturation unchanged.
|
52
|
+
# When brightness is 0, hue will be nil, and saturation will be 0.
|
53
|
+
alias hsb_b= hsv_v=
|
54
|
+
|
55
|
+
# Sets red, green, and blue by rotating the object's HSB-hue a number of degrees.
|
56
|
+
alias hsb_rotate! hsv_rotate!
|
57
|
+
|
58
|
+
# Creates one or more new RGB objects by rotating this object's HSB-hue a number of degrees.
|
59
|
+
alias hsb_rotate hsv_rotate
|
60
|
+
|
61
|
+
end
|