function.image.php
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005-2015 wemove digital solutions GmbH
5  *
6  * Licensed under the terms of the MIT License.
7  *
8  * See the LICENSE file distributed with this work for
9  * additional information.
10  */
14 
15 /*
16 * Smarty plugin
17 * -------------------------------------------------------------
18 * File: function.image.php
19 * Type: function
20 * Name: image
21 * Purpose: Renders an image tag, if the 'src' value points to an image file or the 'default' parameter is
22 * given. If 'width' or 'height' are given, the image will be resized to that values. The resize method
23 * depends on the 'sizemode' parameter. If the image size will be physically changed, a copy will be created
24 * in the cache directory that is used by the View class, which means that invalidating the View
25 * cache invalidates the image cache too. The content of the 'params' parameter will be put as is in the
26 * created image tag. If the image url has to be translated, use the 'base' parameter (see
27 * smarty_function_translate_url).
28 * The 'sizemode' parameter can have one of the followig values:
29 * - resize: The browser scales the image to fit inside the given dimensions
30 * - resample: The image will be physically scaled to fit inside the given dimensions
31 * - crop: The image will be clipped from the middle to fit inside the given dimensions
32 * If the parameter is not given, it defaults to resample.
33 * The 'valueMode' parameter can have one of the following values:
34 * - fitInto: The image is resized if it's width or height exceeds one of the given values. Image proportions will be kept.
35 * - scaleTo: The image is resized if it's width or height differs from the given values. Image proportions will be kept.
36 * - default: The image is resized if it's width or height differs from the given values. Image proportions will be ignored.
37 * The image will be resized according to the given sizemode. The image won't be cropped with 'valuemode' set to anything else than default.
38 * If the parameter is not given, default is used. Size attributes may be skipped using the nosizeoutput parameter.
39 * Usage: {image src=$image->getFile() base="cms/application/" width="100" alt="Image 1" params='border="0"'
40 * default="images/blank.gif" sizemode="resize" nosizeoutput=true}
41 * -------------------------------------------------------------
42 */
43 function smarty_function_image($params, \Smarty_Internal_Template $template) {
44  $file = $params['src'];
45  $default = isset($params['default']) ? $params['default'] : '';
46  $sizemode = isset($params['sizemode']) ? $params['sizemode'] : 'resample';
47  $valuemode = isset($params['valuemode']) ? $params['valuemode'] : 'default';
48  $alt = isset($params['alt']) ? $params['alt'] : '';
49  $imageParams = isset($params['params']) ? $params['params'] : '';
50 
51  if (strlen($file) == 0 && strlen($default) == 0) {
52  return;
53  }
54 
55  // translate the file url using base
56  if (isset($params['base'])) {
57  $base = $params['base'];
58  // translate file url
59  $urls = URIUtil::translate($file, $base);
60  $file = $urls['relative'];
61  // translate default file url
62  $urls = URIUtil::translate($default, $base);
63  $default = $urls['relative'];
64  }
65 
66  // check if the file exists
67  if (!is_file($file)) {
68  // try the default
69  $file = $default;
70  if (!is_file($file)) {
71  return;
72  }
73  }
74 
75  // get the image size in order to see if we have to resize
76  $imageSize = getimagesize($file);
77  if ($imageSize == false) {
78  // the file is no image
79  return;
80  }
81 
82  $requestedWidth = isset($params['width']) ? $params['width']: null;
83  $requestedHeight = isset($params['height']) ? $params['height']: null;
84 
85  // calculate new dimensions if value mode is set
86  if ($valuemode == 'scaleTo' || $valuemode == 'fitInto') {
87  if ($valuemode == 'fitInto' && $requestedHeight && $requestedHeight > $imageSize[1]) {
88  // if image should fit into a rectangle and it's height is smaller than the requested, leave image untouched
89  $requestedHeight = $imageSize[1];
90  }
91  else if ($valuemode == 'fitInto' && $requestedWidth && $requestedWidth > $imageSize[0]) {
92  // if image should fit into a rectangle and it's width is smaller than the requested, leave image untouched
93  $requestedWidth = $imageSize[0];
94  }
95  if ($requestedHeight == null) {
96  // calculate height if only width is given
97  $requestedHeight = floor(($imageSize[1] * $requestedWidth) / $imageSize[0]);
98  }
99  else if ($requestedWidth == null) {
100  // calculate width if only height is given
101  $requestedWidth = floor(($imageSize[0] * $requestedHeight) / $imageSize[1]);
102  }
103  else {
104  // calculate either width or height depending on the ratio
105  $requestedAspectRatio = $requestedHeight / $requestedWidth;
106  $imageAspectRatio = $imageSize[1] / $imageSize[0];
107  if ($requestedAspectRatio >= $imageAspectRatio) {
108  // scale based on width, keep requestedWidth
109  $requestedHeight = ($imageSize[1] * $requestedWidth) / $imageSize[0];
110  }
111  else {
112  // scale based on height, keep requestedHeight
113  $requestedWidth = ($imageSize[0] * $requestedHeight) / $imageSize[1];
114  }
115  }
116  }
117 
118  // don't resize big images, because of resource limits
119  if (filesize($file) > 2500000) {
120  $sizemode = 'resize';
121  }
122 
123  if (($sizemode != 'resize') && ($requestedWidth != null || $requestedHeight != null) &&
124  ($requestedWidth < $imageSize[0] || $requestedHeight < $imageSize[1])) {
125  // if 'width' or 'height' are given and they differ from the image values,
126  // we have to resize the image
127 
128  // get the file extension
129  preg_match('/\.(\w+)$/', $file, $matches);
130  $extension = $matches[1];
131 
132  $destNameAbs = $template->cache_dir.md5($file.filectime($file).$requestedWidth.$requestedHeight.$sizemode).'.'.$extension;
133  $destName = URIUtil::makeRelative($destNameAbs, dirname(FileUtil::realpath($_SERVER['SCRIPT_FILENAME'])).'/');
134 
135  // if the file does not exist in the cache, we have to create it
136  $dateOrig = @fileatime($file);
137  $dateCache = @fileatime($destName);
138  if (!file_exists($destName) || $dateOrig > $dateCache) {
139  $graphicsUtil = new GraphicsUtil();
140  if ($sizemode == 'resample') {
141  $graphicsUtil->createThumbnail($file, $destName, $requestedWidth, $requestedHeight);
142  }
143  else {
144  $graphicsUtil->cropImage($file, $destName, $requestedWidth, $requestedHeight);
145  }
146  }
147 
148  // use the cached file
149  if (file_exists($destName)) {
150  $file = $destName;
151  }
152  }
153 
154  $widthStr = "";
155  $heightStr = "";
156  if (!isset($params['nosizeoutput']) || $params['nosizeoutput'] == false) {
157  if ($requestedWidth != null) {
158  $widthStr = ' width="'.$requestedWidth.'"';
159  }
160  if ($requestedHeight != null) {
161  $heightStr = ' height="'.$requestedHeight.'"';
162  }
163  }
164 
165  echo '<img src="'.$file.'"'.$widthStr.$heightStr.' alt="'.$alt.'" '.$imageParams.'>';
166 }
167 ?>
GraphicsUtil provides support for graphic manipulation.