/[drupal]/drupal/includes/image.inc
ViewVC logotype

Contents of /drupal/includes/image.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.38 - (show annotations) (download) (as text)
Tue Sep 1 17:49:10 2009 UTC (2 months, 3 weeks ago) by webchick
Branch: MAIN
CVS Tags: DRUPAL-7-0-UNSTABLE-9, DRUPAL-7-0-UNSTABLE-10, HEAD
Changes since 1.37: +32 -26 lines
File MIME type: text/x-php
#269337 by egfrith and wrunt: Added support for more image types (PDF, TIFF, EPS, etc.).
1 <?php
2 // $Id: image.inc,v 1.37 2009/08/24 00:14:18 webchick 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 discovered based on the associated module's
25 * hook_image_toolkits. Additionally the image toolkit include file
26 * must be identified in the files array in the module.info file. The
27 * toolkit must then be enabled using the admin/config/media/image-toolkit
28 * form.
29 *
30 * Only one toolkit may be selected at a time. If a module author wishes to call
31 * a specific toolkit they can check that it is installed by calling
32 * image_get_available_toolkits(), and then calling its functions directly.
33 */
34
35 /**
36 * Return a list of available toolkits.
37 *
38 * @return
39 * An array with the toolkit names as keys and the descriptions as values.
40 */
41 function image_get_available_toolkits() {
42 // hook_image_toolkits returns an array of toolkit names.
43 $toolkits = module_invoke_all('image_toolkits');
44
45 $output = array();
46 foreach ($toolkits as $name => $info) {
47 // Only allow modules that aren't marked as unavailable.
48 if ($info['available']) {
49 $output[$name] = $info['title'];
50 }
51 }
52
53 return $output;
54 }
55
56 /**
57 * Retrieve the name of the currently used toolkit.
58 *
59 * @return
60 * String containing the name of the selected toolkit, or FALSE on error.
61 */
62 function image_get_toolkit() {
63 static $toolkit;
64
65 if (!isset($toolkit)) {
66 $toolkits = image_get_available_toolkits();
67 $toolkit = variable_get('image_toolkit', 'gd');
68 if (!isset($toolkits[$toolkit]) || !function_exists('image_' . $toolkit . '_load')) {
69 // The selected toolkit isn't available so return the first one found. If
70 // none are available this will return FALSE.
71 reset($toolkits);
72 $toolkit = key($toolkits);
73 }
74 }
75
76 return $toolkit;
77 }
78
79 /**
80 * Invokes the given method using the currently selected toolkit.
81 *
82 * @param $method
83 * A string containing the method to invoke.
84 * @param $image
85 * An image object returned by image_load().
86 * @param $params
87 * An optional array of parameters to pass to the toolkit method.
88 * @return
89 * Mixed values (typically Boolean indicating successful operation).
90 */
91 function image_toolkit_invoke($method, stdClass $image, array $params = array()) {
92 $function = 'image_' . $image->toolkit . '_' . $method;
93 if (function_exists($function)) {
94 array_unshift($params, $image);
95 return call_user_func_array($function, $params);
96 }
97 watchdog('image', 'The selected image handling toolkit %toolkit can not correctly process %function.', array('%toolkit' => $image->toolkit, '%function' => $function), WATCHDOG_ERROR);
98 return FALSE;
99 }
100
101 /**
102 * Get details about an image.
103 *
104 * Drupal supports GIF, JPG and PNG file formats when used with the GD
105 * toolkit, and may support others, depending on which toolkits are
106 * installed.
107 *
108 * @param $filepath
109 * String specifying the path of the image file.
110 * @param $toolkit
111 * An optional image toolkit name to override the default.
112 * @return
113 * FALSE, if the file could not be found or is not an image. Otherwise, a
114 * keyed array containing information about the image:
115 * - "width": Width, in pixels.
116 * - "height": Height, in pixels.
117 * - "extension": Commonly used file extension for the image.
118 * - "mime_type": MIME type ('image/jpeg', 'image/gif', 'image/png').
119 * - "file_size": File size in bytes.
120 */
121 function image_get_info($filepath, $toolkit = FALSE) {
122 $details = FALSE;
123 if (!is_file($filepath)) {
124 return $details;
125 }
126
127 if (!$toolkit) {
128 $toolkit = image_get_toolkit();
129 }
130 if ($toolkit) {
131 $image = new stdClass();
132 $image->source = $filepath;
133 $image->toolkit = $toolkit;
134 $details = image_toolkit_invoke('get_info', $image);
135 if (isset($details) && is_array($details)) {
136 $details['file_size'] = filesize($filepath);
137 }
138 }
139
140 return $details;
141 }
142
143 /**
144 * Scales an image to the exact width and height given.
145 *
146 * This function achieves the target aspect ratio by cropping the original image
147 * equally on both sides, or equally on the top and bottom. This function is
148 * useful to create uniform sized avatars from larger images.
149 *
150 * The resulting image always has the exact target dimensions.
151 *
152 * @param $image
153 * An image object returned by image_load().
154 * @param $width
155 * The target width, in pixels.
156 * @param $height
157 * The target height, in pixels.
158 * @return
159 * TRUE or FALSE, based on success.
160 *
161 * @see image_load()
162 * @see image_resize()
163 * @see image_crop()
164 */
165 function image_scale_and_crop(stdClass $image, $width, $height) {
166 $scale = max($width / $image->info['width'], $height / $image->info['height']);
167 $x = ($image->info['width'] * $scale - $width) / 2;
168 $y = ($image->info['height'] * $scale - $height) / 2;
169
170 if (image_resize($image, $image->info['width'] * $scale, $image->info['height'] * $scale)) {
171 return image_crop($image, $x, $y, $width, $height);
172 }
173 return FALSE;
174 }
175
176 /**
177 * Scales an image to the given width and height while maintaining aspect ratio.
178 *
179 * The resulting image can be smaller for one or both target dimensions.
180 *
181 * @param $image
182 * An image object returned by image_load().
183 * @param $width
184 * The target width, in pixels. This value is omitted then the scaling will
185 * based only on the height value.
186 * @param $height
187 * The target height, in pixels. This value is omitted then the scaling will
188 * based only on the width value.
189 * @param $upscale
190 * Boolean indicating that files smaller than the dimensions will be scalled
191 * up. This generally results in a low quality image.
192 * @return
193 * TRUE or FALSE, based on success.
194 *
195 * @see image_load()
196 * @see image_scale_and_crop()
197 */
198 function image_scale(stdClass $image, $width = NULL, $height = NULL, $upscale = FALSE) {
199 $aspect = $image->info['height'] / $image->info['width'];
200
201 if ($upscale) {
202 // Set width/height according to aspect ratio if either is empty.
203 $width = !empty($width) ? $width : $height / $aspect;
204 $height = !empty($height) ? $height : $width / $aspect;
205 }
206 else {
207 // Set impossibly large values if the width and height aren't set.
208 $width = !empty($width) ? $width : 9999999;
209 $height = !empty($height) ? $height : 9999999;
210
211 // Don't scale up.
212 if (round($width) >= $image->info['width'] && round($height) >= $image->info['height']) {
213 return TRUE;
214 }
215 }
216
217 if ($aspect < $height / $width) {
218 $height = $width * $aspect;
219 }
220 else {
221 $width = $height / $aspect;
222 }
223
224 return image_resize($image, $width, $height);
225 }
226
227 /**
228 * Resize an image to the given dimensions (ignoring aspect ratio).
229 *
230 * @param $image
231 * An image object returned by image_load().
232 * @param $width
233 * The target width, in pixels.
234 * @param $height
235 * The target height, in pixels.
236 * @return
237 * TRUE or FALSE, based on success.
238 *
239 * @see image_load()
240 * @see image_gd_resize()
241 */
242 function image_resize(stdClass $image, $width, $height) {
243 $width = (int) round($width);
244 $height = (int) round($height);
245
246 return image_toolkit_invoke('resize', $image, array($width, $height));
247 }
248
249 /**
250 * Rotate an image by the given number of degrees.
251 *
252 * @param $image
253 * An image object returned by image_load().
254 * @param $degrees
255 * The number of (clockwise) degrees to rotate the image.
256 * @param $background
257 * An hexadecimal integer specifying the background color to use for the
258 * uncovered area of the image after the rotation. E.g. 0x000000 for black,
259 * 0xff00ff for magenta, and 0xffffff for white. For images that support
260 * transparency, this will default to transparent. Otherwise it will
261 * be white.
262 * @return
263 * TRUE or FALSE, based on success.
264 *
265 * @see image_load()
266 * @see image_gd_rotate()
267 */
268 function image_rotate(stdClass $image, $degrees, $background = NULL) {
269 return image_toolkit_invoke('rotate', $image, array($degrees, $background));
270 }
271
272 /**
273 * Crop an image to the rectangle specified by the given rectangle.
274 *
275 * @param $image
276 * An image object returned by image_load().
277 * @param $x
278 * The top left coordinate, in pixels, of the crop area (x axis value).
279 * @param $y
280 * The top left coordinate, in pixels, of the crop area (y axis value).
281 * @param $width
282 * The target width, in pixels.
283 * @param $height
284 * The target height, in pixels.
285 * @return
286 * TRUE or FALSE, based on success.
287 *
288 * @see image_load()
289 * @see image_scale_and_crop()
290 * @see image_gd_crop()
291 */
292 function image_crop(stdClass $image, $x, $y, $width, $height) {
293 $aspect = $image->info['height'] / $image->info['width'];
294 if (empty($height)) $height = $width / $aspect;
295 if (empty($width)) $width = $height * $aspect;
296
297 $width = (int) round($width);
298 $height = (int) round($height);
299
300 return image_toolkit_invoke('crop', $image, array($x, $y, $width, $height));
301 }
302
303 /**
304 * Convert an image to grayscale.
305 *
306 * @param $image
307 * An image object returned by image_load().
308 * @return
309 * TRUE or FALSE, based on success.
310 *
311 * @see image_load()
312 * @see image_gd_desaturate()
313 */
314 function image_desaturate(stdClass $image) {
315 return image_toolkit_invoke('desaturate', $image);
316 }
317
318
319 /**
320 * Load an image file and return an image object.
321 *
322 * Any changes to the file are not saved until image_save() is called.
323 *
324 * @param $file
325 * Path to an image file.
326 * @param $toolkit
327 * An optional, image toolkit name to override the default.
328 * @return
329 * An image object or FALSE if there was a problem loading the file. The
330 * image object has the following properties:
331 * - 'source' - The original file path.
332 * - 'info' - The array of information returned by image_get_info()
333 * - 'toolkit' - The name of the image toolkit requested when the image was
334 * loaded.
335 * Image tookits may add additional properties. The caller is advised not to
336 * monkey about with them.
337 *
338 * @see image_save()
339 * @see image_get_info()
340 * @see image_get_available_toolkits()
341 * @see image_gd_load()
342 */
343 function image_load($file, $toolkit = FALSE) {
344 if (!$toolkit) {
345 $toolkit = image_get_toolkit();
346 }
347 if ($toolkit) {
348 $image = new stdClass();
349 $image->source = $file;
350 $image->info = image_get_info($file, $toolkit);
351 if (isset($image->info) && is_array($image->info)) {
352 $image->toolkit = $toolkit;
353 if (image_toolkit_invoke('load', $image)) {
354 return $image;
355 }
356 }
357 }
358 return FALSE;
359 }
360
361 /**
362 * Close the image and save the changes to a file.
363 *
364 * @param $image
365 * An image object returned by image_load(). The object's 'info' property
366 * will be updated if the file is saved successfully.
367 * @param $destination
368 * Destination path where the image should be saved. If it is empty the
369 * original image file will be overwritten.
370 * @return
371 * TRUE or FALSE, based on success.
372 *
373 * @see image_load()
374 * @see image_gd_save()
375 */
376 function image_save(stdClass $image, $destination = NULL) {
377 if (empty($destination)) {
378 $destination = $image->source;
379 }
380 if ($return = image_toolkit_invoke('save', $image, array($destination))) {
381 // Clear the cached file size and refresh the image information.
382 clearstatcache();
383 $image->info = image_get_info($destination, $image->toolkit);
384
385 if (drupal_chmod($destination)) {
386 return $return;
387 }
388 }
389 return FALSE;
390 }
391
392 /**
393 * @} End of "defgroup image".
394 */

  ViewVC Help
Powered by ViewVC 1.1.2