diff --git a/CImage.php b/CImage.php index 4ffade1..87b7346 100644 --- a/CImage.php +++ b/CImage.php @@ -12,7 +12,9 @@ class CImage { * Properties */ private $image = null; // Object for open image - public $pathToImage; + public $imageFolder; // root folder of images + public $imageName; // image filename, may include subdirectory, relative from $imageFolder + public $pathToImage; // $imageFolder . '/' . $imageName; private $fileExtension; public $newWidth; public $newHeight; @@ -39,12 +41,15 @@ class CImage { /** * Constructor, can take arguments to init the object. * - * @param $pathToImage string the filepath to the image. - * @param $saveFolder string path to folder where to save the new file or null to skip saving. - * @param $newName string new filename or leave to null to autogenerate filename. + * @param string $imageName filename which may contain subdirectory. + * @param string $imageFolder path to root folder for images. + * @param string $saveFolder path to folder where to save the new file or null to skip saving. + * @param string $newName new filename or leave to null to autogenerate filename. */ - public function __construct($pathToImage=null, $saveFolder=null, $newName=null) { - $this->pathToImage = $pathToImage; + public function __construct($imageName=null, $imageFolder=null, $saveFolder=null, $newName=null) { + $this->imageName = ltrim($imageName, '/'); + $this->imageFolder = rtrim($imageFolder, '/'); + $this->pathToImage = $this->imageFolder . '/' . $this->imageName; $this->fileExtension = pathinfo($this->pathToImage, PATHINFO_EXTENSION); $this->saveFolder = $saveFolder; $this->newName = $newName; @@ -66,20 +71,24 @@ class CImage { */ public function CreateFilename() { $parts = pathinfo($this->pathToImage); - $crop = $this->cropToFit ? '_cf' : null; + $cropToFit = $this->cropToFit ? '_cf' : null; $crop_x = $this->crop_x ? "_x{$this->crop_x}" : null; $crop_y = $this->crop_y ? "_y{$this->crop_y}" : null; $quality = $this->quality == 100 ? null : "_q{$this->quality}"; + $crop = $this->crop ? '_c' . $this->crop['width'] . '-' . $this->crop['height'] . '-' . $this->crop['start_x'] . '-' . $this->crop['start_y'] : null; $filters = null; - foreach($this->filters as $filter) { - if(is_array($filter)) { - $filters .= "_f{$filter['id']}"; - for($i=1;$i<=$filter['argc'];$i++) { - $filters .= ":".$filter["arg{$i}"]; + if(isset($this->filters)) { + foreach($this->filters as $filter) { + if(is_array($filter)) { + $filters .= "_f{$filter['id']}"; + for($i=1;$i<=$filter['argc'];$i++) { + $filters .= ":".$filter["arg{$i}"]; + } } } } - return $this->saveFolder . '/' . $parts['filename'] . '_' . round($this->newWidth) . '_' . round($this->newHeight) . $crop . $crop_x . $crop_y . $quality . $filters . '.' . $parts['extension']; + $subdir = str_replace('/', '-', dirname($this->imageName)); + return $this->saveFolder . '/' . $subdir . '_' . $parts['filename'] . '_' . round($this->newWidth) . '_' . round($this->newHeight) . $crop . $cropToFit . $crop_x . $crop_y . $quality . $filters . '.' . $parts['extension']; } @@ -111,7 +120,7 @@ class CImage { */ protected function Output($file) { $time = filemtime($file); - if(isset($_SERVER['If-Modified-Since']) && strtotime($_SERVER['If-Modified-Since']) >= $time){ + if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $time){ header("HTTP/1.0 304 Not Modified"); } else { header('Content-type: ' . $this->mime); @@ -120,7 +129,7 @@ class CImage { } exit; } - + /** * Open image. @@ -170,49 +179,65 @@ class CImage { * Calculate new width and height of image. */ protected function CalculateNewWidthAndHeight() { - // Only calculate new width and height if keeping aspect-ratio. + // Crop, use cropped width and height as base for calulations + $width = $this->width; + $height = $this->height; + if($this->crop) { + if(empty($this->crop['width'])) { + $this->crop['width'] = $this->width - $this->crop['start_x']; + } + if(empty($this->crop['height'])) { + $this->crop['height'] = $this->height - $this->crop['start_y']; + } + $width = $this->crop['width']; + $height = $this->crop['height']; + } + + // Calculate new width and height if keeping aspect-ratio. if($this->keepRatio) { - + // Both new width and height are set. if(isset($this->newWidth) && isset($this->newHeight)) { - - // Use newWidth and newHeigh as min width/height, image should fit the area. - if($this->cropToFit) { - $ratioWidth = $this->width/$this->newWidth; - $ratioHeight = $this->height/$this->newHeight; - $ratio = ($ratioWidth < $ratioHeight) ? $ratioWidth : $ratioHeight; - $this->cropWidth = $this->width / $ratio; - $this->cropHeight = $this->height / $ratio; - } - // Use newWidth and newHeigh as max width/height, image should not be larger. - else { - $ratioWidth = $this->width/$this->newWidth; - $ratioHeight = $this->height/$this->newHeight; - $ratio = ($ratioWidth > $ratioHeight) ? $ratioWidth : $ratioHeight; - $this->newWidth = $this->width / $ratio; - $this->newHeight = $this->height / $ratio; - } + $ratioWidth = $width / $this->newWidth; + $ratioHeight = $height / $this->newHeight; + $ratio = ($ratioWidth > $ratioHeight) ? $ratioWidth : $ratioHeight; + $this->newWidth = $width / $ratio; + $this->newHeight = $height / $ratio; } // Use new width as max-width elseif(isset($this->newWidth)) { - $factor = (float)$this->newWidth / (float)$this->width; - $this->newHeight = $factor * $this->height; + $factor = (float)$this->newWidth / (float)$width; + $this->newHeight = $factor * $height; } // Use new height as max-hight elseif(isset($this->newHeight)) { - $factor = (float)$this->newHeight / (float)$this->height; - $this->newWidth = $factor * $this->width; - } + $factor = (float)$this->newHeight / (float)$height; + $this->newWidth = $factor * $width; + } + + // Use newWidth and newHeigh as min width/height, image should fit the area. + if($this->cropToFit) { + $ratioWidth = $width / $this->newWidth; + $ratioHeight = $height / $this->newHeight; + $ratio = ($ratioWidth < $ratioHeight) ? $ratioWidth : $ratioHeight; + $this->cropWidth = $width / $ratio; + $this->cropHeight = $height / $ratio; + } } - // Do not keep aspect ratio, but both newWidth and newHeight must be set - else { - $this->newWidth = isset($this->newWidth) ? $this->newWidth : $this->width; - $this->newHeight = isset($this->newHeight) ? $this->newHeight : $this->height; - } + // Crop, ensure to set new width and height + if($this->crop) { + $this->newWidth = isset($this->newWidth) ? $this->newWidth : $this->crop['width']; + $this->newHeight = isset($this->newHeight) ? $this->newHeight : $this->crop['height']; + } + + // No new height or width is set, use existing measures. + $this->newWidth = round(isset($this->newWidth) ? $this->newWidth : $this->width); + $this->newHeight = round(isset($this->newHeight) ? $this->newHeight : $this->height); + return $this; } @@ -225,7 +250,7 @@ class CImage { * @param boolean $keepRatio true to keep aspect ratio else false. Default is true. * @param boolean $cropToFit true to crop image to fit in box specified by $newWidth and $newHeight. Default is false. * @param integer $quality the quality to use when saving the file, range 0-100, default is full quality which is 100. - * @param array $crop. + * @param array/string $crop converts string of 1,2,3,4 to array 'width'=>1, 'height'=>2, 'start_x'=>3, 'start_y'=>4. * @param array $filter. */ public function ResizeAndOutput($args) { @@ -235,12 +260,19 @@ class CImage { 'keepRatio'=>true, 'cropToFit'=>false, 'quality'=>100, - 'crop'=>array('w'=>null, 'h'=>null, 'x'=>0, 'y'=>0), + 'crop'=>null, //array('width'=>null, 'height'=>null, 'start_x'=>0, 'start_y'=>0), 'filters'=>null, ); + // Convert crop settins from string to array if(isset($args['crop']) && !is_array($args['crop'])) { - $args['crop'] = array(); + $pices = explode(',', $args['crop']); + $args['crop'] = array( + 'width' => $pices[0], + 'height' => $pices[1], + 'start_x' => $pices[2], + 'start_y' => $pices[3], + ); } // Convert filter settins from array of string to array of array @@ -262,13 +294,16 @@ class CImage { //echo "
" . print_r($args['filters'], true) . ""; // Merge default arguments with incoming and set properties. + //$args = array_merge_recursive($defaults, $args); $args = array_merge($defaults, $args); foreach($defaults as $key=>$val) { $this->{$key} = $args[$key]; } + //echo "
" . print_r($this, true) . ""; // Init the object and do sanity checks on arguments $this->Init()->CalculateNewWidthAndHeight(); + //echo "
" . print_r($this, true) . ""; // Use original image? if(is_null($this->newWidth) && is_null($this->newHeight)) { @@ -278,35 +313,75 @@ class CImage { // Check cache before resizing. $this->newFileName = $this->CreateFilename(); if(is_readable($this->newFileName)) { - $fileTime = filemtime($this->pathToImage); - $cacheTime = filemtime($this->newFileName); + $fileTime = filemtime($this->pathToImage); + $cacheTime = filemtime($this->newFileName); if($fileTime <= $cacheTime) { $this->Output($this->newFileName); } } - // Resize and output + // Resize and output and save new to cache $this->Open()->ResizeAndSave(); } + /** + * Create a image and keep transparency for png and gifs. + * + * $param int $width of the new image. + * @param int $height of the new image. + * @returns image resource. + */ + public function CreateImageKeepTransparency($width, $height) { + //echo $width . "x" . $height . "
Supported arguments throught the querystring are:
imagefilter()
Supports .jpg
, .png
and .gif
.
Sourcecode and issues on github: https://github.com/mosbth/cimage
-Mikael Roos (mos@dbwebb.se)
+Copyright 2012, Mikael Roos (mos@dbwebb.se)