This program uses a (quarter of a) sine wave to vary red, green, and
blue values from 0 to 1 over the range of the gradient. Offsets for
each component are used to determine the starting point of the wave.
ColorFoo
#!/usr/bin/perl
use strict;
use CGI qw(:standard *table :nodebug);
use Data::Dumper;
#-------------------
# Configuration
my $NUM_STEPS = 32; # Number of colors in gradient
my $WRAPPING = 1; # Makes the end match the beginning
my $OUT_HTML = 1; # Output as HTML, otherwise Dumper
#-------------------
my $PI = atan2(0, -1);
my $USE_STEPS = $WRAPPING ? $NUM_STEPS : $NUM_STEPS * 2;
my $EACH_STEP = $PI / $USE_STEPS;
my $offs = make_offsets_random();
my $grad = make_gradient($offs);
if ($OUT_HTML) { output_html($offs, $grad); }
else { output_dump($offs, $grad); }
#-----------------------------------------------------------
sub make_gradient {
my $offs = shift;
my @grad;
for my $i (0..$NUM_STEPS-1) {
push @grad, make_rgb($i, $offs);
}
return \@grad;
}
#-----------------------------------------------------------
sub make_rgb {
my $i = shift;
my $offs = shift;
my $r = ($i + $offs->{r}) % $USE_STEPS;
my $g = ($i + $offs->{g}) % $USE_STEPS;
my $b = ($i + $offs->{b}) % $USE_STEPS;
return
sprintf "%2.2x%2.2x%2.2x",
int(sin($r * $EACH_STEP) * 255),
int(sin($g * $EACH_STEP) * 255),
int(sin($b * $EACH_STEP) * 255);
}
#-----------------------------------------------------------
sub make_offsets_random {
return {
r => int(rand() * $USE_STEPS),
g => int(rand() * $USE_STEPS),
b => int(rand() * $USE_STEPS),
};
}
#-----------------------------------------------------------
sub output_html {
my $offs = shift;
my $grad = shift;
print header();
print start_html();
print start_table({-cellspacing=>0});
my @rows;
push @rows,
Tr(td("Offsets $offs->{r} $offs->{g} $offs->{b}"));
for my $i (@$grad) {
push @rows, Tr(td({-bgcolor=>$i}, $i));
}
print join("\n", @rows);
print end_table();
print end_html();
}
#-----------------------------------------------------------
sub output_dump {
my $offs = shift;
my $grad = shift;
print Dumper $offs;
print Dumper $grad;
}