Making Things Pink
21 June 2008
As promised in my last post about the Damaged Goods site I'm going to do a quick run through of how the site turns images pink (or any other colour, if you're not so keen on pink).
First things first, this requires you to be running a server that has PHP with GD image installed on it. GD image is an image processing library that you can use from PHP, and that's what we're going to use for all the 'magic'. I'm going to assume that you're not a PHP whizz either, as if you are you can probably work this out for yourself! I'd also like to point out at this juncture that I'm not a PHP whizz either - I'm pretty much making it up as I go along, so if you spot anything that looks a bit dodgy let me know.
To start with, make a new text file called 'image.php' in the same folder you keep images in on your server. Instead of including images directly with the image tag in our html, we're going to route them through this PHP file - so your image tag will look a bit like this:
<img src="/images/image.php?i=yourimage.jpg" alt="Your Image (but pink!)" />
In the image.php, type in these lines:
<?php
if(isset($_GET["i"])){
$image = $_GET["i"];
}
?>
What we're doing here is checking to see if we have a GET variable called 'i', and if we do we're setting the variable 'image' to it. GET variables are the things you see after a '?' in an URL and they're a way of passing data into a PHP script. In this case we're passing the PHP script the name of the file that we want to turn pink.
Next, add these lines after the $image = $_GET["i"]; line:
if (preg_match('/jpg|jpeg|JPG/', $image))
{
$source = imagecreatefromjpeg($image);
} else if (preg_match('/png|PNG/', $image))
{
$source = imagecreatefrompng($image);
} else if (preg_match('/gif|GIF/', $image))
{
$source = imagecreatefromgif($image);
}
In this step we're turning the image into something we can manipulate in GD image - we have to use slightly different functions depending on the image type, so first we check the filename to try and figure out the appropriate function to call.
list($width, $height) = getimagesize($image);
$bwimage = imagecreate($width, $height);
Now, we getting the size of the existing image, and creating a new image of the same size which we're going to copy the image into (and pink-ify in the process). Before that, however, we need to make the pink colour palette that we going to use for our new image:
for ($c=0;$c<256;$c++)
{
// r=255, g=21, b=159
$palette[$c] = imagecolorallocate($bwimage, (($c / 256) * 255 ), (($c/256) * 21 ), (($c/256) * 159));
}
What we're doing here is creating a 256 colour palette for our image. Most images these days are in millions of colours, but for black and white (or tinted) images we only need 256. For each colour, we set three values - one for the red channel, one for the green and one for the blue. This is where we do our tinting - you'll notice that we divide each channel value by 256, then multiplying it by a value. These values we're multiplying by are the RGB values of the colour we want the brightest point of the resulting image to be - in this case pink (which is Red=255, Green=21 and Blue=159), but you can modify these to whatever you want (or set it them all to 256 to make the image black and white).
for ($y=0;$y<$height;$y++)
{
for ($x=0;$x<$width;$x++)
{
$rgb = imagecolorat($source,$x,$y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
$gs = (($r*0.299)+($g*0.587)+($b*0.114));
imagesetpixel($bwimage,$x,$y,$palette[$gs]);
}
}
This is where we actually change the colours of the image. We go through, pixel by pixel and get the RGB index of each one, which we then convert into separate RGB values. We then turn those three values into one brightness value by using a YIQ transformation. Finally, we set the appropriate pixel in our destination image with the correct colour from our tinted palette based on the brightness from the original pixel. Phew!
header('Content-type: image/jpeg');
imagejpeg($bwimage, null, 95);
Finally, we set the page header so that the browser knows we're outputting a jpeg, and then we output the (now pink) image. All done!
You can download the finished version of the script here:
This is really just the starting point - if you wanted to use this on a real site you would probably want to implement some form of caching so that the image didn't need to be rendered every time it's loaded (which is fairly easy, as you can make imagejpeg() generate a file instead of displaying the image quite easily). You can also use GD image to do things like automatically resizing images (which I do on this site) and composing images on top of each other - the possibilities are almost endless!
David Emery Online