<?php
/**
* class to take an image in gif/png/jpeg formats and rescale it downwards to a particular dimension, finally saving it in a given path
*
* if a corresponding filename already exists at the given path, a suffix will be appended
*
* sample usage
*
$iR = new imageResizer('imagename.png', 100, '.');
if ($iR->isError()){
$iR->outputErrors();
}
$result = $iR->convert();
if ($result == false){
$iR->outputErrors();
} else {
echo $result;
}
*
*/
class imageResizer{
private $error = false;
private $errorMessages = array();
/**
* constructor
*
* @param object $file the full path of the image to be resampeld
* @param object $maxDimension the maximum permitted dimension
* @param object $outputDirectory the output directory for the resultant file
* @param object $outputFileName [optional] if no value is provided a unique name will be created
* @return
*/
public function __construct($file, $maxDimension, $outputDirectory, $outputFileName = null){
$this->setInputFile($file);
$this->setMaxDimension($maxDimension);
$this->setOutputDirectory($outputDirectory);
$this->setImageData($file);
$this->setOutputFileName($outputFileName);
}
/**
* method to determine the filename to use for the saved image.
*
* if a file name is already taken a suffix (_XX) is appended before the extension
* @param object $file
* @return
*/
private function setOutputFileName($file){
if (empty($file)){
$file = uniqid('', true);
} else {
$p = pathinfo($file);
if (version_compare(PHP_VERSION, "5.2") === 1){
$file = $p['filename'];
} else {
$file = substr($file, 0, (strlen($p['extension']) + 1) * -1);
}
}
//now check whether the file name exists and appends an incrementing suffix if so
$c = 0;
if (file_exists($this->outputDirectory . $file . $this->extension)){
do{
$c++;
$_file = $file . '_' . $c . $this->extension;
} while (file_exists($this->outputDirectory . $_file));
$this->outputFile = $_file;
} else {
$this->outputFile = $file . $this->extension;
}
}
/**
* method to set the maximum dimension of the new image
* @param object $dimension
* @return
*/
private function setMaxDimension($dimension){
if (is_numeric($dimension)){
$this->dimension = $dimension;
} else {
$this->setError('Maximum Dimension is not numeric');
}
}
/**
* method to set the output directory of the new image.
*
* will test to ensure that the output directory exists and is writable.
* @param object $dir
* @return
*/
private function setOutputDirectory($dir){
if (is_dir($dir)){
if (is_writable($dir)){
$this->outputDirectory = realpath($dir);
if (substr($this->outputDirectory, -1) != DIRECTORY_SEPARATOR){
$this->outputDirectory .= DIRECTORY_SEPARATOR;
}
} else {
$this->setError('Output Directory '. $dir . 'is not writable');
}
} else {
$this->setError($dir .' is not a directory');
}
}
/**
* method to set the input image for resampling.
*
* will test to ensure that the file exists and is readable
* @param object $file
* @return
*/
private function setInputFile($file){
if (!is_file($file)){
$this->setError($file .' does not exist');
} elseif (!is_readable($file)){
$this->setError($file .' is not readable');
} else {
$this->file = $file;
}
}
/**
* method to set an error message
* @param object $message
* @return
*/
private function setError($message){
$this->error= true;
$this->errorMessages[] = $message;
}
/**
* method to read in information about the image (height, width and image type)
*
* @return
*/
private function setImageData(){
$data = getimagesize($this->file);
$this->width = $data[0];
$this->height = $data[1];
$this->imageType = $data[2];
$this->extension = image_type_to_extension($this->imageType);
}
/**
* method to determine whether a conversion is necessary (i.e. are both dimensions already below the required maximum)
* @return
*/
private function needsConversion(){
if ($this->height <= $this->dimension && $this->width <= $this->dimension){
return false;
} else {
return true;
}
}
/**
* method that performs the resampling
* @return false on error or the full canonical path of the resultant image
*/
public function convert(){
if (!$this->needsConversion()){
$output = $this->outputDirectory . $this->outputFile;
$result = copy($this->file, $output);
if (!$result){
$this->setError('Cannot move uploaded file that does not need conversion');
return false;
} else {
return $output;
}
}
//calculate new sizes
if ($this->height > $this->width){
$this->newHeight = $this->dimension;
$this->newWidth = $this->dimension * $this->width/$this->height;
} else {
$this->newWidth = $this->dimension;
$this->newHeight = $this->dimension * $this->height/$this->width;
}
//create new canvas
$nC = imagecreatetruecolor($this->newWidth, $this->newHeight);
if (!$nC){
$this->setError('Cannot create new image canvas');
}
//open up old image
$oI = $this->getCurrentImage();
if (!$oI){
$this->setError('Image Type is unsupported');
}
//merge images
imagecopyresampled ( $nC, $oI, 0,0,0,0 , $this->newWidth, $this->newHeight, $this->width, $this->height );
//now output the new image
$output = $this->outputDirectory . $this->outputFile;
if (call_user_func($this->outputFunction,$nC, $output, 100)){
return $output;
} else {
$this->setError('Cannot output the image to file');
return false;
}
}
/**
* method to create a gd image resource and determine what type of output function to use
*
* @return false on error or an imageresource if successful
*/
public function getCurrentImage(){
switch ($this->imageType){
case IMAGETYPE_GIF:
$this->outputFunction = 'imagegif';
return imagecreatefromgif($this->file);
case IMAGETYPE_JPEG:
$this->outputFunction = 'imagejpeg';
return imagecreatefromjpeg($this->file);
case IMAGETYPE_PNG:
$this->outputFunction = 'imagepng';
return imagecreatefrompng($this->file);
default:
return false;
}
}
/**
* method to output errors to the browser.
* kills the script execution after
* @return
*/
public function outputErrors(){
echo implode ("\r\n<br/>", $this->errorMessages);
exit;
}
/**
* method to determine the error state of the script
* @return bool true if errors exist
*/
public function isError(){
if (empty($this->error) || $this->error === false){
return false;
} else {
return true;
}
}
}
$iR = new imageResizer('imagename.png', 100, '.'); //save with random name in current working directory
if ($iR->isError()){
$iR->outputErrors();
}
$result = $iR->convert();
if ($result == false){
$iR->outputErrors();
} else {
echo $result;
}
?>