eliminate use vars
[imager.git] / lib / Imager / Color.pm
CommitLineData
02d1d628 1package Imager::Color;
ee64a81f 2use 5.006;
02d1d628
AMH
3use Imager;
4use strict;
f17b46d8 5
ee64a81f 6our $VERSION = "1.013";
02d1d628
AMH
7
8# It's just a front end to the XS creation functions.
9
faa9b3e7 10# used in converting hsv to rgb
bb138da3 11my @hsv_map =
faa9b3e7
TC
12 (
13 'vkm', 'nvm', 'mvk', 'mnv', 'kmv', 'vmn'
14 );
15
16sub _hsv_to_rgb {
17 my ($hue, $sat, $val) = @_;
18
bb138da3 19 # HSV conversions from pages 401-403 "Procedural Elements for Computer
faa9b3e7
TC
20 # Graphics", 1985, ISBN 0-07-053534-5.
21
22 my @result;
23 if ($sat <= 0) {
24 return ( 255 * $val, 255 * $val, 255 * $val );
25 }
26 else {
27 $val >= 0 or $val = 0;
28 $val <= 1 or $val = 1;
29 $sat <= 1 or $sat = 1;
30 $hue >= 360 and $hue %= 360;
31 $hue < 0 and $hue += 360;
32 $hue /= 60.0;
33 my $i = int($hue);
34 my $f = $hue - $i;
35 $val *= 255;
36 my $m = $val * (1.0 - $sat);
37 my $n = $val * (1.0 - $sat * $f);
38 my $k = $val * (1.0 - $sat * (1 - $f));
39 my $v = $val;
9d540150 40 my %fields = ( 'm'=>$m, 'n'=>$n, 'v'=>$v, 'k'=>$k, );
faa9b3e7
TC
41 return @fields{split //, $hsv_map[$i]};
42 }
43}
44
45# cache of loaded gimp files
08af8ecb 46# each key is a filename, under each key is a hashref with the following
faa9b3e7
TC
47# keys:
48# mod_time => last mod_time of file
49# colors => hashref name to arrayref of colors
50my %gimp_cache;
51
52# palette search locations
53# this is pretty rude
54# $HOME is replaced at runtime
55my @gimp_search =
56 (
57 '$HOME/.gimp-1.2/palettes/Named_Colors',
58 '$HOME/.gimp-1.1/palettes/Named_Colors',
59 '$HOME/.gimp/palettes/Named_Colors',
60 '/usr/share/gimp/1.2/palettes/Named_Colors',
61 '/usr/share/gimp/1.1/palettes/Named_Colors',
62 '/usr/share/gimp/palettes/Named_Colors',
63 );
64
173c91ba
TC
65my $default_gimp_palette;
66
faa9b3e7
TC
67sub _load_gimp_palette {
68 my ($filename) = @_;
69
70 if (open PAL, "< $filename") {
71 my $hdr = <PAL>;
72 chomp $hdr;
73 unless ($hdr =~ /GIMP Palette/) {
74 close PAL;
75 $Imager::ERRSTR = "$filename is not a GIMP palette file";
76 return;
77 }
78 my $line;
79 my %pal;
80 my $mod_time = (stat PAL)[9];
81 while (defined($line = <PAL>)) {
82 next if $line =~ /^#/ || $line =~ /^\s*$/;
83 chomp $line;
84 my ($r,$g, $b, $name) = split ' ', $line, 4;
85 if ($name) {
86 $name =~ s/\s*\([\d\s]+\)\s*$//;
87 $pal{lc $name} = [ $r, $g, $b ];
88 }
89 }
90 close PAL;
91
92 $gimp_cache{$filename} = { mod_time=>$mod_time, colors=>\%pal };
93
94 return 1;
95 }
96 else {
97 $Imager::ERRSTR = "Cannot open palette file $filename: $!";
98 return;
99 }
100}
101
102sub _get_gimp_color {
103 my %args = @_;
104
105 my $filename;
106 if ($args{palette}) {
107 $filename = $args{palette};
108 }
173c91ba
TC
109 elsif (defined $default_gimp_palette) {
110 # don't search again and again and again ...
111 if (!length $default_gimp_palette
112 || !-f $default_gimp_palette) {
113 $Imager::ERRSTR = "No GIMP palette found";
114 $default_gimp_palette = "";
115 return;
116 }
117
118 $filename = $default_gimp_palette;
119 }
faa9b3e7
TC
120 else {
121 # try to make one up - this is intended to die if tainting is
122 # enabled and $ENV{HOME} is tainted. To avoid that untaint $ENV{HOME}
123 # or set the palette parameter
124 for my $attempt (@gimp_search) {
125 my $work = $attempt; # don't modify the source array
3d782fde
TC
126 $work =~ /\$HOME/ && !defined $ENV{HOME}
127 and next;
faa9b3e7
TC
128 $work =~ s/\$HOME/$ENV{HOME}/;
129 if (-e $work) {
130 $filename = $work;
131 last;
132 }
133 }
134 if (!$filename) {
135 $Imager::ERRSTR = "No GIMP palette found";
173c91ba 136 $default_gimp_palette = "";
faa9b3e7
TC
137 return ();
138 }
173c91ba
TC
139
140 $default_gimp_palette = $filename;
faa9b3e7
TC
141 }
142
bb138da3 143 if ((!$gimp_cache{$filename}
faa9b3e7
TC
144 || (stat $filename)[9] != $gimp_cache{$filename})
145 && !_load_gimp_palette($filename)) {
146 return ();
147 }
148
149 if (!$gimp_cache{$filename}{colors}{lc $args{name}}) {
150 $Imager::ERRSTR = "Color '$args{name}' isn't in $filename";
151 return ();
152 }
153
154 return @{$gimp_cache{$filename}{colors}{lc $args{name}}};
155}
156
bb138da3 157my @x_search =
faa9b3e7 158 (
d034a178 159 '/usr/share/X11/rgb.txt', # newer Xorg X11 dists use this
faa9b3e7
TC
160 '/usr/lib/X11/rgb.txt', # seems fairly standard
161 '/usr/local/lib/X11/rgb.txt', # seems possible
162 '/usr/X11R6/lib/X11/rgb.txt', # probably the same as the first
08af8ecb
AMH
163 '/usr/openwin/lib/rgb.txt',
164 '/usr/openwin/lib/X11/rgb.txt',
faa9b3e7
TC
165 );
166
173c91ba
TC
167my $default_x_rgb;
168
d034a178
TC
169# called by the test code to check if we can test this stuff
170sub _test_x_palettes {
171 @x_search;
172}
173
faa9b3e7
TC
174# x rgb.txt cache
175# same structure as %gimp_cache
176my %x_cache;
177
178sub _load_x_rgb {
179 my ($filename) = @_;
180
181 local *RGB;
182 if (open RGB, "< $filename") {
183 my $line;
184 my %pal;
185 my $mod_time = (stat RGB)[9];
186 while (defined($line = <RGB>)) {
187 # the version of rgb.txt supplied with GNU Emacs uses # for comments
188 next if $line =~ /^[!#]/ || $line =~ /^\s*$/;
189 chomp $line;
190 my ($r,$g, $b, $name) = split ' ', $line, 4;
191 if ($name) {
192 $pal{lc $name} = [ $r, $g, $b ];
193 }
194 }
195 close RGB;
196
197 $x_cache{$filename} = { mod_time=>$mod_time, colors=>\%pal };
198
199 return 1;
200 }
201 else {
202 $Imager::ERRSTR = "Cannot open palette file $filename: $!";
203 return;
204 }
205}
206
207sub _get_x_color {
208 my %args = @_;
209
210 my $filename;
211 if ($args{palette}) {
212 $filename = $args{palette};
213 }
173c91ba
TC
214 elsif (defined $default_x_rgb) {
215 unless (length $default_x_rgb) {
216 $Imager::ERRSTR = "No X rgb.txt palette found";
217 return ();
218 }
219 $filename = $default_x_rgb;
220 }
faa9b3e7
TC
221 else {
222 for my $attempt (@x_search) {
223 if (-e $attempt) {
224 $filename = $attempt;
225 last;
226 }
227 }
228 if (!$filename) {
229 $Imager::ERRSTR = "No X rgb.txt palette found";
173c91ba 230 $default_x_rgb = "";
faa9b3e7
TC
231 return ();
232 }
233 }
234
bb138da3 235 if ((!$x_cache{$filename}
173c91ba 236 || (stat $filename)[9] != $x_cache{$filename}{mod_time})
faa9b3e7
TC
237 && !_load_x_rgb($filename)) {
238 return ();
239 }
240
173c91ba
TC
241 $default_x_rgb = $filename;
242
faa9b3e7
TC
243 if (!$x_cache{$filename}{colors}{lc $args{name}}) {
244 $Imager::ERRSTR = "Color '$args{name}' isn't in $filename";
245 return ();
246 }
247
248 return @{$x_cache{$filename}{colors}{lc $args{name}}};
249}
02d1d628
AMH
250
251# Parse color spec into an a set of 4 colors
252
d5556805 253sub _pspec {
faa9b3e7
TC
254 return (@_,255) if @_ == 3 && !grep /[^\d.+eE-]/, @_;
255 return (@_ ) if @_ == 4 && !grep /[^\d.+eE-]/, @_;
bb138da3 256 if ($_[0] =~
02d1d628
AMH
257 /^\#?([\da-f][\da-f])([\da-f][\da-f])([\da-f][\da-f])([\da-f][\da-f])/i) {
258 return (hex($1),hex($2),hex($3),hex($4));
259 }
260 if ($_[0] =~ /^\#?([\da-f][\da-f])([\da-f][\da-f])([\da-f][\da-f])/i) {
261 return (hex($1),hex($2),hex($3),255);
262 }
faa9b3e7
TC
263 if ($_[0] =~ /^\#([\da-f])([\da-f])([\da-f])$/i) {
264 return (hex($1) * 17, hex($2) * 17, hex($3) * 17, 255);
265 }
266 my %args;
267 if (@_ == 1) {
268 # a named color
269 %args = ( name => @_ );
270 }
271 else {
272 %args = @_;
273 }
274 my @result;
275 if (exists $args{gray}) {
276 @result = $args{gray};
277 }
278 elsif (exists $args{grey}) {
279 @result = $args{grey};
280 }
bb138da3 281 elsif ((exists $args{red} || exists $args{r})
faa9b3e7
TC
282 && (exists $args{green} || exists $args{g})
283 && (exists $args{blue} || exists $args{b})) {
284 @result = ( exists $args{red} ? $args{red} : $args{r},
285 exists $args{green} ? $args{green} : $args{g},
286 exists $args{blue} ? $args{blue} : $args{b} );
287 }
bb138da3 288 elsif ((exists $args{hue} || exists $args{h})
faa9b3e7
TC
289 && (exists $args{saturation} || exists $args{'s'})
290 && (exists $args{value} || exists $args{v})) {
291 my $hue = exists $args{hue} ? $args{hue} : $args{h};
292 my $sat = exists $args{saturation} ? $args{saturation} : $args{'s'};
293 my $val = exists $args{value} ? $args{value} : $args{v};
08af8ecb 294
faa9b3e7
TC
295 @result = _hsv_to_rgb($hue, $sat, $val);
296 }
297 elsif (exists $args{web}) {
298 if ($args{web} =~ /^#?([\da-f][\da-f])([\da-f][\da-f])([\da-f][\da-f])$/i) {
299 @result = (hex($1),hex($2),hex($3));
300 }
301 elsif ($args{web} =~ /^#?([\da-f])([\da-f])([\da-f])$/i) {
302 @result = (hex($1) * 17, hex($2) * 17, hex($3) * 17);
303 }
304 }
305 elsif ($args{name}) {
306 unless (@result = _get_gimp_color(%args)) {
307 unless (@result = _get_x_color(%args)) {
1c00d65b
TC
308 require Imager::Color::Table;
309 unless (@result = Imager::Color::Table->get($args{name})) {
310 $Imager::ERRSTR = "No color named $args{name} found";
311 return ();
312 }
faa9b3e7
TC
313 }
314 }
315 }
316 elsif ($args{gimp}) {
317 @result = _get_gimp_color(name=>$args{gimp}, %args);
318 }
319 elsif ($args{xname}) {
320 @result = _get_x_color(name=>$args{xname}, %args);
321 }
1c00d65b
TC
322 elsif ($args{builtin}) {
323 require Imager::Color::Table;
324 @result = Imager::Color::Table->get($args{builtin});
325 }
faa9b3e7
TC
326 elsif ($args{rgb}) {
327 @result = @{$args{rgb}};
328 }
329 elsif ($args{rgba}) {
330 @result = @{$args{rgba}};
331 return @result if @result == 4;
332 }
333 elsif ($args{hsv}) {
334 @result = _hsv_to_rgb(@{$args{hsv}});
335 }
336 elsif ($args{channels}) {
d1baf8e4
TC
337 my @ch = @{$args{channels}};
338 return ( @ch, (0) x (4 - @ch) );
faa9b3e7
TC
339 }
340 elsif (exists $args{channel0} || $args{c0}) {
341 my $i = 0;
342 while (exists $args{"channel$i"} || exists $args{"c$i"}) {
bb138da3 343 push(@result,
faa9b3e7
TC
344 exists $args{"channel$i"} ? $args{"channel$i"} : $args{"c$i"});
345 ++$i;
346 }
347 }
348 else {
349 $Imager::ERRSTR = "No color specification found";
350 return ();
351 }
352 if (@result) {
353 if (exists $args{alpha} || exists $args{a}) {
354 push(@result, exists $args{alpha} ? $args{alpha} : $args{a});
355 }
356 while (@result < 4) {
357 push(@result, 255);
358 }
359 return @result;
360 }
02d1d628
AMH
361 return ();
362}
363
02d1d628
AMH
364sub new {
365 shift; # get rid of class name.
d5556805 366 my @arg = _pspec(@_);
02d1d628
AMH
367 return @arg ? new_internal($arg[0],$arg[1],$arg[2],$arg[3]) : ();
368}
369
370sub set {
371 my $self = shift;
d5556805 372 my @arg = _pspec(@_);
02d1d628
AMH
373 return @arg ? set_internal($self, $arg[0],$arg[1],$arg[2],$arg[3]) : ();
374}
375
5f8cbeac
TC
376sub equals {
377 my ($self, %opts) = @_;
378
379 my $other = $opts{other}
380 or return Imager->_set_error("'other' parameter required");
381 my $ignore_alpha = $opts{ignore_alpha} || 0;
382
383 my @left = $self->rgba;
384 my @right = $other->rgba;
385 my $last_chan = $ignore_alpha ? 2 : 3;
386 for my $ch (0 .. $last_chan) {
387 $left[$ch] == $right[$ch]
388 or return;
389 }
bb138da3 390
5f8cbeac
TC
391 return 1;
392}
393
ffddd407
TC
394sub CLONE_SKIP { 1 }
395
bb138da3 396# Lifted from Graphics::Color::RGB
d5fb1fdf
PG
397# Thank you very much
398sub hsv {
399 my( $self ) = @_;
400
401 my( $red, $green, $blue, $alpha ) = $self->rgba;
402 my $max = $red;
403 my $maxc = 'r';
404 my $min = $red;
405
406 if($green > $max) {
bb138da3
TC
407 $max = $green;
408 $maxc = 'g';
d5fb1fdf
PG
409 }
410 if($blue > $max) {
bb138da3
TC
411 $max = $blue;
412 $maxc = 'b';
d5fb1fdf
PG
413 }
414
415 if($green < $min) {
bb138da3 416 $min = $green;
d5fb1fdf
PG
417 }
418 if($blue < $min) {
bb138da3 419 $min = $blue;
d5fb1fdf
PG
420 }
421
422 my ($h, $s, $v);
423
424 if($max == $min) {
425 $h = 0;
bb138da3 426 }
d5fb1fdf
PG
427 elsif($maxc eq 'r') {
428 $h = 60 * (($green - $blue) / ($max - $min)) % 360;
bb138da3 429 }
d5fb1fdf
PG
430 elsif($maxc eq 'g') {
431 $h = (60 * (($blue - $red) / ($max - $min)) + 120);
bb138da3 432 }
d5fb1fdf
PG
433 elsif($maxc eq 'b') {
434 $h = (60 * (($red - $green) / ($max - $min)) + 240);
435 }
436
437 $v = $max/255;
438 if($max == 0) {
439 $s = 0;
bb138da3 440 }
d5fb1fdf
PG
441 else {
442 $s = 1 - ($min / $max);
443 }
444
445 return int($h), $s, $v, $alpha;
446
447}
448
02d1d628
AMH
4491;
450
451__END__
452
453=head1 NAME
454
455Imager::Color - Color handling for Imager.
456
457=head1 SYNOPSIS
458
668c4f62
TC
459 use Imager;
460
02d1d628
AMH
461 $color = Imager::Color->new($red, $green, $blue);
462 $color = Imager::Color->new($red, $green, $blue, $alpha);
463 $color = Imager::Color->new("#C0C0FF"); # html color specification
464
465 $color->set($red, $green, $blue);
466 $color->set($red, $green, $blue, $alpha);
467 $color->set("#C0C0FF"); # html color specification
468
469 ($red, $green, $blue, $alpha) = $color->rgba();
d5fb1fdf 470 @hsv = $color->hsv();
02d1d628
AMH
471
472 $color->info();
473
bb138da3 474 if ($color->equals(other=>$other_color)) {
5f8cbeac
TC
475 ...
476 }
477
02d1d628
AMH
478
479=head1 DESCRIPTION
480
5715f7c3
TC
481This module handles creating color objects used by Imager. The idea
482is that in the future this module will be able to handle color space
483calculations as well.
02d1d628 484
0462442b
TC
485An Imager color consists of up to four components, each in the range 0
486to 255. Unfortunately the meaning of the components can change
487depending on the type of image you're dealing with:
488
489=over
490
491=item *
492
493for 3 or 4 channel images the color components are red, green, blue,
494alpha.
495
496=item *
497
498for 1 or 2 channel images the color components are gray, alpha, with
499the other two components ignored.
500
501=back
502
503An alpha value of zero is fully transparent, an alpha value of 255 is
504fully opaque.
505
42f8a929 506=head1 METHODS
0462442b 507
02d1d628
AMH
508=over 4
509
510=item new
511
512This creates a color object to pass to functions that need a color argument.
513
514=item set
515
516This changes an already defined color. Note that this does not affect any places
517where the color has been used previously.
518
5715f7c3 519=item rgba()
02d1d628 520
5715f7c3
TC
521This returns the red, green, blue and alpha channels of the color the
522object contains.
02d1d628
AMH
523
524=item info
525
5715f7c3 526Calling info merely dumps the relevant color to the log.
02d1d628 527
5f8cbeac
TC
528=item equals(other=>$other_color)
529
530=item equals(other=>$other_color, ignore_alpha=>1)
531
532Compares $self and color $other_color returning true if the color
533components are the same.
534
535Compares all four channels unless C<ignore_alpha> is set. If
536C<ignore_alpha> is set only the first three channels are compared.
537
02d1d628
AMH
538=back
539
faa9b3e7
TC
540You can specify colors in several different ways, you can just supply
541simple values:
542
543=over
544
545=item *
546
547simple numeric parameters - if you supply 3 or 4 numeric arguments, you get a color made up of those RGB (and possibly A) components.
548
549=item *
550
5715f7c3 551a six hex digit web color, either C<RRGGBB> or C<#RRGGBB>
faa9b3e7
TC
552
553=item *
554
5715f7c3 555an eight hex digit web color, either C<RRGGBBAA> or C<#RRGGBBAA>.
faa9b3e7
TC
556
557=item *
558
5715f7c3 559a 3 hex digit web color, C<#RGB> - a value of F becomes 255.
faa9b3e7
TC
560
561=item *
562
5715f7c3
TC
563a color name, from whichever of the gimp C<Named_Colors> file or X
564C<rgb.txt> is found first. The same as using the C<name> keyword.
faa9b3e7
TC
565
566=back
567
568You can supply named parameters:
569
570=over
571
572=item *
573
574'red', 'green' and 'blue', optionally shortened to 'r', 'g' and 'b'.
575The color components in the range 0 to 255.
576
577 # all of the following are equivalent
578 my $c1 = Imager::Color->new(red=>100, blue=>255, green=>0);
579 my $c2 = Imager::Color->new(r=>100, b=>255, g=>0);
580 my $c3 = Imager::Color->new(r=>100, blue=>255, g=>0);
581
582=item *
583
5715f7c3
TC
584C<hue>, C<saturation> and C<value>, optionally shortened to C<h>, C<s> and
585C<v>, to specify a HSV color. 0 <= hue < 360, 0 <= s <= 1 and 0 <= v
faa9b3e7
TC
586<= 1.
587
588 # the same as RGB(127,255,127)
589 my $c1 = Imager::Color->new(hue=>120, v=>1, s=>0.5);
590 my $c1 = Imager::Color->new(hue=>120, value=>1, saturation=>0.5);
591
592=item *
593
5715f7c3
TC
594C<web>, which can specify a 6 or 3 hex digit web color, in any of the
595forms C<#RRGGBB>, C<#RGB>, C<RRGGBB> or C<RGB>.
faa9b3e7
TC
596
597 my $c1 = Imager::Color->new(web=>'#FFC0C0'); # pale red
598
599=item *
600
5715f7c3 601C<gray> or C<grey> which specifies a single channel, from 0 to 255.
faa9b3e7
TC
602
603 # exactly the same
604 my $c1 = Imager::Color->new(gray=>128);
605 my $c1 = Imager::Color->new(grey=>128);
606
607=item *
608
5715f7c3 609C<rgb> which takes a 3 member arrayref, containing each of the red,
faa9b3e7
TC
610green and blue values.
611
612 # the same
613 my $c1 = Imager::Color->new(rgb=>[255, 100, 0]);
614 my $c1 = Imager::Color->new(r=>255, g=>100, b=>0);
615
616=item *
617
5715f7c3 618C<hsv> which takes a 3 member arrayref, containing each of hue,
faa9b3e7
TC
619saturation and value.
620
621 # the same
622 my $c1 = Imager::Color->new(hsv=>[120, 0.5, 1]);
623 my $c1 = Imager::Color->new(hue=>120, v=>1, s=>0.5);
624
625=item *
626
5715f7c3
TC
627C<gimp> which specifies a color from a GIMP palette file. You can
628specify the file name of the palette file with the 'palette'
629parameter, or let Imager::Color look in various places, typically
630C<$HOME/gimp-1.x/palettes/Named_Colors> with and without the version
631number, and in C</usr/share/gimp/palettes/>. The palette file must
632have color names.
faa9b3e7
TC
633
634 my $c1 = Imager::Color->new(gimp=>'snow');
635 my $c1 = Imager::Color->new(gimp=>'snow', palette=>'testimg/test_gimp_pal);
636
637=item *
638
5715f7c3
TC
639C<xname> which specifies a color from an X11 C<rgb.txt> file. You can
640specify the file name of the C<rgb.txt> file with the C<palette>
641parameter, or let Imager::Color look in various places, typically
642C</usr/lib/X11/rgb.txt>.
faa9b3e7
TC
643
644 my $c1 = Imager::Color->new(xname=>'blue') # usually RGB(0, 0, 255)
645
646=item *
647
5715f7c3 648C<builtin> which specifies a color from the built-in color table in
1c00d65b 649Imager::Color::Table. The colors in this module are the same as the
5715f7c3 650default X11 C<rgb.txt> file.
1c00d65b
TC
651
652 my $c1 = Imager::Color->new(builtin=>'black') # always RGB(0, 0, 0)
653
654=item *
655
5715f7c3
TC
656C<name> which specifies a name from either a GIMP palette, an X
657C<rgb.txt> file or the built-in color table, whichever is found first.
faa9b3e7
TC
658
659=item *
660
661'channel0', 'channel1', etc, each of which specifies a single channel. These can be abbreviated to 'c0', 'c1' etc.
662
bb138da3 663=item *
faa9b3e7
TC
664
665'channels' which takes an arrayref of the channel values.
666
667=back
668
669Optionally you can add an alpha channel to a color with the 'alpha' or
670'a' parameter.
671
672These color specifications can be used for both constructing new
673colors with the new() method and modifying existing colors with the
674set() method.
675
d5fb1fdf
PG
676=head1 METHODS
677
d2549cc4
TC
678=over
679
680=item hsv()
d5fb1fdf 681
d2549cc4 682 my($h, $s, $v, $alpha) = $color->hsv();
d5fb1fdf 683
d2549cc4
TC
684Returns the color as a Hue/Saturation/Value/Alpha tuple.
685
0231b97e
TC
686=item red
687
688=item green
689
690=item blue
691
692=item alpha
693
694Returns the respective component as an integer from 0 to 255.
695
d2549cc4 696=back
d5fb1fdf 697
02d1d628
AMH
698=head1 AUTHOR
699
700Arnar M. Hrafnkelsson, addi@umich.edu
5715f7c3 701And a great deal of help from others - see the C<README> for a complete
02d1d628
AMH
702list.
703
704=head1 SEE ALSO
705
0462442b 706Imager(3), Imager::Color
8f22b8d8 707http://imager.perl.org/
02d1d628
AMH
708
709=cut