Page 1 of 1

How to create your own ImageFlip()-functions using the GD Library Rate Topic: ***** 1 Votes

#1 Wimpy  Icon User is offline

  • R.I.P. ( Really Intelligent Person, right? )
  • member icon

Reputation: 159
  • View blog
  • Posts: 1,038
  • Joined: 02-May 09

Post icon  Posted 23 May 2009 - 07:42 AM

Well, imagerotate() is already out there and it works like a charm... But, it lacks some functionality: What if you want to mirror an image an turn it all around(?), then imagerotate() won't help you that very much and there are no other native PHP functions that could do it for you either, at least none that I know of!

Therefore I had to make such a function myself, and here's a tutorial showing you how to do it:

First, we have to come up with a name to our new function, I think that is the most important part, I don't know why, but that's how I feel about it. I can't just simply name a function "DoSomeStuff()" and be happy about it, it does not explain anything to anyone more than that it does something.

I named my function "ImageFlip()":
<?php
function ImageFlip($source_image)
{
	// Implementation
}
?>

Now when the hard part is done we can take care of the easy one: Detemerning how we should flip the image, vertically or horizontally? Well, the implementation looks almost the same no matter what way you want to do it and I will show the solution to both. For the moment, let's decide we are going to flip it horizontally.

So, what else do we need to know? I think the image dimensions is a good start since we are going to use them quite a bit:
<?php
function ImageFlip($source_image)
{
	$width  = imagesx($source_image);
	$height = imagesy($source_image);
	// More implementation
}
?>
If you haven't heard of imagesx() and imagesy() before I suggest you check them up in the PHP Documentation at php.net.

Now we know the dimensions of the source image, what else? We need to create a new image with the same dimensions so that we have an image to work with. We use imagecreatetruecolor() for that, imagecreate() won't be sufficient enough if the source has a lot of colors since imagecreate() only has 8-bits of color depth (a total of 256 colors):
<?php
function ImageFlip($source_image)
{
	$width  = imagesx($source_image);
	$height = imagesy($source_image);
	$dest   = imagecreatetruecolor($width, $height);
}
?>

Now we have the basic foundation, and it's time to think about the logic, how would we do this? Well there are, I think, two common solutions to this kind of a problem. One of them is to only use loops and another is to combine a loop with the modulus-operator ( % ) and create an algorithm.

Since I have notice many people don't even seem to know what modulus is or how it works I will use that model to give you an insight to what it can be used for.

(If you don't know how modulus works I would suggest you to Google it up and read about it. I can simply explain it like this though: the modulus operator calculates a division but return the rest value instead of the even number of times a value could be divided, some examples:
6 % 2 = 0
7 % 2 = 1
5 % 3 = 2
)


The algorithm we will use in our implementation to get each individual pixel of the source image, look like this:
<?php
for($i = 0; $i < $width * $height; $i++)
{
	if($i % $width == 0)
	{
		$y = ($i / $width);
		$x = 0;
	}
}
?>
First we loop through all the pixels in the source image, in every iteration we check if it's possible to divide $i with $width without getting a rest value. If it is, it means we have reached the end of the image and have to proceed to the next row. We get the next row by dividing $i with $width. We also have to reset the $x coordinate since we do not want to draw a stairway.

Now we only have to draw each pixels color at the correct location in the new image. To do this we will use some additional native functions in PHP, imagecolorat() and imagesetpixel(). The first one returns the color for a pixel (specified by it's coordinates) in an image. The other draws a single pixel in an image.

How do we know where to draw the pixel value in the new image? Well there's an algorithm for that too:
<?php
$dest_x = $width - $x - 1;
$dest_y = $y;
?>
The "- 1" is because an image works a little like arrays, if you have a width of 50 pixels you work with the index 0-49 not 1-50, so we have to correct that by simply decreasing the value by 1.

Now that we have all the small parts figured out individually we just put them together and our function is complete:
<?php
function ImageFlip($source_image)
{
	$width  = imagesx($source_image);
	$height = imagesy($source_image);
	$dest   = imagecreatetruecolor($width, $height);
	$x = $y = 0;
	for($i = 0; $i < $width * $height; $i++)
	{
		if($i % $width == 0)
		{
			$y = ($i / $width);
			$x = 0;
		}
		imagesetpixel($dest, $width - $x - 1, $y, imagecolorat($source_image, $x, $y));
		$x++;
	}
	return $dest;
}
?>

This function flips the image horizontally, to make it flip an image vertically you have to modify the algorithms a little:
<?php
function ImageFlip($source_image)
{
	$width  = imagesx($source_image);
	$height = imagesy($source_image);
	$dest   = imagecreatetruecolor($width, $height);
	$x = $y = 0;
	for($i = 0; $i < $width * $height; $i++)
	{
		if($i % $height == 0)
		{
			$x = ($i / $height);
			$y = 0;
		}
		imagesetpixel($dest, $x, $height - $y - 1, imagecolorat($source_image, $x, $y));
		$y++;
	}
	return $dest;
}
?>

Note that if you want to have both you could simplify one of them by using PHP's native imagerotate() combined with the other custom one:
<?php
function ImageVerticalFlip($source_image)
{
	return imagerotate(ImageHorizontalFlip($source_image), 180, 0);
}
?>
You simply rotate the flipped image 180 degrees and you're done! I've got this kind of solution in my own class library since I think it's very easy to use and maintain!

That's almost it, but before I forget about it(!): I mentioned earlier that you could solve this kind of a problem entirely with loops, here's the corresponding version to the ImageHorizontalFlip()-function:
<?php
function ImageHorizontalFlip($source_image)
{
	$width  = imagesx($source_image);
	$height = imagesy($source_image);
	$dest   = imagecreatetruecolor($width, $height);
	for($x = 0; $x < $width; $x++)
	{
		for($y = 0; $y < $height; $y++)
		{
			imagesetpixel($dest, $width - $x - 1, $y, imagecolorat($source_image, $x, $y));
		}
	}
 	return $dest;
}
?>


Hope it helps someone out there to do their magic! :)

Best regards
/Wimpy

Is This A Good Question/Topic? 0
  • +

Page 1 of 1