# Example usage: say for colors(distribute => 1, format=> "hex", n => 10, colors => [qw/red yellow green/]); =head3 colors At the most basic level, converts colors to different formats, however this subroutine is capable of quite a bit more than that. Examples: colors [qw/red green blue/], format => "ps"; colors [qw/red green blue/], format => "ps", n => 2; =over 4 =item colors A list of colors, can be an X11 color name or any of the other formats recognised by Color::Calc. =item n Only return n colors. =item interpolate If false, requesting more colors than available in the colors list will throw a fatal error. The default is to create new colors between the given colors if there are insufficient colors provided. The interpolate command will also cause colors to be interpolated if the distribute option is set. =item distribute By default, if fewer colors are requested than are contained in the colors list, this subroutine will select the first n colors. Providing a true value for distribute will cause the subroutine to evenly spread out the choice of colors over the range of colors provided (if n E 2 then the first and last colors are guaranteed to be included). =item format Specify the style of the returned colors. Can be anything supported by Color::Calc which is currently (Color::Calc::VERSION == 1.0): "tuple", "hex", "html", "object" (a Graphics::ColorObject object), "pdf". The default format is "object". The following formats are also accepted and are handled by this subroutine directly: "ps" | "postscript". =item background Try to make the colors appear on the given background color. Colors B be altered if this option is provided. =back =cut #BEGIN: colors sub colors { require Color::Calc; unshift @_, "colors" if @_ % 2; my %o = @_; my $c = $o{colors}; my $n = $o{n} ||= @$c; $o{interpolate} = 1 unless exists $o{interpolate}; croak "Not enough "."colors in plot color database" unless $o{interpolate} or $n <= @$c; $o{format} ||= 'object'; $o{format} = lc $o{format}; @o{qw/format _format/} = qw/tuple ps/ if $o{format} =~ /^(?:ps|postscript)$/; my $cct = Color::Calc->new( 'ColorScheme' => 'X', OutputFormat => 'tuple' ); my $cc = Color::Calc->new( 'ColorScheme' => 'X', OutputFormat => $o{format} ); $o{listed} = 1 if $o{format} eq 'tuple'; if (($n > @$c) or ($o{distribute} and $o{interpolate})) { $c = [map [($_==int($_))?$$c[$_]:$cct->mix($$c[int $_],$$c[int($_)+1], $_-int($_))], map +($_*($#{$c})/(($n-1)||1)), 0..$n-1]; } elsif ($o{distribute} and $n < @$c) { $c = [map $$c[int($_*($#{$c})/(($n-1)||1))], 0..$n-1]; } if ($o{background}) { my $fg = $cc->contrast_bw($o{background}); if ($o{listed}) { $c = [ map [$cc->mix($_, $fg, .35)], @$c[0..$n-1] ]; } else { $c = [ map $cc->mix($_, $fg, .35), @$c[0..$n-1] ]; } } else { if ($o{listed}) { $c = [ map [$cc->get($_)], @$c[0..$n-1] ]; } else { $c = [ map $cc->get($_), @$c[0..$n-1] ]; } } if ($o{_format}) { $o{_format} eq 'ps' and do { for (@$c) { $_ /= 255 for @$_ } }; } return wantarray ? @$c : $c; } #END: colors