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;
}
}