Page decorations should be subtle and not distracting. I find that gentle gradients used as backgrounds satisfy this criteria. But making gradients is laborious. So I wrote a script to do it for me.
The script is simple but also quite powerful. Here is some example usage:
Blue to red moving left, produced with
/cgi-bin/gradient.cgi?width=100&height=30&from=00f&to=f00&dir=left
Green to yellow moving up, produced with
/cgi-bin/gradient.cgi?width=100&height=30&from=0f0&to=ff0&dir=up
There are five mandatory arguments for the CGI:
| Argument | Example | Description |
|---|---|---|
width | 150 | Width of image in pixels |
height | 150 | Height of image in pixels |
from | F12 | Starting color in 12-bit hex (See Notes below) |
to | 0E8 | Ending color in 12-bit hex (See Notes below) |
dir | left | Direction, one of "left", "right", "up", or "down" |
I chose to use a three character hexadecimal representation (12-bit) of the RGB color triplet for simplicities sake. I've found that in most situations, specifying six hex characters (24-bits) distracts and impedes a fast-and-loose creative process.
#!/usr/local/bin/perl
#
# Gradient making program.
#
# Author: Michal Guerquin (michalg@gmail.com)
# Date: January, 2005
#
use CGI::Carp qw(fatalsToBrowser);
use CGI;
use GD;
use strict;
sub mkramp #($im, $steps, $r0, $g0, $b0, $r1, $g1, $b1)
{
my ($im, $steps, $r0, $g0, $b0, $r1, $g1, $b1) = @_;
my $dr = ($r1 - $r0) / $steps;
my $dg = ($g1 - $g0) / $steps;
my $db = ($b1 - $b0) / $steps;
my @ramp = ();
my $r = $r0;
my $g = $g0;
my $b = $b0;
for (my $i=0; $i<$steps; $i++)
{
@ramp = (@ramp, $im->colorAllocate($r,$g,$b));
$r += $dr;
$g += $dg;
$b += $db;
}
return @ramp;
}
my $theCGI = new CGI;
my $from = $theCGI->param("from");
my $to = $theCGI->param("to");
my $width = $theCGI->param("width");
my $height = $theCGI->param("height");
my $dir = $theCGI->param("dir");
if (not ($from =~ /[0-9a-fA-F]{3}/)) { die "Missing or bad 'from'"; }
if (not ($to =~ /[0-9a-fA-F]{3}/)) { die "Missing or bad 'to'"; }
if (not ($width =~ /[0-9]+/)) { die "Missing or bad 'width'"; }
if (not ($height =~ /[0-9]+/)) { die "Missing or bad 'height'"; }
if (not ($dir eq "left" or $dir eq "right" or $dir eq "up" or $dir eq "down")) { die "Missing or bad 'dir'"; }
$from =~ s/(.)(.)(.)/$1\|$2\|$3/;
my($from_r,$from_g,$from_b)=split(/\|/,$from);
$to =~ s/(.)(.)(.)/$1\|$2\|$3/;
my($to_r,$to_g,$to_b)=split(/\|/,$to);
my $from_r = 16*hex($from_r) + hex($from_r);
my $from_g = 16*hex($from_g) + hex($from_g);
my $from_b = 16*hex($from_b) + hex($from_b);
my $to_r = 16*hex($to_r) + hex($to_r);
my $to_g = 16*hex($to_g) + hex($to_g);
my $to_b = 16*hex($to_b) + hex($to_b);
my $steps = 1;
if ($dir eq "down") { $steps = $height; }
if ($dir eq "up") { $steps = $height; }
if ($dir eq "left") { $steps = $width; }
if ($dir eq "right") { $steps = $width; }
# create a new image
GD::Image->trueColor(1);
my $im = new GD::Image($width,$height);
my @ramp = &mkramp($im, $steps, $from_r,$from_g,$from_b, $to_r,$to_g,$to_b);
if ($dir eq "down")
{
for (my $i=0; $i<$height; $i++)
{
$im->line(0,$i,$width,$i,$ramp[$i]);
}
}
elsif ($dir eq "up")
{
for (my $i=0; $i<$height; $i++)
{
$im->line(0,$i,$width,$i,$ramp[$height-$i-1]);
}
}
elsif ($dir eq "left")
{
for (my $i=0; $i<$width; $i++)
{
$im->line($i,0,$i,$height,$ramp[$i]);
}
}
elsif ($dir eq "right")
{
for (my $i=0; $i<$width; $i++)
{
$im->line($i,0,$i,$height,$ramp[$width-$i-1]);
}
}
# make sure we are writing to a binary stream
binmode STDOUT;
print "Content-type: image/jpeg\n\n";
# Convert the image to JPG and print it on standard output
print $im->jpeg(100);
Ideas for future improvements:
https://michal.guerquin.com/gradient.html, updated 2005-01-20 03:08 EST