#!/usr/local/perl/perl -w
## Make a gif "transparent"
##
## Jeffrey Friedl
## jfriedl@omrongw.wg.omron.co.jp
## 15 July 1994
## 2 Aug 1994 - added ability to select transparent color by RGB values.
## 940825.3 -- modified to work with possible future versions of the
##             GIF standard... just in case.
##
#$version = "940825.3";
##
## BLURB:
## Transforms a "normal" gif into a "transparent background" gif.
##
##>
##
## I wrote this because people ask for something like this all the time.
## I just learned the format of GIFs a week ago, so this will likely be
## lacking in many respects.
##
##
## Usage:
##      transgif [options] regular.gif > transparent.gif
##   or
##      cat regular.gif | transgif [options] transparent.gif
##
## The default is that whatever color happens to fall into the first colormap
## slot (often black) will be made transparent. This can be changed via the
## the options.
##
## The options are from:
##   -p              print the colormap (to STDERR).
##                   The new gif still goes to STDOUT.
##
##   -###            make colormap index-### transparent (default is -0)
##
##   -rgb ## ## ##   Take the three numbers as R G B values (in the range
##                   of 0..255 (or 0x00..0xff). The first colormap entry
##                   with those RGB values is made transparent.
##
##   -rgb name       Use the R G B values of the color 'name' if known
##                   by this program (data from X11's rgb.txt)
##
## COLORNUM is the index of the color entry to make transparent, and 
## defaults to zero. For those that like the looks of it, you can put
## a leading '-'.
##
##<

sub usage {
   die "@_\nUsage: $0 [-p] [-## | -rgb name | -rgb ## ## ##] [file]\n";
}

$trans_index = 0;
$print_color_map = 0;
$select_via_rgb = 0;

while (@ARGV && $ARGV[0] =~ m/^-/) {
    $arg = shift;
    if ($arg eq '-p') {              ## print color map
        $print_color_map = 1;

    } elsif ($arg =~ m/^-(\d+)$/) {  ## set color map index number
        $trans_index = $1;

    } elsif ($arg eq '-rgb') {       ## set what color to make transparent

        ## if next three args look numerical (## or 0x##), use as R B G.
        if (@ARGV >= 3 &&
            $ARGV[0] =~ m/^(0x[\da-f]+|\d+)$/i &&
            $ARGV[1] =~ m/^(0x[\da-f]+|\d+)$/i &&
            $ARGV[2] =~ m/^(0x[\da-f]+|\d+)$/i)
        {
            ($R, $G, $B) = splice(@ARGV, 0, 3);
            $select_via_rgb = 1;
            $R = eval($R); ## eval these to process any hex or octal values.
            $G = eval($G); ## eval these to process any hex or octal values.
            $B = eval($B); ## eval these to process any hex or octal values.

        ## if next arg looks like a color name, use those R G B values.
        } elsif (@ARGV && (@RGB = &name2rgb($ARGV[0]), @RGB == 3)) {
            shift; ## eat name;
            ($R, $G, $B) = @RGB;
            $select_via_rgb = 1;

        } else {
           warn(qq/(don't understand "$ARGV[0]" as a color name)\n/) if @ARGV;
           die qq/$0: expected color name or a numerical triplet for $arg\n/;
        }
    } else {
        &usage(qq/unknown arg "$arg".\n/);
    }
}

&usage('too many args.') if @ARGV > 1;

if (@ARGV == 0) {
    &giftrans(*STDIN, *STDOUT, $trans_index);
} else {
    open(INPUT,  $file =shift) || die "$0: couldn't open [$file] for input\n";
    &giftrans(*INPUT, *STDOUT, $trans_index);
    close(INPUT);
}
exit(0);



##
## Given indirect references to two filehandles, pass the file from
## one to the other, changing nothing unless it's a GIF that we know
## how to deal with, and if so do so.
##
## This is written rather verbosely for the sake of clarity... speed not
## much of an issue for something like this, and the difference is minimal
## anyway.
##
sub giftrans
{
    local(*IN, *OUT, $trans_index) = @_;
    $trans_index = 0 if !defined $trans_index;
    local($header, $color_table, $nextblock, $buffer) = ('') x 4;

    ## The header looks like:
    ##   byte 0 - 5:  "GIF89a" or "GIF87a"
    ##   byte 6, 7:   width  (low order first)
    ##   byte 8, 9:   height (low order first)
    ##   byte 10:     various flags
    ##   byte 11:     background color index
    ##   byte 12:     aspect ratio
    sysread(IN, $header, 13) || die "sysread header: $!";
    substr($header, 0, 6) = 'GIF89a' if substr($header,0,6) eq 'GIF87a';
    print OUT $header;

    if (substr($header, 0, 3) ne 'GIF') {
        print STDERR "don't know input filetype, passing unchanged\n";
    } else {
        ##
        ## Look at flags (8 bits): hi[MCCCSPPP]low
        ##   M   = global colormap present?
        ##   CCC = bits/color/colormapentry - 1
        ##   S   = color map sorted by importance?
        ##   PPP = bits/pixel - 1
        ## therefore
        ##   Bits/pixel = PPP+1
        ##   Number of possible colors (entries in colormap): 2 ** (PPP+1)
        ##                                                  : 1 << (PPP+1)
        ##   Size (bytes) of colormap: 3 * Number of possible colors
        ##                           : 3 * (1 << (PPP+1))
        ##
        local($flags) = ord(substr($header, 10, 1));
        local($has_global_colormap) = $flags & 0x80;

        ## Copy over the colormap if need be.
        if (!$has_global_colormap)
        {
           die "$0: picture has no colormap, so -rgb arg invalid\n"
                if $select_via_rgb;
           die "$0: no colormap, so any index except 0 or 1 makes no sense\n"
                if $trans_index > 1;
        } else {
            local($bits_per_pixel) = 1 + ($flags & 0x07);
            local($colormap_entries) = 1 << $bits_per_pixel;
            local($color_tbl_size) = 3 * $colormap_entries;

            sysread(IN, $color_table, $color_tbl_size) || die "sysread color";
            print OUT $color_table;

            if ($print_color_map || $select_via_rgb)
            {
                ## For each byte of each colormap's RGB triplit, we'll have
                ## to mask off bits that aren't used when looking at the
                ## color values.
                local($bits_color_byte) = 1 + (($flags >> 4) & 0x07);
                local($rgb_byte_mask) = (1 << $bits_color_byte) - 1;
                local($r,$g,$b);

                local($best_delta) = 1000; ## any big number ok
                local(@delta, @r, @b, @g);

                for ($i = 0; $i < $colormap_entries; $i++)
                {
                   ($r, $g, $b) = unpack("CCC", substr($color_table, $i*3, 3));
                   $r &= $rgb_byte_mask;
                   $g &= $rgb_byte_mask;
                   $b &= $rgb_byte_mask;

                   if ($select_via_rgb) {
                        if ($r == $R && $g == $G && $b == $B) {
                            $select_via_rgb = 0;
                            $trans_index = $i;
                            print(STDERR "Found exact match (index #$i).\n");
                        } else {
                            $delta = ($r < $R ? $R - $r : $r - $R) +
                                     ($g < $G ? $G - $g : $g - $G) +
                                     ($b < $B ? $B - $b : $b - $B);
                            if ($delta < $best_delta) {
                                @delta = ($i);
                                @r = $r; @g = $g; @b = $b;
                                $best_delta = $delta;
                            } elsif ($delta == $best_delta) {
                                push(@delta, $i);
                                push(@r, $r); push(@g, $g); push(@b, $b);
                            }
                        }
                   }

                   printf(STDERR "%03d: %3d %3d %3d (x%02x x%02x x%02x)\n", $i,
                        $r, $g, $b, $r, $g, $b) if $print_color_map;
                }

                if ($select_via_rgb) {
                    ## Mmm, didn't find it. Use one of the close ones.
                    $trans_index = shift(@delta);
                    $r = shift(@r);
                    $g = shift(@g);
                    $b = shift(@b);

                    printf(STDERR "requested color not found, using index ".
                                  "#%d: %3d %3d %3d (x%02x x%02x x%02x)\n",
                                  $trans_index,
                                   $r, $g, $b, $r, $g, $b);
                    if (@delta)
                    {
                        $count = @delta;
                        print(STDERR
                            "note: %d other entrie%s seem equally close:\n",
                                $count, $count == 1 ? "" : "s");
                        while (@delta) {
                            $index = shift(@delta);
                            $r = shift(@r);
                            $g = shift(@g);
                            $b = shift(@b);
                            printf(STDERR "  index %03d: %3d %3d %3d ".
                                          "(x%02x x%02x x%02x)\n",
                                          $index, $r, $g, $b, $r, $g, $b);
                        }
                    }
                }
            }
        }

        ##
        ## The next 8 bytes will either be an already-there graphic-extension
        ## block, or something else that we'll not care about. In the latter
        ## case, we'll add a graphic-extension block saying "color such-and-
        ## such is transparent". If there's already one there, we'll just
        ## ensure that it says that.
        ##
        sysread(IN, $nextblock, 8) || die "sysread nextblock";
        local($extension, $label) = unpack('CC', $nextblock);
        ## If extension is 0x21 and label is 0xf9, that's the magic tha means
        ## there's already a graphic extension there.
        if ($extension == 0x21 && $label == 0xf9) {
            substr($nextblock, 3, 1) = pack('C', 1|substr($nextblock, 3, 1));
            substr($nextblock, 6, 1) = pack('C', $trans_index);
        } else {
            print OUT pack('CCC CCCC C',
                0x21,  ## magic: "Extension Introducer"
                0xf9,  ## magic: "Graphic Control Label"
                   4,  ## bytes in block (between here and terminator)
                0x01,  ## indicates that 'transparet index' is given
                0, 0,  ## delay time.
                $trans_index, ## index number of colormap entry
                0x00); ## terminator.
        }
        print OUT $nextblock;
    }

    ## Now just pass the rest of the file over unchanged.

    print OUT $buffer while sysread(IN, $buffer, 4096);
    close(IN);
    close(OUT);
}

##
## Change a name to a triplet of RGB values.
## name and RGB data taken from the X11 lib/rgb.txt, with the
## name regexe-compressed by me.
##
sub name2rgb
{
    local($_) = @_;  ## name;
    study;
    %rgb = (
        '  0,  0,  0', 'black|gr[ae]y0',
        '  0,  0,128', 'navy([ \-]?blue)?',
        '  0,  0,139', 'blue4',
        '  0,  0,205', 'blue3|medium[ \-]?blue',
        '  0,  0,238', 'blue2',
        '  0,  0,255', 'blue1?',
        '  0,100,  0', 'dark[ \-]?green',
        '  0,104,139', 'deepskyblue4',
        '  0,134,139', 'turquoise4',
        '  0,139,  0', 'green4',
        '  0,139, 69', 'springgreen4',
        '  0,139,139', 'cyan4',
        '  0,154,205', 'deepskyblue3',
        '  0,178,238', 'deepskyblue2',
        '  0,191,255', 'deep( sky blue|-sky-blue|skyblue1?)',
        '  0,197,205', 'turquoise3',
        '  0,205,  0', 'green3',
        '  0,205,102', 'springgreen3',
        '  0,205,205', 'cyan3',
        '  0,206,209', 'dark[ \-]?turquoise',
        '  0,229,238', 'turquoise2',
        '  0,238,  0', 'green2',
        '  0,238,118', 'springgreen2',
        '  0,238,238', 'cyan2',
        '  0,245,255', 'turquoise1',
        '  0,250,154', 'medium[ \-]?spring[ \-]?green',
        '  0,255,  0', 'green1?',
        '  0,255,127', 'spring[ \-]?green1?',
        '  0,255,255', 'cyan1?',
        '  3,  3,  3', 'gr[ae]y1',
        '  5,  5,  5', 'gr[ae]y2',
        '  8,  8,  8', 'gr[ae]y3',
        ' 10, 10, 10', 'gr[ae]y4',
        ' 13, 13, 13', 'gr[ae]y5',
        ' 15, 15, 15', 'gr[ae]y6',
        ' 16, 78,139', 'dodgerblue4',
        ' 18, 18, 18', 'gr[ae]y7',
        ' 20, 20, 20', 'gr[ae]y8',
        ' 23, 23, 23', 'gr[ae]y9',
        ' 24,116,205', 'dodgerblue3',
        ' 25, 25,112', 'midnight[ \-]?blue',
        ' 26, 26, 26', 'gr[ae]y10',
        ' 28, 28, 28', 'gr[ae]y11',
        ' 28,134,238', 'dodgerblue2',
        ' 30,144,255', 'dodger[ \-]?blue1?',
        ' 31, 31, 31', 'gr[ae]y12',
        ' 32,178,170', 'light[ \-]?sea[ \-]?green',
        ' 33, 33, 33', 'gr[ae]y13',
        ' 34,139, 34', 'forest[ \-]?green',
        ' 36, 36, 36', 'gr[ae]y14',
        ' 38, 38, 38', 'gr[ae]y15',
        ' 39, 64,139', 'royalblue4',
        ' 41, 41, 41', 'gr[ae]y16',
        ' 43, 43, 43', 'gr[ae]y17',
        ' 46, 46, 46', 'gr[ae]y18',
        ' 46,139, 87', 'sea[ \-]?green4?',
        ' 47, 79, 79', 'dark( slate gr[ae]|-slate-gr[ae]|slategr[ae])y',
        ' 48, 48, 48', 'gr[ae]y19',
        ' 50,205, 50', 'lime[ \-]?green',
        ' 51, 51, 51', 'gr[ae]y20',
        ' 54, 54, 54', 'gr[ae]y21',
        ' 54,100,139', 'steelblue4',
        ' 56, 56, 56', 'gr[ae]y22',
        ' 58, 95,205', 'royalblue3',
        ' 59, 59, 59', 'gr[ae]y23',
        ' 60,179,113', 'medium[ \-]?sea[ \-]?green',
        ' 61, 61, 61', 'gr[ae]y24',
        ' 64, 64, 64', 'gr[ae]y25',
        ' 64,224,208', 'turquoise',
        ' 65,105,225', 'royal[ \-]?blue',
        ' 66, 66, 66', 'gr[ae]y26',
        ' 67,110,238', 'royalblue2',
        ' 67,205,128', 'seagreen3',
        ' 69, 69, 69', 'gr[ae]y27',
        ' 69,139,  0', 'chartreuse4',
        ' 69,139,116', 'aquamarine4',
        ' 70,130,180', 'steel[ \-]?blue',
        ' 71, 60,139', 'slateblue4',
        ' 71, 71, 71', 'gr[ae]y28',
        ' 72, 61,139', 'dark[ \-]?slate[ \-]?blue',
        ' 72,118,255', 'royalblue1',
        ' 72,209,204', 'medium[ \-]?turquoise',
        ' 74, 74, 74', 'gr[ae]y29',
        ' 74,112,139', 'skyblue4',
        ' 77, 77, 77', 'gr[ae]y30',
        ' 78,238,148', 'seagreen2',
        ' 79, 79, 79', 'gr[ae]y31',
        ' 79,148,205', 'steelblue3',
        ' 82, 82, 82', 'gr[ae]y32',
        ' 82,139,139', 'darkslategray4',
        ' 83,134,139', 'cadetblue4',
        ' 84, 84, 84', 'gr[ae]y33',
        ' 84,139, 84', 'palegreen4',
        ' 84,255,159', 'seagreen1',
        ' 85, 26,139', 'purple4',
        ' 85,107, 47', 'dark[ \-]?olive[ \-]?green',
        ' 87, 87, 87', 'gr[ae]y34',
        ' 89, 89, 89', 'gr[ae]y35',
        ' 92, 92, 92', 'gr[ae]y36',
        ' 92,172,238', 'steelblue2',
        ' 93, 71,139', 'mediumpurple4',
        ' 94, 94, 94', 'gr[ae]y37',
        ' 95,158,160', 'cadet[ \-]?blue',
        ' 96,123,139', 'lightskyblue4',
        ' 97, 97, 97', 'gr[ae]y38',
        ' 99, 99, 99', 'gr[ae]y39',
        ' 99,184,255', 'steelblue1',
        '100,149,237', 'cornflower[ \-]?blue',
        '102,102,102', 'gr[ae]y40',
        '102,139,139', 'paleturquoise4',
        '102,205,  0', 'chartreuse3',
        '102,205,170', 'aquamarine3|medium[ \-]?aquamarine',
        '104, 34,139', 'darkorchid4',
        '104,131,139', 'lightblue4',
        '105, 89,205', 'slateblue3',
        '105,105,105', 'dim( gr[ae]|-gr[ae]|gr[ae])y|gr[ae]y41',
        '105,139, 34', 'olivedrab4',
        '105,139,105', 'darkseagreen4',
        '106, 90,205', 'slate[ \-]?blue',
        '107,107,107', 'gr[ae]y42',
        '107,142, 35', 'olive[ \-]?drab',
        '108,123,139', 'slategray4',
        '108,166,205', 'skyblue3',
        '110,110,110', 'gr[ae]y43',
        '110,123,139', 'lightsteelblue4',
        '110,139, 61', 'darkolivegreen4',
        '112,112,112', 'gr[ae]y44',
        '112,128,144', 'slate( gr[ae]|-gr[ae]|gr[ae])y',
        '115,115,115', 'gr[ae]y45',
        '117,117,117', 'gr[ae]y46',
        '118,238,  0', 'chartreuse2',
        '118,238,198', 'aquamarine2',
        '119,136,153', 'light( slate gr[ae]|-slate-gr[ae]|slategr[ae])y',
        '120,120,120', 'gr[ae]y47',
        '121,205,205', 'darkslategray3',
        '122, 55,139', 'mediumorchid4',
        '122,103,238', 'slateblue2',
        '122,122,122', 'gr[ae]y48',
        '122,139,139', 'lightcyan4',
        '122,197,205', 'cadetblue3',
        '123,104,238', 'medium[ \-]?slate[ \-]?blue',
        '124,205,124', 'palegreen3',
        '124,252,  0', 'lawn[ \-]?green',
        '125, 38,205', 'purple3',
        '125,125,125', 'gr[ae]y49',
        '126,192,238', 'skyblue2',
        '127,127,127', 'gr[ae]y50',
        '127,255,  0', 'chartreuse1?',
        '127,255,212', 'aquamarine1?',
        '130,130,130', 'gr[ae]y51',
        '131,111,255', 'slateblue1',
        '131,139,131', 'honeydew4',
        '131,139,139', 'azure4',
        '132,112,255', 'light[ \-]?slate[ \-]?blue',
        '133,133,133', 'gr[ae]y52',
        '135,135,135', 'gr[ae]y53',
        '135,206,235', 'sky[ \-]?blue',
        '135,206,250', 'light[ \-]?sky[ \-]?blue',
        '135,206,255', 'skyblue1',
        '137,104,205', 'mediumpurple3',
        '138, 43,226', 'blue[ \-]?violet',
        '138,138,138', 'gr[ae]y54',
        '139,  0,  0', 'red4',
        '139,  0,139', 'magenta4',
        '139, 10, 80', 'deeppink4',
        '139, 26, 26', 'firebrick4',
        '139, 28, 98', 'maroon4',
        '139, 34, 82', 'violetred4',
        '139, 35, 35', 'brown4',
        '139, 37,  0', 'orangered4',
        '139, 54, 38', 'tomato4',
        '139, 58, 58', 'indianred4',
        '139, 58, 98', 'hotpink4',
        '139, 62, 47', 'coral4',
        '139, 69,  0', 'darkorange4',
        '139, 69, 19', 'chocolate4|saddle[ \-]?brown',
        '139, 71, 38', 'sienna4',
        '139, 71, 93', 'palevioletred4',
        '139, 71,137', 'orchid4',
        '139, 76, 57', 'salmon4',
        '139, 87, 66', 'lightsalmon4',
        '139, 90,  0', 'orange4',
        '139, 90, 43', 'tan4',
        '139, 95,101', 'lightpink4',
        '139, 99,108', 'pink4',
        '139,101,  8', 'darkgoldenrod4',
        '139,102,139', 'plum4',
        '139,105, 20', 'goldenrod4',
        '139,105,105', 'rosybrown4',
        '139,115, 85', 'burlywood4',
        '139,117,  0', 'gold4',
        '139,119,101', 'peachpuff4',
        '139,121, 94', 'navajowhite4',
        '139,123,139', 'thistle4',
        '139,125,107', 'bisque4',
        '139,125,123', 'mistyrose4',
        '139,126,102', 'wheat4',
        '139,129, 76', 'lightgoldenrod4',
        '139,131,120', 'antiquewhite4',
        '139,131,134', 'lavenderblush4',
        '139,134, 78', 'khaki4',
        '139,134,130', 'seashell4',
        '139,136,120', 'cornsilk4',
        '139,137,112', 'lemonchiffon4',
        '139,137,137', 'snow4',
        '139,139,  0', 'yellow4',
        '139,139,122', 'lightyellow4',
        '139,139,131', 'ivory4',
        '140,140,140', 'gr[ae]y55',
        '141,182,205', 'lightskyblue3',
        '141,238,238', 'darkslategray2',
        '142,229,238', 'cadetblue2',
        '143,143,143', 'gr[ae]y56',
        '143,188,143', 'dark[ \-]?sea[ \-]?green',
        '144,238,144', 'palegreen2',
        '145, 44,238', 'purple2',
        '145,145,145', 'gr[ae]y57',
        '147,112,219', 'medium[ \-]?purple',
        '148,  0,211', 'dark[ \-]?violet',
        '148,148,148', 'gr[ae]y58',
        '150,150,150', 'gr[ae]y59',
        '150,205,205', 'paleturquoise3',
        '151,255,255', 'darkslategray1',
        '152,245,255', 'cadetblue1',
        '152,251,152', 'pale[ \-]?green',
        '153, 50,204', 'dark[ \-]?orchid',
        '153,153,153', 'gr[ae]y60',
        '154, 50,205', 'darkorchid3',
        '154,192,205', 'lightblue3',
        '154,205, 50', 'olivedrab3|yellow[ \-]?green',
        '154,255,154', 'palegreen1',
        '155, 48,255', 'purple1',
        '155,205,155', 'darkseagreen3',
        '156,156,156', 'gr[ae]y61',
        '158,158,158', 'gr[ae]y62',
        '159,121,238', 'mediumpurple2',
        '159,182,205', 'slategray3',
        '160, 32,240', 'purple',
        '160, 82, 45', 'sienna',
        '161,161,161', 'gr[ae]y63',
        '162,181,205', 'lightsteelblue3',
        '162,205, 90', 'darkolivegreen3',
        '163,163,163', 'gr[ae]y64',
        '164,211,238', 'lightskyblue2',
        '165, 42, 42', 'brown',
        '166,166,166', 'gr[ae]y65',
        '168,168,168', 'gr[ae]y66',
        '171,130,255', 'mediumpurple1',
        '171,171,171', 'gr[ae]y67',
        '173,173,173', 'gr[ae]y68',
        '173,216,230', 'light[ \-]?blue',
        '173,255, 47', 'green[ \-]?yellow',
        '174,238,238', 'paleturquoise2',
        '175,238,238', 'pale[ \-]?turquoise',
        '176, 48, 96', 'maroon',
        '176,176,176', 'gr[ae]y69',
        '176,196,222', 'light[ \-]?steel[ \-]?blue',
        '176,224,230', 'powder[ \-]?blue',
        '176,226,255', 'lightskyblue1',
        '178, 34, 34', 'firebrick',
        '178, 58,238', 'darkorchid2',
        '178,223,238', 'lightblue2',
        '179,179,179', 'gr[ae]y70',
        '179,238, 58', 'olivedrab2',
        '180, 82,205', 'mediumorchid3',
        '180,205,205', 'lightcyan3',
        '180,238,180', 'darkseagreen2',
        '181,181,181', 'gr[ae]y71',
        '184,134, 11', 'dark[ \-]?goldenrod',
        '184,184,184', 'gr[ae]y72',
        '185,211,238', 'slategray2',
        '186, 85,211', 'medium[ \-]?orchid',
        '186,186,186', 'gr[ae]y73',
        '187,255,255', 'paleturquoise1',
        '188,143,143', 'rosy[ \-]?brown',
        '188,210,238', 'lightsteelblue2',
        '188,238,104', 'darkolivegreen2',
        '189,183,107', 'dark[ \-]?khaki',
        '189,189,189', 'gr[ae]y74',
        '190,190,190', 'gr[ae]y',
        '191, 62,255', 'darkorchid1',
        '191,191,191', 'gr[ae]y75',
        '191,239,255', 'lightblue1',
        '192,255, 62', 'olivedrab1',
        '193,205,193', 'honeydew3',
        '193,205,205', 'azure3',
        '193,255,193', 'darkseagreen1',
        '194,194,194', 'gr[ae]y76',
        '196,196,196', 'gr[ae]y77',
        '198,226,255', 'slategray1',
        '199, 21,133', 'medium[ \-]?violet[ \-]?red',
        '199,199,199', 'gr[ae]y78',
        '201,201,201', 'gr[ae]y79',
        '202,225,255', 'lightsteelblue1',
        '202,255,112', 'darkolivegreen1',
        '204,204,204', 'gr[ae]y80',
        '205,  0,  0', 'red3',
        '205,  0,205', 'magenta3',
        '205, 16,118', 'deeppink3',
        '205, 38, 38', 'firebrick3',
        '205, 41,144', 'maroon3',
        '205, 50,120', 'violetred3',
        '205, 51, 51', 'brown3',
        '205, 55,  0', 'orangered3',
        '205, 79, 57', 'tomato3',
        '205, 85, 85', 'indianred3',
        '205, 91, 69', 'coral3',
        '205, 92, 92', 'indian[ \-]?red',
        '205, 96,144', 'hotpink3',
        '205,102,  0', 'darkorange3',
        '205,102, 29', 'chocolate3',
        '205,104, 57', 'sienna3',
        '205,104,137', 'palevioletred3',
        '205,105,201', 'orchid3',
        '205,112, 84', 'salmon3',
        '205,129, 98', 'lightsalmon3',
        '205,133,  0', 'orange3',
        '205,133, 63', 'peru|tan3',
        '205,140,149', 'lightpink3',
        '205,145,158', 'pink3',
        '205,149, 12', 'darkgoldenrod3',
        '205,150,205', 'plum3',
        '205,155, 29', 'goldenrod3',
        '205,155,155', 'rosybrown3',
        '205,170,125', 'burlywood3',
        '205,173,  0', 'gold3',
        '205,175,149', 'peachpuff3',
        '205,179,139', 'navajowhite3',
        '205,181,205', 'thistle3',
        '205,183,158', 'bisque3',
        '205,183,181', 'mistyrose3',
        '205,186,150', 'wheat3',
        '205,190,112', 'lightgoldenrod3',
        '205,192,176', 'antiquewhite3',
        '205,193,197', 'lavenderblush3',
        '205,197,191', 'seashell3',
        '205,198,115', 'khaki3',
        '205,200,177', 'cornsilk3',
        '205,201,165', 'lemonchiffon3',
        '205,201,201', 'snow3',
        '205,205,  0', 'yellow3',
        '205,205,180', 'lightyellow3',
        '205,205,193', 'ivory3',
        '207,207,207', 'gr[ae]y81',
        '208, 32,144', 'violet[ \-]?red',
        '209, 95,238', 'mediumorchid2',
        '209,209,209', 'gr[ae]y82',
        '209,238,238', 'lightcyan2',
        '210,105, 30', 'chocolate',
        '210,180,140', 'tan',
        '211,211,211', 'light( gr[ae]|-gr[ae]|gr[ae])y',
        '212,212,212', 'gr[ae]y83',
        '214,214,214', 'gr[ae]y84',
        '216,191,216', 'thistle',
        '217,217,217', 'gr[ae]y85',
        '218,112,214', 'orchid',
        '218,165, 32', 'goldenrod',
        '219,112,147', 'pale[ \-]?violet[ \-]?red',
        '219,219,219', 'gr[ae]y86',
        '220,220,220', 'gainsboro',
        '221,160,221', 'plum',
        '222,184,135', 'burlywood',
        '222,222,222', 'gr[ae]y87',
        '224,102,255', 'mediumorchid1',
        '224,224,224', 'gr[ae]y88',
        '224,238,224', 'honeydew2',
        '224,238,238', 'azure2',
        '224,255,255', 'light[ \-]?cyan1?',
        '227,227,227', 'gr[ae]y89',
        '229,229,229', 'gr[ae]y90',
        '230,230,250', 'lavender',
        '232,232,232', 'gr[ae]y91',
        '233,150,122', 'dark[ \-]?salmon',
        '235,235,235', 'gr[ae]y92',
        '237,237,237', 'gr[ae]y93',
        '238,  0,  0', 'red2',
        '238,  0,238', 'magenta2',
        '238, 18,137', 'deeppink2',
        '238, 44, 44', 'firebrick2',
        '238, 48,167', 'maroon2',
        '238, 58,140', 'violetred2',
        '238, 59, 59', 'brown2',
        '238, 64,  0', 'orangered2',
        '238, 92, 66', 'tomato2',
        '238, 99, 99', 'indianred2',
        '238,106, 80', 'coral2',
        '238,106,167', 'hotpink2',
        '238,118,  0', 'darkorange2',
        '238,118, 33', 'chocolate2',
        '238,121, 66', 'sienna2',
        '238,121,159', 'palevioletred2',
        '238,122,233', 'orchid2',
        '238,130, 98', 'salmon2',
        '238,130,238', 'violet',
        '238,149,114', 'lightsalmon2',
        '238,154,  0', 'orange2',
        '238,154, 73', 'tan2',
        '238,162,173', 'lightpink2',
        '238,169,184', 'pink2',
        '238,173, 14', 'darkgoldenrod2',
        '238,174,238', 'plum2',
        '238,180, 34', 'goldenrod2',
        '238,180,180', 'rosybrown2',
        '238,197,145', 'burlywood2',
        '238,201,  0', 'gold2',
        '238,203,173', 'peachpuff2',
        '238,207,161', 'navajowhite2',
        '238,210,238', 'thistle2',
        '238,213,183', 'bisque2',
        '238,213,210', 'mistyrose2',
        '238,216,174', 'wheat2',
        '238,220,130', 'lightgoldenrod2',
        '238,221,130', 'light[ \-]?goldenrod',
        '238,223,204', 'antiquewhite2',
        '238,224,229', 'lavenderblush2',
        '238,229,222', 'seashell2',
        '238,230,133', 'khaki2',
        '238,232,170', 'pale[ \-]?goldenrod',
        '238,232,205', 'cornsilk2',
        '238,233,191', 'lemonchiffon2',
        '238,233,233', 'snow2',
        '238,238,  0', 'yellow2',
        '238,238,209', 'lightyellow2',
        '238,238,224', 'ivory2',
        '240,128,128', 'light[ \-]?coral',
        '240,230,140', 'khaki',
        '240,240,240', 'gr[ae]y94',
        '240,248,255', 'alice[ \-]?blue',
        '240,255,240', 'honeydew1?',
        '240,255,255', 'azure1?',
        '242,242,242', 'gr[ae]y95',
        '244,164, 96', 'sandy[ \-]?brown',
        '245,222,179', 'wheat',
        '245,245,220', 'beige',
        '245,245,245', 'gr[ae]y96|white[ \-]?smoke',
        '245,255,250', 'mint[ \-]?cream',
        '247,247,247', 'gr[ae]y97',
        '248,248,255', 'ghost[ \-]?white',
        '250,128,114', 'salmon',
        '250,235,215', 'antique[ \-]?white',
        '250,240,230', 'linen',
        '250,250,210', 'light[ \-]?goldenrod[ \-]?yellow',
        '250,250,250', 'gr[ae]y98',
        '252,252,252', 'gr[ae]y99',
        '253,245,230', 'old[ \-]?lace',
        '255,  0,  0', 'red1?',
        '255,  0,255', 'magenta1?',
        '255, 20,147', 'deep[ \-]?pink1?',
        '255, 48, 48', 'firebrick1',
        '255, 52,179', 'maroon1',
        '255, 62,150', 'violetred1',
        '255, 64, 64', 'brown1',
        '255, 69,  0', 'orange[ \-]?red1?',
        '255, 99, 71', 'tomato1?',
        '255,105,180', 'hot[ \-]?pink',
        '255,106,106', 'indianred1',
        '255,110,180', 'hotpink1',
        '255,114, 86', 'coral1',
        '255,127,  0', 'darkorange1',
        '255,127, 36', 'chocolate1',
        '255,127, 80', 'coral',
        '255,130, 71', 'sienna1',
        '255,130,171', 'palevioletred1',
        '255,131,250', 'orchid1',
        '255,140,  0', 'dark[ \-]?orange',
        '255,140,105', 'salmon1',
        '255,160,122', 'light[ \-]?salmon1?',
        '255,165,  0', 'orange1?',
        '255,165, 79', 'tan1',
        '255,174,185', 'lightpink1',
        '255,181,197', 'pink1',
        '255,182,193', 'light[ \-]?pink',
        '255,185, 15', 'darkgoldenrod1',
        '255,187,255', 'plum1',
        '255,192,203', 'pink',
        '255,193, 37', 'goldenrod1',
        '255,193,193', 'rosybrown1',
        '255,211,155', 'burlywood1',
        '255,215,  0', 'gold1?',
        '255,218,185', 'peach[ \-]?puff1?',
        '255,222,173', 'navajo[ \-]?white1?',
        '255,225,255', 'thistle1',
        '255,228,181', 'moccasin',
        '255,228,196', 'bisque1?',
        '255,228,225', 'misty[ \-]?rose1?',
        '255,231,186', 'wheat1',
        '255,235,205', 'blanched[ \-]?almond',
        '255,236,139', 'lightgoldenrod1',
        '255,239,213', 'papaya[ \-]?whip',
        '255,239,219', 'antiquewhite1',
        '255,240,245', 'lavender[ \-]?blush1?',
        '255,245,238', 'seashell1?',
        '255,246,143', 'khaki1',
        '255,248,220', 'cornsilk1?',
        '255,250,205', 'lemon[ \-]?chiffon1?',
        '255,250,240', 'floral[ \-]?white',
        '255,250,250', 'snow1?',
        '255,255,  0', 'yellow1?',
        '255,255,224', 'light[ \-]?yellow1?',
        '255,255,240', 'ivory1?',
        '255,255,255', 'gr[ae]y100|white',
    );
    while (($val, $regex) = each %rgb) {
        return split(',', $val) if m/^$regex$/i;
    }

}
__END__
