1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
module Xterm256Color
VALUERANGE = [
0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF
]
BASIC16 = [
[ 0x00, 0x00, 0x00 ],
[ 0xCD, 0x00, 0x00 ],
[ 0x00, 0xCD, 0x00 ],
[ 0xCD, 0xCD, 0x00 ],
[ 0x00, 0x00, 0xEE ],
[ 0xCD, 0x00, 0xCD ],
[ 0x00, 0xCD, 0xCD ],
[ 0xE5, 0xE5, 0xE5 ],
[ 0x7F, 0x7F, 0x7F ],
[ 0xFF, 0x00, 0x00 ],
[ 0x00, 0xFF, 0x00 ],
[ 0xFF, 0xFF, 0x00 ],
[ 0x5C, 0x5C, 0xFF ],
[ 0xFF, 0x00, 0xFF ],
[ 0x00, 0xFF, 0xFF ],
[ 0xFF, 0xFF, 0xFF ]
]
def self.xterm2rgb(color)
case color
when 0..15
return BASIC16[color].dup
when 16..232
color -= 16
return [VALUERANGE[(color / 36) % 6], VALUERANGE[(color / 6) % 6], VALUERANGE[color % 6]]
when 233..253
return [8 + (color - 232) * 0x0a] * 3
else
raise ArgumentError, "expected color value in range 0..253 but was #{color}"
end
end
def self.make_table
@colortable ||=
begin
colortable = []
0.upto(253) do |color|
rgb = xterm2rgb(color)
colortable << rgb
end
colortable
end
end
def self.rgb2xterm(rgb)
@rgb2xterm_cache ||= {}
return @rgb2xterm_cache[rgb] ||=
begin
self.make_table
smallest_distance = 1_000_000_000_000
best_match = 0
0.upto(253) do |color|
d = self.euclidean_distance(@colortable[color], rgb)
if d < smallest_distance
smallest_distance = d
best_match = color
end
end
best_match
end
end
def self.euclidean_distance(v1, v2)
raise ArgumentError, "Expected two arrays" unless v1.is_a?(Array) && v2.is_a?(Array)
raise ArgumentError, "Expected two array with the same size (#{v1.size} <=> #{v2.size})" if v1.size != v2.size
sum_of_squares = 0
v1.size.times do |i|
sum_of_squares += (v1[i] - v2[i]) * (v1[i] - v2[i])
end
return Math.sqrt(sum_of_squares)
end
end
|