Ars Informatica
August 12, 2020
Health Care Informatics
Web-based MySQL/PHP Databasing
Web Development
Favourite Software
Hardware for the Frugal Fanatic
Graphic Design and Image Processing
Free Scripts and Software
About Us
Contact Us

 Article Feed for this site

Easy-to-use, tunable, custom Grayscale Function for dynamic Image Conversion using PHP and the gd Graphics Library

February 18, 2008

In this article, we present a simple grayscale function for use with the gd graphics library - one that is both easy to use, and customizable. Other grayscale functions typically average the red, green, and blue values of each of an image's pixels, then set each RGB value to that average. Our grayscale function does that, too, and it works fine - but it also does more.

As to why one would need PHP and gd functionality, well - sometimes you want to be able to dynamically generate custom charts or graphics on your site, for immediate display to the end user. Or offer dynamic image format conversions. Or you want a script to log images to a database, and create thumbnails in the process.

If you're at liberty to install and run the ImageMagick suite on your system, I'd recommend you do so - so long as you're not exposing a PHP exec() function to the insertion of malicious code - the MagickWand wrapper can help you here. If you can't - use gd. It comes free with PHP, and if not already running, is very simple to activate. See our article Checking for and installing the gd Graphics Library.

Back to grayscales. The gd library has a reasonable number of low-level functions, but they're relatively esoteric, and difficult for the amateur programmer. Higher-level functions, such as grayscale, invert, mirror, flip image functions, simply don't exist. You create your own. Or you use ours.

The simplest way to invoke the AI_grayscale() function is

$image = imagefromfile('yellow_flower.jpg');

(Unfortunately, you can't just drop in the name of the desired image - you have to load the image into memory first.)

Finally, the transformed content needs to be written to a new file, for which we also provide a custom function, in a future article.

Let's illustrate our example. On the left, the source image. On the right is the standard grayscale output - with the intensity of each pixel determined by the average of the red, green, and blue values for that pixel:

This works, and it's okay, but not great ...

Better. This version brings out contrast and details lost in the first version, though it's a little over-exposed. The first method averages the intensity of red, green, and blue channels for each pixel. The second determines the relative amount that each color contributes to the pixel's intensity, multiplies these by the total intensity, and sums them. As a result, pixels that are disproportionately weighted toward one color contribute more to the total intensity than if they tended to neutral - something altogether lost if simply averaging.

To invoke it, use

AI_grayscale($image, 1);

Simple - the additional parameter forces the function to use alternate grayscaling method.

To more clearly illustrate the difference between the two methods, consider the following. With method one, the first row of colors all convert to the same gray values ...

As noted, method two handles these values completely differently. Though technically these colors all have the same intensity, subjectively they often do not. If green or red or blue dominates and thus the color seems brighter than its actual average intensity suggests, this color is proportionately over-represented in the final pixel intensity. You may prefer the following grayscaling - or not.

Finally, you may wish to blend the two methods. Second parameter set to 1 gives you the full effect of the second method. Any fraction between 0 and 1 gives you a blend, i.e.

AI_grayscale($image, 0.8);

Which produces

I like it. You might want to tweak it further. Doesn't matter - with this function you can create your grayscales however you like.

(For the record, a setting of around 0.8 produces the best results, in most cases. Still, you should check this on an image-by-image basis, as significant variability can occur.)

The Code

The AI_grayscale() function determines the dimensions of the image, then processes every pixel, row by row and column by column. First, the red, green and blue pixel intensities are averaged (pixel averaging - method one). If a second parameter is defined, the relative intensities of red, green and blue are determined, then multiplied by their actual intensities (method two - relative weighting of pixel intensities). Again, dominant colors may make the color seem brighter than its actual average intensity; such colors are weighted more in the final pixel intensity.

If the second parameter is a number between 0 and 1, then the two methods are blended. Relatively-weighted pixel intensities are multiplied by the fraction desired, $v, and the average-weighted intensity is multiplied by fraction $1-v (i.e. 0.8 and 0.2, 0.5 and 0.5, etc.)

function AI_grayscale($image, $v = 0) {
	$width = imagesx($image);
	$height = imagesy($image);
	for ($x = 0; $x < $width; $x++) for ($y = 0; $y < $height; $y++) {
		$rgb = imageColorsForIndex($image, ImageColorAt($image,
		$x, $y));
		$gray = ($rgb["red"] + $rgb["green"] + $rgb["blue"])/3;
		if ($v != 0) {
			$sum = $rgb["red"] + $rgb["green"] + $rgb["blue"];
			if ($sum == 0) $relR = $relG = $relB = 0;
			else {
				$relR = $rgb["red"]/$sum;
				$relG = $rgb["green"]/$sum;
				$relB = $rgb["blue"]/$sum;
			$gray = ($rgb["red"]*$relR + $rgb["green"]*$relG +
		imagesetpixel($image, $x, $y, imagecolorallocate($image,
			$gray, $gray, $gray));
	return $image;

It should be noted that this function operates on true-color images only, as do all of the Ars Informatica gd transformation functions. Our AI_readImage() function outputs true-color content from GIF, JPEG and PNG files; AI_writeImage() writes such files from true-color data.

More on the gd graphics library

Image creation and manipulation using the gd Graphics Library
Checking for and installing the gd Graphics Library


Copyright © 2020 Ars Informatica. All Rights Reserved.