—=encoding utf-8
=head1 NAME
-Msubst::dyncmap - Getopt::EX Dynamic colormap module
=head1 SYNOPSIS
option --subst-color-light \
-Msubst::dyncmap \
--colormap \
--dyncmap \
range=0-2,except=000:111:222,shift=3,even="555D/%s",odd="I;000/%s"
=head1 DESCRIPTION
Parameter is given in a form of B<name>=I<value> and connected by
comma.
=over 7
=item B<range>=I<s>-I<e>[:I<s>-I<e>[:I<s>-I<e>]]
RGB range. All range can be given like C<0-2:0-2:0-2>, or if the
number of range is less than three, last range is repeated.
Each RGB value is in the range of 0 to 5, and produces 6x6x6 216
colors.
=item B<except>
Specify exception value, like C<000:111:222>.
=item B<even>=I<colormap>
=item B<odd>=I<colormap>
Colormap string for even and odd index. String is given to C<sprintf>
function with RGB parameter.
=item B<shift>=I<number>
Range is shifted by this value for odd index map. Shifted value have
to be in the range of 0 to 5.
=item B<sort>=[I<none>,I<average>,I<luminance>]
Specify sort algorithm. Default is B<average>.
=item B<reverse>=[0,1]
If true, map is reversed.
=back
=head1 SEE ALSO
L<Getopt::EX>, L<Getopt::EX::Colormap>
L<App::Greple>, L<App::Greple::subst>
=head1 AUTHOR
Kazumasa Utashiro
=head1 LICENSE
Copyright 2020-2021 Kazumasa Utashiro.
You can redistribute it and/or modify it under the same terms
as Perl itself.
=cut
package
App::Greple::subst::dyncmap;
use
v5.14;
use
strict;
use
warnings;
use
Carp;
use
Data::Dumper;
##
## Dyamic colormap generator
##
sub
dyncmap {
my
%opt
=
@_
;
for
(
$opt
{range}) {
my
@range
= pairmap { [
$a
..
$b
] } /([0-5])-([0-5])/g
or
die
"$_: range format error"
;
push
@range
,
$range
[-1]
while
@range
< 3;
$_
= \
@range
;
}
my
@cm
= cmap(
%opt
);
join
','
,
@cm
;
}
sub
combination {
my
$c
= reduce {
[
map
{
my
@a
=
@$_
;
map
{ [
@a
,
$_
] }
@$b
}
@$a
];
} [ [] ],
@_
;
@$c
;
}
sub
rgb {
if
(notall { 0 <=
$_
&&
$_
<= 5 }
@_
) {
local
$" =
''
;
die
"@_: Invalid RGB value"
;
}
my
(
$r
,
$g
,
$b
) =
@_
;
if
(
$r
==
$g
and
$r
==
$b
) {
qw(L03 L07 L11 L15 L19 L23)
[
$r
];
}
else
{
"$r$g$b"
;
}
}
my
%sort
= (
none
=>
undef
,
average
=>
sub
{
local
$" =
''
;
map
{
$_
->[0] }
sort
{
$a
->[1] <=>
$b
->[1] ||
$a
->[2] cmp
$b
->[2] }
map
{ [
$_
, sum(
@$_
),
"@$_"
] }
@_
;
},
luminance
=>
sub
{
map
{
$_
->[0] }
sort
{
$a
->[1] <=>
$b
->[1] }
map
{ [
$_
,
$$_
[0]*30 +
$$_
[1]*59 +
$$_
[2]*11 ] }
@_
;
},
);
sub
cmap {
my
%opt
= (
shift
=> 0,
except
=>
''
,
sort
=>
'average'
,
@_
);
my
@cm
= combination @{
$opt
{range}};
if
(
my
%except
=
map
{
$_
=> 1 }
$opt
{except} =~ /\b(\d\d\d)\b/g) {
local
$" =
''
;
@cm
=
grep
{ not
$except
{
"@$_"
} }
@cm
;
}
if
(
my
$algorithm
=
$opt
{
sort
}) {
exists
$sort
{
$algorithm
} or
die
"$algorithm: unknown algorithm"
;
if
(
my
$sort
=
$sort
{
$algorithm
}) {
@cm
=
$sort
->(
@cm
);
}
}
@cm
=
reverse
@cm
if
$opt
{
reverse
};
my
@map
=
map
{
(
sprintf
(
$opt
{even}, rgb(
@$_
) ),
sprintf
(
$opt
{odd}, rgb(
map
$_
+
$opt
{
shift
},
@$_
) ) );
}
@cm
;
}
1;
__DATA__
mode function
option --dyncmap &dyncmap($<shift>)