http://www.perlmonks.org?node_id=214357


in reply to Convert RGB to an actual color

I read this to say you want to obtain color names for nearby rgb values. Is that correct? Assuming so, GD can give you a great deal of help. I'll go over how to produce a new copy of an image from a restricted set of colors, and the names will fall right out.

Declare we will make use of GD objects and define a function to return the index of a GD object's palette color from an rgb triple, allocating a new color if necessary:

use GD; sub getindex { my $image = shift; my $index = $image->colorExact(@_); $index == -1 ? $image->colorAllocate(@_) : $index; }
Here lets read all the named colors from /usr/X11/lib/X11/rgb.txt and provide them to a reference GD image's color table:
my $reference_image = new GD::Image(100,100); my @colornames; { my $goodline = qr/^\d/; open my $rgbdat, '<', '/usr/X11/lib/X11/rgb.txt' or die $!; while (<$rgbdat>) { /$goodline/ or next; my @dat = split " ", $_, 4; my $color = pop @dat; $colornames[getindex($reference_image, @dat)] = $color; } close $rgbdat or die $!; }
Now read the jpeg file into a GD::Image
my $image = GD::Image->newFromJpeg('many.jpg') or die $!; my @size = $image->Bounds();
Start a new GD::Image to be built with only named colors my $new_image = GD::Image->new @size;
and fill it in
{ my ($ix, $iy, @rgb); # preallocate and reuse for $ix (0 .. $size[0]-1) { for $iy (0 .. $size[1]-1) { @rgb = $image->rgb(image->getPixel($ix,$iy))); @rgb = $reference_image->rgb( $reference_image->colorClose +stHWB( @rgb )); $new_image->setPixel($ix, $iy, getindex($new_image, @rgb)) +; } } }
The new image's colors are obtained by grabbing the pixel's rgb color, finding the closest reference color's rgb values, and setting the corresponding pixel in the new image, allocating the named color to the new palette if necessary.

We can define a function to return the name of the nearest color, given an rgb pair, but as this code is written there is a closure with $reference_image and @colornames. It would be better to put the reference structures in a module, or case them up in constants with initialization in a BEGIN{} block.

sub getcolor { return "puke" unless @_ == 3; $colornames[$reference_image->colorClosestHWB(@_)] }

You'll notice that GD provided all the heavy lifting for this. Have fun!

After Compline,
Zaxo