red-colors 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/colors.rb +5 -0
- data/lib/colors/abstract_color.rb +4 -0
- data/lib/colors/colormap.rb +131 -0
- data/lib/colors/linear_segmented_colormap.rb +119 -0
- data/lib/colors/listed_colormap.rb +41 -0
- data/lib/colors/utils.rb +18 -0
- data/lib/colors/version.rb +1 -1
- data/test/test-linear-segmented-colormap.rb +119 -0
- data/test/test-listed-colormap.rb +115 -0
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 161a952cf581167db1ac2391f1a4f80c83affbc838efdfc7c525587c0c1c8cdb
|
4
|
+
data.tar.gz: b0aa23b1537ded3aa6484eaffd646877da5c53b784a721d7a324c94788ecb842
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e244463b3bd3137808915397688141c67d99298290484c91f94be576b1821f94ad6ce9181a5518ce8d77faddb9a37dbaa0f6c462d1009e7d7bfa6a887fa678fd
|
7
|
+
data.tar.gz: 802cef85dc8c270094812522afffe5571833a2b044145132902939edb5bf118a740a36d07b40583ccfd3ab0f94ec97ccc5f9b8891f00a63b348bfe4519d7dda5
|
data/lib/colors.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require_relative "colors/utils"
|
1
2
|
require_relative "colors/alpha_component"
|
2
3
|
require_relative "colors/convert"
|
3
4
|
require_relative "colors/helper"
|
@@ -15,6 +16,10 @@ require_relative "colors/xyz"
|
|
15
16
|
require_relative "colors/color_data"
|
16
17
|
require_relative "colors/named_colors"
|
17
18
|
|
19
|
+
require_relative "colors/colormap"
|
20
|
+
require_relative "colors/listed_colormap"
|
21
|
+
require_relative "colors/linear_segmented_colormap"
|
22
|
+
|
18
23
|
module Colors
|
19
24
|
# ITU-R BT.709 D65 white point
|
20
25
|
# See https://en.wikipedia.org/wiki/Rec._709 for details
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module Colors
|
2
|
+
class Colormap
|
3
|
+
def initialize(name, n_colors)
|
4
|
+
@name = name
|
5
|
+
@n_colors = n_colors.to_int
|
6
|
+
@bad_color = RGBA.new(0r, 0r, 0r, 0r)
|
7
|
+
@under_color = nil
|
8
|
+
@over_color = nil
|
9
|
+
@under_index = self.n_colors
|
10
|
+
@over_index = self.n_colors + 1
|
11
|
+
@bad_index = self.n_colors + 2
|
12
|
+
@initialized = false
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :name, :n_colors
|
16
|
+
|
17
|
+
def [](x)
|
18
|
+
init_colormap unless @initialized
|
19
|
+
|
20
|
+
xs = Array(x)
|
21
|
+
scalar_p = (xs.length == 1) && xs[0] == x
|
22
|
+
|
23
|
+
if all_ratio?(xs)
|
24
|
+
xs.map! do |v|
|
25
|
+
v *= self.n_colors
|
26
|
+
v = -1 if v < 0
|
27
|
+
v = self.n_colors - 1 if v == self.n_colors
|
28
|
+
v.clamp(-1, self.n_colors).to_i
|
29
|
+
end
|
30
|
+
end
|
31
|
+
ys = xs.map do |v|
|
32
|
+
v = case
|
33
|
+
when v >= self.n_colors
|
34
|
+
@over_index
|
35
|
+
when v < 0
|
36
|
+
@under_index
|
37
|
+
else
|
38
|
+
v
|
39
|
+
end
|
40
|
+
@lookup_table[v]
|
41
|
+
end
|
42
|
+
|
43
|
+
if scalar_p
|
44
|
+
ys[0]
|
45
|
+
else
|
46
|
+
ys
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def over_color
|
51
|
+
init_colormap unless @initialized
|
52
|
+
@lookup_table[@over_index]
|
53
|
+
end
|
54
|
+
|
55
|
+
def over_color=(color)
|
56
|
+
@over_color = color
|
57
|
+
update_extreme_colors if @initialized
|
58
|
+
end
|
59
|
+
|
60
|
+
def under_color
|
61
|
+
init_colormap unless @initialized
|
62
|
+
@lookup_table[@under_index]
|
63
|
+
end
|
64
|
+
|
65
|
+
def under_color=(color)
|
66
|
+
@under_color = color
|
67
|
+
update_extreme_colors if @initialized
|
68
|
+
end
|
69
|
+
|
70
|
+
PNG_WIDTH = 512
|
71
|
+
PNG_HEIGHT = 64
|
72
|
+
|
73
|
+
def to_png
|
74
|
+
require "chunky_png"
|
75
|
+
png = ChunkyPNG::Image.new(PNG_WIDTH, PNG_HEIGHT, ChunkyPNG::Color::TRANSPARENT)
|
76
|
+
x = Utils.linspace(0, 1, PNG_WIDTH)
|
77
|
+
(0 ... PNG_WIDTH).each do |i|
|
78
|
+
color = self[x[i].to_f]
|
79
|
+
png_color = ChunkyPNG::Color.rgba(*color.components.map{|v| (v*255).to_i })
|
80
|
+
png.line(i, 0, i, PNG_HEIGHT-1, png_color)
|
81
|
+
end
|
82
|
+
png.to_blob
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_html
|
86
|
+
require "base64"
|
87
|
+
png_blob = to_png
|
88
|
+
png_base64 = Base64.encode64(png_blob)
|
89
|
+
html = %Q[<div style="vertical-align: middle;">] +
|
90
|
+
%Q[<strong>#{self.name}</strong> ] +
|
91
|
+
%Q[</div>] +
|
92
|
+
%Q[<div class="cmap"><img alt="#{self.name} colormap" ] +
|
93
|
+
%Q[title="#{self.name}" style="border: 1px solid #555;" ] +
|
94
|
+
%Q[src="data:image/png;base64,#{png_base64}"></div>] +
|
95
|
+
%Q[<div style="vertical-align: middle; ] +
|
96
|
+
%Q[max-width: #{PNG_WIDTH + 2}px; ] +
|
97
|
+
%Q[display: flex; justify-content: space-between;">] +
|
98
|
+
%Q[<div style="float: left;">] +
|
99
|
+
%Q[#{html_color_block(under_color)} under</div>] +
|
100
|
+
# TODO: bad_color support
|
101
|
+
# %Q[<div style="margin: 0 auto; display: inline-block;">] +
|
102
|
+
# %Q[bad #{html_color_block(bad_color)}</div>] +
|
103
|
+
%Q[<div style="float: right;">] +
|
104
|
+
%Q[over #{html_color_block(over_color)}</div>]
|
105
|
+
["text/html", html]
|
106
|
+
end
|
107
|
+
|
108
|
+
private def html_color_block(color)
|
109
|
+
hex_color = color.to_hex_string
|
110
|
+
html = %Q[<div title="#{hex_color}" style="display: inline-block; ] +
|
111
|
+
%Q[width: 1em; height: 1em; margin: 0; vertical-align: middle; ] +
|
112
|
+
%Q[border: 1px solid #555; background-color: #{hex_color};">] +
|
113
|
+
%Q[</div>]
|
114
|
+
html
|
115
|
+
end
|
116
|
+
|
117
|
+
private def init_colormap
|
118
|
+
raise NotImplementedError
|
119
|
+
end
|
120
|
+
|
121
|
+
private def all_ratio?(ary)
|
122
|
+
ary.all? {|x| x.is_a?(Float) || x.is_a?(Rational) }
|
123
|
+
end
|
124
|
+
|
125
|
+
private def update_extreme_colors
|
126
|
+
@lookup_table[@under_index] = Utils.make_color(@under_color || @lookup_table[0]).to_rgba
|
127
|
+
@lookup_table[@over_index] = Utils.make_color(@over_color || @lookup_table[self.n_colors - 1]).to_rgba
|
128
|
+
@lookup_table[@bad_index] = Utils.make_color(@bad_color).to_rgba
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Colors
|
2
|
+
class LinearSegmentedColormap < Colormap
|
3
|
+
def initialize(name, segmented_data, n_colors: 256, gamma: 1.0)
|
4
|
+
super(name, n_colors)
|
5
|
+
|
6
|
+
@monochrome = false
|
7
|
+
@segmented_data = segmented_data
|
8
|
+
@gamma = gamma
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :segmented_data, :gamma
|
12
|
+
|
13
|
+
def self.new_from_list(name, colors, n_colors: 256, gamma: 1.0)
|
14
|
+
case colors
|
15
|
+
when Enumerable
|
16
|
+
colors = colors.to_a
|
17
|
+
else
|
18
|
+
ary = Array.try_convert(colors)
|
19
|
+
if ary.nil?
|
20
|
+
raise ArgumentError, "colors must be convertible to an array"
|
21
|
+
else
|
22
|
+
colors = ary
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
case colors[0]
|
27
|
+
when Array
|
28
|
+
unless colors.all? {|a| a.length == 2 }
|
29
|
+
raise ArgumentError, "colors array has invalid items"
|
30
|
+
end
|
31
|
+
vals, colors = colors.transpose
|
32
|
+
else
|
33
|
+
vals = Utils.linspace(0r, 1r, colors.length)
|
34
|
+
end
|
35
|
+
|
36
|
+
r, g, b, a = colors.map { |c|
|
37
|
+
Utils.make_color(c).to_rgba.components
|
38
|
+
}.transpose
|
39
|
+
|
40
|
+
segmented_data = {
|
41
|
+
red: [vals, r, r].transpose,
|
42
|
+
green: [vals, g, g].transpose,
|
43
|
+
blue: [vals, b, b].transpose,
|
44
|
+
alpha: [vals, a, a].transpose
|
45
|
+
}
|
46
|
+
|
47
|
+
new(name, segmented_data, n_colors: n_colors, gamma: gamma)
|
48
|
+
end
|
49
|
+
|
50
|
+
def gamma=(val)
|
51
|
+
@gamma = val
|
52
|
+
@initialized = false
|
53
|
+
end
|
54
|
+
|
55
|
+
private def init_colormap
|
56
|
+
red = create_lookup_table(self.n_colors, @segmented_data[:red], @gamma)
|
57
|
+
green = create_lookup_table(self.n_colors, @segmented_data[:green], @gamma)
|
58
|
+
blue = create_lookup_table(self.n_colors, @segmented_data[:blue], @gamma)
|
59
|
+
alpha = if @segmented_data.key?(:alpha)
|
60
|
+
create_lookup_table(self.n_colors, @segmented_data[:alpha], @gamma)
|
61
|
+
end
|
62
|
+
@lookup_table = Array.new(self.n_colors) do |i|
|
63
|
+
Colors::RGBA.new(red[i], green[i], blue[i], alpha ? alpha[i] : 1r)
|
64
|
+
end
|
65
|
+
@initialized = true
|
66
|
+
update_extreme_colors
|
67
|
+
end
|
68
|
+
|
69
|
+
private def create_lookup_table(n, data, gamma=1.0)
|
70
|
+
if data.respond_to?(:call)
|
71
|
+
xind = Utils.linspace(0r, 1r, n).map {|x| x ** gamma }
|
72
|
+
lut = xind.map {|i| data.(i).clamp(0, 1).to_f }
|
73
|
+
return lut
|
74
|
+
end
|
75
|
+
|
76
|
+
ary = Array.try_convert(data)
|
77
|
+
if ary.nil?
|
78
|
+
raise ArgumentError, "data must be convertible to an array"
|
79
|
+
elsif ary.any? {|sub| sub.length != 3 }
|
80
|
+
raise ArgumentError, "data array must consist of 3-length arrays"
|
81
|
+
end
|
82
|
+
|
83
|
+
shape = [ary.length, 3]
|
84
|
+
|
85
|
+
x, y0, y1 = ary.transpose
|
86
|
+
|
87
|
+
if x[0] != 0.0 || x[-1] != 1.0
|
88
|
+
raise ArgumentError,
|
89
|
+
"data mapping points must start with x=0 and end with x=1"
|
90
|
+
end
|
91
|
+
|
92
|
+
unless x.each_cons(2).all? {|a, b| a < b }
|
93
|
+
raise ArgumentError,
|
94
|
+
"data mapping points must have x in increasing order"
|
95
|
+
end
|
96
|
+
|
97
|
+
if n == 1
|
98
|
+
# Use the `y = f(x=1)` value for a 1-element lookup table
|
99
|
+
lut = [y0[-1]]
|
100
|
+
else
|
101
|
+
x.map! {|v| v.to_f * (n - 1) }
|
102
|
+
xind = Utils.linspace(0r, 1r, n).map {|i| (n - 1) * i ** gamma }
|
103
|
+
ind = (0 ... n).map {|i| x.find_index {|v| xind[i] < v } }[1 ... -1]
|
104
|
+
|
105
|
+
distance = ind.map.with_index do |i, j|
|
106
|
+
(xind[j+1] - x[i - 1]) / (x[i] - x[i - 1])
|
107
|
+
end
|
108
|
+
|
109
|
+
lut = [
|
110
|
+
y1[0],
|
111
|
+
*ind.map.with_index {|i, j| distance[j] * (y0[i] - y1[i - 1]) + y1[i - 1] },
|
112
|
+
y0[-1]
|
113
|
+
]
|
114
|
+
end
|
115
|
+
|
116
|
+
return lut.map {|v| v.clamp(0, 1).to_f }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Colors
|
2
|
+
class ListedColormap < Colormap
|
3
|
+
def initialize(colors, name: :from_list, n_colors: nil)
|
4
|
+
@monochrome = false
|
5
|
+
if n_colors.nil?
|
6
|
+
@colors = Array.try_convert(colors)
|
7
|
+
n_colors = @colors.length
|
8
|
+
else
|
9
|
+
case colors
|
10
|
+
when String, Symbol
|
11
|
+
@colors = Array.new(n_colors) { colors }
|
12
|
+
@monochrome = true
|
13
|
+
when Enumerable
|
14
|
+
@colors = colors.cycle.take(n_colors)
|
15
|
+
@monochrome = @colors.all? {|x| x == @colors[0] }
|
16
|
+
else
|
17
|
+
begin
|
18
|
+
gray = Float(colors)
|
19
|
+
rescue TypeError, ArgumentError
|
20
|
+
raise ArgumentError,
|
21
|
+
"invalid value for `colors` (%p)" % colors
|
22
|
+
else
|
23
|
+
@colors = Array.new(n_colors) { gray }
|
24
|
+
end
|
25
|
+
@monochrome = true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
@colors.freeze
|
29
|
+
|
30
|
+
super(name, n_colors)
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_reader :colors
|
34
|
+
|
35
|
+
private def init_colormap
|
36
|
+
@lookup_table = self.colors.map {|color| Utils.make_color(color).to_rgba }
|
37
|
+
@initialized = true
|
38
|
+
update_extreme_colors
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/colors/utils.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Colors
|
2
|
+
module Utils
|
3
|
+
module_function def linspace(x0, x1, n)
|
4
|
+
Array.new(n) { |i|
|
5
|
+
x0 + i*(x1 - x0)/(n-1r)
|
6
|
+
}
|
7
|
+
end
|
8
|
+
|
9
|
+
module_function def make_color(value)
|
10
|
+
case value
|
11
|
+
when Colors::AbstractColor
|
12
|
+
value
|
13
|
+
else
|
14
|
+
Colors[value]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/colors/version.rb
CHANGED
@@ -0,0 +1,119 @@
|
|
1
|
+
class ColorsLinearSegmentedColormapTest < Test::Unit::TestCase
|
2
|
+
include TestHelper
|
3
|
+
|
4
|
+
sub_test_case("#[]") do
|
5
|
+
def setup
|
6
|
+
@cm = Colors::LinearSegmentedColormap.new_from_list(:triple_colors, [:red, :green, :blue], n_colors: 11)
|
7
|
+
@cm.under_color = :black
|
8
|
+
@cm.over_color = :white
|
9
|
+
end
|
10
|
+
|
11
|
+
sub_test_case("with an integer") do
|
12
|
+
data do
|
13
|
+
expected = [
|
14
|
+
Colors::RGBA.new(1r, 0r, 0r, 1r),
|
15
|
+
Colors::RGBA.new(0r, 128/255r, 0r, 1r),
|
16
|
+
Colors::RGBA.new(0r, 0r, 1r, 1r),
|
17
|
+
Colors::RGBA.new(1r, 1r, 1r, 1r),
|
18
|
+
Colors::RGBA.new(0r, 0r, 0r, 1r),
|
19
|
+
]
|
20
|
+
indices = [0, 5, 10, 11, -1]
|
21
|
+
indices.zip(expected).map { |i, c|
|
22
|
+
["cmap[#{i}]", {i: i, expected_color: c}]
|
23
|
+
}.to_h
|
24
|
+
end
|
25
|
+
def test_aref(data)
|
26
|
+
i, expected = data.values_at(:i, :expected_color)
|
27
|
+
assert_near(expected, @cm[i])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
sub_test_case("with an array of integers") do
|
32
|
+
def test_aref
|
33
|
+
indices = [0, 5, 10, 11, -1]
|
34
|
+
assert_equal(indices.map {|i| @cm[i] },
|
35
|
+
@cm[indices])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
sub_test_case("with a float") do
|
40
|
+
data do
|
41
|
+
expected = [
|
42
|
+
Colors::RGBA.new(0.6r, 0.20078431372549022r, 0.0r, 1r),
|
43
|
+
Colors::RGBA.new(0.19999999999999996r, 0.40156862745098043r, 0.0r, 1r),
|
44
|
+
Colors::RGBA.new(0.0r, 0.4015686274509803r, 0.20000000000000018r, 1r),
|
45
|
+
Colors::RGBA.new(0.0r, 0.20078431372549022r, 0.6r, 1r),
|
46
|
+
Colors::RGBA.new(1r, 1r, 1r, 1r),
|
47
|
+
Colors::RGBA.new(0r, 0r, 0r, 1r),
|
48
|
+
]
|
49
|
+
indices = [0.2, 0.4, 0.6, 0.8, 1.2, -0.2]
|
50
|
+
indices.zip(expected).map { |i, c|
|
51
|
+
["cmap[#{i}]", {i: i, expected_color: c}]
|
52
|
+
}.to_h
|
53
|
+
end
|
54
|
+
def test_aref(data)
|
55
|
+
i, expected = data.values_at(:i, :expected_color)
|
56
|
+
assert_near(expected, @cm[i])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
sub_test_case("with an array of floats") do
|
61
|
+
def test_aref
|
62
|
+
indices = [0.2, 0.4, 0.6, 0.8, 1.2, -0.2]
|
63
|
+
assert_equal(indices.map {|i| @cm[i] },
|
64
|
+
@cm[indices])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_over_color
|
70
|
+
cm = Colors::LinearSegmentedColormap.new_from_list(:blue_and_red, [:blue, :red])
|
71
|
+
|
72
|
+
before = cm[[0, 255, 256]]
|
73
|
+
cm.over_color = :black
|
74
|
+
after = cm[[0, 255, 256]]
|
75
|
+
|
76
|
+
assert_equal([
|
77
|
+
[
|
78
|
+
Colors::RGBA.new(0r, 0r, 1r, 1r),
|
79
|
+
Colors::RGBA.new(1r, 0r, 0r, 1r),
|
80
|
+
Colors::RGBA.new(1r, 0r, 0r, 1r),
|
81
|
+
],
|
82
|
+
[
|
83
|
+
Colors::RGBA.new(0r, 0r, 1r, 1r),
|
84
|
+
Colors::RGBA.new(1r, 0r, 0r, 1r),
|
85
|
+
Colors::RGBA.new(0r, 0r, 0r, 1r),
|
86
|
+
]
|
87
|
+
],
|
88
|
+
[
|
89
|
+
before,
|
90
|
+
after
|
91
|
+
])
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_under_color
|
95
|
+
cm = Colors::LinearSegmentedColormap.new_from_list(:blue_and_red, [:blue, :red])
|
96
|
+
|
97
|
+
before = cm[[0, 255, -1]]
|
98
|
+
cm.under_color = :black
|
99
|
+
after = cm[[0, 255, -1]]
|
100
|
+
|
101
|
+
assert_equal([
|
102
|
+
[
|
103
|
+
Colors::RGBA.new(0r, 0r, 1r, 1r),
|
104
|
+
Colors::RGBA.new(1r, 0r, 0r, 1r),
|
105
|
+
Colors::RGBA.new(0r, 0r, 1r, 1r),
|
106
|
+
],
|
107
|
+
[
|
108
|
+
Colors::RGBA.new(0r, 0r, 1r, 1r),
|
109
|
+
Colors::RGBA.new(1r, 0r, 0r, 1r),
|
110
|
+
Colors::RGBA.new(0r, 0r, 0r, 1r),
|
111
|
+
]
|
112
|
+
],
|
113
|
+
[
|
114
|
+
before,
|
115
|
+
after
|
116
|
+
])
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
@@ -0,0 +1,115 @@
|
|
1
|
+
class ColorsListedColormapTest < Test::Unit::TestCase
|
2
|
+
include TestHelper
|
3
|
+
|
4
|
+
sub_test_case("#[]") do
|
5
|
+
def setup
|
6
|
+
@cm = Colors::ListedColormap.new([:red, :green, :blue])
|
7
|
+
@cm.under_color = :black
|
8
|
+
@cm.over_color = :white
|
9
|
+
end
|
10
|
+
|
11
|
+
sub_test_case("with an integer") do
|
12
|
+
def test_aref
|
13
|
+
assert_equal([
|
14
|
+
Colors::RGBA.new(1r, 0r, 0r, 1r),
|
15
|
+
Colors::RGBA.new(0r, 128/255r, 0r, 1r),
|
16
|
+
Colors::RGBA.new(0r, 0r, 1r, 1r),
|
17
|
+
Colors::RGBA.new(1r, 1r, 1r, 1r),
|
18
|
+
Colors::RGBA.new(0r, 0r, 0r, 1r),
|
19
|
+
],
|
20
|
+
[
|
21
|
+
@cm[0],
|
22
|
+
@cm[1],
|
23
|
+
@cm[2],
|
24
|
+
@cm[3],
|
25
|
+
@cm[-1],
|
26
|
+
])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
sub_test_case("with an array of integers") do
|
31
|
+
def test_aref
|
32
|
+
indices = [0, 1, 2, 3, -1]
|
33
|
+
assert_equal(indices.map {|i| @cm[i] },
|
34
|
+
@cm[indices])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
sub_test_case("with a float") do
|
39
|
+
def test_aref
|
40
|
+
assert_equal([
|
41
|
+
Colors::RGBA.new(1r, 0r, 0r, 1r),
|
42
|
+
Colors::RGBA.new(0r, 128/255r, 0r, 1r),
|
43
|
+
Colors::RGBA.new(0r, 0r, 1r, 1r),
|
44
|
+
Colors::RGBA.new(1r, 1r, 1r, 1r),
|
45
|
+
Colors::RGBA.new(0r, 0r, 0r, 1r),
|
46
|
+
],
|
47
|
+
[
|
48
|
+
@cm[0.1],
|
49
|
+
@cm[0.5],
|
50
|
+
@cm[0.8],
|
51
|
+
@cm[1.1],
|
52
|
+
@cm[-0.1]
|
53
|
+
])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
sub_test_case("with an array of floats") do
|
58
|
+
def test_aref
|
59
|
+
indices = [0.1, 0.5, 0.8, 1.1, -0.1]
|
60
|
+
assert_equal(indices.map {|i| @cm[i] },
|
61
|
+
@cm[indices])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_over_color
|
67
|
+
cm = Colors::ListedColormap.new([:blue, :red])
|
68
|
+
|
69
|
+
before = cm[[0, 1, 2]]
|
70
|
+
cm.over_color = :black
|
71
|
+
after = cm[[0, 1, 2]]
|
72
|
+
|
73
|
+
assert_equal([
|
74
|
+
[
|
75
|
+
Colors::RGBA.new(0r, 0r, 1r, 1r),
|
76
|
+
Colors::RGBA.new(1r, 0r, 0r, 1r),
|
77
|
+
Colors::RGBA.new(1r, 0r, 0r, 1r),
|
78
|
+
],
|
79
|
+
[
|
80
|
+
Colors::RGBA.new(0r, 0r, 1r, 1r),
|
81
|
+
Colors::RGBA.new(1r, 0r, 0r, 1r),
|
82
|
+
Colors::RGBA.new(0r, 0r, 0r, 1r),
|
83
|
+
]
|
84
|
+
],
|
85
|
+
[
|
86
|
+
before,
|
87
|
+
after
|
88
|
+
])
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_under_color
|
92
|
+
cm = Colors::ListedColormap.new([:blue, :red])
|
93
|
+
|
94
|
+
before = cm[[0, 1, -1]]
|
95
|
+
cm.under_color = :black
|
96
|
+
after = cm[[0, 1, -1]]
|
97
|
+
|
98
|
+
assert_equal([
|
99
|
+
[
|
100
|
+
Colors::RGBA.new(0r, 0r, 1r, 1r),
|
101
|
+
Colors::RGBA.new(1r, 0r, 0r, 1r),
|
102
|
+
Colors::RGBA.new(0r, 0r, 1r, 1r),
|
103
|
+
],
|
104
|
+
[
|
105
|
+
Colors::RGBA.new(0r, 0r, 1r, 1r),
|
106
|
+
Colors::RGBA.new(1r, 0r, 0r, 1r),
|
107
|
+
Colors::RGBA.new(0r, 0r, 0r, 1r),
|
108
|
+
]
|
109
|
+
],
|
110
|
+
[
|
111
|
+
before,
|
112
|
+
after
|
113
|
+
])
|
114
|
+
end
|
115
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: red-colors
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kenta Murata
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-06-
|
11
|
+
date: 2021-06-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: matrix
|
@@ -110,14 +110,18 @@ files:
|
|
110
110
|
- lib/colors/abstract_color.rb
|
111
111
|
- lib/colors/alpha_component.rb
|
112
112
|
- lib/colors/color_data.rb
|
113
|
+
- lib/colors/colormap.rb
|
113
114
|
- lib/colors/convert.rb
|
114
115
|
- lib/colors/helper.rb
|
115
116
|
- lib/colors/hsl.rb
|
116
117
|
- lib/colors/hsla.rb
|
117
118
|
- lib/colors/husl.rb
|
119
|
+
- lib/colors/linear_segmented_colormap.rb
|
120
|
+
- lib/colors/listed_colormap.rb
|
118
121
|
- lib/colors/named_colors.rb
|
119
122
|
- lib/colors/rgb.rb
|
120
123
|
- lib/colors/rgba.rb
|
124
|
+
- lib/colors/utils.rb
|
121
125
|
- lib/colors/version.rb
|
122
126
|
- lib/colors/xterm256.rb
|
123
127
|
- lib/colors/xyy.rb
|
@@ -128,6 +132,8 @@ files:
|
|
128
132
|
- test/test-hsl.rb
|
129
133
|
- test/test-hsla.rb
|
130
134
|
- test/test-husl.rb
|
135
|
+
- test/test-linear-segmented-colormap.rb
|
136
|
+
- test/test-listed-colormap.rb
|
131
137
|
- test/test-named-color.rb
|
132
138
|
- test/test-rgb.rb
|
133
139
|
- test/test-rgba.rb
|
@@ -163,6 +169,8 @@ test_files:
|
|
163
169
|
- test/test-hsl.rb
|
164
170
|
- test/test-hsla.rb
|
165
171
|
- test/test-husl.rb
|
172
|
+
- test/test-linear-segmented-colormap.rb
|
173
|
+
- test/test-listed-colormap.rb
|
166
174
|
- test/test-named-color.rb
|
167
175
|
- test/test-rgb.rb
|
168
176
|
- test/test-rgba.rb
|