Outer-glow effect with PHP and the GD library
I was recently working on a photo gallery project for a friend who is an avid Flickr user. She had an established workflow when it came to making her work available to her friends and clients on Flickr and didn't want to change that workflow if she didn't have to.
Ok, now it's time to skip ahead. I built the side using the Flickr API, and everything is working swimmingly. I decided to hire my friend Matthew Armendariz to handle the interface design. Since the client was a friend of mine, having someone else be responsible for the creative would keep me free from having to worry about that process, and Matt is a pretty good designer.
It took no time for Matt to whip up a few comps, the one we ended up going with had a slight outer-glow around each photograph, and since we were working with seemingly fixed output from Flickr, I figured, no worries, I'll just create two "glowing" background images, and display one or the other depending on whether the current photo was portrait or landscape.
It worked like a charm... until I came across a few photographs that the client had uploaded with non-standard aspect ratios. Then I had the realization that these outer glows needed to be dynamically generated. Since as the developer there wasn't any way that I could trust that she upload files of any specific aspect ratio, and since she was using Flickr to manage her photos I couldn't (and wouldn't want to anyway) enforce any specific sizes uploaded, I needed to come up with a an easy, browser agnostic, and friendly solution.
CSS wasn't going to help me. SVG and Canvas isn't broadly enough supported. And since this site was pretty much Javascript free, I had to look to the server to help me execute the agreed upon creative work
Oh my GD!
The GD library is an often overlooked alternative to ImageMagick, but since it's light weight, comes with most PHP installs, and was already available on the production server, it seemed like the best choice.
First I had to start with making sure that the file I was generating was going to identify itself properly
Next was to pull in the parameters i was going to need to generate the correct size image... I decided to go with a 22px "border", which is really just the size of the glow.
-
$border = ($_REQUEST['b'])? $_REQUEST['b'] : 22;
-
$width = ($_REQUEST['w']) ? $_REQUEST['w']+($border*2): 500;
Next we create the image, using the specified or default dimensions. And then define the colors (in RGB) that will be used to generate the image... white and light gray.
-
$im = @imagecreatetruecolor($width, $height)
-
$white = imagecolorallocate($im, 255, 255, 255);
-
$gray= imagecolorallocate($im,200,200,200);
Now it's time to create our initial shape... First the image is painted entirely white, and then a box is drawn inside of the white image with the gray color.
-
imagefill($im, 0, 0, $white);
-
imagefilledrectangle($im, $border, $border, $width-$border, $height-$border,$gray);
Now there's just a grey box with a white border... not only is it boring, but it's not glowing at all. It's time to fix this. GD has a few decent filters built in, just as any image library should, and the ones that I chose to use for this were IMG_FILTER_SMOOTH and IMG_FILTER_GAUSSIAN_BLUR. The gaussian blur filter, unlike the one you find in PhotoShop, does not unfortunately accept parameters, so instead I had to put calls to GD's imagefilter() method in a for loop. The loop allowed me to also easily play around with the number of times and in what order each filter was applied to the image without having to do too much cutting and pasting.
-
for($i = 0; $i <10; $i++){
-
imagefilter($im,IMG_FILTER_SMOOTH, 0);
-
imagefilter($im,IMG_FILTER_GAUSSIAN_BLUR);
-
imagefilter($im,IMG_FILTER_GAUSSIAN_BLUR);
-
}
Now we just generate the image as a png, and then clear the memory
-
imagepng($im);
-
imagedestroy($im);
And that's all there is too it. Since the default size specified is 500px square, the default output looks like this. If I need to generate an outer–glow for an image that's 250px tall by 400px wide, I add the following query to the URI of the file blur.php?h=250&w=400 and voila! Of course caching the output of this file on the server will speed up any requests after the initial one, but that is beyond the scope of this post.
I've included the source of the file below.
-
<?php
-
$border = ($_REQUEST['b'])? $_REQUEST['b'] : 22;
-
$width = ($_REQUEST['w']) ? $_REQUEST['w']+($border*2): 500;
-
$im = @imagecreatetruecolor($width, $height)
-
$white = imagecolorallocate($im, 255, 255, 255);
-
$gray= imagecolorallocate($im,200,200,200);
-
imagefill($im, 0, 0, $white);
-
imagefilledrectangle($im, $border, $border, $width-$border, $height-$border,$gray);
-
for($i = 0; $i <10; $i++){
-
imagefilter($im,IMG_FILTER_SMOOTH, 0);
-
imagefilter($im,IMG_FILTER_GAUSSIAN_BLUR);
-
imagefilter($im,IMG_FILTER_GAUSSIAN_BLUR);
-
}
-
imagepng($im);
-
imagedestroy($im);
-
?>


June 4th, 2008 at 9:26 pm
hope you added some sort of caching logic so you don't actually have to do this for every request. cool stuff. I've had also a chance to work with GD in the past, not with filters (so I learned something new), but with other transformations and overlays.
June 4th, 2008 at 9:26 pm
hope you added some sort of caching logic so you don't actually have to do this for every request. cool stuff. I've had also a chance to work with GD in the past, not with filters (so I learned something new), but with other transformations and overlays.
June 4th, 2008 at 9:26 pm
hope you added some sort of caching logic so you don't actually have to do this for every request. cool stuff. I've had also a chance to work with GD in the past, not with filters (so I learned something new), but with other transformations and overlays.
June 4th, 2008 at 9:26 pm
hope you added some sort of caching logic so you don't actually have to do this for every request. cool stuff. I've had also a chance to work with GD in the past, not with filters (so I learned something new), but with other transformations and overlays.
June 4th, 2008 at 9:46 pm
Of course the server caches all requests to that file. Since caching was outside the scope of the article I didn't go into it. One of the many reasons I love working with CakePHP is how incredibly easy it is to setup and manage caching throughout various levels of a site or application.
June 4th, 2008 at 9:46 pm
Of course the server caches all requests to that file. Since caching was outside the scope of the article I didn't go into it. One of the many reasons I love working with CakePHP is how incredibly easy it is to setup and manage caching throughout various levels of a site or application.
June 4th, 2008 at 9:46 pm
Of course the server caches all requests to that file. Since caching was outside the scope of the article I didn't go into it. One of the many reasons I love working with CakePHP is how incredibly easy it is to setup and manage caching throughout various levels of a site or application.
June 4th, 2008 at 9:46 pm
Of course the server caches all requests to that file. Since caching was outside the scope of the article I didn't go into it. One of the many reasons I love working with CakePHP is how incredibly easy it is to setup and manage caching throughout various levels of a site or application.
June 5th, 2008 at 12:25 pm
sweet, but you don't give the working link...
June 5th, 2008 at 12:25 pm
sweet, but you don't give the working link...
June 5th, 2008 at 12:25 pm
sweet, but you don't give the working link...
June 5th, 2008 at 12:25 pm
sweet, but you don't give the working link...
June 5th, 2008 at 2:46 pm
@nicholas: the final site is http://www.rysq.net
the urls are ugly, just a warning.
June 5th, 2008 at 2:46 pm
@nicholas: the final site is http://www.rysq.net
the urls are ugly, just a warning.
June 5th, 2008 at 2:46 pm
@nicholas: the final site is http://www.rysq.net
the urls are ugly, just a warning.
June 5th, 2008 at 2:46 pm
@nicholas: the final site is http://www.rysq.net
the urls are ugly, just a warning.
September 7th, 2008 at 1:59 am
Hi, just a newbie at this, how do I use this to create a border on an image. As I see it the code creates a blank image but I would like to add it to photos.
Forgive me if I sound really dumb!!!
Cheers
September 7th, 2008 at 1:59 am
Hi, just a newbie at this, how do I use this to create a border on an image. As I see it the code creates a blank image but I would like to add it to photos.
Forgive me if I sound really dumb!!!
Cheers
September 7th, 2008 at 1:59 am
Hi, just a newbie at this, how do I use this to create a border on an image. As I see it the code creates a blank image but I would like to add it to photos.
Forgive me if I sound really dumb!!!
Cheers
September 7th, 2008 at 1:59 am
Hi, just a newbie at this, how do I use this to create a border on an image. As I see it the code creates a blank image but I would like to add it to photos.
Forgive me if I sound really dumb!!!
Cheers
September 7th, 2008 at 3:59 am
Hi, just a newbie at this, how do I use this to create a border on an image. As I see it the code creates a blank image but I would like to add it to photos.
Forgive me if I sound really dumb!!!
Cheers
December 8th, 2009 at 6:18 pm
Great job applying Outer Glow to a square photo, but do you have any idea how this could be done to an object of irregular shape on an image with transparent background? I haven't tried to apply your code, but I think it would break the transparency. I tried imageconvolution() and it returned black background instead of transparent.
December 8th, 2009 at 6:44 pm
This doesn't directly manipulate the image itself, but was just intended to dynamically create a background image that can be used to give an outer glow effect. This is now achievable with CSS3. As far as semi-transparent images go... can't help you there, you're stuck with photoshop or reading the bitmap data and re-compositing with Canvas.
December 8th, 2009 at 11:18 pm
Great job applying Outer Glow to a square photo, but do you have any idea how this could be done to an object of irregular shape on an image with transparent background? I haven't tried to apply your code, but I think it would break the transparency. I tried imageconvolution() and it returned black background instead of transparent.
December 8th, 2009 at 11:44 pm
This doesn't directly manipulate the image itself, but was just intended to dynamically create a background image that can be used to give an outer glow effect. This is now achievable with CSS3. As far as semi-transparent images go... can't help you there, you're stuck with photoshop or reading the bitmap data and re-compositing with Canvas.
November 6th, 2011 at 6:56 am
thanks a lot bro. it helped me out big time.