9 # It's just a front end to the XS creation functions.
11 # used in converting hsv to rgb
14 'vkm', 'nvm', 'mvk', 'mnv', 'kmv', 'vmn'
18 my ($hue, $sat, $val) = @_;
20 # HSV conversions from pages 401-403 "Procedural Elements for Computer
21 # Graphics", 1985, ISBN 0-07-053534-5.
25 return ( 255 * $val, 255 * $val, 255 * $val );
28 $val >= 0 or $val = 0;
29 $val <= 1 or $val = 1;
30 $sat <= 1 or $sat = 1;
31 $hue >= 360 and $hue %= 360;
32 $hue < 0 and $hue += 360;
37 my $m = $val * (1.0 - $sat);
38 my $n = $val * (1.0 - $sat * $f);
39 my $k = $val * (1.0 - $sat * (1 - $f));
41 my %fields = ( 'm'=>$m, 'n'=>$n, 'v'=>$v, 'k'=>$k, );
42 return @fields{split //, $hsv_map[$i]};
46 # cache of loaded gimp files
47 # each key is a filename, under each key is a hashref with the following
49 # mod_time => last mod_time of file
50 # colors => hashref name to arrayref of colors
53 # palette search locations
55 # $HOME is replaced at runtime
58 '$HOME/.gimp-1.2/palettes/Named_Colors',
59 '$HOME/.gimp-1.1/palettes/Named_Colors',
60 '$HOME/.gimp/palettes/Named_Colors',
61 '/usr/share/gimp/1.2/palettes/Named_Colors',
62 '/usr/share/gimp/1.1/palettes/Named_Colors',
63 '/usr/share/gimp/palettes/Named_Colors',
66 my $default_gimp_palette;
68 sub _load_gimp_palette {
71 if (open PAL, "< $filename") {
74 unless ($hdr =~ /GIMP Palette/) {
76 $Imager::ERRSTR = "$filename is not a GIMP palette file";
81 my $mod_time = (stat PAL)[9];
82 while (defined($line = <PAL>)) {
83 next if $line =~ /^#/ || $line =~ /^\s*$/;
85 my ($r,$g, $b, $name) = split ' ', $line, 4;
87 $name =~ s/\s*\([\d\s]+\)\s*$//;
88 $pal{lc $name} = [ $r, $g, $b ];
93 $gimp_cache{$filename} = { mod_time=>$mod_time, colors=>\%pal };
98 $Imager::ERRSTR = "Cannot open palette file $filename: $!";
103 sub _get_gimp_color {
107 if ($args{palette}) {
108 $filename = $args{palette};
110 elsif (defined $default_gimp_palette) {
111 # don't search again and again and again ...
112 if (!length $default_gimp_palette
113 || !-f $default_gimp_palette) {
114 $Imager::ERRSTR = "No GIMP palette found";
115 $default_gimp_palette = "";
119 $filename = $default_gimp_palette;
122 # try to make one up - this is intended to die if tainting is
123 # enabled and $ENV{HOME} is tainted. To avoid that untaint $ENV{HOME}
124 # or set the palette parameter
125 for my $attempt (@gimp_search) {
126 my $work = $attempt; # don't modify the source array
127 $work =~ /\$HOME/ && !defined $ENV{HOME}
129 $work =~ s/\$HOME/$ENV{HOME}/;
136 $Imager::ERRSTR = "No GIMP palette found";
137 $default_gimp_palette = "";
141 $default_gimp_palette = $filename;
144 if ((!$gimp_cache{$filename}
145 || (stat $filename)[9] != $gimp_cache{$filename})
146 && !_load_gimp_palette($filename)) {
150 if (!$gimp_cache{$filename}{colors}{lc $args{name}}) {
151 $Imager::ERRSTR = "Color '$args{name}' isn't in $filename";
155 return @{$gimp_cache{$filename}{colors}{lc $args{name}}};
160 '/usr/share/X11/rgb.txt', # newer Xorg X11 dists use this
161 '/usr/lib/X11/rgb.txt', # seems fairly standard
162 '/usr/local/lib/X11/rgb.txt', # seems possible
163 '/usr/X11R6/lib/X11/rgb.txt', # probably the same as the first
164 '/usr/openwin/lib/rgb.txt',
165 '/usr/openwin/lib/X11/rgb.txt',
170 # called by the test code to check if we can test this stuff
171 sub _test_x_palettes {
176 # same structure as %gimp_cache
183 if (open RGB, "< $filename") {
186 my $mod_time = (stat RGB)[9];
187 while (defined($line = <RGB>)) {
188 # the version of rgb.txt supplied with GNU Emacs uses # for comments
189 next if $line =~ /^[!#]/ || $line =~ /^\s*$/;
191 my ($r,$g, $b, $name) = split ' ', $line, 4;
193 $pal{lc $name} = [ $r, $g, $b ];
198 $x_cache{$filename} = { mod_time=>$mod_time, colors=>\%pal };
203 $Imager::ERRSTR = "Cannot open palette file $filename: $!";
212 if ($args{palette}) {
213 $filename = $args{palette};
215 elsif (defined $default_x_rgb) {
216 unless (length $default_x_rgb) {
217 $Imager::ERRSTR = "No X rgb.txt palette found";
220 $filename = $default_x_rgb;
223 for my $attempt (@x_search) {
225 $filename = $attempt;
230 $Imager::ERRSTR = "No X rgb.txt palette found";
236 if ((!$x_cache{$filename}
237 || (stat $filename)[9] != $x_cache{$filename}{mod_time})
238 && !_load_x_rgb($filename)) {
242 $default_x_rgb = $filename;
244 if (!$x_cache{$filename}{colors}{lc $args{name}}) {
245 $Imager::ERRSTR = "Color '$args{name}' isn't in $filename";
249 return @{$x_cache{$filename}{colors}{lc $args{name}}};
252 # Parse color spec into an a set of 4 colors
255 return (@_,255) if @_ == 3 && !grep /[^\d.+eE-]/, @_;
256 return (@_ ) if @_ == 4 && !grep /[^\d.+eE-]/, @_;
258 /^\#?([\da-f][\da-f])([\da-f][\da-f])([\da-f][\da-f])([\da-f][\da-f])/i) {
259 return (hex($1),hex($2),hex($3),hex($4));
261 if ($_[0] =~ /^\#?([\da-f][\da-f])([\da-f][\da-f])([\da-f][\da-f])/i) {
262 return (hex($1),hex($2),hex($3),255);
264 if ($_[0] =~ /^\#([\da-f])([\da-f])([\da-f])$/i) {
265 return (hex($1) * 17, hex($2) * 17, hex($3) * 17, 255);
270 %args = ( name => @_ );
276 if (exists $args{gray}) {
277 @result = $args{gray};
279 elsif (exists $args{grey}) {
280 @result = $args{grey};
282 elsif ((exists $args{red} || exists $args{r})
283 && (exists $args{green} || exists $args{g})
284 && (exists $args{blue} || exists $args{b})) {
285 @result = ( exists $args{red} ? $args{red} : $args{r},
286 exists $args{green} ? $args{green} : $args{g},
287 exists $args{blue} ? $args{blue} : $args{b} );
289 elsif ((exists $args{hue} || exists $args{h})
290 && (exists $args{saturation} || exists $args{'s'})
291 && (exists $args{value} || exists $args{v})) {
292 my $hue = exists $args{hue} ? $args{hue} : $args{h};
293 my $sat = exists $args{saturation} ? $args{saturation} : $args{'s'};
294 my $val = exists $args{value} ? $args{value} : $args{v};
296 @result = _hsv_to_rgb($hue, $sat, $val);
298 elsif (exists $args{web}) {
299 if ($args{web} =~ /^#?([\da-f][\da-f])([\da-f][\da-f])([\da-f][\da-f])$/i) {
300 @result = (hex($1),hex($2),hex($3));
302 elsif ($args{web} =~ /^#?([\da-f])([\da-f])([\da-f])$/i) {
303 @result = (hex($1) * 17, hex($2) * 17, hex($3) * 17);
306 elsif ($args{name}) {
307 unless (@result = _get_gimp_color(%args)) {
308 unless (@result = _get_x_color(%args)) {
309 require Imager::Color::Table;
310 unless (@result = Imager::Color::Table->get($args{name})) {
311 $Imager::ERRSTR = "No color named $args{name} found";
317 elsif ($args{gimp}) {
318 @result = _get_gimp_color(name=>$args{gimp}, %args);
320 elsif ($args{xname}) {
321 @result = _get_x_color(name=>$args{xname}, %args);
323 elsif ($args{builtin}) {
324 require Imager::Color::Table;
325 @result = Imager::Color::Table->get($args{builtin});
328 @result = @{$args{rgb}};
330 elsif ($args{rgba}) {
331 @result = @{$args{rgba}};
332 return @result if @result == 4;
335 @result = _hsv_to_rgb(@{$args{hsv}});
337 elsif ($args{channels}) {
338 my @ch = @{$args{channels}};
339 return ( @ch, (0) x (4 - @ch) );
341 elsif (exists $args{channel0} || $args{c0}) {
343 while (exists $args{"channel$i"} || exists $args{"c$i"}) {
345 exists $args{"channel$i"} ? $args{"channel$i"} : $args{"c$i"});
350 $Imager::ERRSTR = "No color specification found";
354 if (exists $args{alpha} || exists $args{a}) {
355 push(@result, exists $args{alpha} ? $args{alpha} : $args{a});
357 while (@result < 4) {
366 shift; # get rid of class name.
367 my @arg = _pspec(@_);
368 return @arg ? new_internal($arg[0],$arg[1],$arg[2],$arg[3]) : ();
373 my @arg = _pspec(@_);
374 return @arg ? set_internal($self, $arg[0],$arg[1],$arg[2],$arg[3]) : ();
378 my ($self, %opts) = @_;
380 my $other = $opts{other}
381 or return Imager->_set_error("'other' parameter required");
382 my $ignore_alpha = $opts{ignore_alpha} || 0;
384 my @left = $self->rgba;
385 my @right = $other->rgba;
386 my $last_chan = $ignore_alpha ? 2 : 3;
387 for my $ch (0 .. $last_chan) {
388 $left[$ch] == $right[$ch]
397 # Lifted from Graphics::Color::RGB
398 # Thank you very much
402 my( $red, $green, $blue, $alpha ) = $self->rgba;
428 elsif($maxc eq 'r') {
429 $h = 60 * (($green - $blue) / ($max - $min)) % 360;
431 elsif($maxc eq 'g') {
432 $h = (60 * (($blue - $red) / ($max - $min)) + 120);
434 elsif($maxc eq 'b') {
435 $h = (60 * (($red - $green) / ($max - $min)) + 240);
443 $s = 1 - ($min / $max);
446 return int($h), $s, $v, $alpha;
456 Imager::Color - Color handling for Imager.
462 $color = Imager::Color->new($red, $green, $blue);
463 $color = Imager::Color->new($red, $green, $blue, $alpha);
464 $color = Imager::Color->new("#C0C0FF"); # html color specification
466 $color->set($red, $green, $blue);
467 $color->set($red, $green, $blue, $alpha);
468 $color->set("#C0C0FF"); # html color specification
470 ($red, $green, $blue, $alpha) = $color->rgba();
471 @hsv = $color->hsv();
475 if ($color->equals(other=>$other_color)) {
482 This module handles creating color objects used by Imager. The idea
483 is that in the future this module will be able to handle color space
484 calculations as well.
486 An Imager color consists of up to four components, each in the range 0
487 to 255. Unfortunately the meaning of the components can change
488 depending on the type of image you're dealing with:
494 for 3 or 4 channel images the color components are red, green, blue,
499 for 1 or 2 channel images the color components are gray, alpha, with
500 the other two components ignored.
504 An alpha value of zero is fully transparent, an alpha value of 255 is
513 This creates a color object to pass to functions that need a color argument.
517 This changes an already defined color. Note that this does not affect any places
518 where the color has been used previously.
522 This returns the red, green, blue and alpha channels of the color the
527 Calling info merely dumps the relevant color to the log.
529 =item equals(other=>$other_color)
531 =item equals(other=>$other_color, ignore_alpha=>1)
533 Compares $self and color $other_color returning true if the color
534 components are the same.
536 Compares all four channels unless C<ignore_alpha> is set. If
537 C<ignore_alpha> is set only the first three channels are compared.
541 You can specify colors in several different ways, you can just supply
548 simple numeric parameters - if you supply 3 or 4 numeric arguments, you get a color made up of those RGB (and possibly A) components.
552 a six hex digit web color, either C<RRGGBB> or C<#RRGGBB>
556 an eight hex digit web color, either C<RRGGBBAA> or C<#RRGGBBAA>.
560 a 3 hex digit web color, C<#RGB> - a value of F becomes 255.
564 a color name, from whichever of the gimp C<Named_Colors> file or X
565 C<rgb.txt> is found first. The same as using the C<name> keyword.
569 You can supply named parameters:
575 'red', 'green' and 'blue', optionally shortened to 'r', 'g' and 'b'.
576 The color components in the range 0 to 255.
578 # all of the following are equivalent
579 my $c1 = Imager::Color->new(red=>100, blue=>255, green=>0);
580 my $c2 = Imager::Color->new(r=>100, b=>255, g=>0);
581 my $c3 = Imager::Color->new(r=>100, blue=>255, g=>0);
585 C<hue>, C<saturation> and C<value>, optionally shortened to C<h>, C<s> and
586 C<v>, to specify a HSV color. 0 <= hue < 360, 0 <= s <= 1 and 0 <= v
589 # the same as RGB(127,255,127)
590 my $c1 = Imager::Color->new(hue=>120, v=>1, s=>0.5);
591 my $c1 = Imager::Color->new(hue=>120, value=>1, saturation=>0.5);
595 C<web>, which can specify a 6 or 3 hex digit web color, in any of the
596 forms C<#RRGGBB>, C<#RGB>, C<RRGGBB> or C<RGB>.
598 my $c1 = Imager::Color->new(web=>'#FFC0C0'); # pale red
602 C<gray> or C<grey> which specifies a single channel, from 0 to 255.
605 my $c1 = Imager::Color->new(gray=>128);
606 my $c1 = Imager::Color->new(grey=>128);
610 C<rgb> which takes a 3 member arrayref, containing each of the red,
611 green and blue values.
614 my $c1 = Imager::Color->new(rgb=>[255, 100, 0]);
615 my $c1 = Imager::Color->new(r=>255, g=>100, b=>0);
619 C<hsv> which takes a 3 member arrayref, containing each of hue,
620 saturation and value.
623 my $c1 = Imager::Color->new(hsv=>[120, 0.5, 1]);
624 my $c1 = Imager::Color->new(hue=>120, v=>1, s=>0.5);
628 C<gimp> which specifies a color from a GIMP palette file. You can
629 specify the file name of the palette file with the 'palette'
630 parameter, or let Imager::Color look in various places, typically
631 C<$HOME/gimp-1.x/palettes/Named_Colors> with and without the version
632 number, and in C</usr/share/gimp/palettes/>. The palette file must
635 my $c1 = Imager::Color->new(gimp=>'snow');
636 my $c1 = Imager::Color->new(gimp=>'snow', palette=>'testimg/test_gimp_pal);
640 C<xname> which specifies a color from an X11 C<rgb.txt> file. You can
641 specify the file name of the C<rgb.txt> file with the C<palette>
642 parameter, or let Imager::Color look in various places, typically
643 C</usr/lib/X11/rgb.txt>.
645 my $c1 = Imager::Color->new(xname=>'blue') # usually RGB(0, 0, 255)
649 C<builtin> which specifies a color from the built-in color table in
650 Imager::Color::Table. The colors in this module are the same as the
651 default X11 C<rgb.txt> file.
653 my $c1 = Imager::Color->new(builtin=>'black') # always RGB(0, 0, 0)
657 C<name> which specifies a name from either a GIMP palette, an X
658 C<rgb.txt> file or the built-in color table, whichever is found first.
662 'channel0', 'channel1', etc, each of which specifies a single channel. These can be abbreviated to 'c0', 'c1' etc.
666 'channels' which takes an arrayref of the channel values.
670 Optionally you can add an alpha channel to a color with the 'alpha' or
673 These color specifications can be used for both constructing new
674 colors with the new() method and modifying existing colors with the
683 my($h, $s, $v, $alpha) = $color->hsv();
685 Returns the color as a Hue/Saturation/Value/Alpha tuple.
691 Arnar M. Hrafnkelsson, addi@umich.edu
692 And a great deal of help from others - see the C<README> for a complete
697 Imager(3), Imager::Color
698 http://imager.perl.org/