Grayscaling Images With Perl

One thing that caught my interest today was how to convert a colour image into grayscale.

It turns out the basic algorithm is very simple. Basically it’s just…

grey = 0.15 * red + 0.55 * green + 0.30 * blue;

This can be turned into a Perl subroutine using the following code.

sub grayscale {
my ($r, $g, $b) = @_;
my $s = 0.15 * $r + 0.55 * $g + 0.30 * $b;
return int($s);
}

Here we pass in the RGB values of the colour we want to turn into gray. We apply the algorithm and return the integer value of gray.

The value we get for gray is used to replace each of the values for red, green and blue.

We can test this subroutine out with the help of the Perl GD module (available for free on CPAN).

#!/usr/bin/perl -w
use GD;
## grayscale subroutine
sub grayscale {
my ($r, $g,$b) = @_;
my $s = 0.15 * $r + 0.55 * $g + 0.30 * $b;
return int($s);
}
## create a new GD object with the data passed via STDIN
my $image = new GD::Image(*STDIN);
## iterate over the number of colours in the colour table
for (my $i = 0; $i < $image->colorsTotal(); $i++) {
## get the RGB values for the colour at index $i
my ($r, $g, $b) = $image->rgb($i);
## convert the RGB to grayscale
my $gray = grayscale($r,$g,$b);
## remove the original colour from the colour table
$image->colorDeallocate($i);
## add in the new gray
$image->colorAllocate($gray,$gray,$gray);
}
## make sure we output binary
binmode STDOUT;
## pass the image as a raw GIF to STDOUT
print $image->gif;

This code takes an image piped in from STDIN and outputs a grayscale GIF version of the image to STDOUT.

If the code was called convert.pl it would be called as ./convert.pl <test.gif >>test_result.gif.

Here’s a conversion I did earlier of a GIF image of Kitt, Bev and Justin at the Emap Performance Awards 2004 using the above Perl code.

Kitt, Bev and Justin in colour

Kitt, Bev and Justin in grayscale