As a lazy programmer I don’t like resizing images all the time. So I made this bit of code to let me write a URL including the file size and have the work done for me.
- Written for Zend Framework 1.11.12
- It will resize the image and save it into the correct location so that Apache will find it next time and not call the PHP.
- You can specify the required width, height, both or neither.
- If a width or height is given as 0 then the original dimension will be used.
Add some settings to application.ini
cache.publicDir = '/cache' cache.dataDir = APPLICATION_PATH "/../public/cache" data.dataDir = APPLICATION_PATH "/../public/data
Add a route in the Bootstrap
The regex router must match a URL containing the required file sizes, the file name and as many sub directories as thrown at it. It matches the following and sends them to the ThumbAction on FilesController:
- /cache/100/200/file.jpg
- /cache/100/200/subdir/file.jpg
- /cache/100/200/another-subdir/file.jpg
$router->addRoute('file_resized_thumbnail', new Zend_Controller_Router_Route_Regex( 'cache/([0-9]*)/([0-9]*)(.*/?)/([^/]*?)', array( 'controller' => 'files', 'action' => 'thumb', ), array( 1 => 'width', 2 => 'height', 3 => 'subdir', 4 => 'file' ), '/cache/%d/%d/%s/%s' ));
FilesController.php::ThumbAction()
/** * Loads the file, gets a resized version and saves it in a location identical to * the current URL so Apache can find it next time. **/ public function thumbAction() { $this->view->layout()->disableLayout(); $options = $this->_helper->container->get('options'); $fileName = $this->getRequest()->getParam('file'); $subdir = $this->getRequest()->getParam('subdir'); $width = $this->getRequest()->getParam('width'); $height = $this->getRequest()->getParam('height'); $cacheUrlPrefix = $options['cache']['publicDir']; $cachePathPrefix = $options['cache']['dataDir']; $dataPathPrefix = $options['data']['dataDir']; $fileName = urldecode($fileName); $subdir = ($subdir == "") ? "" : urldecode($subdir); $fullPath = $dataPathPrefix.'/'.$subdir.$fileName; if(realpath($fullPath) == false){ throw new Zend_Controller_Action_Exception('File not Found: '.$fullPath, 404); } $file = new Pata_File(array( 'path' => $fullPath )); if ($file == false) { throw new Zend_Controller_Dispatcher_Exception('That file was not found in that subdir'); } $cacheDir = $cachePathPrefix.'/'.$width.'/'.$height.$subdir; $cacheFile = $cacheDir.'/'.$fileName; if (file_exists($cacheDir) == false) { mkdir($cacheDir, 0777, true); } imagepng($file->getThumbnailPng($width, $height), $cacheFile); header('content-type: image/png'); readfile($cacheFile); }
library/Pata/File.php
/* * This is a model I use to make working with files a bit easier. Several of the functions are used by thumbAction but the code could be moved to the controller if you so desired. */ <?php class Pata_File { protected $path; protected $relativePath; protected $url; protected $image; protected $thumbUrl; protected $thumbnailDimensions = array(); protected $thumbnailPng = array(); protected $description; public function __construct($options) { if (isset($options['path'])) { $this->path = $options['path']; } if (isset($options['relativePath'])) { $this->relativePath = $options['relativePath']; } if (isset($options['url'])) { $this->url = $options['url']; } if (isset($options['thumbUrl'])) { $this->thumbUrl = $options['thumbUrl']; } } public function getName() { return basename($this->getPath()); } public function getPath() { if ($this->path == null) { throw new Exception('No path has been set'); } return $this->path; } public function getRelativePath() { return $this->relativePath; } public function getDir() { return substr($this->getPath(), 0, - strlen($this->getName())); } public function setDescription($description) { $this->description = $description; } public function getDescription() { return $this->description; } /** * The URL to the actual file itself - not a page displaying it, see getPageUrl() * @return type */ public function getUrl($width = 800, $height = null) { if ($this->url == null) { throw new Exception('No url has been set'); } $height = $height ?: round($width * 0.75, 0); return str_replace(array(':width:', ':height:'), array($width, $height), $this->url); } public function getThumbUrl($width = 120, $height = null) { if ($this->thumbUrl == null) { throw new Exception('No thumbUrl has been set'); } $height = $height ?: round($width * 0.75, 0); return str_replace(array(':width:', ':height:'), array($width, $height), $this->thumbUrl); } public function setPath($new) { $this->path = $new; } public function setUrl($new) { $this->url = $new; } public function setThumbUrl($new) { $this->thumbUrl = $new; } public function setPageUrl($new) { $this->pageUrl = $new; } /** * Page Url is the URL to the page on which this image can be viewed */ public function getPageUrl() { if ($this->pageUrl == null) { throw new Exception('No pageUrl has been set'); } return $this->pageUrl; } public function getExtention() { if (preg_match('/\.[A-z0-9]+$/', $this->getPath(), $ext)) { $ext = $ext[0]; $ext = substr($ext, 1); } else { $finfo = new finfo(FILEINFO_MIME); $mime = $finfo->file($this->getPath()); $mime = explode(";", $mime); $mime = $mime[0]; $mimeToExt = array( "text/plain" => "txt", ); if (isset($mimeToExt[$mime])) { $ext = $mimeToExt[$mime]; } else { $ext = ""; } } return $ext; } public function freeMemory() { imagedestroy($this->getImage()); $this->img = null; } public function getImage() { if ($this->image == null) { switch(strtolower($this->getExtention())){ case "jpg": case "jpeg": $this->img = imagecreatefromjpeg($this->getPath()); break; case "png": $this->img = imagecreatefrompng($this->getPath()); break; case "gif"; $this->img = imagecreatefromgif($this->getPath()); break; case "bmp"; $this->img = imagecreatefrombmp($this->getPath()); break; case ".txt"; case "doc"; $this->img = imagecreatefrompng(realpath(dirname(__FILE__).'/File/Images/thumb_doc.png')); break; case "xls"; $this->img = imagecreatefrompng(realpath(dirname(__FILE__).'/File/Images/thumb_excel.png')); break; default; $this->img = imagecreatefrompng(realpath(dirname(__FILE__).'/File/Images/thumb_unknown.png')); break; } } return $this->img; } public function getThumbnailDimensions($width, $height, $return = 'both') { $cacheName = $width.'x'.$height.$return; if (isset($this->thumbnailDimensions[$cacheName])) { return $this->thumbnailDimensions[$cacheName]; } if ($this->getType() == 'images') { $imgSize = getimagesize($this->getPath()); $imgWidth = $imgSize[0]; $imgHeight = $imgSize[1]; } else { $img = $this->getImage(); $imgWidth = imagesx($img); $imgHeight = imagesy($img); } if ($width > 0) { $thumbWidth = $width; } else { $thumbWidth = ($imgWidth / $imgHeight) * $height; } if ($height > 0) { $thumbHeight = $height; } else { $thumbHeight = ($imgHeight / $imgWidth) * $width; } $thumbWidth = floor($thumbWidth); $thumbHeight = floor($thumbHeight); $returnValue = null; if ($return == 'both') { $returnValue = array('width' => $thumbWidth, 'height' => $thumbHeight); } elseif ($return == 'width') { $returnValue = $thumbWidth; } elseif ($return == 'height') { $returnValue = $thumbHeight; } else { throw new Exception($return . ' is not a valid parameter for return type for getThumbnailDimensions in Pata_File'); } $this->thumbnailDimensions[$cacheName] = $returnValue; return $returnValue; } public function getThumbnailPng($width = 0, $height = 0) { if (!isset($this->thumbnailPng[$width.'x'.$height])) { $img = $this->getImage(); $imgWidth = imagesx($img); $imgHeight = imagesy($img); $thumbTop = 0; $thumbLeft = 0; // If we have specified widths and heights, use them. Otherwise calculate them if ($width == 0 && $height == 0) { $thumbWidth = $imgWidth; $thumbHeight = $imgHeight; } else { $dimensions = $this->getThumbnailDimensions($width, $height); $thumbWidth = $dimensions['width']; $thumbHeight = $dimensions['height']; } // These default to not being changed $scaleWidth = $thumbWidth; $scaleHeight = $thumbHeight; if ($imgWidth > $imgHeight) { $scaleHeight = ($imgHeight / $imgWidth) * $thumbWidth; $thumbTop = ($thumbHeight - $scaleHeight) / 2; } elseif($imgWidth < $imgHeight) { $scaleWidth = ($imgWidth / $imgHeight) * $thumbHeight; $thumbLeft = ($thumbWidth - $scaleWidth) / 2; } $thumb = ImageCreateTrueColor($thumbWidth, $thumbHeight); // Fill the image with transparency imagesavealpha($thumb, true); $trans_colour = imagecolorallocatealpha($thumb, 0, 0, 0, 127); imagefill($thumb, 0, 0, $trans_colour); imagecopyresampled($thumb, $img, $thumbLeft, $thumbTop, 0, 0, $scaleWidth, $scaleHeight, $imgWidth, $imgHeight); imageinterlace($thumb, true); $this->thumbnailPng[$width.'x'.$height] = $thumb; } return $this->thumbnailPng[$width.'x'.$height]; } function getType() { $types = $this->getFileTypeExtentions(); foreach ($types as $type => $exts) { if (in_array(strtolower($this->getExtention()), $exts)) { return $type; } } return 'unknown'; } function getFileTypeExtentions($type = null) { $types = array( 'images' => array('jpg','jpeg','gif','png','tiff','bmp'), 'documents' => array('doc', 'docx', 'txt', 'rtf', 'odt', 'pdf'), 'spreadsheets' => array('xls'), ); if ($type != null) { if (!isset($types[$type])) { throw new Exception('Pata_Gallery->getFileTypeExtentions() does not have a list of extentions for the "'.$type.'" type'); } return $types[$type]; } return $types; } }