Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to learn Perl via the Learning Perl/Tk book published by O"Reilly. There's a nifty little color changer program on page 95, this is where I started. The program has evolved some and mostly works however I have a problem that has hounded me for too long. Changing the background color is okay using fixed names such as purple3. Here's the problem: When I invoke the following:
$rb_value = "purple3" ($red, $green, $blue) = $widget->rgb($rb_value);
I expect to get three decimal numbers between 0 and 255 as stated on page 293. What I get are three numbers much larger than anticipated. for purple3, I get 32125, 9766, 52685. WHY? I'd like to use the results to reset some rgb sliders I use to display specific colors. HELP. I tried dividing the large numbers by 256 and that gets me close and even correct once in a while, but it isn't the right solution. Sorry for the lengthy dialog.

2001-03-27 Edit by Corion : Added CODE tags. And it's a monolog(ue), not a dialog(ue).

Replies are listed 'Best First'.
Re: What's up with the RGB method?
by baku (Scribe) on Mar 28, 2001 at 00:44 UTC

    Taking a stab in the dark...

    It may be that the colours are on a 48-bit scale in stead of 24-bit; that is, 16 bits are available for each channel (red, green, and blue).

    This is becoming increasingly common in anticipation of 48-bit consumer-level hardware, ie: pretty soon you'll actually need the extra bits, and be glad that they're there.

    If this is the case here (but I don't know Tk, so YMMV), the range would be 0..65535; everything else should remain unchanged. Try grabbing $widget->rgb('white') and $widget->rgb('black'), and using their triplets as the limits of your sliders:

    something like...

    my %colour_min, %colour_max; @colour_min{ 'red', 'green', 'blue' } = $widget->rgb('black'); @colour_max{ 'red', 'green', 'blue' } = $widget->rgb('white'); # ... my %triplet; @triplet{ 'red', 'green', 'blue' } = $widget->rgb($user_entry); my %slider; # 0..1 range [eg. 50% grey might be (.5,.5,.5) ] for my $channel ('red', 'green', 'blue') { $slider{$channel} = ( $triplet{$channel} - $colour_min{$channel} ) / + ( $colour_max{$channel} / $colour_min{$channel} ) ); }

    That's probably overkill, though, since you can generally assume that black will be (0,0,0), which reduces the final block to

    for my $channel ('red', 'green', 'blue') { $slider{$channel} = $triplet{$channel} / $colour_max{$channel}; }

    There's also probably a right way to do this that I don't know about... :-)

      You are correct, the RGB compoments are 16 bits. On my machine, purple3 is 125,38,205 at 8 bits each (you might have this information in a file called rgb.txt), which corresponds exactly to the OP's colors in a 16 bit colorspace (multiply each by 257 (257 = 65535/255)).