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 sub _load_gimp_palette {
69 if (open PAL, "< $filename") {
72 unless ($hdr =~ /GIMP Palette/) {
74 $Imager::ERRSTR = "$filename is not a GIMP palette file";
79 my $mod_time = (stat PAL)[9];
80 while (defined($line = <PAL>)) {
81 next if $line =~ /^#/ || $line =~ /^\s*$/;
83 my ($r,$g, $b, $name) = split ' ', $line, 4;
85 $name =~ s/\s*\([\d\s]+\)\s*$//;
86 $pal{lc $name} = [ $r, $g, $b ];
91 $gimp_cache{$filename} = { mod_time=>$mod_time, colors=>\%pal };
96 $Imager::ERRSTR = "Cannot open palette file $filename: $!";
101 sub _get_gimp_color {
105 if ($args{palette}) {
106 $filename = $args{palette};
109 # try to make one up - this is intended to die if tainting is
110 # enabled and $ENV{HOME} is tainted. To avoid that untaint $ENV{HOME}
111 # or set the palette parameter
112 for my $attempt (@gimp_search) {
113 my $work = $attempt; # don't modify the source array
114 $work =~ /\$HOME/ && !defined $ENV{HOME}
116 $work =~ s/\$HOME/$ENV{HOME}/;
123 $Imager::ERRSTR = "No GIMP palette found";
128 if ((!$gimp_cache{$filename}
129 || (stat $filename)[9] != $gimp_cache{$filename})
130 && !_load_gimp_palette($filename)) {
134 if (!$gimp_cache{$filename}{colors}{lc $args{name}}) {
135 $Imager::ERRSTR = "Color '$args{name}' isn't in $filename";
139 return @{$gimp_cache{$filename}{colors}{lc $args{name}}};
144 '/usr/share/X11/rgb.txt', # newer Xorg X11 dists use this
145 '/usr/lib/X11/rgb.txt', # seems fairly standard
146 '/usr/local/lib/X11/rgb.txt', # seems possible
147 '/usr/X11R6/lib/X11/rgb.txt', # probably the same as the first
148 '/usr/openwin/lib/rgb.txt',
149 '/usr/openwin/lib/X11/rgb.txt',
152 # called by the test code to check if we can test this stuff
153 sub _test_x_palettes {
158 # same structure as %gimp_cache
165 if (open RGB, "< $filename") {
168 my $mod_time = (stat RGB)[9];
169 while (defined($line = <RGB>)) {
170 # the version of rgb.txt supplied with GNU Emacs uses # for comments
171 next if $line =~ /^[!#]/ || $line =~ /^\s*$/;
173 my ($r,$g, $b, $name) = split ' ', $line, 4;
175 $pal{lc $name} = [ $r, $g, $b ];
180 $x_cache{$filename} = { mod_time=>$mod_time, colors=>\%pal };
185 $Imager::ERRSTR = "Cannot open palette file $filename: $!";
194 if ($args{palette}) {
195 $filename = $args{palette};
198 for my $attempt (@x_search) {
200 $filename = $attempt;
205 $Imager::ERRSTR = "No X rgb.txt palette found";
210 if ((!$x_cache{$filename}
211 || (stat $filename)[9] != $x_cache{$filename})
212 && !_load_x_rgb($filename)) {
216 if (!$x_cache{$filename}{colors}{lc $args{name}}) {
217 $Imager::ERRSTR = "Color '$args{name}' isn't in $filename";
221 return @{$x_cache{$filename}{colors}{lc $args{name}}};
224 # Parse color spec into an a set of 4 colors
227 return (@_,255) if @_ == 3 && !grep /[^\d.+eE-]/, @_;
228 return (@_ ) if @_ == 4 && !grep /[^\d.+eE-]/, @_;
230 /^\#?([\da-f][\da-f])([\da-f][\da-f])([\da-f][\da-f])([\da-f][\da-f])/i) {
231 return (hex($1),hex($2),hex($3),hex($4));
233 if ($_[0] =~ /^\#?([\da-f][\da-f])([\da-f][\da-f])([\da-f][\da-f])/i) {
234 return (hex($1),hex($2),hex($3),255);
236 if ($_[0] =~ /^\#([\da-f])([\da-f])([\da-f])$/i) {
237 return (hex($1) * 17, hex($2) * 17, hex($3) * 17, 255);
242 %args = ( name => @_ );
248 if (exists $args{gray}) {
249 @result = $args{gray};
251 elsif (exists $args{grey}) {
252 @result = $args{grey};
254 elsif ((exists $args{red} || exists $args{r})
255 && (exists $args{green} || exists $args{g})
256 && (exists $args{blue} || exists $args{b})) {
257 @result = ( exists $args{red} ? $args{red} : $args{r},
258 exists $args{green} ? $args{green} : $args{g},
259 exists $args{blue} ? $args{blue} : $args{b} );
261 elsif ((exists $args{hue} || exists $args{h})
262 && (exists $args{saturation} || exists $args{'s'})
263 && (exists $args{value} || exists $args{v})) {
264 my $hue = exists $args{hue} ? $args{hue} : $args{h};
265 my $sat = exists $args{saturation} ? $args{saturation} : $args{'s'};
266 my $val = exists $args{value} ? $args{value} : $args{v};
268 @result = _hsv_to_rgb($hue, $sat, $val);
270 elsif (exists $args{web}) {
271 if ($args{web} =~ /^#?([\da-f][\da-f])([\da-f][\da-f])([\da-f][\da-f])$/i) {
272 @result = (hex($1),hex($2),hex($3));
274 elsif ($args{web} =~ /^#?([\da-f])([\da-f])([\da-f])$/i) {
275 @result = (hex($1) * 17, hex($2) * 17, hex($3) * 17);
278 elsif ($args{name}) {
279 unless (@result = _get_gimp_color(%args)) {
280 unless (@result = _get_x_color(%args)) {
281 require Imager::Color::Table;
282 unless (@result = Imager::Color::Table->get($args{name})) {
283 $Imager::ERRSTR = "No color named $args{name} found";
289 elsif ($args{gimp}) {
290 @result = _get_gimp_color(name=>$args{gimp}, %args);
292 elsif ($args{xname}) {
293 @result = _get_x_color(name=>$args{xname}, %args);
295 elsif ($args{builtin}) {
296 require Imager::Color::Table;
297 @result = Imager::Color::Table->get($args{builtin});
300 @result = @{$args{rgb}};
302 elsif ($args{rgba}) {
303 @result = @{$args{rgba}};
304 return @result if @result == 4;
307 @result = _hsv_to_rgb(@{$args{hsv}});
309 elsif ($args{channels}) {
310 return @{$args{channels}};
312 elsif (exists $args{channel0} || $args{c0}) {
314 while (exists $args{"channel$i"} || exists $args{"c$i"}) {
316 exists $args{"channel$i"} ? $args{"channel$i"} : $args{"c$i"});
321 $Imager::ERRSTR = "No color specification found";
325 if (exists $args{alpha} || exists $args{a}) {
326 push(@result, exists $args{alpha} ? $args{alpha} : $args{a});
328 while (@result < 4) {
337 shift; # get rid of class name.
338 my @arg = _pspec(@_);
339 return @arg ? new_internal($arg[0],$arg[1],$arg[2],$arg[3]) : ();
344 my @arg = _pspec(@_);
345 return @arg ? set_internal($self, $arg[0],$arg[1],$arg[2],$arg[3]) : ();
349 my ($self, %opts) = @_;
351 my $other = $opts{other}
352 or return Imager->_set_error("'other' parameter required");
353 my $ignore_alpha = $opts{ignore_alpha} || 0;
355 my @left = $self->rgba;
356 my @right = $other->rgba;
357 my $last_chan = $ignore_alpha ? 2 : 3;
358 for my $ch (0 .. $last_chan) {
359 $left[$ch] == $right[$ch]
372 Imager::Color - Color handling for Imager.
376 $color = Imager::Color->new($red, $green, $blue);
377 $color = Imager::Color->new($red, $green, $blue, $alpha);
378 $color = Imager::Color->new("#C0C0FF"); # html color specification
380 $color->set($red, $green, $blue);
381 $color->set($red, $green, $blue, $alpha);
382 $color->set("#C0C0FF"); # html color specification
384 ($red, $green, $blue, $alpha) = $color->rgba();
385 @hsv = $color->hsv(); # not implemented but proposed
389 if ($color->equals(other=>$other_color)) {
396 This module handles creating color objects used by imager. The idea is
397 that in the future this module will be able to handle colorspace calculations
404 This creates a color object to pass to functions that need a color argument.
408 This changes an already defined color. Note that this does not affect any places
409 where the color has been used previously.
413 This returns the rgba code of the color the object contains.
417 Calling info merely dumps the relevant colorcode to the log.
419 =item equals(other=>$other_color)
421 =item equals(other=>$other_color, ignore_alpha=>1)
423 Compares $self and color $other_color returning true if the color
424 components are the same.
426 Compares all four channels unless C<ignore_alpha> is set. If
427 C<ignore_alpha> is set only the first three channels are compared.
431 You can specify colors in several different ways, you can just supply
438 simple numeric parameters - if you supply 3 or 4 numeric arguments, you get a color made up of those RGB (and possibly A) components.
442 a six hex digit web color, either 'RRGGBB' or '#RRGGBB'
446 an eight hex digit web color, either 'RRGGBBAA' or '#RRGGBBAA'.
450 a 3 hex digit web color, '#RGB' - a value of F becomes 255.
454 a color name, from whichever of the gimp Named_Colors file or X
455 rgb.txt is found first. The same as using the name keyword.
459 You can supply named parameters:
465 'red', 'green' and 'blue', optionally shortened to 'r', 'g' and 'b'.
466 The color components in the range 0 to 255.
468 # all of the following are equivalent
469 my $c1 = Imager::Color->new(red=>100, blue=>255, green=>0);
470 my $c2 = Imager::Color->new(r=>100, b=>255, g=>0);
471 my $c3 = Imager::Color->new(r=>100, blue=>255, g=>0);
475 'hue', 'saturation' and 'value', optionally shortened to 'h', 's' and
476 'v', to specify a HSV color. 0 <= hue < 360, 0 <= s <= 1 and 0 <= v
479 # the same as RGB(127,255,127)
480 my $c1 = Imager::Color->new(hue=>120, v=>1, s=>0.5);
481 my $c1 = Imager::Color->new(hue=>120, value=>1, saturation=>0.5);
485 'web', which can specify a 6 or 3 hex digit web color, in any of the
486 forms '#RRGGBB', '#RGB', 'RRGGBB' or 'RGB'.
488 my $c1 = Imager::Color->new(web=>'#FFC0C0'); # pale red
492 'gray' or 'grey' which specifies a single channel, from 0 to 255.
495 my $c1 = Imager::Color->new(gray=>128);
496 my $c1 = Imager::Color->new(grey=>128);
500 'rgb' which takes a 3 member arrayref, containing each of the red,
501 green and blue values.
504 my $c1 = Imager::Color->new(rgb=>[255, 100, 0]);
505 my $c1 = Imager::Color->new(r=>255, g=>100, b=>0);
509 'hsv' which takes a 3 member arrayref, containting each of hue,
510 saturation and value.
513 my $c1 = Imager::Color->new(hsv=>[120, 0.5, 1]);
514 my $c1 = Imager::Color->new(hue=>120, v=>1, s=>0.5);
518 'gimp' which specifies a color from a GIMP palette file. You can
519 specify the filename of the palette file with the 'palette' parameter,
520 or let Imager::Color look in various places, typically
521 "$HOME/gimp-1.x/palettes/Named_Colors" with and without the version
522 number, and in /usr/share/gimp/palettes/. The palette file must have
525 my $c1 = Imager::Color->new(gimp=>'snow');
526 my $c1 = Imager::Color->new(gimp=>'snow', palette=>'testimg/test_gimp_pal);
530 'xname' which specifies a color from an X11 rgb.txt file. You can
531 specify the filename of the rgb.txt file with the 'palette' parameter,
532 or let Imager::Color look in various places, typically
533 '/usr/lib/X11/rgb.txt'.
535 my $c1 = Imager::Color->new(xname=>'blue') # usually RGB(0, 0, 255)
539 'builtin' which specifies a color from the built-in color table in
540 Imager::Color::Table. The colors in this module are the same as the
541 default X11 rgb.txt file.
543 my $c1 = Imager::Color->new(builtin=>'black') # always RGB(0, 0, 0)
547 'name' which specifies a name from either a GIMP palette, an X rgb.txt
548 file or the built-in color table, whichever is found first.
552 'channel0', 'channel1', etc, each of which specifies a single channel. These can be abbreviated to 'c0', 'c1' etc.
556 'channels' which takes an arrayref of the channel values.
560 Optionally you can add an alpha channel to a color with the 'alpha' or
563 These color specifications can be used for both constructing new
564 colors with the new() method and modifying existing colors with the
569 Arnar M. Hrafnkelsson, addi@umich.edu
570 And a great deal of help from others - see the README for a complete
576 http://imager.perl.org/