PHP GD performance improvements resize and crop the background of the image, keeping the correct aspect ratio
I have developed an image resizing and cropping class using the PHP GD library. I used the skibulks image trim script to crop the background of the image in the first step and scale the image in the second step to the required dimensions (while maintaining the original ratio).
Question: Is it really necessary to do the first task imagecopy
after getting the new cropped sizes from the function $this->_trimBackground()
to recreate the image first with the imagecopy
new cropped dimensions (and resize it again)? Or , is it possible to combine this assignment with the next resizing part imagecopyresampled
?
Are there any other possible performance improvements that I'm not aware of? Every job offer is welcome!
Function 1:
/**
* Resize image file
*
* @param string $filepath the image filepath
* @param integer $width the width to resize
* @param integer $height the height to resize
* @return (image blob|boolean status)
* @throws Asset_Model_Image_Exception
*/
private function _resizeImageByFilepathAndReturn($filepath, $width, $height) {
list($imageWidth, $imageHeight, $imageType) = getimagesize($filepath);
switch($imageType) {
case IMAGETYPE_GIF:
$gdImage = imagecreatefromgif($filepath);
break;
case IMAGETYPE_JPEG:
$gdImage = imagecreatefromjpeg($filepath);
break;
case IMAGETYPE_PNG:
$gdImage = imagecreatefrompng($filepath);
break;
default:
return false;
}
if($box = $this->_trimBackground($gdImage)) {
$gdTrimmed = imagecreatetruecolor($box['w'], $box['h']);
imagecopy($gdTrimmed, $gdImage, 0, 0, $box['l'], $box['t'], $box['w'], $box['h']);
$imageWidth = $box['w'];
$imageHeight = $box['h'];
$gdImage = $gdTrimmed;
unset($gdTrimmed);
}
if($imageWidth <= $width && $imageHeight <= $height) {
$fwidth = $imageWidth;
$fheight = $imageHeight;
} else {
$wscale = $width / $imageWidth;
$hscale = $height / $imageHeight;
$scale = min($wscale, $hscale);
$fwidth = $scale * $imageWidth;
$fheight = $scale * $imageHeight;
}
$gdThumbnail = imagecreatetruecolor($width, $height);
imagefill($gdThumbnail, 0, 0, 0x00FFFFFF);
imagecopyresampled($gdThumbnail, $gdImage, ($width - $fwidth) / 2, ($height - $fheight) / 2, 0, 0, $fwidth, $fheight, $imageWidth, $imageHeight);
ob_start();
imagejpeg($gdThumbnail, null, 90);
$image = ob_get_contents();
ob_end_clean();
imagedestroy($gdImage);
imagedestroy($gdThumbnail);
return $image;
}
Function 2:
/**
* Trim image background
*
* @param $gdImage image ressource
*/
private function _trimBackground($gdImage){
$hex = imagecolorat($gdImage, 0,0);
$width = imagesx($gdImage);
$height = imagesy($gdImage);
$bTop = 0;
$bLft = 0;
$bBtm = $height - 1;
$bRt = $width - 1;
for(; $bTop < $height; ++$bTop) {
for($x = 0; $x < $width; ++$x) {
if(imagecolorat($gdImage, $x, $bTop) != $hex) {
break 2;
}
}
}
if($bTop == $height) {
return false;
}
for(; $bBtm >= 0; --$bBtm) {
for($x = 0; $x < $width; ++$x) {
if(imagecolorat($gdImage, $x, $bBtm) != $hex) {
break 2;
}
}
}
for(; $bLft < $width; ++$bLft) {
for($y = $bTop; $y <= $bBtm; ++$y) {
if(imagecolorat($gdImage, $bLft, $y) != $hex) {
break 2;
}
}
}
for(; $bRt >= 0; --$bRt) {
for($y = $bTop; $y <= $bBtm; ++$y) {
if(imagecolorat($gdImage, $bRt, $y) != $hex) {
break 2;
}
}
}
$bBtm++;
$bRt++;
return array('l' => $bLft, 't' => $bTop, 'r' => $bRt, 'b' => $bBtm, 'w' => $bRt - $bLft, 'h' => $bBtm - $bTop);
}
imagecopy () copies the section of your $ gdImage to $ gdTrimmed, and a few lines later overwrites $ gdImage with $ gdTrimmed.
Do you really need to do the first imagecopy?
This is what you need to ask yourself.
Using a function imagedestroy()
instead unset()
can greatly improve your productivity. Here's a helpful comment by imagedestroy () :
Reusing an image variable does NOT clear old data from memory! You have to use imagedestroy () to clear the data. (I don't know if unset () also works).
Also note that the image data in memory is raw, so don't base how much memory you are using based on the original compressed image format (like jpeg or png).
source to share