|
1 <?php |
|
2 // $Id: image.inc,v 1.24 2008/01/28 16:05:17 goba Exp $ |
|
3 |
|
4 /** |
|
5 * @file |
|
6 * API for manipulating images. |
|
7 */ |
|
8 |
|
9 /** |
|
10 * @defgroup image Image toolkits |
|
11 * @{ |
|
12 * Drupal's image toolkits provide an abstraction layer for common image file |
|
13 * manipulations like scaling, cropping, and rotating. The abstraction frees |
|
14 * module authors from the need to support multiple image libraries, and it |
|
15 * allows site administrators to choose the library that's best for them. |
|
16 * |
|
17 * PHP includes the GD library by default so a GD toolkit is installed with |
|
18 * Drupal. Other toolkits like ImageMagic are available from contrib modules. |
|
19 * GD works well for small images, but using it with larger files may cause PHP |
|
20 * to run out of memory. In contrast the ImageMagick library does not suffer |
|
21 * from this problem, but it requires the ISP to have installed additional |
|
22 * software. |
|
23 * |
|
24 * Image toolkits are installed by copying the image.ToolkitName.inc file into |
|
25 * Drupal's includes directory. The toolkit must then be enabled using the |
|
26 * admin/settings/image-toolkit form. |
|
27 * |
|
28 * Only one toolkit maybe selected at a time. If a module author wishes to call |
|
29 * a specific toolkit they can check that it is installed by calling |
|
30 * image_get_available_toolkits(), and then calling its functions directly. |
|
31 */ |
|
32 |
|
33 /** |
|
34 * Return a list of available toolkits. |
|
35 * |
|
36 * @return |
|
37 * An array of toolkit name => descriptive title. |
|
38 */ |
|
39 function image_get_available_toolkits() { |
|
40 $toolkits = file_scan_directory('includes', 'image\..*\.inc$'); |
|
41 |
|
42 $output = array(); |
|
43 foreach ($toolkits as $file => $toolkit) { |
|
44 include_once "./$file"; |
|
45 $function = str_replace('.', '_', $toolkit->name) .'_info'; |
|
46 if (function_exists($function)) { |
|
47 $info = $function(); |
|
48 $output[$info['name']] = $info['title']; |
|
49 } |
|
50 } |
|
51 |
|
52 return $output; |
|
53 } |
|
54 |
|
55 /** |
|
56 * Retrieve the name of the currently used toolkit. |
|
57 * |
|
58 * @return |
|
59 * String containing the name of the selected toolkit, or FALSE on error. |
|
60 */ |
|
61 function image_get_toolkit() { |
|
62 static $toolkit; |
|
63 |
|
64 if (!$toolkit) { |
|
65 $toolkit = variable_get('image_toolkit', 'gd'); |
|
66 $toolkit_file = './includes/image.'. $toolkit .'.inc'; |
|
67 if (isset($toolkit) && file_exists($toolkit_file)) { |
|
68 include_once $toolkit_file; |
|
69 } |
|
70 elseif (!image_gd_check_settings()) { |
|
71 $toolkit = FALSE; |
|
72 } |
|
73 } |
|
74 |
|
75 return $toolkit; |
|
76 } |
|
77 |
|
78 /** |
|
79 * Invokes the given method using the currently selected toolkit. |
|
80 * |
|
81 * @param $method |
|
82 * A string containing the method to invoke. |
|
83 * @param $params |
|
84 * An optional array of parameters to pass to the toolkit method. |
|
85 * @return |
|
86 * Mixed values (typically Boolean indicating successful operation). |
|
87 */ |
|
88 function image_toolkit_invoke($method, $params = array()) { |
|
89 if ($toolkit = image_get_toolkit()) { |
|
90 $function = 'image_'. $toolkit .'_'. $method; |
|
91 if (function_exists($function)) { |
|
92 return call_user_func_array($function, $params); |
|
93 } |
|
94 else { |
|
95 watchdog('php', 'The selected image handling toolkit %toolkit can not correctly process %function.', array('%toolkit' => $toolkit, '%function' => $function), WATCHDOG_ERROR); |
|
96 return FALSE; |
|
97 } |
|
98 } |
|
99 } |
|
100 |
|
101 |
|
102 /** |
|
103 * Get details about an image. |
|
104 * |
|
105 * Drupal only supports GIF, JPG and PNG file formats. |
|
106 * |
|
107 * @return |
|
108 * FALSE, if the file could not be found or is not an image. Otherwise, a |
|
109 * keyed array containing information about the image: |
|
110 * 'width' - Width in pixels. |
|
111 * 'height' - Height in pixels. |
|
112 * 'extension' - Commonly used file extension for the image. |
|
113 * 'mime_type' - MIME type ('image/jpeg', 'image/gif', 'image/png'). |
|
114 * 'file_size' - File size in bytes. |
|
115 */ |
|
116 function image_get_info($file) { |
|
117 if (!is_file($file)) { |
|
118 return FALSE; |
|
119 } |
|
120 |
|
121 $details = FALSE; |
|
122 $data = @getimagesize($file); |
|
123 $file_size = @filesize($file); |
|
124 |
|
125 if (isset($data) && is_array($data)) { |
|
126 $extensions = array('1' => 'gif', '2' => 'jpg', '3' => 'png'); |
|
127 $extension = array_key_exists($data[2], $extensions) ? $extensions[$data[2]] : ''; |
|
128 $details = array('width' => $data[0], |
|
129 'height' => $data[1], |
|
130 'extension' => $extension, |
|
131 'file_size' => $file_size, |
|
132 'mime_type' => $data['mime']); |
|
133 } |
|
134 |
|
135 return $details; |
|
136 } |
|
137 |
|
138 /** |
|
139 * Scales an image to the exact width and height given. Achieves the |
|
140 * target aspect ratio by cropping the original image equally on both |
|
141 * sides, or equally on the top and bottom. This function is, for |
|
142 * example, useful to create uniform sized avatars from larger images. |
|
143 * |
|
144 * The resulting image always has the exact target dimensions. |
|
145 * |
|
146 * @param $source |
|
147 * The file path of the source image. |
|
148 * @param $destination |
|
149 * The file path of the destination image. |
|
150 * @param $width |
|
151 * The target width, in pixels. |
|
152 * @param $height |
|
153 * The target height, in pixels. |
|
154 * @return |
|
155 * TRUE or FALSE, based on success. |
|
156 */ |
|
157 function image_scale_and_crop($source, $destination, $width, $height) { |
|
158 $info = image_get_info($source); |
|
159 |
|
160 $scale = max($width / $info['width'], $height / $info['height']); |
|
161 $x = round(($info['width'] * $scale - $width) / 2); |
|
162 $y = round(($info['height'] * $scale - $height) / 2); |
|
163 |
|
164 if (image_toolkit_invoke('resize', array($source, $destination, $info['width'] * $scale, $info['height'] * $scale))) { |
|
165 return image_toolkit_invoke('crop', array($destination, $destination, $x, $y, $width, $height)); |
|
166 } |
|
167 return FALSE; |
|
168 } |
|
169 |
|
170 /** |
|
171 * Scales an image to the given width and height while maintaining aspect |
|
172 * ratio. |
|
173 * |
|
174 * The resulting image can be smaller for one or both target dimensions. |
|
175 * |
|
176 * @param $source |
|
177 * The file path of the source image. |
|
178 * @param $destination |
|
179 * The file path of the destination image. |
|
180 * @param $width |
|
181 * The target width, in pixels. |
|
182 * @param $height |
|
183 * The target height, in pixels. |
|
184 * @return |
|
185 * TRUE or FALSE, based on success. |
|
186 */ |
|
187 function image_scale($source, $destination, $width, $height) { |
|
188 $info = image_get_info($source); |
|
189 |
|
190 // Don't scale up. |
|
191 if ($width >= $info['width'] && $height >= $info['height']) { |
|
192 return FALSE; |
|
193 } |
|
194 |
|
195 $aspect = $info['height'] / $info['width']; |
|
196 if ($aspect < $height / $width) { |
|
197 $width = (int)min($width, $info['width']); |
|
198 $height = (int)round($width * $aspect); |
|
199 } |
|
200 else { |
|
201 $height = (int)min($height, $info['height']); |
|
202 $width = (int)round($height / $aspect); |
|
203 } |
|
204 |
|
205 return image_toolkit_invoke('resize', array($source, $destination, $width, $height)); |
|
206 } |
|
207 |
|
208 /** |
|
209 * Resize an image to the given dimensions (ignoring aspect ratio). |
|
210 * |
|
211 * @param $source |
|
212 * The file path of the source image. |
|
213 * @param $destination |
|
214 * The file path of the destination image. |
|
215 * @param $width |
|
216 * The target width, in pixels. |
|
217 * @param $height |
|
218 * The target height, in pixels. |
|
219 * @return |
|
220 * TRUE or FALSE, based on success. |
|
221 */ |
|
222 function image_resize($source, $destination, $width, $height) { |
|
223 return image_toolkit_invoke('resize', array($source, $destination, $width, $height)); |
|
224 } |
|
225 |
|
226 /** |
|
227 * Rotate an image by the given number of degrees. |
|
228 * |
|
229 * @param $source |
|
230 * The file path of the source image. |
|
231 * @param $destination |
|
232 * The file path of the destination image. |
|
233 * @param $degrees |
|
234 * The number of (clockwise) degrees to rotate the image. |
|
235 * @param $background |
|
236 * An hexidecimal integer specifying the background color to use for the |
|
237 * uncovered area of the image after the rotation. E.g. 0x000000 for black, |
|
238 * 0xff00ff for magenta, and 0xffffff for white. |
|
239 * @return |
|
240 * TRUE or FALSE, based on success. |
|
241 */ |
|
242 function image_rotate($source, $destination, $degrees, $background = 0x000000) { |
|
243 return image_toolkit_invoke('rotate', array($source, $destination, $degrees, $background)); |
|
244 } |
|
245 |
|
246 /** |
|
247 * Crop an image to the rectangle specified by the given rectangle. |
|
248 * |
|
249 * @param $source |
|
250 * The file path of the source image. |
|
251 * @param $destination |
|
252 * The file path of the destination image. |
|
253 * @param $x |
|
254 * The top left co-ordinate, in pixels, of the crop area (x axis value). |
|
255 * @param $y |
|
256 * The top left co-ordinate, in pixels, of the crop area (y axis value). |
|
257 * @param $width |
|
258 * The target width, in pixels. |
|
259 * @param $height |
|
260 * The target height, in pixels. |
|
261 * @return |
|
262 * TRUE or FALSE, based on success. |
|
263 */ |
|
264 function image_crop($source, $destination, $x, $y, $width, $height) { |
|
265 return image_toolkit_invoke('crop', array($source, $destination, $x, $y, $width, $height)); |
|
266 } |
|
267 |
|
268 /** |
|
269 * @} End of "defgroup image". |
|
270 */ |