File Coverage

blib/lib/Term/Colormap.pm
Criterion Covered Total %
statement 14 75 18.6
branch 0 16 0.0
condition 0 7 0.0
subroutine 5 16 31.2
pod 8 8 100.0
total 27 122 22.1


line stmt bran cond sub pod time code
1             package Term::Colormap;
2              
3 1     1   44158 use 5.006;
  1         3  
4 1     1   5 use strict;
  1         2  
  1         19  
5 1     1   4 use warnings FATAL => 'all';
  1         3  
  1         36  
6 1     1   5 use Exporter 'import';
  1         2  
  1         27  
7 1     1   5 use Scalar::Util qw( looks_like_number );
  1         1  
  1         999  
8              
9             our $VERSION = '0.11';
10              
11             our @EXPORT_OK = qw(
12             colorbar
13             colormap
14             color2rgb
15             rgb2color
16             print_colored
17             print_colored_text
18             color_table
19             add_mapping
20             );
21              
22             my $color_mapping = {};
23              
24             # http://www.calmar.ws/vim/256-xterm-24bit-rgb-color-chart.html
25             $color_mapping->{rainbow} = [
26             1, # Red
27             196, 202, 208, 214, 220, 226,
28             11, # Yellow
29             190, 154, 118, 82, 46,
30             10, # Green
31             47, 48, 49, 50, 51,
32             14, # Cyan
33             45, 39, 33, 27, 21,
34             12, # Blue
35             57, 93, 129, 165, 201,
36             5, # Magenta
37             ];
38              
39             $color_mapping->{primary} = [
40             # Black, Red, Green, Yellow, Blue, Magenta, Cyan, Off-White
41             0,1,2,3,4,5,6,7
42             ];
43              
44             $color_mapping->{bright} = [
45             # Gray, Bright Red, Bright Green, Bright Yellow,
46             8,9,10,11,
47             # Bright Blue, Bright Magenta, Bright Cyan, White
48             12,13,14,15
49             ];
50              
51             $color_mapping->{ash} = [
52             # Black <--------------------------------> Gray
53             232,233,234,235,236,237,238,239,240,241,242,243,
54             ];
55              
56             $color_mapping->{snow} = [
57             # Gray <--------------------------------> White
58             244,245,246,247,248,249,250,251,252,253,254,255,
59             ];
60              
61             $color_mapping->{gray} = [ @{ $color_mapping->{ash} }, @{ $color_mapping->{snow} } ];
62              
63             $color_mapping->{'blue-cyan-green'} = [
64             # Blue <------------------ Cyan -----------------> Green
65             17,18,19,20,21,27,33,39,45,51,50,49,48,47,46,40,34,28,22
66             ];
67              
68             $color_mapping->{'red-pink-yellow'} = [
69             # Red <------------------ Pink ------------------------> Yellow
70             196,197,198,199,200,201,207,213,219,225,231,230,229,228,227,226
71             ];
72              
73             $color_mapping->{'green-orange-pink-blue'} = [
74             # Green <-------- Orange -------- Pink --------------> Blue
75             28,64,100,136,172,208,209,210,211,212,213,177,141,105,69,33
76             ];
77              
78             # 0-255
79             my $color2rgb = [
80             '000000', '800000', '008000', '808000', '000080', '800080',
81             '008080', 'c0c0c0', '808080', 'ff0000', '00ff00', 'ffff00',
82             '0000ff', 'ff00ff', '00ffff', 'ffffff', '000000', '00005f',
83             '000087', '0000af', '0000d7', '0000ff', '005f00', '005f5f',
84             '005f87', '005faf', '005fd7', '005fff', '008700', '00875f',
85             '008787', '0087af', '0087d7', '0087ff', '00af00', '00af5f',
86             '00af87', '00afaf', '00afd7', '00afff', '00d700', '00d75f',
87             '00d787', '00d7af', '00d7d7', '00d7ff', '00ff00', '00ff5f',
88             '00ff87', '00ffaf', '00ffd7', '00ffff', '5f0000', '5f005f',
89             '5f0087', '5f00af', '5f00d7', '5f00ff', '5f5f00', '5f5f5f',
90             '5f5f87', '5f5faf', '5f5fd7', '5f5fff', '5f8700', '5f875f',
91             '5f8787', '5f87af', '5f87d7', '5f87ff', '5faf00', '5faf5f',
92             '5faf87', '5fafaf', '5fafd7', '5fafff', '5fd700', '5fd75f',
93             '5fd787', '5fd7af', '5fd7d7', '5fd7ff', '5fff00', '5fff5f',
94             '5fff87', '5fffaf', '5fffd7', '5fffff', '870000', '87005f',
95             '870087', '8700af', '8700d7', '8700ff', '875f00', '875f5f',
96             '875f87', '875faf', '875fd7', '875fff', '878700', '87875f',
97             '878787', '8787af', '8787d7', '8787ff', '87af00', '87af5f',
98             '87af87', '87afaf', '87afd7', '87afff', '87d700', '87d75f',
99             '87d787', '87d7af', '87d7d7', '87d7ff', '87ff00', '87ff5f',
100             '87ff87', '87ffaf', '87ffd7', '87ffff', 'af0000', 'af005f',
101             'af0087', 'af00af', 'af00d7', 'af00ff', 'af5f00', 'af5f5f',
102             'af5f87', 'af5faf', 'af5fd7', 'af5fff', 'af8700', 'af875f',
103             'af8787', 'af87af', 'af87d7', 'af87ff', 'afaf00', 'afaf5f',
104             'afaf87', 'afafaf', 'afafd7', 'afafff', 'afd700', 'afd75f',
105             'afd787', 'afd7af', 'afd7d7', 'afd7ff', 'afff00', 'afff5f',
106             'afff87', 'afffaf', 'afffd7', 'afffff', 'd70000', 'd7005f',
107             'd70087', 'd700af', 'd700d7', 'd700ff', 'd75f00', 'd75f5f',
108             'd75f87', 'd75faf', 'd75fd7', 'd75fff', 'd78700', 'd7875f',
109             'd78787', 'd787af', 'd787d7', 'd787ff', 'd7af00', 'd7af5f',
110             'd7af87', 'd7afaf', 'd7afd7', 'd7afff', 'd7d700', 'd7d75f',
111             'd7d787', 'd7d7af', 'd7d7d7', 'd7d7ff', 'd7ff00', 'd7ff5f',
112             'd7ff87', 'd7ffaf', 'd7ffd7', 'd7ffff', 'ff0000', 'ff005f',
113             'ff0087', 'ff00af', 'ff00d7', 'ff00ff', 'ff5f00', 'ff5f5f',
114             'ff5f87', 'ff5faf', 'ff5fd7', 'ff5fff', 'ff8700', 'ff875f',
115             'ff8787', 'ff87af', 'ff87d7', 'ff87ff', 'ffaf00', 'ffaf5f',
116             'ffaf87', 'ffafaf', 'ffafd7', 'ffafff', 'ffd700', 'ffd75f',
117             'ffd787', 'ffd7af', 'ffd7d7', 'ffd7ff', 'ffff00', 'ffff5f',
118             'ffff87', 'ffffaf', 'ffffd7', 'ffffff', '080808', '121212',
119             '1c1c1c', '262626', '303030', '3a3a3a', '444444', '4e4e4e',
120             '585858', '626262', '626262', '767676', '808080', '8a8a8a',
121             '949494', '9e9e9e', 'a8a8a8', 'b2b2b2', 'bcbcbc', 'c6c6c6',
122             'd0d0d0', 'dadada', 'e4e4e4', 'eeeeee',
123             ];
124              
125             my $color = 0;
126             my $rgb2color = { map { $_ => $color++ } @$color2rgb };
127              
128             sub add_mapping {
129 0     0 1   my ($name, $mapping) = @_;
130 0           $color_mapping->{$name} = $mapping;
131             }
132              
133             sub rgb2color {
134 0     0 1   my ($rgb) = @_;
135              
136 0           my $original_rgb = $rgb;
137 0           $rgb =~ s|^#||;
138 0           $rgb = lc($rgb);
139 0 0         if ( $rgb =~ m|[^a-f0-9]| ) {
140 0           die "Invalid RGB color '$original_rgb'"
141             }
142              
143 0 0         unless (defined $rgb2color->{$rgb}) {
144 0           $rgb2color->{ $rgb } = $rgb2color->{ _get_nearest_color($rgb) };
145             }
146              
147 0           return $rgb2color->{$rgb};
148             }
149              
150             sub _get_nearest_color {
151 0     0     my ($rgb) = @_;
152 0           my $closest = 3 * (scalar @$color2rgb);
153 0           my $best_color;
154 0           for my $color ( @$color2rgb ) {
155 0           my $dist = _color_distance($rgb, $color);
156 0 0         if ($dist < $closest) {
157 0           $best_color = $color;
158 0           $closest = $dist;
159             }
160             }
161 0           return $best_color;
162             }
163              
164             sub _color_distance {
165 0     0     my ($rgb0, $rgb1) = @_;
166 0           my $rgb = $rgb0 . $rgb1;
167             my ($r0, $g0, $b0,
168 0           $r1, $g1, $b1) = map { hex } ( $rgb =~ m/../g );
  0            
169 0           return abs($r1 - $r0)
170             + abs($g1 - $g0)
171             + abs($b1 - $b0);
172             }
173              
174             sub colormap {
175 0     0 1   my ($name) = @_;
176              
177 0 0         if ( exists $color_mapping->{ lc($name) } ) {
178 0           return $color_mapping->{ lc($name) };
179             }
180              
181 0           die "Invalid colormap name : '$name'\n" .
182             "Choose one of ( " . ( join ", ", sort keys %$color_mapping ) . " )\n";
183              
184             }
185              
186             sub color2rgb {
187 0     0 1   my ($color) = @_;
188              
189 0 0 0       if ($color < 0 or $color >= scalar @$color2rgb) {
190 0           die "Invalid color value : $color";
191             }
192              
193 0           return $color2rgb->[$color];
194             }
195              
196              
197             sub colorbar {
198 0     0 1   my ($colors, $width, $orientation ) = @_;
199              
200 0   0       $width ||= 2;
201 0   0       $orientation ||= 'h'; # Horizontal
202              
203 0           for my $color (@$colors) {
204 0           print_colored( $color, ' 'x$width );
205 0 0         unless ('h' eq substr(lc($orientation),0,1)) {
206 0           print "\n";
207             }
208             }
209 0           print "\n";
210             }
211              
212             sub color_table {
213 0     0 1   my ($name) = @_;
214 0           my $mapping = colormap($name);
215              
216 0           my $header = "color number rgb";
217 0           my $indent = (length($header) - length($name) - 1) / 2; # spaces around name
218              
219 0           my $ii = int($indent);
220 0           print '-'x$ii . " $name " . '-'x$ii;
221 0 0         print '-' if ($ii < $indent);
222 0           print "\n";
223              
224 0           print $header . "\n";
225 0           for my $color (@$mapping) {
226 0           print_colored($color, ' 'x8 );
227 0           print sprintf(" %3d ", $color) . color2rgb($color) . "\n";
228             }
229 0           print "\n";
230             }
231              
232             sub print_colored {
233 0     0 1   my ($color, $txt) = @_;
234 0           _print_with_color('bg',$color,$txt);
235             }
236              
237             sub print_colored_text {
238 0     0 1   my ($color, $txt) = @_;
239 0           _print_with_color('fg',$color,$txt);
240             }
241              
242             sub _print_with_color {
243 0     0     my ($bg_or_fg, $color, $txt) = @_;
244              
245 0 0         my $code = $bg_or_fg eq 'fg' ? 38 : 48;
246 0           print "\x1b[${code};5;${color}m" . $txt . "\x1b[0m";
247             }
248              
249             1; # End of Term::Colormap
250              
251             __END__