initial import from onelab svn codebase
[plewww.git] / includes / image.inc
1 <?php
2 // $Id: image.inc 144 2007-03-28 07:52:20Z thierry $
3
4 /**
5  * Return a list of available toolkits.
6  *
7  * @return An array of toolkit name => descriptive title.
8  */
9 function image_get_available_toolkits() {
10   $toolkits = file_scan_directory('includes', 'image\..*\.inc$');
11
12   $output = array();
13   foreach ($toolkits as $file => $toolkit) {
14     include_once "./$file";
15     $function = str_replace('.', '_', $toolkit->name) .'_info';
16     if (function_exists($function)) {
17       $info = $function();
18       $output[$info['name']] = $info['title'];
19     }
20   }
21   $output['gd'] = t('Built-in GD2 toolkit');
22   return $output;
23 }
24
25 /**
26  * Retrieve the name of the currently used toolkit.
27  *
28  * @return String containing the name of the toolkit.
29  */
30 function image_get_toolkit() {
31   static $toolkit;
32   if (!$toolkit) {
33     $toolkit = variable_get('image_toolkit', 'gd');
34    $toolkit_file = './includes/image.'.$toolkit.'.inc';
35     if ($toolkit != 'gd' && file_exists($toolkit_file)) {
36       include_once $toolkit_file;
37     }
38     elseif (!image_gd_check_settings()) {
39       $toolkit = false;
40     }
41   }
42
43   return $toolkit;
44 }
45
46 /**
47  * Invokes the given method using the currently selected toolkit.
48  *
49  * @param $method A string containing the method to invoke.
50  * @param $params An optional array of parameters to pass to the toolkit method.
51  *
52  * @return Mixed values (typically Boolean for successful operation).
53  */
54 function image_toolkit_invoke($method, $params = array()) {
55   if ($toolkit = image_get_toolkit()) {
56     $function = 'image_'. $toolkit .'_'. $method;
57     if (function_exists($function)) {
58       return call_user_func_array($function, $params);
59     }
60     else {
61       watchdog('php', t("The selected image handling toolkit '%toolkit' can not correctly process '%function'.", array('%toolkit' => "<em>$toolkit</em>", '%function' => "<em>$function</em>")), WATCHDOG_ERROR);
62       return false;
63     }
64   }
65   else {
66     if ($method == 'settings') {
67       return image_gd_settings();
68     }
69   }
70 }
71
72
73 /**
74  * Get details about an image.
75  *
76  * @return array containing information about the image
77  *      'width': image's width in pixels
78  *      'height': image's height in pixels
79  *      'extension': commonly used extension for the image
80  *      'mime_type': image's MIME type ('image/jpeg', 'image/gif', etc.)
81  *      'file_size': image's physical size (in bytes)
82  */
83 function image_get_info($file) {
84   if (!is_file($file)) {
85     return false;
86   }
87
88   $details = false;
89   $data = @getimagesize($file);
90   $file_size = @filesize($file);
91
92   if (isset($data) && is_array($data)) {
93     $extensions = array('1' => 'gif', '2' => 'jpg', '3' => 'png');
94     $extension = array_key_exists($data[2], $extensions) ?  $extensions[$data[2]] : '';
95     $details = array('width'     => $data[0],
96                      'height'    => $data[1],
97                      'extension' => $extension,
98                      'file_size' => $file_size,
99                      'mime_type' => $data['mime']);
100   }
101
102   return $details;
103 }
104
105 /**
106  * Scales an image to the given width and height while maintaining aspect
107  * ratio.
108  *
109  * @param $source         The filepath of the source image
110  * @param $destination    The file path of the destination image
111  * @param $width          The target width
112  * @param $height         The target height
113  *
114  * @return True or false, based on success
115  */
116 function image_scale($source, $destination, $width, $height) {
117   $info = image_get_info($source);
118
119   // don't scale up
120   if ($width > $info['width'] && $height > $info['height']) {
121     return false;
122   }
123
124   $aspect = $info['height'] / $info['width'];
125   if ($aspect < $height / $width) {
126     $width = (int)min($width, $info['width']);
127     $height = (int)round($width * $aspect);
128   }
129   else {
130     $height = (int)min($height, $info['height']);
131     $width = (int)round($height / $aspect);
132   }
133
134   return image_toolkit_invoke('resize', array($source, $destination, $width, $height));
135 }
136
137 /**
138  * Resize an image to the given dimensions (ignoring aspect ratio).
139  *
140  * @param $source        The filepath of the source image.
141  * @param $destination   The file path of the destination image.
142  * @param $width         The target width.
143  * @param $height        The target height.
144  */
145 function image_resize($source, $destination, $width, $height) {
146   return image_toolkit_invoke('resize', array($source, $destination, $width, $height));
147 }
148
149 /**
150  * Rotate an image by the given number of degrees.
151  *
152  * @param $source  The filepath of the source image
153  * @param $destination    The file path of the destination image
154  * @param $degrees The number of (clockwise) degrees to rotate the image
155  */
156 function image_rotate($source, $destination, $degrees) {
157   return image_toolkit_invoke('rotate', array($source, $destination, $degrees));
158 }
159
160 /**
161  * Crop an image to the rectangle specified by the given rectangle.
162  *
163  * @param $source        The filepath of the source image
164  * @param $destination   The file path of the destination image
165  * @param $x             The top left co-ordinate of the crop area (x axis value)
166  * @param $y             The top left co-ordinate of the crop area (y axis value)
167  * @param $width         The target width
168  * @param $height        The target height
169  */
170 function image_crop($source, $destination, $x, $y, $width, $height) {
171   return image_toolkit_invoke('crop', array($source, $destination, $x, $y, $width, $height));
172 }
173
174 /**
175  * GD2 toolkit functions
176  * With the minimal requirements of PHP 4.3 for Drupal, we use the built-in version of GD.
177  */
178
179 /**
180  * Retrieve settings for the GD2 toolkit (not used).
181  */
182 function image_gd_settings() {
183   if (image_gd_check_settings()) {
184     return t('The built-in GD2 toolkit is installed and working properly.');
185   }
186   else {
187     form_set_error('image_toolkit', t("The built-in GD image toolkit requires that the GD module for PHP be installed and configured properly. For more information see %url.", array('%url' => '<a href="http://php.net/image">http://php.net/image</a>')));
188     return false;
189   }
190 }
191
192 /**
193  * Verify GD2 settings (that the right version is actually installed).
194  *
195  * @return boolean
196  */
197 function image_gd_check_settings() {
198   if ($check = get_extension_funcs('gd')) {
199     if (in_array('imagegd2', $check)) {
200       // GD2 support is available.
201       return true;
202     }
203   }
204   return false;
205 }
206
207 /**
208  * Scale an image to the specified size using GD.
209  */
210 function image_gd_resize($source, $destination, $width, $height) {
211   if (!file_exists($source)) {
212     return false;
213   }
214
215   $info = image_get_info($source);
216   if (!$info) {
217     return false;
218   }
219
220   $im = image_gd_open($source, $info['extension']);
221   if (!$im) {
222     return false;
223   }
224
225   $res = imageCreateTrueColor($width, $height);
226   imageCopyResampled($res, $im, 0, 0, 0, 0, $width, $height, $info['width'], $info['height']);
227   $result = image_gd_close($res, $destination, $info['extension']);
228
229   imageDestroy($res);
230   imageDestroy($im);
231
232   return $result;
233 }
234
235 /**
236  * Rotate an image the given number of degrees.
237  */
238 function image_gd_rotate($source, $destination, $degrees, $bg_color = 0) {
239   if (!function_exists('imageRotate')) {
240     return false;
241   }
242
243   $info = image_get_info($source);
244   if (!$info) {
245     return false;
246   }
247
248   $im = image_gd_open($source, $info['extension']);
249   if (!$im) {
250     return false;
251   }
252
253   $res = imageRotate($im, $degrees, $bg_color);
254   $result = image_gd_close($res, $destination, $info['extension']);
255
256   return $result;
257 }
258
259 /**
260  * Crop an image using the GD toolkit.
261  */
262 function image_gd_crop($source, $destination, $x, $y, $width, $height) {
263   $info = image_get_info($source);
264   if (!$info) {
265     return false;
266   }
267
268   $im = image_gd_open($source, $info['extension']);
269   $res = imageCreateTrueColor($width, $height);
270   imageCopy($res, $im, 0, 0, $x, $y, $width, $height);
271   $result = image_gd_close($res, $destination, $info['extension']);
272
273   imageDestroy($res);
274   imageDestroy($im);
275
276   return $result;
277 }
278
279 /**
280  * GD helper function to create an image resource from a file.
281  */
282 function image_gd_open($file, $extension) {
283   $extension = str_replace('jpg', 'jpeg', $extension);
284   $open_func = 'imageCreateFrom'. $extension;
285   if (!function_exists($open_func)) {
286     return false;
287   }
288   return $open_func($file);
289 }
290
291 /**
292  * GD helper to write an image resource to a destination file.
293  */
294 function image_gd_close($res, $destination, $extension) {
295   $extension = str_replace('jpg', 'jpeg', $extension);
296   $close_func = 'image'. $extension;
297   if (!function_exists($close_func)) {
298     return false;
299   }
300   return $close_func($res, $destination);
301 }
302
303