Graphics-ColorUtils-0.17/0000755000076400001440000000000010624161717014511 5ustar janertusersGraphics-ColorUtils-0.17/t/0000755000076400001440000000000010624161717014754 5ustar janertusersGraphics-ColorUtils-0.17/t/01sanity.t0000644000076400001440000000012410525503272016602 0ustar janertusers use Test::More tests => 1; use Graphics::ColorUtils; # Sanity: ok( 1, "Loaded" ); Graphics-ColorUtils-0.17/t/04gradients.t0000644000076400001440000000510010624161651017256 0ustar janertusers use Test::More qw( no_plan ); # tests => 118; use Graphics::ColorUtils qw( :gradients ); my %grads = available_gradients(); is( scalar keys %grads, 4, "Available gradients" ); foreach ( values %grads ) { is( $_, 240, "Colors per gradient" ); } ok( exists $grads{ 'heat' }, "Heat gradient found" ); ok( !exists $grads{ 'foobar' }, "Foobar grad not found" ); # --- my $grad = gradient( 'heat' ); ok( defined $grad, "Heat gradient assigned" ); my $i = 0; foreach( @$grad ) { is( scalar @{ $_ }, 3, "Heat element is triple" ); ok( 0 <= $_->[0] && $_->[0] < 256, "Heat - Red legal value" ); ok( 0 <= $_->[1] && $_->[1] < 256, "Heat - Green legal value" ); ok( 0 <= $_->[2] && $_->[2] < 256, "Heat - Blue legal value" ); if( $i++ > 10 ) { last; } } ok( !defined gradient( 'foobar' ), "Foobar gradient not defined" ); # --- for( my $x=0; $x<1; $x+=0.1 ) { like( grad2rgb( 'heat', $x ), qr/#[0-9a-fA-F]{6}/, "Heat is hex-string" ); my ( $r, $g, $b ) = grad2rgb( 'heat', $x ); ok( 0 <= $r && $r < 256, "Heat element - Red legal value" ); ok( 0 <= $g && $g < 256, "Heat element - Green legal value" ); ok( 0 <= $b && $b < 256, "Heat element - Blue legal value" ); } ok( !defined grad2rgb( 'heat', -0.1 ), "Heat element : -.1 not found" ); ok( defined grad2rgb( 'heat', 0.0 ), "Heat element : 0.0 found" ); ok( !defined grad2rgb( 'heat', 1.0 ), "Heat element : 1.0 not found" ); ok( !defined grad2rgb( 'heat', 1.1 ), "Heat element : 1.1 not found" ); ok( !defined grad2rgb( 'foobar', 0.5 ), "Foobar element not found" ); # --- my @foo = ( [ 0, 0, 0 ], [ 16, 32, 64 ], [ 255, 255, 255 ] ); my $old = register_gradient( 'foo', \@foo ); ok( !defined $old, "Registered new gradient name" ); ok( defined gradient( 'foo' ), "New gradient name found" ); is( grad2rgb( 'foo', 0 ), '#000000', "First new element found" ); is( grad2rgb( 'foo', 0.99 ), '#ffffff', "Last new element found" ); push @foo, [ 8, 8, 8 ]; my $renew = register_gradient( 'foo', \@foo ); ok( defined $renew, "Renewed gradient - old value found" ); is( scalar @$renew, 4, "Modified gradient is reference to old one" ); is( grad2rgb( 'foo', 0.99 ), '#080808', "New last element correct" ); my @bar = ( [0,0,0],[3,3,3],[1,2.3],[10,0,20],[1,1,1] ); $renew = register_gradient( 'foo', \@bar ); ok( defined $renew, "Renewed gradient - old value found" ); is( scalar @$renew, 4, "Modified gradient unrelated to old gradient" ); $grad = gradient( 'foo' ); is( scalar @$grad, 5, "New gradient correct element count" ); is( grad2rgb( 'foo', 0.99 ), '#010101', "New-new last element correct" ); ok( 1, "All done" ); # --- blank comment Graphics-ColorUtils-0.17/t/03names.t0000644000076400001440000001172510525503272016411 0ustar janertusers use Test::More tests => 103; use Graphics::ColorUtils qw( :names ); my $names = available_names(); ok( scalar keys %$names, "Names found" ); my $j = 0; foreach( values %$names ) { my ( $r, $g, $b ) = @$_; ok( 0 <= $r && $r < 256, "ForName element - Red legal value" ); ok( 0 <= $g && $g < 256, "ForName element - Green legal value" ); ok( 0 <= $b && $b < 256, "ForName element - Blue legal value" ); if( $j++ > 10 ) { last; } } # --- is( get_default_namespace(), 'x11', "Default namespace" ); # Basic lookup is( name2rgb( 'red' ), '#ff0000', "Default red" ); is( name2rgb( 'x11:red' ), '#ff0000', "X11 red" ); is( name2rgb( 'svg:red' ), '#ff0000', "SVG red" ); is( name2rgb( 'www:red' ), '#ff0000', "WWW red" ); # Name normalization is( name2rgb( 'RED' ), '#ff0000', "Default red - caps1" ); is( name2rgb( 'rEd' ), '#ff0000', "Default red - caps2" ); is( name2rgb( ' red ' ), '#ff0000', "Default red - whitespace1" ); is( name2rgb( ' rEd ' ), '#ff0000', "Default red - whitespace2" ); is( name2rgb( " r\tEd " ), '#ff0000', "Default red - whitespace3" ); is( name2rgb( " r E\nd " ), '#ff0000', "Default red - whitespace4" ); is( name2rgb( ' x11:red' ), '#ff0000', "X11 red - whitespace1" ); is( name2rgb( ' x11: red' ), '#ff0000', "X11 red - whitespace2" ); ok( name2rgb( 'grey' ), 'grey' ); ok( name2rgb( 'gray' ), 'gray' ); is( name2rgb( 'grey' ), name2rgb( 'gray' ), "grey == gray" ); is( name2rgb( 'grey' ), "#bebebe" ); # More lookup ok( !defined name2rgb( 'redd' ), "redd not found" ); ok( !defined name2rgb( 'www:redd' ), "www:redd not found" ); ok( name2rgb( 'lightgoldenrod' ), "lightgoldenrod" ); ok( name2rgb( 'svg:beige' ), 'svg:beige' ); ok( !defined name2rgb( 'www:beige' ), "www:beige not found" ); ok( defined name2rgb( 'lemonchiffon2' ), "lemonchiffon2 - only in X11" ); ok( !defined name2rgb( ':red' ), ":red not found - force global namespace" ); # Evaluate in list context my @f = name2rgb( 'blue' ); is( scalar @f, 3, "Return triple" ); ok( 0 <= $f[0] && $f[0] < 256, "Name=Blue - Red ok" ); ok( 0 <= $f[1] && $f[1] < 256, "Name=Blue - Green ok" ); ok( 0 <= $f[2] && $f[2] < 256, "Name=Blue - Blue ok" ); # --- # Register a color my $redd = register_name( 'svg:redd', 255, 1, 1 ); ok( !defined $redd, "Old name did not exist" ); ok( !defined name2rgb( 'redd' ), "redd not found in default namespace" ); is( name2rgb( 'svg:redd' ), '#ff0101', "redd found in proper namespace" ); $redd = register_name( 'svg:redd', 255, 2, 2 ); is( $redd, '#ff0101', "Old name is found" ); is( name2rgb( 'svg:redd' ), '#ff0202', "Renewed redd found" ); my @redd = register_name( 'svg:redd', 255, 2, 2 ); # Eval in list context is( scalar @redd, 3, "Return triple" ); ok( 0 <= $redd[0] && $redd[0] < 256, "Name=Redd - Red ok" ); ok( 0 <= $redd[1] && $redd[1] < 256, "Name=Redd - Green ok" ); ok( 0 <= $redd[2] && $redd[2] < 256, "Name=Redd - Blue ok" ); $redd = register_name( 'x11:redd', 255, 3, 3 ); ok( !defined $redd, "redd not found in default namespace" ); is( name2rgb( 'x11:redd' ), '#ff0303', "redd found in X11 namespace" ); is( name2rgb( 'redd' ), '#ff0303', "redd found in default namespace" ); ok( !defined name2rgb( ':redd' ), "redd not found in global namespace" ); $redd = register_name( 'redd', 255, 4, 4 ); ok( !defined $redd, "Global namespace empty" ); is( name2rgb( 'redd' ), '#ff0404', "redd value ok 1" ); is( name2rgb( ':redd' ), '#ff0404', ":redd value ok 1" ); is( name2rgb( ':redd' ), name2rgb( 'redd' ), ":redd = redd 1" ); $redd = register_name( ':redd', 255, 4, 4 ); ok( defined $redd, ":redd clobbers redd" ); is( $redd, '#ff0404', "redd proper value" ); is( name2rgb( 'redd' ), '#ff0404', "redd value ok 2" ); is( name2rgb( ':redd' ), '#ff0404', ":redd value ok 2" ); is( name2rgb( ':redd' ), name2rgb( 'redd' ), ":redd = redd 2" ); # Note: now :redd=ff0404, x11:redd=ff0303, svg:redd=ff0202 register_name( 'x11:ggrn', 1, 255, 1 ); is( name2rgb( 'svg:redd' ), '#ff0202', "Explicit ns lookup" ); is( name2rgb( 'redd' ), '#ff0404', "Implicit ns lookup - global first" ); isnt( name2rgb( 'redd' ), name2rgb( 'x11:redd' ),"Implicit - default ns last"); is( name2rgb( 'x11:ggrn' ), '#01ff01', "Explicit X11 lookup" ); is( name2rgb( 'ggrn' ), '#01ff01', "Implicit lookup - default ns" ); ok( !defined name2rgb( ':ggrn' ), "Force global - not found" ); # --- # Change default namespace my $ns = set_default_namespace( 'svg' ); is( $ns, 'x11', "Old namespace: X11" ); is( get_default_namespace(), 'svg', "New namespace: svg" ); my $ggrn = register_name( 'svg:ggrn', 2, 255, 2 ); ok( !defined $ggrn, "svg:ggrn did not exist" ); is( name2rgb( 'ggrn' ), '#02ff02', "Found ggrn in new default ns" ); is( name2rgb( 'ggrn' ), name2rgb( 'svg:ggrn' ), "Is equal to SVG ns" ); isnt( name2rgb( 'ggrn' ), name2rgb( 'x11:ggrn' ), "Is not equal to X11 ns" ); is( name2rgb( 'x11:ggrn' ), '#01ff01', "X11 ggrn found" ); is( name2rgb( 'svg:ggrn' ), '#02ff02', "svg ggrn found" ); isnt( name2rgb( 'ggrn' ), name2rgb( ':ggrn' ), "Is not equal to global ns" ); ok( !defined name2rgb( ':ggrn' ), "Global ggrn not defined" ); Graphics-ColorUtils-0.17/t/02conversions.t0000644000076400001440000001351110607537720017656 0ustar janertusers use Test::More tests => 3486; # qw( no_plan ); use Graphics::ColorUtils; # ================================================== # Globals my $d = 64; # Stepsize for back/forth tests - use smaller steps if you like my @c; # Color triple # ================================================== # YIQ for( my $rr=0; $rr<256; $rr+=$d ) { for( my $gg=0; $gg<256; $gg+=$d ) { for( my $bb=0; $bb<256; $bb+=$d ) { @c = yiq2rgb( rgb2yiq( $rr, $gg, $bb ) ); ok( abs($c[0] - $rr) < 2, "YIQ 1 Back/Forth Red" ); ok( abs($c[1] - $gg) < 2, "YIQ 1 Back/Forth Green" ); ok( abs($c[2] - $bb) < 2, "YIQ 1 Back/Forth Blue" ); } } } for( my $y=0; $y<1; $y+=0.2 ) { for( my $i=0; $i<1; $i+=0.2 ) { for( my $q=.1; $q<1; $q+=0.2 ) { @c = rgb2yiq( yiq2rgb( $y, $i, $q ) ); ok( abs($c[0] - $y) < .02, "YIQ 2 Back/Forth Y" ); ok( abs($c[1] - $i) < .02, "YIQ 2 Back/Forth I" ); ok( abs($c[2] - $q) < .02, "YIQ 2 Back/Forth Q" ); like( yiq2rgb( $y, $i, $q ), qr/#[0-9a-fA-F]{6}/, "YIQ - scalar" ); } } } # ================================================== # CMY for( my $rr=0; $rr<256; $rr+=$d ) { for( my $gg=0; $gg<256; $gg+=$d ) { for( my $bb=0; $bb<256; $bb+=$d ) { @c = cmy2rgb( rgb2cmy( $rr, $gg, $bb ) ); ok( abs($c[0] - $rr) < 2, "CMY 1 Back/Forth Red" ); ok( abs($c[1] - $gg) < 2, "CMY 1 Back/Forth Green" ); ok( abs($c[2] - $bb) < 2, "CMY 1 Back/Forth Blue" ); @c = rgb2cmy( $rr, $gg, $bb ); is( 255-255*$c[0], $rr, "CMY - Red" ); is( 255-255*$c[1], $gg, "CMY - Green" ); is( 255-255*$c[2], $bb, "CMY - Blue" ); } } } for( my $c=0; $c<1; $c+=0.2 ) { for( my $m=0; $m<1; $m+=0.2 ) { for( my $y=.1; $y<1; $y+=0.2 ) { @c = rgb2cmy( cmy2rgb( $c, $m, $y ) ); ok( abs($c[0] - $c) < .02, "CMY 2 Back/Forth C" ); ok( abs($c[1] - $m) < .02, "CMY 2 Back/Forth M" ); ok( abs($c[2] - $y) < .02, "CMY 2 Back/Forth Y" ); like( cmy2rgb( $c, $m, $y ), qr/#[0-9a-fA-F]{6}/, "CMY - scalar" ); } } } # ================================================== # HLS is( hls2rgb( 0, 0.5, 1 ), '#ff0000', "hls2rgb( 0, 0.5, 1 )" ); is( hls2rgb( 120, 0.5, 1 ), '#00ff00', "hls2rgb( 120, 0.5, 1 )" ); is( hls2rgb( 240, 0.5, 1 ), '#0000ff', "hls2rgb( 0, 0.5, 1 )" ); is( hls2rgb( 360, 0.5, 1 ), '#ff0000', "hls2rgb( 360, 0.5, 1)" ); is( hls2rgb(5, 0.2, 0.2), hls2rgb(365, 0.2, 0.2), "HLS: Wrap hue positive" ); is( hls2rgb(55, 0.2, 0.2), hls2rgb(415, 0.2, 0.2), "HLS: Wrap hue positive" ); is( hls2rgb(-1, 0.2, 0.2), hls2rgb(359, 0.2, 0.2), "HLS: Wrap hue negative" ); is( hls2rgb( 17, 0, 0.4 ), '#000000', "HLS: Black" ); is( hls2rgb( 23, 1, 0.2 ), '#ffffff', "HLS: White" ); @c = hls2rgb( 17, 0.8, 0 ); ok( $c[0] == $c[1] && $c[1] == $c[2], 'HLS: Saturation 0 => achromatic' ); @c = hls2rgb( 38, .8, .2 ); ok( 0 <= $c[0] && $c[0] < 256, "HLS - Red" ); ok( 0 <= $c[1] && $c[1] < 256, "HLS - Green" ); ok( 0 <= $c[2] && $c[2] < 256, "HLS - Blue" ); # --- for( my $rr=0; $rr<256; $rr+=$d ) { for( my $gg=0; $gg<256; $gg+=$d ) { for( my $bb=0; $bb<256; $bb+=$d ) { @c = hls2rgb( rgb2hls( $rr, $gg, $bb ) ); ok( abs($c[0] - $rr) < 2, "HLS 1 Back/Forth Red" ); # Roundoff! ok( abs($c[1] - $gg) < 2, "HLS 1 Back/Forth Green" ); ok( abs($c[2] - $bb) < 2, "HLS 1 Back/Forth Blue" ); } } } for( my $hh=0; $hh<360; $hh+=36 ) { for( my $ll=0; $ll<1; $ll+=0.2 ) { for( my $ss=.1; $ss<1; $ss+=0.2 ) { # Don't start sat at 0 - achromatic @c = rgb2hls( hls2rgb( $hh, $ll, $ss ) ); if( $c[1] == 0 ) { # Saturation=0 -> do not check hue ok( 1, "HLS 2 Back/Forth - sat=1, do not check Hue" ); } else { ok( abs($c[0] - $hh) < 9, "HLS 2 Back/Forth Hue" ); } ok( abs($c[1] - $ll) < .02, "HLS 2 Back/Forth Lit" ); if( $c[1] == 0 ) { ok( 1, "HLS 2 Back/Forth - lit=1, do not check Sat" ); } else { ok( abs($c[2] - $ss) < .02, "HLS 2 Back/Forth Sat" ); } } } } # ================================================== # HSV is( hsv2rgb( 0, 1, 1 ), '#ff0000', "hsv2rgb( 0, 1, 1 )" ); is( hsv2rgb( 120, 1, 1 ), '#00ff00', "hsv2rgb( 120, 1, 1 )" ); is( hsv2rgb( 240, 1, 1 ), '#0000ff', "hsv2rgb( 0, 1, 1 )" ); is( hsv2rgb( 360, 1, 1 ), '#ff0000', "hsv2rgb( 360, 1, 1)" ); is( hsv2rgb(5, 0.2, 0.2), hsv2rgb(365, 0.2, 0.2), "HSV: Wrap hue positive" ); is( hsv2rgb(55, 0.2, 0.2), hsv2rgb(415, 0.2, 0.2), "HSV: Wrap hue positive" ); is( hsv2rgb(-1, 0.2, 0.2), hsv2rgb(359, 0.2, 0.2), "HSV: Wrap hue negative" ); # larger negative wrap runs into round-off is( hsv2rgb( 17, 0.4, 0 ), '#000000', "HSV Black" ); is( hsv2rgb( 23, 0, 1 ), '#ffffff', "HSV White" ); @c = hsv2rgb( 17, 0, 0.8 ); ok( $c[0] == $c[1] && $c[1] == $c[2], 'HSV: Saturation 0 => achromatic' ); @c = hsv2rgb( 38, .8, .2 ); ok( 0 <= $c[0] && $c[0] < 256, "HSV - Red" ); ok( 0 <= $c[1] && $c[1] < 256, "HSV - Green" ); ok( 0 <= $c[2] && $c[2] < 256, "HSV - Blue" ); # --- for( my $rr=0; $rr<256; $rr+=$d ) { for( my $gg=0; $gg<256; $gg+=$d ) { for( my $bb=0; $bb<256; $bb+=$d ) { @c = hsv2rgb( rgb2hsv( $rr, $gg, $bb ) ); ok( abs($c[0] - $rr) < 2, "HSV 1 Back/Forth Red" ); # Roundoff! ok( abs($c[1] - $gg) < 2, "HSV 1 Back/Forth Green" ); ok( abs($c[2] - $bb) < 2, "HSV 1 Back/Forth Blue" ); } } } for( my $hh=0; $hh<360; $hh+=36 ) { for( my $ss=.1; $ss<1; $ss+=0.2 ) { # Don't start sat at 0 - achromatic for( my $vv=0; $vv<1; $vv+=0.2 ) { @c = rgb2hsv( hsv2rgb( $hh, $ss, $vv ) ); if( $c[1] == 0 ) { # Saturation=0 -> do not check hue ok( 1, "HSV 2 Back/Forth - sat=1, do not check Hue" ); } else { ok( abs($c[0] - $hh) < 9, "HSV 2 Back/Forth Hue" ); } if( $c[2] == 0 ) { ok( 1, "HSV 2 Back/Forth - val=1, do not check Sat" ); } else { ok( abs($c[1] - $ss) < .02, "2 Back/Forth Sat" ); } ok( abs($c[2] - $vv) < .02, "HSV 2 Back/Forth Val" ); } } } Graphics-ColorUtils-0.17/lib/0000755000076400001440000000000010624161717015257 5ustar janertusersGraphics-ColorUtils-0.17/lib/Graphics/0000755000076400001440000000000010624161717017017 5ustar janertusersGraphics-ColorUtils-0.17/lib/Graphics/ColorUtils.pm0000644000076400001440000016307010624161230021451 0ustar janertusers package Graphics::ColorUtils; use 5.008003; use strict; use warnings; use Carp; require Exporter; our @ISA = qw(Exporter); our %EXPORT_TAGS = ( 'gradients' => [ qw( gradient grad2rgb available_gradients register_gradient) ], 'names' => [ qw( name2rgb available_names register_name set_default_namespace get_default_namespace ) ], 'all' => [ qw( rgb2yiq yiq2rgb rgb2cmy cmy2rgb rgb2hls hls2rgb rgb2hsv hsv2rgb gradient grad2rgb available_gradients register_gradient name2rgb available_names register_name set_default_namespace get_default_namespace ) ], ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( rgb2yiq yiq2rgb rgb2cmy cmy2rgb rgb2hls hls2rgb rgb2hsv hsv2rgb ); our $VERSION = '0.17'; # ================================================== # ++++++++++++++++++++++++++++++++++++++++++++++++++ # ================================================== # ================================================== # Utility # Takes a (r,g,b) triple of numbers (possibly floats) and returns # - a string like '#33FF21' in scalar context # - a triple of corresponding integers in array context sub _fmt { return wantarray ? map { int } @_ : sprintf( "#%02x%02x%02x", @_ ); } # ================================================== # YIQ sub rgb2yiq { # $r, $g, $b : 0..255 my ( $r, $g, $b ) = map { $_/255.0 } @_; # Scale RGB to 0..1 my $y = 0.299*$r + 0.587*$g + 0.114*$b; my $i = 0.596*$r - 0.275*$g - 0.321*$b; my $q = 0.212*$r - 0.523*$g + 0.311*$b; return ( $y, $i, $q ); } sub yiq2rgb { # $y, $i, $q : 0..1 my ( $y, $i, $q ) = @_; my $r = 255.0*( $y + 0.956*$i + 0.621*$q ); my $g = 255.0*( $y - 0.272*$i - 0.647*$q ); my $b = 255.0*( $y - 1.105*$i + 1.705*$q ); return _fmt( $r, $g, $b ); } # ================================================== # CMY sub rgb2cmy { # $r, $g, $b : 0..255 my ( $r, $g, $b ) = map { $_/255.0 } @_; # Scale RGB to 0..1 return ( 1.0 - $r, 1.0 - $g, 1.0 - $b ); } sub cmy2rgb { # $c, $m, $y : 0..1 my ( $c, $m, $y ) = @_; return _fmt( 255*(1.0-$c), 255*(1.0-$m), 255*(1.0-$y) ); } # ================================================== # HLS # Foley, van Dam, et al: # Computer Grapics-Principles and Practice (1990) p595f sub rgb2hls { # $r, $g, $b : 0..255 # Note special name '$bb' to avoid conflict with ($a,$b) in sort() my ( $r, $g, $bb ) = map { $_/255.0 } @_; # Scale RGB to 0..1 my ( $minc, $maxc ) = ( sort { $a <=> $b } ( $r, $g, $bb ) )[0,2]; my $m = $minc + $maxc; # "Mean" if( $maxc == $minc ) { return ( 0, 0.5*$m, 0 ); } # Achromatic case my $d = $maxc - $minc; # "Delta" my $s = ( $m <= 1.0 ) ? $d/$m : $d/(2.0-$m ); # Saturation my $h = 0; # Hue if( $r == $maxc ) { $h = ( $g-$bb )/$d; } elsif( $g == $maxc ) { $h = 2 + ( $bb-$r )/$d; } elsif( $bb == $maxc ) { $h = 4 + ( $r-$g )/$d; } else { # Never get here! croak "Internal Error: Unexpected value ,$maxc, in Graphics::ColorUtils::rgb2hls( $r, $g, $bb )"; } $h *= 60; # Convert to degrees if( $h < 0 ) { $h += 360; } # Ensure positive hue return ( $h, 0.5*$m, $s ); } sub hls2rgb { # $h: 0..360 (red=0->yellow->green=120->cyan->blue=240->magenta steps of 60) # $l, $s : 0..1 (inclusive) my ( $h, $l, $s ) = @_; if( $s == 0.0 ) { return _fmt(255*$l, 255*$l, 255*$l); } # achromatic (grey) # This is the INCORRECT line as it is in the book quoted above: # my $m2 = ( $l <= 0.5 ) ? ($l*($l+$s)) : ($l - $l*$s + $s); # This is the CORRECT line: (first alternative: 1 vs $l) my $m2 = ( $l <= 0.5 ) ? ($l*(1+$s)) : ($l - $l*$s + $s); my $m1 = 2.0*$l - $m2; my $r = 255 * _value( $m1, $m2, $h + 120 ); my $g = 255 * _value( $m1, $m2, $h ); my $b = 255 * _value( $m1, $m2, $h - 120 ); return _fmt( $r, $g, $b ); } sub _value { my ( $n1, $n2, $hue ) = @_; if( $hue > 360 ) { $hue -= 360; } elsif( $hue < 0 ) { $hue += 360; } if( $hue < 60 ) { return $n1 + $hue * ( $n2-$n1 )/60.0; } elsif( $hue < 180 ) { return $n2; } elsif( $hue < 240 ) { return $n1 + ( 240-$hue ) * ( $n2-$n1 )/60.0; } else { return $n1; } } # ================================================== # HSV # Foley, van Dam, et al: # Computer Grapics-Principles and Practice (1990) p592f sub rgb2hsv { # $r, $g, $b : 0..25 # Note special name '$bb' to avoid conflict with ($a,$b) in sort() my ( $r, $g, $bb ) = map { $_/255.0 } @_; # Scale RGB to 0..1 my ( $minc, $maxc ) = ( sort { $a <=> $b } ( $r, $g, $bb ) )[0,2]; my $v = $maxc; # Value my $d = $maxc - $minc; # "Delta" my $s = ( $maxc == 0 ) ? 0 : $d/$maxc; # No saturation if R=G=B=0 if( $s == 0 ) { return ( 0, 0, $v ); } # Achromatic case my $h = 0; # Hue if( $r == $maxc ) { $h = ( $g-$bb )/$d; } elsif( $g == $maxc ) { $h = 2 + ( $bb-$r )/$d; } elsif( $bb == $maxc ) { $h = 4 + ( $r-$g )/$d; } else { # Never get here! croak "Internal Error: Unexpected value ,$maxc, in Graphics::ColorUtils::rgb2hsv( $r, $g, $bb )"; } $h *= 60; # Convert to degrees if( $h < 0 ) { $h += 360; } # Ensure positive hue return ( $h, $s, $v ); } sub hsv2rgb { # $h: 0..360 (red=0->yellow->green=120->cyan->blue=240->magenta steps of 60) # (tolerates larger values of $h by reducing them to the standard circle) # $s, $v : 0..1 (inclusive) my ( $h, $s, $v ) = @_; $v *= 255; if( $s == 0 ) { return _fmt( $v, $v, $v ); } # achromatic (grey) my $i = int( $h/60 ); # sector 0 to 5 my $f = ($h/60) - $i; # fractional part of h/60 my $p = $v * ( 1 - $s ); my $q = $v * ( 1 - $s * $f ); my $t = $v * ( 1 - $s * ( 1 - $f ) ); $i %= 6; # tolerate values of $h larger than 360 if( $i==0 ) { return _fmt( $v, $t, $p ); } elsif( $i==1 ) { return _fmt( $q, $v, $p ); } elsif( $i==2 ) { return _fmt( $p, $v, $t ); } elsif( $i==3 ) { return _fmt( $p, $q, $v ); } elsif( $i==4 ) { return _fmt( $t, $p, $v ); } elsif( $i==5 ) { return _fmt( $v, $p, $q ); } else { # Never get here! croak "Internal Error: Unexpected value ,$i, in Graphics::ColorUtils::hsv2rgb( $h, $s, $v )"; } } # ================================================== # Gradients # Gradients grey, heat, map, and rainbow have been inspired by similar # ideas in Yorick. # For Yorick, cf http://yorick.sourceforge.net # and also http://www.maumae.net/yorick/doc/index.php # as well as http://www.mhatt.aps.anl.gov/dohn/software/yorick/ BEGIN { my %_gradients = ( 'grey' => [ [ 0, 0, 0],[ 1, 1, 1],[ 2, 2, 2],[ 3, 3, 3],[ 4, 4, 4], [ 5, 5, 5],[ 6, 6, 6],[ 7, 7, 7],[ 9, 9, 9],[ 10, 10, 10], [ 11, 11, 11],[ 12, 12, 12],[ 13, 13, 13],[ 14, 14, 14],[ 15, 15, 15], [ 16, 16, 16],[ 17, 17, 17],[ 18, 18, 18],[ 19, 19, 19],[ 20, 20, 20], [ 21, 21, 21],[ 22, 22, 22],[ 23, 23, 23],[ 25, 25, 25],[ 26, 26, 26], [ 27, 27, 27],[ 28, 28, 28],[ 29, 29, 29],[ 30, 30, 30],[ 31, 31, 31], [ 32, 32, 32],[ 33, 33, 33],[ 34, 34, 34],[ 35, 35, 35],[ 36, 36, 36], [ 37, 37, 37],[ 38, 38, 38],[ 39, 39, 39],[ 41, 41, 41],[ 42, 42, 42], [ 43, 43, 43],[ 44, 44, 44],[ 45, 45, 45],[ 46, 46, 46],[ 47, 47, 47], [ 48, 48, 48],[ 49, 49, 49],[ 50, 50, 50],[ 51, 51, 51],[ 52, 52, 52], [ 53, 53, 53],[ 54, 54, 54],[ 55, 55, 55],[ 57, 57, 57],[ 58, 58, 58], [ 59, 59, 59],[ 60, 60, 60],[ 61, 61, 61],[ 62, 62, 62],[ 63, 63, 63], [ 64, 64, 64],[ 65, 65, 65],[ 66, 66, 66],[ 67, 67, 67],[ 68, 68, 68], [ 69, 69, 69],[ 70, 70, 70],[ 71, 71, 71],[ 73, 73, 73],[ 74, 74, 74], [ 75, 75, 75],[ 76, 76, 76],[ 77, 77, 77],[ 78, 78, 78],[ 79, 79, 79], [ 80, 80, 80],[ 81, 81, 81],[ 82, 82, 82],[ 83, 83, 83],[ 84, 84, 84], [ 85, 85, 85],[ 86, 86, 86],[ 87, 87, 87],[ 89, 89, 89],[ 90, 90, 90], [ 91, 91, 91],[ 92, 92, 92],[ 93, 93, 93],[ 94, 94, 94],[ 95, 95, 95], [ 96, 96, 96],[ 97, 97, 97],[ 98, 98, 98],[ 99, 99, 99],[100,100,100], [101,101,101],[102,102,102],[103,103,103],[105,105,105],[106,106,106], [107,107,107],[108,108,108],[109,109,109],[110,110,110],[111,111,111], [112,112,112],[113,113,113],[114,114,114],[115,115,115],[116,116,116], [117,117,117],[118,118,118],[119,119,119],[121,121,121],[122,122,122], [123,123,123],[124,124,124],[125,125,125],[126,126,126],[127,127,127], [128,128,128],[129,129,129],[130,130,130],[131,131,131],[132,132,132], [133,133,133],[134,134,134],[135,135,135],[137,137,137],[138,138,138], [139,139,139],[140,140,140],[141,141,141],[142,142,142],[143,143,143], [144,144,144],[145,145,145],[146,146,146],[147,147,147],[148,148,148], [149,149,149],[150,150,150],[151,151,151],[153,153,153],[154,154,154], [155,155,155],[156,156,156],[157,157,157],[158,158,158],[159,159,159], [160,160,160],[161,161,161],[162,162,162],[163,163,163],[164,164,164], [165,165,165],[166,166,166],[167,167,167],[169,169,169],[170,170,170], [171,171,171],[172,172,172],[173,173,173],[174,174,174],[175,175,175], [176,176,176],[177,177,177],[178,178,178],[179,179,179],[180,180,180], [181,181,181],[182,182,182],[183,183,183],[185,185,185],[186,186,186], [187,187,187],[188,188,188],[189,189,189],[190,190,190],[191,191,191], [192,192,192],[193,193,193],[194,194,194],[195,195,195],[196,196,196], [197,197,197],[198,198,198],[199,199,199],[201,201,201],[202,202,202], [203,203,203],[204,204,204],[205,205,205],[206,206,206],[207,207,207], [208,208,208],[209,209,209],[210,210,210],[211,211,211],[212,212,212], [213,213,213],[214,214,214],[215,215,215],[217,217,217],[218,218,218], [219,219,219],[220,220,220],[221,221,221],[222,222,222],[223,223,223], [224,224,224],[225,225,225],[226,226,226],[227,227,227],[228,228,228], [229,229,229],[230,230,230],[231,231,231],[233,233,233],[234,234,234], [235,235,235],[236,236,236],[237,237,237],[238,238,238],[239,239,239], [240,240,240],[241,241,241],[242,242,242],[243,243,243],[244,244,244], [245,245,245],[246,246,246],[247,247,247],[249,249,249],[250,250,250], [251,251,251],[252,252,252],[253,253,253],[254,254,254],[255,255,255] ], 'heat' => [ [ 0, 0, 0],[ 1, 0, 0],[ 2, 0, 0],[ 4, 0, 0],[ 5, 0, 0], [ 7, 0, 0],[ 8, 0, 0],[ 10, 0, 0],[ 11, 0, 0],[ 13, 0, 0], [ 15, 0, 0],[ 17, 0, 0],[ 18, 0, 0],[ 20, 0, 0],[ 21, 0, 0], [ 23, 0, 0],[ 24, 0, 0],[ 26, 0, 0],[ 27, 0, 0],[ 28, 0, 0], [ 30, 0, 0],[ 31, 0, 0],[ 33, 0, 0],[ 34, 0, 0],[ 36, 0, 0], [ 37, 0, 0],[ 39, 0, 0],[ 40, 0, 0],[ 42, 0, 0],[ 43, 0, 0], [ 46, 0, 0],[ 47, 0, 0],[ 49, 0, 0],[ 50, 0, 0],[ 52, 0, 0], [ 53, 0, 0],[ 55, 0, 0],[ 56, 0, 0],[ 57, 0, 0],[ 59, 0, 0], [ 60, 0, 0],[ 62, 0, 0],[ 63, 0, 0],[ 65, 0, 0],[ 66, 0, 0], [ 68, 0, 0],[ 69, 0, 0],[ 70, 0, 0],[ 72, 0, 0],[ 73, 0, 0], [ 76, 0, 0],[ 78, 0, 0],[ 79, 0, 0],[ 81, 0, 0],[ 82, 0, 0], [ 84, 0, 0],[ 85, 0, 0],[ 86, 0, 0],[ 88, 0, 0],[ 89, 0, 0], [ 92, 0, 0],[ 94, 0, 0],[ 95, 0, 0],[ 97, 0, 0],[ 98, 0, 0], [ 99, 0, 0],[101, 0, 0],[102, 0, 0],[104, 0, 0],[105, 0, 0], [108, 0, 0],[110, 0, 0],[111, 0, 0],[113, 0, 0],[114, 0, 0], [115, 0, 0],[117, 0, 0],[118, 0, 0],[120, 0, 0],[121, 0, 0], [123, 0, 0],[124, 0, 0],[126, 0, 0],[127, 0, 0],[128, 0, 0], [130, 0, 0],[131, 0, 0],[133, 0, 0],[134, 0, 0],[136, 0, 0], [139, 0, 0],[140, 0, 0],[141, 0, 0],[143, 0, 0],[144, 0, 0], [146, 0, 0],[147, 0, 0],[149, 0, 0],[150, 0, 0],[152, 0, 0], [153, 0, 0],[155, 0, 0],[156, 0, 0],[157, 0, 0],[159, 0, 0], [160, 0, 0],[162, 0, 0],[163, 0, 0],[165, 0, 0],[166, 0, 0], [169, 0, 0],[170, 0, 0],[172, 0, 0],[173, 0, 0],[175, 1, 0], [176, 3, 0],[178, 5, 0],[179, 7, 0],[181, 9, 0],[182, 11, 0], [185, 15, 0],[186, 17, 0],[188, 18, 0],[189, 20, 0],[191, 22, 0], [192, 24, 0],[194, 26, 0],[195, 28, 0],[197, 30, 0],[198, 32, 0], [201, 35, 0],[202, 37, 0],[204, 39, 0],[205, 41, 0],[207, 43, 0], [208, 45, 0],[210, 47, 0],[211, 49, 0],[212, 51, 0],[214, 52, 0], [215, 54, 0],[217, 56, 0],[218, 58, 0],[220, 60, 0],[221, 62, 0], [223, 64, 0],[224, 66, 0],[226, 68, 0],[227, 69, 0],[228, 71, 0], [231, 75, 0],[233, 77, 0],[234, 79, 0],[236, 81, 0],[237, 83, 0], [239, 85, 0],[240, 86, 0],[241, 88, 0],[243, 90, 0],[244, 92, 0], [246, 94, 0],[247, 96, 0],[249, 98, 0],[250,100, 0],[252,102, 0], [253,103, 0],[255,105, 0],[255,107, 0],[255,109, 0],[255,111, 0], [255,115, 0],[255,117, 0],[255,119, 0],[255,120, 0],[255,122, 0], [255,124, 0],[255,126, 0],[255,128, 0],[255,130, 0],[255,132, 0], [255,136, 7],[255,137, 11],[255,139, 15],[255,141, 19],[255,143, 23], [255,145, 27],[255,147, 31],[255,149, 35],[255,151, 39],[255,153, 43], [255,156, 51],[255,158, 54],[255,160, 58],[255,162, 62],[255,164, 66], [255,166, 70],[255,168, 74],[255,170, 78],[255,171, 82],[255,173, 86], [255,175, 90],[255,177, 94],[255,179, 98],[255,181,102],[255,183,105], [255,185,109],[255,187,113],[255,188,117],[255,190,121],[255,192,125], [255,196,133],[255,198,137],[255,200,141],[255,202,145],[255,204,149], [255,205,153],[255,207,156],[255,209,160],[255,211,164],[255,213,168], [255,215,172],[255,217,176],[255,219,180],[255,221,184],[255,222,188], [255,224,192],[255,226,196],[255,228,200],[255,230,204],[255,232,207], [255,236,215],[255,238,219],[255,239,223],[255,241,227],[255,243,231], [255,245,235],[255,247,239],[255,249,243],[255,251,247],[255,253,251] ], 'map' => [ [ 0, 0, 0],[ 0, 0, 46],[ 0, 0, 58],[ 0, 0, 69],[ 0, 0, 81], [ 0, 0, 92],[ 0, 0,104],[ 0, 0,116],[ 0, 3,116],[ 1, 6,116], [ 2, 8,116],[ 2, 11,116],[ 3, 13,117],[ 4, 16,117],[ 5, 18,117], [ 5, 21,117],[ 6, 23,117],[ 7, 26,118],[ 8, 28,118],[ 8, 31,118], [ 9, 33,118],[ 10, 36,118],[ 11, 38,119],[ 11, 41,119],[ 12, 43,119], [ 13, 45,119],[ 14, 48,119],[ 15, 50,120],[ 15, 52,120],[ 16, 55,120], [ 17, 57,120],[ 18, 59,120],[ 18, 61,121],[ 19, 64,121],[ 20, 66,121], [ 21, 68,121],[ 22, 70,121],[ 22, 72,122],[ 23, 74,122],[ 24, 77,122], [ 25, 79,122],[ 26, 81,122],[ 26, 83,123],[ 27, 85,123],[ 28, 87,123], [ 29, 89,123],[ 30, 91,123],[ 31, 93,124],[ 31, 95,124],[ 32, 97,124], [ 33, 99,124],[ 34,100,124],[ 35,102,125],[ 36,104,125],[ 36,106,125], [ 37,108,125],[ 38,109,125],[ 39,111,126],[ 40,113,126],[ 41,115,126], [ 41,116,126],[ 42,118,126],[ 43,120,127],[ 44,121,127],[ 45,123,127], [ 46,125,127],[ 47,126,127],[ 48,128,128],[ 48,128,126],[ 48,129,125], [ 49,129,124],[ 49,130,123],[ 50,131,122],[ 50,131,120],[ 51,132,119], [ 51,133,118],[ 52,133,117],[ 52,134,115],[ 53,134,114],[ 53,135,113], [ 54,136,111],[ 54,136,110],[ 55,137,109],[ 55,138,108],[ 56,138,106], [ 56,139,105],[ 57,140,104],[ 57,140,102],[ 58,141,101],[ 58,141,100], [ 59,142, 98],[ 59,143, 97],[ 60,143, 96],[ 61,144, 94],[ 61,145, 93], [ 62,145, 92],[ 62,146, 90],[ 63,146, 89],[ 63,147, 88],[ 64,148, 86], [ 64,148, 85],[ 65,149, 84],[ 65,150, 82],[ 66,150, 81],[ 67,151, 80], [ 67,151, 78],[ 68,152, 77],[ 68,153, 76],[ 69,153, 74],[ 69,154, 73], [ 70,155, 71],[ 71,155, 70],[ 73,156, 71],[ 76,156, 72],[ 78,157, 72], [ 81,158, 73],[ 83,158, 73],[ 86,159, 74],[ 88,160, 75],[ 91,160, 75], [ 94,161, 76],[ 96,161, 76],[ 99,162, 77],[101,163, 77],[104,163, 78], [106,164, 79],[109,165, 79],[111,165, 80],[114,166, 80],[117,166, 81], [119,167, 82],[121,168, 82],[122,168, 82],[124,168, 83],[126,169, 83], [128,169, 83],[129,170, 84],[131,170, 84],[133,171, 84],[135,171, 85], [136,172, 85],[138,172, 85],[140,172, 86],[141,173, 86],[143,173, 86], [145,174, 87],[147,174, 87],[149,175, 87],[150,175, 88],[152,175, 88], [154,176, 88],[156,176, 89],[157,177, 89],[159,177, 89],[161,178, 90], [163,178, 90],[165,179, 90],[166,179, 91],[168,179, 91],[170,180, 91], [172,180, 92],[174,181, 92],[175,181, 92],[177,182, 93],[179,182, 93], [181,183, 93],[183,183, 94],[183,182, 94],[184,181, 94],[184,181, 95], [185,180, 95],[185,179, 95],[186,178, 96],[186,177, 96],[187,176, 97], [187,175, 97],[187,174, 97],[188,173, 98],[188,172, 98],[189,171, 98], [189,170, 99],[190,169, 99],[190,168, 99],[190,167,100],[191,166,100], [191,165,100],[192,164,101],[192,163,101],[193,163,104],[195,164,106], [196,164,108],[197,165,111],[198,165,113],[199,166,116],[201,167,118], [202,167,121],[203,168,123],[204,169,126],[205,170,129],[207,171,131], [208,172,134],[209,173,137],[210,174,139],[211,175,142],[213,176,145], [214,177,148],[215,178,150],[216,179,153],[217,181,156],[219,182,159], [220,184,162],[221,185,165],[222,187,168],[223,188,170],[225,190,173], [226,192,176],[227,194,179],[228,196,182],[229,198,185],[231,200,189], [232,202,192],[233,204,195],[234,206,198],[235,208,201],[237,211,204], [238,213,207],[239,215,211],[240,218,214],[241,221,217],[243,223,220], [244,226,224],[245,229,227],[246,232,230],[247,235,234],[249,238,237], [250,241,241],[251,244,244],[252,248,248],[253,251,251],[255,255,255] ], 'rainbow' => [ [255, 0, 42],[255, 0, 36],[255, 0, 31],[255, 0, 26],[255, 0, 20], [255, 0, 15],[255, 0, 10],[255, 0, 4],[255, 5, 0],[255, 11, 0], [255, 16, 0],[255, 22, 0],[255, 27, 0],[255, 32, 0],[255, 38, 0], [255, 43, 0],[255, 48, 0],[255, 54, 0],[255, 59, 0],[255, 65, 0], [255, 70, 0],[255, 75, 0],[255, 81, 0],[255, 91, 0],[255, 97, 0], [255,102, 0],[255,108, 0],[255,113, 0],[255,118, 0],[255,124, 0], [255,129, 0],[255,135, 0],[255,140, 0],[255,145, 0],[255,151, 0], [255,156, 0],[255,161, 0],[255,167, 0],[255,178, 0],[255,183, 0], [255,188, 0],[255,194, 0],[255,199, 0],[255,204, 0],[255,210, 0], [255,215, 0],[255,221, 0],[255,226, 0],[255,231, 0],[255,237, 0], [255,242, 0],[255,247, 0],[255,253, 0],[245,255, 0],[240,255, 0], [235,255, 0],[229,255, 0],[224,255, 0],[219,255, 0],[213,255, 0], [208,255, 0],[202,255, 0],[197,255, 0],[192,255, 0],[186,255, 0], [181,255, 0],[175,255, 0],[170,255, 0],[159,255, 0],[154,255, 0], [149,255, 0],[143,255, 0],[138,255, 0],[132,255, 0],[127,255, 0], [122,255, 0],[116,255, 0],[111,255, 0],[106,255, 0],[100,255, 0], [ 95,255, 0],[ 89,255, 0],[ 84,255, 0],[ 73,255, 0],[ 68,255, 0], [ 63,255, 0],[ 57,255, 0],[ 52,255, 0],[ 46,255, 0],[ 41,255, 0], [ 36,255, 0],[ 30,255, 0],[ 25,255, 0],[ 19,255, 0],[ 14,255, 0], [ 9,255, 0],[ 3,255, 0],[ 0,255, 1],[ 0,255, 12],[ 0,255, 17], [ 0,255, 23],[ 0,255, 28],[ 0,255, 33],[ 0,255, 39],[ 0,255, 44], [ 0,255, 49],[ 0,255, 55],[ 0,255, 60],[ 0,255, 66],[ 0,255, 71], [ 0,255, 76],[ 0,255, 82],[ 0,255, 87],[ 0,255, 98],[ 0,255,103], [ 0,255,109],[ 0,255,114],[ 0,255,119],[ 0,255,125],[ 0,255,130], [ 0,255,135],[ 0,255,141],[ 0,255,146],[ 0,255,152],[ 0,255,157], [ 0,255,162],[ 0,255,168],[ 0,255,173],[ 0,255,184],[ 0,255,189], [ 0,255,195],[ 0,255,200],[ 0,255,205],[ 0,255,211],[ 0,255,216], [ 0,255,222],[ 0,255,227],[ 0,255,232],[ 0,255,238],[ 0,255,243], [ 0,255,248],[ 0,255,254],[ 0,250,255],[ 0,239,255],[ 0,234,255], [ 0,228,255],[ 0,223,255],[ 0,218,255],[ 0,212,255],[ 0,207,255], [ 0,201,255],[ 0,196,255],[ 0,191,255],[ 0,185,255],[ 0,180,255], [ 0,174,255],[ 0,169,255],[ 0,164,255],[ 0,153,255],[ 0,148,255], [ 0,142,255],[ 0,137,255],[ 0,131,255],[ 0,126,255],[ 0,121,255], [ 0,115,255],[ 0,110,255],[ 0,105,255],[ 0, 99,255],[ 0, 94,255], [ 0, 88,255],[ 0, 83,255],[ 0, 78,255],[ 0, 67,255],[ 0, 62,255], [ 0, 56,255],[ 0, 51,255],[ 0, 45,255],[ 0, 40,255],[ 0, 35,255], [ 0, 29,255],[ 0, 24,255],[ 0, 18,255],[ 0, 13,255],[ 0, 8,255], [ 0, 2,255],[ 2, 0,255],[ 7, 0,255],[ 18, 0,255],[ 24, 0,255], [ 29, 0,255],[ 34, 0,255],[ 40, 0,255],[ 45, 0,255],[ 50, 0,255], [ 56, 0,255],[ 61, 0,255],[ 67, 0,255],[ 72, 0,255],[ 77, 0,255], [ 83, 0,255],[ 88, 0,255],[ 93, 0,255],[104, 0,255],[110, 0,255], [115, 0,255],[120, 0,255],[126, 0,255],[131, 0,255],[136, 0,255], [142, 0,255],[147, 0,255],[153, 0,255],[158, 0,255],[163, 0,255], [169, 0,255],[174, 0,255],[180, 0,255],[190, 0,255],[196, 0,255], [201, 0,255],[206, 0,255],[212, 0,255],[217, 0,255],[223, 0,255], [228, 0,255],[233, 0,255],[239, 0,255],[244, 0,255],[249, 0,255], [255, 0,254],[255, 0,249],[255, 0,243],[255, 0,233],[255, 0,227], [255, 0,222],[255, 0,217],[255, 0,211],[255, 0,206],[255, 0,201] ] ); # Returns a hash: gradient-name => color-count sub available_gradients { return map { $_, scalar( @{ $_gradients{$_} } ) } keys %_gradients; } # Returns array-ref of rgb-triples, undef if gradient-name not found sub gradient { my ( $name ) = @_; unless( exists $_gradients{ $name } ) { return; } return $_gradients{$name}; } # Returns the color corresponding to the position in the gradient given by f. # Returns undef when gradient not found or f outside valid range. sub grad2rgb { my ( $name, $frac ) = @_; unless( exists $_gradients{ $name } ) { return; } if( $frac < 0.0 || $frac >= 1.0 ) { return; } my $idx = int( $frac * scalar( @{$_gradients{$name}} ) ); return _fmt( @{ $_gradients{$name}[$idx] } ); } # Expects a gradient and and array-ref to an array of rgb triples. # If the name already exists, the function returns the old array; undef otherws sub register_gradient { my ( $name, $array_ref ) = @_; if( exists $_gradients{ $name } ) { my $old = $_gradients{ $name }; $_gradients{ $name } = $array_ref; return $old; } $_gradients{ $name } = $array_ref; return undef; } } # end BEGIN (Gradients) # ================================================== # Names BEGIN { my $_default_namespace = 'x11'; my %_colors = ( 'www:aqua' => [ 0,255,255],'www:black' => [ 0, 0, 0], 'www:blue' => [ 0, 0,255],'www:fuchsia' => [255, 0,255], 'www:gray' => [190,190,190],'www:green' => [ 0,128, 0], 'www:lime' => [ 0,255, 0],'www:maroon' => [128, 0, 0], 'www:navy' => [ 0, 0,128],'www:olive' => [128,128, 0], 'www:purple' => [128, 0,128],'www:red' => [255, 0, 0], 'www:silver' => [192,192,192],'www:teal' => [ 0,128,128], 'www:white' => [255,255,255],'www:yellow' => [255,255, 0], 'www:orange' => [255,165, 0], 'svg:palevioletred' => [219,112,147],'svg:mediumslateblue' => [123,104,238], 'svg:gold' => [255,215,0],'svg:gainsboro' => [220,220,220], 'svg:yellow' => [255,255,0],'svg:limegreen' => [50,205,50], 'svg:lightgoldenrodyellow' => [250,250,210],'svg:lavenderblush' => [255,240,245], 'svg:darkmagenta' => [139,0,139],'svg:darkgrey' => [169,169,169], 'svg:blanchedalmond' => [255,235,205],'svg:ghostwhite' => [248,248,255], 'svg:floralwhite' => [255,250,240],'svg:coral' => [255,127,80], 'svg:honeydew' => [240,255,240],'svg:mistyrose' => [255,228,225], 'svg:slateblue' => [106,90,205],'svg:goldenrod' => [218,165,32], 'svg:darkcyan' => [0,139,139],'svg:moccasin' => [255,228,181], 'svg:mediumvioletred' => [199,21,133],'svg:maroon' => [128,0,0], 'svg:lightpink' => [255,182,193],'svg:lightsalmon' => [255,160,122], 'svg:paleturquoise' => [175,238,238],'svg:darksalmon' => [233,150,122], 'svg:yellowgreen' => [154,205,50],'svg:mediumturquoise' => [72,209,204], 'svg:chartreuse' => [127,255,0],'svg:peru' => [205,133,63], 'svg:palegoldenrod' => [238,232,170],'svg:red' => [255,0,0], 'svg:lavender' => [230,230,250],'svg:lightseagreen' => [32,178,170], 'svg:powderblue' => [176,224,230],'svg:orchid' => [218,112,214], 'svg:cornsilk' => [255,248,220],'svg:seagreen' => [46,139,87], 'svg:royalblue' => [65,105,225],'svg:ivory' => [255,255,240], 'svg:tan' => [210,180,140],'svg:linen' => [250,240,230], 'svg:darkorchid' => [153,50,204],'svg:tomato' => [255,99,71], 'svg:lightcyan' => [224,255,255],'svg:darkolivegreen' => [85,107,47], 'svg:sienna' => [160,82,45],'svg:lightsteelblue' => [176,196,222], 'svg:indigo' => [75,0,130],'svg:peachpuff' => [255,218,185], 'svg:lime' => [0,255,0],'svg:mediumspringgreen' => [0,250,154], 'svg:silver' => [192,192,192],'svg:saddlebrown' => [139,69,19], 'svg:lightyellow' => [255,255,224],'svg:grey' => [128,128,128], 'svg:thistle' => [216,191,216],'svg:deepskyblue' => [0,191,255], 'svg:lightgreen' => [144,238,144],'svg:blueviolet' => [138,43,226], 'svg:aqua' => [0,255,255],'svg:cyan' => [0,255,255], 'svg:papayawhip' => [255,239,213],'svg:deeppink' => [255,20,147], 'svg:firebrick' => [178,34,34],'svg:navy' => [0,0,128], 'svg:hotpink' => [255,105,180],'svg:pink' => [255,192,203], 'svg:darkturquoise' => [0,206,209],'svg:navajowhite' => [255,222,173], 'svg:lightslategrey' => [119,136,153],'svg:lawngreen' => [124,252,0], 'svg:lightcoral' => [240,128,128],'svg:palegreen' => [152,251,152], 'svg:dodgerblue' => [30,144,255],'svg:greenyellow' => [173,255,47], 'svg:lightskyblue' => [135,206,250],'svg:brown' => [165,42,42], 'svg:dimgrey' => [105,105,105],'svg:aquamarine' => [127,255,212], 'svg:darkseagreen' => [143,188,143],'svg:fuchsia' => [255,0,255], 'svg:magenta' => [255,0,255],'svg:chocolate' => [210,105,30], 'svg:mediumseagreen' => [60,179,113],'svg:cadetblue' => [95,158,160], 'svg:purple' => [128,0,128],'svg:turquoise' => [64,224,208], 'svg:darkkhaki' => [189,183,107],'svg:antiquewhite' => [250,235,215], 'svg:skyblue' => [135,206,235],'svg:sandybrown' => [244,164,96], 'svg:mediumblue' => [0,0,205],'svg:steelblue' => [70,130,180], 'svg:indianred' => [205,92,92],'svg:khaki' => [240,230,140], 'svg:lightblue' => [173,216,230],'svg:green' => [0,128,0], 'svg:olive' => [128,128,0],'svg:mediumorchid' => [186,85,211], 'svg:blue' => [0,0,255],'svg:snow' => [255,250,250], 'svg:rosybrown' => [188,143,143],'svg:orange' => [255,165,0], 'svg:slategrey' => [112,128,144],'svg:darkorange' => [255,140,0], 'svg:violet' => [238,130,238],'svg:darkslategrey' => [47,79,79], 'svg:whitesmoke' => [245,245,245],'svg:burlywood' => [222,184,135], 'svg:darkgreen' => [0,100,0],'svg:lemonchiffon' => [255,250,205], 'svg:midnightblue' => [25,25,112],'svg:mintcream' => [245,255,250], 'svg:oldlace' => [253,245,230],'svg:black' => [0,0,0], 'svg:bisque' => [255,228,196],'svg:mediumaquamarine' => [102,205,170], 'svg:olivedrab' => [107,142,35],'svg:salmon' => [250,128,114], 'svg:teal' => [0,128,128],'svg:seashell' => [255,245,238], 'svg:springgreen' => [0,255,127],'svg:plum' => [221,160,221], 'svg:darkviolet' => [148,0,211],'svg:wheat' => [245,222,179], 'svg:mediumpurple' => [147,112,219],'svg:cornflowerblue' => [100,149,237], 'svg:forestgreen' => [34,139,34],'svg:darkgoldenrod' => [184,134,11], 'svg:aliceblue' => [240,248,255],'svg:white' => [255,255,255], 'svg:darkblue' => [0,0,139],'svg:azure' => [240,255,255], 'svg:darkred' => [139,0,0],'svg:orangered' => [255,69,0], 'svg:darkslateblue' => [72,61,139],'svg:crimson' => [220,20,60], 'svg:lightgrey' => [211,211,211],'svg:beige' => [245,245,220], 'x11:deepskyblue3' => [0,154,205],'x11:gold' => [255,215,0], 'x11:gold1' => [255,215,0],'x11:mediumpurple3' => [137,104,205], 'x11:royalblue3' => [58,95,205],'x11:lightgoldenrodyellow' => [250,250,210], 'x11:lavenderblush' => [255,240,245],'x11:lavenderblush1' => [255,240,245], 'x11:pink1' => [255,181,197],'x11:green3' => [0,205,0], 'x11:lightsteelblue1' => [202,225,255],'x11:blanchedalmond' => [255,235,205], 'x11:salmon1' => [255,140,105],'x11:ghostwhite' => [248,248,255], 'x11:floralwhite' => [255,250,240],'x11:dodgerblue4' => [16,78,139], 'x11:grey43' => [110,110,110],'x11:indianred4' => [139,58,58], 'x11:mistyrose1' => [255,228,225],'x11:mistyrose' => [255,228,225], 'x11:dodgerblue2' => [28,134,238],'x11:grey37' => [94,94,94], 'x11:grey9' => [23,23,23],'x11:purple4' => [85,26,139], 'x11:orchid2' => [238,122,233],'x11:cornsilk3' => [205,200,177], 'x11:goldenrod' => [218,165,32],'x11:hotpink4' => [139,58,98], 'x11:lightpink' => [255,182,193],'x11:coral2' => [238,106,80], 'x11:cyan2' => [0,238,238],'x11:grey87' => [222,222,222], 'x11:grey91' => [232,232,232],'x11:violetred4' => [139,34,82], 'x11:violetred2' => [238,58,140],'x11:indianred2' => [238,99,99], 'x11:lightyellow3' => [205,205,180],'x11:darkolivegreen2' => [188,238,104], 'x11:magenta3' => [205,0,205],'x11:grey64' => [163,163,163], 'x11:honeydew3' => [193,205,193],'x11:lightsalmon3' => [205,129,98], 'x11:springgreen4' => [0,139,69],'x11:grey57' => [145,145,145], 'x11:grey50' => [127,127,127],'x11:grey66' => [168,168,168], 'x11:antiquewhite1' => [255,239,219],'x11:paleturquoise' => [175,238,238], 'x11:navajowhite2' => [238,207,161],'x11:lightpink3' => [205,140,149], 'x11:darksalmon' => [233,150,122],'x11:grey52' => [133,133,133], 'x11:slategrey3' => [159,182,205],'x11:darkseagreen4' => [105,139,105], 'x11:chartreuse' => [127,255,0],'x11:chartreuse1' => [127,255,0], 'x11:grey42' => [107,107,107],'x11:peru' => [205,133,63], 'x11:tan3' => [205,133,63],'x11:grey19' => [48,48,48], 'x11:palegreen3' => [124,205,124],'x11:lavender' => [230,230,250], 'x11:red3' => [205,0,0],'x11:orchid' => [218,112,214], 'x11:powderblue' => [176,224,230],'x11:grey35' => [89,89,89], 'x11:plum4' => [139,102,139],'x11:cornsilk' => [255,248,220], 'x11:cornsilk1' => [255,248,220],'x11:royalblue' => [65,105,225], 'x11:darkgoldenrod2' => [238,173,14],'x11:lightpink4' => [139,95,101], 'x11:springgreen2' => [0,238,118],'x11:tan' => [210,180,140], 'x11:lightslateblue' => [132,112,255],'x11:darkorchid' => [153,50,204], 'x11:orangered2' => [238,64,0],'x11:palevioletred1' => [255,130,171], 'x11:grey63' => [161,161,161],'x11:maroon2' => [238,48,167], 'x11:blue2' => [0,0,238],'x11:turquoise4' => [0,134,139], 'x11:lightcyan1' => [224,255,255],'x11:lightcyan' => [224,255,255], 'x11:springgreen3' => [0,205,102],'x11:darkorchid4' => [104,34,139], 'x11:sienna' => [160,82,45],'x11:goldenrod2' => [238,180,34], 'x11:lightgoldenrod3' => [205,190,112],'x11:green' => [0,255,0], 'x11:green1' => [0,255,0],'x11:peachpuff1' => [255,218,185], 'x11:peachpuff' => [255,218,185],'x11:yellow3' => [205,205,0], 'x11:mediumspringgreen' => [0,250,154],'x11:cadetblue3' => [122,197,205], 'x11:royalblue1' => [72,118,255],'x11:deepskyblue1' => [0,191,255], 'x11:deepskyblue' => [0,191,255],'x11:firebrick1' => [255,48,48], 'x11:grey80' => [204,204,204],'x11:grey28' => [71,71,71], 'x11:palegreen2' => [144,238,144],'x11:lightgreen' => [144,238,144], 'x11:blueviolet' => [138,43,226],'x11:deeppink1' => [255,20,147], 'x11:deeppink' => [255,20,147],'x11:deeppink2' => [238,18,137], 'x11:lightskyblue2' => [164,211,238],'x11:grey77' => [196,196,196], 'x11:grey72' => [184,184,184],'x11:tomato2' => [238,92,66], 'x11:steelblue2' => [92,172,238],'x11:hotpink' => [255,105,180], 'x11:slateblue4' => [71,60,139],'x11:pink' => [255,192,203], 'x11:darkturquoise' => [0,206,209],'x11:antiquewhite3' => [205,192,176], 'x11:grey32' => [82,82,82],'x11:lightyellow2' => [238,238,209], 'x11:olivedrab4' => [105,139,34],'x11:lightblue4' => [104,131,139], 'x11:royalblue2' => [67,110,238],'x11:navajowhite1' => [255,222,173], 'x11:navajowhite' => [255,222,173],'x11:lightgoldenrod' => [238,221,130], 'x11:grey85' => [217,217,217],'x11:maroon4' => [139,28,98], 'x11:grey90' => [229,229,229],'x11:grey17' => [43,43,43], 'x11:seashell4' => [139,134,130],'x11:greenyellow' => [173,255,47], 'x11:dodgerblue1' => [30,144,255],'x11:dodgerblue' => [30,144,255], 'x11:grey89' => [227,227,227],'x11:brown2' => [238,59,59], 'x11:paleturquoise2' => [174,238,238],'x11:lightskyblue' => [135,206,250], 'x11:salmon4' => [139,76,57],'x11:chocolate3' => [205,102,29], 'x11:grey70' => [179,179,179],'x11:grey25' => [64,64,64], 'x11:darkolivegreen4' => [110,139,61],'x11:mediumorchid2' => [209,95,238], 'x11:brown' => [165,42,42],'x11:grey67' => [171,171,171], 'x11:grey41' => [105,105,105],'x11:dimgrey' => [105,105,105], 'x11:grey60' => [153,153,153],'x11:indianred3' => [205,85,85], 'x11:chocolate' => [210,105,30],'x11:darkslategrey1' => [151,255,255], 'x11:grey2' => [5,5,5],'x11:firebrick3' => [205,38,38], 'x11:snow4' => [139,137,137],'x11:mediumseagreen' => [60,179,113], 'x11:darkorchid1' => [191,62,255],'x11:pink3' => [205,145,158], 'x11:violetred1' => [255,62,150],'x11:grey83' => [212,212,212], 'x11:olivedrab1' => [192,255,62],'x11:darkkhaki' => [189,183,107], 'x11:deepskyblue4' => [0,104,139],'x11:darkorchid2' => [178,58,238], 'x11:skyblue' => [135,206,235],'x11:mediumorchid3' => [180,82,205], 'x11:rosybrown4' => [139,105,105],'x11:grey16' => [41,41,41], 'x11:yellow4' => [139,139,0],'x11:maroon' => [176,48,96], 'x11:turquoise2' => [0,229,238],'x11:mistyrose2' => [238,213,210], 'x11:blue3' => [0,0,205],'x11:mediumblue' => [0,0,205], 'x11:grey4' => [10,10,10],'x11:pink2' => [238,169,184], 'x11:chocolate2' => [238,118,33],'x11:lightyellow4' => [139,139,122], 'x11:grey99' => [252,252,252],'x11:red2' => [238,0,0], 'x11:tan4' => [139,90,43],'x11:yellow2' => [238,238,0], 'x11:grey12' => [31,31,31],'x11:deeppink4' => [139,10,80], 'x11:lightsalmon4' => [139,87,66],'x11:lightcyan4' => [122,139,139], 'x11:snow1' => [255,250,250],'x11:snow' => [255,250,250], 'x11:brown4' => [139,35,35],'x11:darkseagreen2' => [180,238,180], 'x11:lightsteelblue2' => [188,210,238],'x11:rosybrown' => [188,143,143], 'x11:maroon1' => [255,52,179],'x11:slategrey' => [112,128,144], 'x11:orange' => [255,165,0],'x11:orange1' => [255,165,0], 'x11:orangered3' => [205,55,0],'x11:plum3' => [205,150,205], 'x11:turquoise3' => [0,197,205],'x11:pink4' => [139,99,108], 'x11:violet' => [238,130,238],'x11:grey96' => [245,245,245], 'x11:whitesmoke' => [245,245,245],'x11:lightgoldenrod1' => [255,236,139], 'x11:darkorange1' => [255,127,0],'x11:seashell2' => [238,229,222], 'x11:midnightblue' => [25,25,112],'x11:grey27' => [69,69,69], 'x11:mediumpurple2' => [159,121,238],'x11:bisque4' => [139,125,107], 'x11:black' => [0,0,0],'x11:grey0' => [0,0,0], 'x11:lavenderblush4' => [139,131,134],'x11:bisque1' => [255,228,196], 'x11:bisque' => [255,228,196],'x11:mediumaquamarine' => [102,205,170], 'x11:aquamarine3' => [102,205,170],'x11:goldenrod1' => [255,193,37], 'x11:green4' => [0,139,0],'x11:bisque3' => [205,183,158], 'x11:salmon' => [250,128,114],'x11:grey1' => [3,3,3], 'x11:purple3' => [125,38,205],'x11:khaki4' => [139,134,78], 'x11:grey' => [190,190,190],'x11:cadetblue4' => [83,134,139], 'x11:cadetblue1' => [152,245,255],'x11:hotpink3' => [205,96,144], 'x11:antiquewhite2' => [238,223,204],'x11:darkorange4' => [139,69,0], 'x11:cornsilk2' => [238,232,205],'x11:grey93' => [237,237,237], 'x11:thistle3' => [205,181,205],'x11:plum2' => [238,174,238], 'x11:burlywood2' => [238,197,145],'x11:skyblue4' => [74,112,139], 'x11:peachpuff2' => [238,203,173],'x11:grey62' => [158,158,158], 'x11:paleturquoise3' => [150,205,205],'x11:lightblue1' => [191,239,255], 'x11:mediumpurple' => [147,112,219],'x11:peachpuff3' => [205,175,149], 'x11:grey49' => [125,125,125],'x11:grey3' => [8,8,8], 'x11:steelblue1' => [99,184,255],'x11:grey73' => [186,186,186], 'x11:grey44' => [112,112,112],'x11:palevioletred4' => [139,71,93], 'x11:khaki2' => [238,230,133],'x11:gold3' => [205,173,0], 'x11:grey47' => [120,120,120],'x11:aliceblue' => [240,248,255], 'x11:grey58' => [148,148,148],'x11:darkslategrey4' => [82,139,139], 'x11:mediumorchid4' => [122,55,139],'x11:thistle1' => [255,225,255], 'x11:mistyrose4' => [139,125,123],'x11:orchid1' => [255,131,250], 'x11:hotpink2' => [238,106,167],'x11:azure' => [240,255,255], 'x11:azure1' => [240,255,255],'x11:darkred' => [139,0,0], 'x11:red4' => [139,0,0],'x11:chartreuse2' => [118,238,0], 'x11:slateblue1' => [131,111,255],'x11:grey15' => [38,38,38], 'x11:grey71' => [181,181,181],'x11:darkslategrey2' => [141,238,238], 'x11:snow3' => [205,201,201],'x11:bisque2' => [238,213,183], 'x11:darkslateblue' => [72,61,139],'x11:coral4' => [139,62,47], 'x11:grey69' => [176,176,176],'x11:burlywood4' => [139,115,85], 'x11:coral3' => [205,91,69],'x11:purple' => [160,32,240], 'x11:grey36' => [92,92,92],'x11:grey94' => [240,240,240], 'x11:palevioletred2' => [238,121,159],'x11:grey46' => [117,117,117], 'x11:palevioletred' => [219,112,147],'x11:mediumslateblue' => [123,104,238], 'x11:seagreen1' => [84,255,159],'x11:gainsboro' => [220,220,220], 'x11:yellow1' => [255,255,0],'x11:yellow' => [255,255,0], 'x11:limegreen' => [50,205,50],'x11:darkgrey' => [169,169,169], 'x11:darkmagenta' => [139,0,139],'x11:magenta4' => [139,0,139], 'x11:grey59' => [150,150,150],'x11:firebrick2' => [238,44,44], 'x11:coral' => [255,127,80],'x11:honeydew' => [240,255,240], 'x11:honeydew1' => [240,255,240],'x11:grey86' => [219,219,219], 'x11:grey13' => [33,33,33],'x11:purple1' => [155,48,255], 'x11:grey82' => [209,209,209],'x11:grey65' => [166,166,166], 'x11:grey97' => [247,247,247],'x11:azure4' => [131,139,139], 'x11:darkslategrey3' => [121,205,205],'x11:lightcyan3' => [180,205,205], 'x11:aquamarine2' => [118,238,198],'x11:grey92' => [235,235,235], 'x11:slateblue' => [106,90,205],'x11:darkcyan' => [0,139,139], 'x11:cyan4' => [0,139,139],'x11:chartreuse3' => [102,205,0], 'x11:moccasin' => [255,228,181],'x11:mediumvioletred' => [199,21,133], 'x11:tomato3' => [205,79,57],'x11:grey31' => [79,79,79], 'x11:sienna2' => [238,121,66],'x11:grey98' => [250,250,250], 'x11:gold4' => [139,117,0],'x11:slateblue3' => [105,89,205], 'x11:grey14' => [36,36,36],'x11:honeydew4' => [131,139,131], 'x11:grey61' => [156,156,156],'x11:violetred3' => [205,50,120], 'x11:grey39' => [99,99,99],'x11:aquamarine4' => [69,139,116], 'x11:darkgoldenrod4' => [139,101,8],'x11:mediumpurple1' => [171,130,255], 'x11:lightsalmon1' => [255,160,122],'x11:lightsalmon' => [255,160,122], 'x11:darkolivegreen3' => [162,205,90],'x11:grey10' => [26,26,26], 'x11:khaki3' => [205,198,115],'x11:navajowhite3' => [205,179,139], 'x11:lightpink1' => [255,174,185],'x11:grey81' => [207,207,207], 'x11:grey45' => [115,115,115],'x11:wheat3' => [205,186,150], 'x11:steelblue4' => [54,100,139],'x11:grey48' => [122,122,122], 'x11:olivedrab3' => [154,205,50],'x11:yellowgreen' => [154,205,50], 'x11:mediumturquoise' => [72,209,204],'x11:palegoldenrod' => [238,232,170], 'x11:ivory2' => [238,238,224],'x11:darkolivegreen1' => [202,255,112], 'x11:red1' => [255,0,0],'x11:red' => [255,0,0], 'x11:lemonchiffon4' => [139,137,112],'x11:lightseagreen' => [32,178,170], 'x11:seagreen4' => [46,139,87],'x11:seagreen' => [46,139,87], 'x11:ivory' => [255,255,240],'x11:ivory1' => [255,255,240], 'x11:linen' => [250,240,230],'x11:grey34' => [87,87,87], 'x11:thistle2' => [238,210,238],'x11:tomato' => [255,99,71], 'x11:tomato1' => [255,99,71],'x11:slategrey1' => [198,226,255], 'x11:orchid3' => [205,105,201],'x11:lightcyan2' => [209,238,238], 'x11:grey54' => [138,138,138],'x11:darkolivegreen' => [85,107,47], 'x11:lightsteelblue' => [176,196,222],'x11:grey33' => [84,84,84], 'x11:chocolate4' => [139,69,19],'x11:saddlebrown' => [139,69,19], 'x11:orange3' => [205,133,0],'x11:lightyellow' => [255,255,224], 'x11:lightyellow1' => [255,255,224],'x11:grey75' => [191,191,191], 'x11:khaki1' => [255,246,143],'x11:thistle' => [216,191,216], 'x11:grey79' => [201,201,201],'x11:plum1' => [255,187,255], 'x11:paleturquoise4' => [102,139,139],'x11:cyan1' => [0,255,255], 'x11:cyan' => [0,255,255],'x11:maroon3' => [205,41,144], 'x11:papayawhip' => [255,239,213],'x11:seagreen3' => [67,205,128], 'x11:lightgoldenrod4' => [139,129,76],'x11:lightskyblue1' => [176,226,255], 'x11:firebrick' => [178,34,34],'x11:grey30' => [77,77,77], 'x11:grey26' => [66,66,66],'x11:antiquewhite4' => [139,131,120], 'x11:navyblue' => [0,0,128],'x11:navy' => [0,0,128], 'x11:grey7' => [18,18,18],'x11:grey5' => [13,13,13], 'x11:grey29' => [74,74,74],'x11:turquoise1' => [0,245,255], 'x11:darkgoldenrod3' => [205,149,12],'x11:goldenrod4' => [139,105,20], 'x11:palevioletred3' => [205,104,137],'x11:lightslategrey' => [119,136,153], 'x11:snow2' => [238,233,233],'x11:grey24' => [61,61,61], 'x11:slategrey4' => [108,123,139],'x11:grey55' => [140,140,140], 'x11:seashell3' => [205,197,191],'x11:deeppink3' => [205,16,118], 'x11:lawngreen' => [124,252,0],'x11:darkorchid3' => [154,50,205], 'x11:lightcoral' => [240,128,128],'x11:palegreen' => [152,251,152], 'x11:grey56' => [143,143,143],'x11:grey23' => [59,59,59], 'x11:grey74' => [189,189,189],'x11:azure2' => [224,238,238], 'x11:darkseagreen3' => [155,205,155],'x11:grey20' => [51,51,51], 'x11:cadetblue2' => [142,229,238],'x11:grey84' => [214,214,214], 'x11:cornsilk4' => [139,136,120],'x11:grey38' => [97,97,97], 'x11:magenta1' => [255,0,255],'x11:magenta' => [255,0,255], 'x11:darkseagreen' => [143,188,143],'x11:aquamarine1' => [127,255,212], 'x11:aquamarine' => [127,255,212],'x11:lightblue3' => [154,192,205], 'x11:olivedrab2' => [179,238,58],'x11:grey40' => [102,102,102], 'x11:peachpuff4' => [139,119,101],'x11:paleturquoise1' => [187,255,255], 'x11:darkseagreen1' => [193,255,193],'x11:darkorange3' => [205,102,0], 'x11:brown3' => [205,51,51],'x11:grey51' => [130,130,130], 'x11:mediumpurple4' => [93,71,139],'x11:lightpink2' => [238,162,173], 'x11:cadetblue' => [95,158,160],'x11:lemonchiffon2' => [238,233,191], 'x11:green2' => [0,238,0],'x11:azure3' => [193,205,205], 'x11:turquoise' => [64,224,208],'x11:brown1' => [255,64,64], 'x11:lightsteelblue4' => [110,123,139],'x11:orange2' => [238,154,0], 'x11:antiquewhite' => [250,235,215],'x11:wheat2' => [238,216,174], 'x11:rosybrown2' => [238,180,180],'x11:lightsteelblue3' => [162,181,205], 'x11:grey78' => [199,199,199],'x11:grey21' => [54,54,54], 'x11:sandybrown' => [244,164,96],'x11:lavenderblush2' => [238,224,229], 'x11:steelblue' => [70,130,180],'x11:grey95' => [242,242,242], 'x11:indianred' => [205,92,92],'x11:skyblue1' => [135,206,255], 'x11:khaki' => [240,230,140],'x11:orchid4' => [139,71,137], 'x11:chocolate1' => [255,127,36],'x11:goldenrod3' => [205,155,29], 'x11:sienna4' => [139,71,38],'x11:lightblue' => [173,216,230], 'x11:grey88' => [224,224,224],'x11:palegreen4' => [84,139,84], 'x11:mediumorchid' => [186,85,211],'x11:blue' => [0,0,255], 'x11:blue1' => [0,0,255],'x11:dodgerblue3' => [24,116,205], 'x11:indianred1' => [255,106,106],'x11:cyan3' => [0,205,205], 'x11:tan1' => [255,165,79],'x11:darkorange' => [255,140,0], 'x11:skyblue2' => [126,192,238],'x11:coral1' => [255,114,86], 'x11:darkslategrey' => [47,79,79],'x11:burlywood' => [222,184,135], 'x11:sienna3' => [205,104,57],'x11:darkgreen' => [0,100,0], 'x11:mistyrose3' => [205,183,181],'x11:grey68' => [173,173,173], 'x11:grey53' => [135,135,135],'x11:lemonchiffon' => [255,250,205], 'x11:lemonchiffon1' => [255,250,205],'x11:palegreen1' => [154,255,154], 'x11:grey76' => [194,194,194],'x11:steelblue3' => [79,148,205], 'x11:grey11' => [28,28,28],'x11:oldlace' => [253,245,230], 'x11:mintcream' => [245,255,250],'x11:firebrick4' => [139,26,26], 'x11:lemonchiffon3' => [205,201,165],'x11:olivedrab' => [107,142,35], 'x11:honeydew2' => [224,238,224],'x11:deepskyblue2' => [0,178,238], 'x11:slateblue2' => [122,103,238],'x11:slategrey2' => [185,211,238], 'x11:seagreen2' => [78,238,148],'x11:salmon2' => [238,130,98], 'x11:ivory3' => [205,205,193],'x11:mediumorchid1' => [224,102,255], 'x11:tan2' => [238,154,73],'x11:springgreen' => [0,255,127], 'x11:springgreen1' => [0,255,127],'x11:seashell1' => [255,245,238], 'x11:seashell' => [255,245,238],'x11:skyblue3' => [108,166,205], 'x11:chartreuse4' => [69,139,0],'x11:burlywood3' => [205,170,125], 'x11:plum' => [221,160,221],'x11:ivory4' => [139,139,131], 'x11:darkviolet' => [148,0,211],'x11:lightblue2' => [178,223,238], 'x11:wheat' => [245,222,179],'x11:darkgoldenrod1' => [255,185,15], 'x11:cornflowerblue' => [100,149,237],'x11:purple2' => [145,44,238], 'x11:grey6' => [15,15,15],'x11:magenta2' => [238,0,238], 'x11:sienna1' => [255,130,71],'x11:darkgoldenrod' => [184,134,11], 'x11:forestgreen' => [34,139,34],'x11:navajowhite4' => [139,121,94], 'x11:royalblue4' => [39,64,139],'x11:wheat1' => [255,231,186], 'x11:lightskyblue4' => [96,123,139],'x11:grey18' => [46,46,46], 'x11:orangered4' => [139,37,0],'x11:salmon3' => [205,112,84], 'x11:white' => [255,255,255],'x11:grey100' => [255,255,255], 'x11:orange4' => [139,90,0],'x11:wheat4' => [139,126,102], 'x11:rosybrown1' => [255,193,193],'x11:grey8' => [20,20,20], 'x11:lightgoldenrod2' => [238,220,130],'x11:lightskyblue3' => [141,182,205], 'x11:violetred' => [208,32,144],'x11:blue4' => [0,0,139], 'x11:darkblue' => [0,0,139],'x11:lavenderblush3' => [205,193,197], 'x11:thistle4' => [139,123,139],'x11:hotpink1' => [255,110,180], 'x11:darkorange2' => [238,118,0],'x11:lightsalmon2' => [238,149,114], 'x11:orangered1' => [255,69,0],'x11:orangered' => [255,69,0], 'x11:burlywood1' => [255,211,155],'x11:lightgrey' => [211,211,211], 'x11:grey22' => [56,56,56],'x11:tomato4' => [139,54,38], 'x11:rosybrown3' => [205,155,155],'x11:gold2' => [238,201,0], 'x11:beige' => [245,245,220] ); # Returns a hash-ref: color-name => RGB triple sub available_names { return \%_colors; } # Returns the RGB triple for a name, undef if name not found # The name is normalized before lookup is attempted. Normalization consists # of: lowercasing and elimination of whitespace. Also, "gray" is replaced # with "grey". # If the name is prefixed with a namespace (separated by colon ':'), # only this namespace is searched. If no namespace is specified, then # the lookup occurs first in the global namespace, then in the default # namespace. sub name2rgb { my ( $name ) = @_; my ( $ns, $core, $norm ) = _normalize_name( $name ); # If explicit namespace: if( $ns ne '' ) { if( exists $_colors{ $norm } ) { return _fmt( @{ $_colors{ $norm } } ); } else { return; # Do not search further if explicit namespace is given } } # No explicit namespace if( exists $_colors{ $core } ) { return _fmt( @{ $_colors{ $core } } ); # global namespace } # No namespace, but ':' prefix: search global ONLY, but not default ns if( $core ne $norm ) { return; } $norm = get_default_namespace() . ':' . $core; if( exists $_colors{ $norm } ) { return _fmt( @{ $_colors{ $norm } } ); # default namespace } # Not found return; } # Takes a name and an RGB triple. Registers the triple for the given name. # The name will be normalized (lowercased, whitespace eliminated, 'gray' # replaced by 'grey') before assignment is made. # If the name is not prefixed by a namespace, the color will be entered # into the global namespace. # Returns the old value for the name, if the name already exists. sub register_name { my ( $name, $r, $g, $b ) = @_; my ( $ns, $core, $norm ) = _normalize_name( $name ); # If no explicit ns is given, lookup and replace for $core, which is # guaranteed not preceeded by ':'. Otherwise, use fully qualified name. my $crr = ( $ns eq '' ) ? $core : $norm; if( exists $_colors{ $crr } ) { my $old = $_colors{ $crr }; $_colors{ $crr } = [ $r, $g, $b ]; return _fmt( @$old ); } $_colors{ $crr } = [ $r, $g, $b ]; return; } sub _normalize_name { my ( $name ) = @_; $name = lc( $name ); # Lowercase $name =~ s/\s//g; # Eliminate whitespace $name =~ s/gray/grey/; # gray -> grey my ( $ns, $core ) = ( '', $name ); if( $name =~ /:/ ) { ( $ns, $core ) = split ':', $name; } return ( $ns, $core, $name ); } # Sets the default namespace. Returns the previous value. # Giving an empty string as argument makes the global namespace the default. # Note that the global namespace is initially EMPTY! sub set_default_namespace { my $old = $_default_namespace; $_default_namespace = $_[0]; return $old; } sub get_default_namespace { return $_default_namespace; } } # end BEGIN (Names) 1; __END__ # ================================================== # ++++++++++++++++++++++++++++++++++++++++++++++++++ # ================================================== =head1 NAME Graphics::ColorUtils - Easy-to-use color space conversions and more. =head1 SYNOPSIS use Graphics::ColorUtils; ( $y, $i, $q ) = rgb2yiq( $r, $g, $b ); ( $r, $g, $b ) = yiq2rgb( $y, $i, $q ); $hex_string = yiq2rgb( $y, $i, $q ); ( $c, $m, $y ) = rgb2cmy( $r, $g, $b ); ( $r, $g, $b ) = cmy2rgb( $c, $m, $y ); $hex_string = cmy2rgb( $c, $m, $y ); ( $h, $l, $s ) = rgb2hls( $r, $g, $b ); ( $r, $g, $b ) = hls2rgb( $h, $l, $s ); $hex_string = hls2rgb( $h, $l, $s ); ( $h, $s, $v ) = rgb2hsv( $r, $g, $b ); ( $r, $g, $b ) = hsv2rgb( $h, $s, $v ); $hex_string = hsv2rgb( $h, $s, $v ); # ----- use Graphics::ColorUtils qw( :gradients ); ( $r, $g, $b ) = grad2rgb( $name, $f ); # where 0.0 <= $f < 1.0 $hex_string = grad2rgb( $name, $f ); %color_count_for_gradient_name = available_gradients(); $array_ref_of_rgb_triples = gradient( $name ); $array_ref_old_grad = register_gradient( $name, $array_ref_of_rgb_triples ); # ----- use Graphics::ColorUtils qw( :names ); ( $r, $g, $b ) = name2rgb( $name ); $hex_string = name2rgb( $name ); $hash_ref_rgb_triples_for_name = available_names(); ( $old_r, $old_g, $old_b ) = register_name( $name, $r, $g, $b ); $old_hex_string = register_name( $name, $r, $g, $b ); $default_ns = get_default_namespace(); $old_ns = set_default_namespace( $new_ns ); =head1 DESCRIPTION This modules provides some utility functions to handle colors and color space conversions. The interface has been kept simple, so that most functions can be called "inline" when making calls to graphics libraries such as GD, Tk, or when generating HTML/CSS. (E.g. for GD: C<$c = $img-EcolorAllocate( hsv2rgb( 270, 0.5, 0.3 ) );>.) Features: =over 4 =item Color Space Conversions Color space conversions, in particular between the "intuitive" color spaces HSV (Hue/Saturation/Value) and HLS (Hue/Lightness/Saturation) to and from RGB (Red/Green/Blue). =item Color Lookup Color lookup by name for three standard sets of colors: WWW/CSS, SVG, and X11. =item Color Gradients Management of color gradients, which can be indexed by a floating point number in the range 0..1. (Mostly intended for false-color data visualization.) =back =head1 CONVENTIONS Legal values: Y, I, Q: 0..1 C, M, Y: 0..1 R, G, B: 0..255 (may be float on input, guaranteed int on output) H: 0..360 (red=0->yellow->green=120->cyan->blue=240->magenta steps of 60) S, V: 0..1 L, S: 0..1 All C<...2rgb> functions return a three-element array in list context, and a string formatted according to C<"#%02x%02x%02x"> (e.g. C<'#ff3a18'>) in scalar context. =head1 METHODS =head2 Color Space Conversions =over 4 =item YIQ C and C =item CMY C and C =item HSV C and C =item HLS C and C =back All these methods take a triple of values and return a triple of converted values. However, B the C<...2rgb> methods return a string formatted according to C<"#%02x%02x%02x"> (e.g. C<'#ff3a18'>). This format is appropriate e.g. for calls to Tk routines: C<$mw-Ewidget( -color => hls2rgb( 180, 0.2, 0.1 ) );>, etc. =head2 Color Names Names can be arbitrary strings. If names contain a colon (C<':'>), the part of the name before the colon is considered a "namespace" specification. Namespaces allow to have multiple color values corresponding to the same name and to control the priority in which those values will be retrieved. =over 4 =item C Returns a triple C<( $r, $g, $b )> in list context or a a hex-string in scalar context if the name has been found, C otherwise. The name is normalized before lookup is attempted. Normalization consists of: lowercasing and elimination of whitespace. Also, "gray" is replaced with "grey". If the name is prefixed with a namespace (separated by colon a C<':'>), only this namespace is searched. If no namespace is specified, then the lookup occurs first in the global namespace, then in the default namespace. =item C Returns a reference to a hash, the keys of which are the color names, and the values are references to three-element arrays of RGB values. =item C Takes a name and an RGB triple. Stores the triple for the given name. The name will be normalized (lowercased, whitespace eliminated, 'gray' replaced by 'grey') before assignment is made. If the name is not prefixed by a namespace, the color will be entered into the global namespace. Returns the old value for the name, if the name already exists, C otherwise. =item C Returns the current value of the default namespace. Note that the empty string C<''> corresponds to the I namespace. =item C Sets the default namespace. Returns the previous value. Giving an empty string as argument makes the global namespace the default. Note that the global namespace is initially I. (On startup, the default namespace is C<'x11'>.) =back =head2 Color Gradients =over 4 =item C Given the name of a gradient and a floating point number between 0 and 1, returns the color (as RGB triple or formatted hex-string) corresponding to the position in the gradient given by C<$f>. Returns C when gradient not found or C<$f> outside valid range. =item C Returns a hash, the keys of which are the names of the known gradients and the values being the number of colors in the corresponding gradient. =item C Given the name of a gradient, returns a reference to an array of RGB triples or C if the gradient is not found. =item C Takes the name of a (possibly new) gradient and a reference to an array of RGB triples. Stores the array as gradient for that name. If the gradient name already existed, returns a reference to the old array, C otherwise. =back An introduction, together with a large number of sample gradients can be found at Paul Bourke's webpage: http://local.wasp.uwa.edu.au/~pbourke/texture_colour/colourramp/ =head1 EXPORT Exports by default: rgb2yiq(), yiq2rgb() rgb2cmy(), cmy2rgb() rgb2hls(), hls2rgb() rgb2hsv(), hsv2rgb() Using the export tag C<:names>, exports the following additional methods: name2rgb() available_names() register_name() set_default_namespace() get_default_namespace() Using the export tag C<:gradients>, exports the following additional methods: gradient() grad2rgb() available_gradients() register_gradient() =head1 BUGS =over 4 =item Input parameter validation Most methods do I explicitly validate that their arguments lie in the valid range. =item Multiple namespaces Names containing multiple colons may not be handled correctly. =item Hue wrap-around While hue should be restricted to 0..360, both C and C tolerate "moderate" violation of this constraint (up to +/- 359). =back =head1 TODO =over 4 =item Perl Versions This module has only been explicitly tested with Perl 5.8, but nothing (should) prevent it from running fine with other versions of Perl. =item Additional color space conversions For instance to and from XYZ, CIE, Luv; I. =item Additional pre-defined gradients Suggestions welcome! =back =head1 SEE ALSO =head2 Related Modules =over 4 =item Color::Rgb Lookup of color values for names. Similar to the "names" methods in this module. Requires F. =item Graphics::ColorNames Lookup of color values for names. Similar to the "names" methods in this module. Does I require F. Comes with several sets of predefined color names (similar to this module). =item Graphics::ColorObject Color space conversions, including conversions to and from XYZ and Luv. Object-oriented interface requires instantiation of a "color-object" for each color, which can then provide a representation of itself in all color spaces. =item Color::Scheme Generates pleasant color schemes (sets of colors). =back =head2 Standard Color Sets =over 4 =item WWW/CSS The 16 (or 17, including "orange") colors defined by the W3: http://www.w3.org/TR/css3-color =item SVG The 138 unique named colors (140 normalized unique names) defined for SVG by the W3: http://www.w3.org/TR/SVG/types.html#ColorKeywords =item X11 The 502 unique named colors (549 normalized unique names) defined by the X11 libraries in /usr/lib/X11/rgb.txt on an X11 system =back =head2 Websites =over 4 =item * Poynton's Color FAQ: http://www.poynton.com/ColorFAQ.html =item * Paper on Color Conversion Algorithms: http://www.poynton.com/PDFs/coloureq.pdf =item * Paul Bourke's Webpage with many relevant details: http://local.wasp.uwa.edu.au/~pbourke/texture_colour/ =back =head2 Books =over 4 =item * B by James D. Foley, Andries van Dam, Steven K. Feiner, John F. Hughes (Second Edition in C, 1990, mult. print runs) I> =item * B by James D. Foley, Andries van Dam, Steven K. Feiner, John F. Hughes, Richard L. Phillips (1990, mult. print runs) I =item * B by Donald Hearn and M. Pauline Baker (2nd ed, 1997) I =back =begin IMPLEMENTATION_NOTE There were two intents that drove part of the design: - I wanted to avoid dependency on other modules as much as possible. (This is a small module, it should not have all kinds of requirements on its installation environment.) - Including the VALUES for the color names and gradients in the source file itself is certainly a somewhat contentious decision. Here is the rationale: By embedding the data directly, we avoid the issue of files missing at run-time and the required error detection and recovery code. The impact on loading the module (as compared to requiring the data files) should be minimal - the same amount of data gets read one way or the other. - And obviously I did not want to rely on the file rgb.txt to be there. That's fine for Unix, not ok elsewhere. =end IMPLEMENTATION_NOTE =head1 AUTHOR Philipp K. Janert, Ejanert at ieee dot org E, http://www.beyondcode.org =head1 COPYRIGHT AND LICENSE Copyright (C) 2006 by Philipp K. Janert This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.3 or, at your option, any later version of Perl 5 you may have available. =cut Graphics-ColorUtils-0.17/README0000644000076400001440000000160710624161261015367 0ustar janertusersGraphics-ColorUtils version 0.17 ================================ A collection of easy-to-use utilities for handling colors: - Color space conversions - Color lookup by name - Color gradients Initial Release Version (alpha) INSTALLATION To install this module type the following: perl Makefile.PL make make test make install DEPENDENCIES This module was designed to have as few dependencies as possible, in particular it does NOT rely on any specific OS or graphical environment. This module requires the standard "Carp" module. EXAMPLES AND WEBSITE Check the author's website at www.beyondcode.org. COPYRIGHT AND LICENCE Copyright (C) 2006,2007 by Philipp K. Janert This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.3 or, at your option, any later version of Perl 5 you may have available. Graphics-ColorUtils-0.17/Changes0000644000076400001440000000137110624161347016005 0ustar janertusersRevision history for Perl extension Graphics::ColorUtils. 0.17 Sun May 20 2007 - Eliminating the explicit test counter from 04gradients.t. 0.15 Thu Apr 12 2007 - Still dealing with the problem that 04gradients.t dies prematurely on some platforms. 0.11 Sun Apr 08 2007 - Adding some references to POD. - Adding a single newline at the end of 04gradients.t (!). 0.09 Sun Mar 18 2007 - Removing offending tests while searching for root cause details 0.07 Sat Mar 17 2007 - Fixing test failures on some platforms 0.05 Fri Mar 16 2007 - Fixed some documentation bugs 0.03 Fri Oct 27 2006 - Initial release version (alpha) 0.01 Wed Oct 18 15:16:05 2006 - original version; created by h2xs 1.23 with options -AX -n Graphics::ColorUtils Graphics-ColorUtils-0.17/Makefile.PL0000644000076400001440000000111510525503272016455 0ustar janertusersuse 5.008003; use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( NAME => 'Graphics::ColorUtils', VERSION_FROM => 'lib/Graphics/ColorUtils.pm', # finds $VERSION PREREQ_PM => { Carp }, # e.g., Module::Name => 1.1 ($] >= 5.005 ? ## Add these new keywords supported since 5.005 (ABSTRACT_FROM => 'lib/Graphics/ColorUtils.pm', # retrieve abstract from module AUTHOR => 'Philipp K. Janert ') : ()), ); Graphics-ColorUtils-0.17/META.yml0000644000076400001440000000054610624161717015767 0ustar janertusers# http://module-build.sourceforge.net/META-spec.html #XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX# name: Graphics-ColorUtils version: 0.17 version_from: lib/Graphics/ColorUtils.pm installdirs: site requires: Carp: distribution_type: module generated_by: ExtUtils::MakeMaker version 6.30 Graphics-ColorUtils-0.17/MANIFEST0000644000076400001440000000031110624161717015635 0ustar janertusersChanges Makefile.PL MANIFEST README t/01sanity.t t/02conversions.t t/03names.t t/04gradients.t lib/Graphics/ColorUtils.pm META.yml Module meta-data (added by MakeMaker)