Optimize Your JPEGs with PHP

If you’re anything like me, you put a lot of images and photographs on your Web site without opening them in PhotoShop to optimize them for the Web, first. Generally, if I download an image from the Web or I get an image e-mailed to me to add to the Web site, as long as it’s the right size, I just upload it and move on.

Unfortunately, however, those images are usually quite bloated and not compressed properly for the Web. With PHP, though, you can easily optimize an entire directory full of JPEG and PNG images with one simple script without losing any noticeable quality.To begin with, I used the getDirectorySize and sizeFormat functions found in a thread on the Go4Expert forums. These functions aren’t necessary for the optimization script (in fact, if you are just planning to optimize the files in the background, it’s better not to use these functions), but it makes it nice to see how much space you’re freeing up.

I then wrote a simple function to recurse through a specified directory and optimize all JPEG and PNG files found in that directory. I then wrote a function to optimize the JPEG images and a function to optimize the PNG images. Those functions are shown below.

function recursedir($path,$print=true) {
	if($handle = opendir($path)) {
		while(false !== ($file=readdir($handle))) {
			if($print) {
				echo "\n<li>$path/$file";
			}
			if(!is_dir($path.'/'.$file) && $file != '.' && $file != '..') {
				$start = filesize($path.'/'.$file);
				if(exif_imagetype($path.'/'.$file) == IMAGETYPE_JPEG) {
					optimize_jpeg($path.'/'.$file);
				}
				elseif(exif_imagetype($path.'/'.$file) == IMAGETYPE_PNG) {
					optimize_png($path.'/'.$file);
				}
				$end = filesize($path.'/'.$file);
				if($print) {
					echo "</li>";
				}
			}
			elseif(is_dir($path.'/'.$file) && $file != '.' && $file != '..') {
				if($print) {
					echo "\n<ul>";
				}
				recursedir($path.'/'.$file);
				if($print) {
					echo "</ul>";
				}
			}
		}
	}
	return true;
}

function optimize_jpeg($file) {
	if(!isset($GLOBALS['jpegquality']) || !is_numeric($GLOBALS['jpegquality'])) {
		return false;
	}
	if($GLOBALS['jpegquality'] > 100 || $GLOBALS['jpegquality'] < 0) {
		$GLOBALS['jpegquality'] = 80;
	}
	list($w,$h) = @getimagesize($file);
	if(empty($w) || empty($h)) {
		return false;
	}
	$src = imagecreatefromjpeg($file);
	$tmp = imagecreatetruecolor($w,$h);
	imagecopyresampled($tmp,$src,0,0,0,0,$w,$h,$w,$h);
	$src = imagejpeg($tmp,$file,$GLOBALS['jpegquality']);
	imagedestroy($tmp);
	return true;
}

function optimize_png($file) {
	if(!isset($GLOBALS['pngquality']) || !is_numeric($GLOBALS['pngquality'])) {
		return false;
	}
	if($GLOBALS['pngquality'] > 9 || $GLOBALS['pngquality'] < 0) {
		$GLOBALS['pngquality'] = 9;
	}
	list($w,$h) = @getimagesize($file);
	if(empty($w) || empty($h)) {
		return false;
	}
	$src = imagecreatefrompng($file);
	$tmp = imagecreatetruecolor($w,$h);
	imagecopyresampled($tmp,$src,0,0,0,0,$w,$h,$w,$h);
	$src = imagepng($tmp,$file,$GLOBALS['pngquality']);
	imagedestroy($tmp);
	return true;
}

I then put all of those functions together in a PHP file and added some HTML so that it prints out a simple page showing the total size of the directory before optimization, the list of the files in the directory and the final size of the directory after optimization. In one example at work, I reduced the size of a directory from 3.6 megabytes to 2.2 megabytes when I ran this script.

5 Responses

  • Naushad Alam

    Thanks so much, It saves my day, Thanks alot

  • Naushad Alam

    How can i remove png optimization from this code, because it add a black background in every png images.

  • Vick Keane

    Works Great .optimize the images and increase my pagespeed . Thanks a lot

  • Thank you very mush Sir, you saved my life today. The script is perfect (a directory of 950 Mb was compresed to 390 Mb and the images look very nice)

  • Castiel

    Thank you very mush Sir, you saved my life today.