| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @file 5 * 6 * An ImageAPI supporting additional image plugins as modules. 7 * Images are treated as objects, and images are not written per 8 * manipulation as Drupal's core image handling works. 9 * 10 * 11 * imageapi image api workflow... 12 * $image = imageapi_image_open($path) to get an image object for $path... 13 * image_X($image, $arg1, $arg2) to manipulate image object... 14 * imageapi_image_close($image) to overwrite original image. 15 * 16 */ 17 18 /** 19 * Implementation of hook_perm(). 20 */ 21 function imageapi_perm() { 22 return array('administer imageapi'); 23 } 24 25 /** 26 * Implementation of hook_menu(). 27 */ 28 function imageapi_menu() { 29 $items = array(); 30 $items['admin/settings/imageapi'] = array( 31 'title' => 'ImageAPI', 32 'description' => 'Configure ImageAPI.', 33 'page callback' => 'drupal_get_form', 34 'page arguments' => array('imageapi_settings'), 35 'access arguments' => array('administer imageapi'), 36 ); 37 38 $toolkits = imageapi_get_available_toolkits(); 39 if ($toolkits) { 40 $items['admin/settings/imageapi/list'] = array( 41 'title' => 'List', 42 'type' => MENU_DEFAULT_LOCAL_TASK, 43 'weight' => -1, 44 ); 45 $items['admin/settings/imageapi/config'] = array( 46 'title' => 'Configure', 47 'type' => MENU_LOCAL_TASK, 48 'page callback' => 'drupal_get_form', 49 'page arguments' => array(imageapi_default_toolkit() .'_settings_form'), 50 'access arguments' => array('administer imageapi'), 51 ); 52 foreach ($toolkits as $module => $info) { 53 if (function_exists($module .'_settings_form')) { 54 $items['admin/settings/imageapi/config/'. $module] = array( 55 'title' => '@name', 56 'title arguments' => array('@name' => $info['name']), 57 'page callback' => 'drupal_get_form', 58 'page arguments' => array($module .'_settings_form'), 59 'access arguments' => array('administer imageapi'), 60 'type' => $module == imageapi_default_toolkit() ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK, 61 ); 62 } 63 else { 64 drupal_set_message(t('ImageAPI toolkit missing settings form'), 'error'); 65 } 66 } 67 } 68 return $items; 69 } 70 71 function imageapi_settings() { 72 $form = array(); 73 74 $toolkits = imageapi_get_available_toolkits(); 75 76 switch (count($toolkits)) { 77 case 0: 78 $form['imageapi_toolkits']['#value'] = t('There are no image toolkit modules enabled. Toolkit modules can be enabled from the <a href="!admin-build-modules">module configuration page</a>.', array('!admin-build-modules' => url('admin/build/modules'))); 79 return $form; 80 81 case 1: 82 $toolkit = key($toolkits); 83 // The variable needs to be manually set. Otherwise, if a user has two 84 // toolkits and disables the selected one they won't be able to select the 85 // remaing toolkit. 86 variable_set('imageapi_image_toolkit', $toolkit); 87 $form['imageapi_image_toolkit']['#value'] = t('The %toolkit module is the only enabled image toolkit. Drupal will use it for resizing, cropping and other image manipulations.', array('%toolkit' => $toolkits[$toolkit]['name'])); 88 return $form; 89 90 default: 91 $options = array(); 92 foreach ($toolkits as $module => $info) { 93 $options[$module] = $info['name']; 94 } 95 $form['imageapi_image_toolkit'] = array( 96 '#type' => 'radios', 97 '#title' => t('Select a default image processing toolkit'), 98 '#default_value' => imageapi_default_toolkit(), 99 '#options' => $options, 100 '#description' => t('This setting lets you choose which toolkit Drupal uses resizing, cropping and other image manipulations.'), 101 ); 102 } 103 104 return system_settings_form($form); 105 } 106 107 /** 108 * Return a list of available toolkits. 109 * 110 * @return 111 * An array of the enabled image toolkit modules. The module name is the key 112 * and the value is a sub-array with the module's 'name' and 'description'. 113 */ 114 function imageapi_get_available_toolkits() { 115 static $toolkits; 116 117 if (!isset($toolkits)) { 118 $toolkits = array(); 119 foreach (module_implements('imageapi_toolkit', TRUE) as $module) { 120 $info = drupal_parse_info_file(drupal_get_path('module', $module) .'/'. $module .'.info'); 121 $toolkits[$module] = array('name' => $info['name'], 'description' => $info['description']); 122 } 123 } 124 125 return $toolkits; 126 } 127 128 /** 129 * Retrieve the name of the currently used toolkit. 130 * 131 * @return 132 * String containing the name of the toolkit, or FALSE if none is available. 133 */ 134 function imageapi_default_toolkit() { 135 $toolkit = variable_get('imageapi_image_toolkit', 'imageapi_gd'); 136 // Verify that the image toolkit is available. 137 if (isset($toolkit) && module_exists($toolkit)) { 138 return $toolkit; 139 } 140 // If it's not fall back to first available toolist. 141 foreach (imageapi_get_available_toolkits() as $toolkit => $info) { 142 return $toolkit; 143 } 144 return FALSE; 145 } 146 147 148 /** 149 * Invokes the given method using the currently selected toolkit. 150 * 151 * @param $method 152 * A string containing the method to invoke. 153 * @param $image 154 * An image object returned by imageapi_image_open(). 155 * @param $params 156 * An optional array of parameters to pass to the toolkit method. 157 * @return 158 * Mixed values (typically Boolean indicating successful operation). 159 */ 160 function imageapi_toolkit_invoke($method, &$image, array $params = array()) { 161 $function = $image->toolkit . '_image_' . $method; 162 if (function_exists($function)) { 163 array_unshift($params, $image); 164 $params[0] = &$image; 165 return call_user_func_array($function, $params); 166 } 167 watchdog('imageapi', 'The selected image handling toolkit %toolkit can not correctly process %function.', array('%toolkit' => $image->toolkit, '%function' => $function), WATCHDOG_ERROR); 168 return FALSE; 169 } 170 171 /** 172 * Scales an image to the exact width and height given. 173 * 174 * This function achieves the target aspect ratio by cropping the original image 175 * equally on both sides, or equally on the top and bottom. This function is 176 * useful to create uniform sized avatars from larger images. 177 * 178 * The resulting image always has the exact target dimensions. 179 * 180 * @param $image 181 * An image object returned by imageapi_image_open(). 182 * @param $width 183 * The target width, in pixels. 184 * @param $height 185 * The target height, in pixels. 186 * @return 187 * TRUE or FALSE, based on success. 188 */ 189 function imageapi_image_scale_and_crop(&$image, $width, $height) { 190 $scale = max($width / $image->info['width'], $height / $image->info['height']); 191 $x = ($image->info['width'] * $scale - $width) / 2; 192 $y = ($image->info['height'] * $scale - $height) / 2; 193 194 if (imageapi_image_resize($image, $image->info['width'] * $scale, $image->info['height'] * $scale)) { 195 return imageapi_image_crop($image, $x, $y, $width, $height); 196 } 197 return FALSE; 198 } 199 200 /** 201 * Scales an image to the given width and height while maintaining aspect 202 * ratio. 203 * 204 * The resulting image can be smaller for one or both target dimensions. 205 * 206 * @param $image 207 * An image object returned by imageapi_image_open(). 208 * @param $width 209 * The target width, in pixels. This value is omitted then the scaling will 210 * based only on the height value. 211 * @param $height 212 * The target height, in pixels. This value is omitted then the scaling will 213 * based only on the width value. 214 * @param $upscale 215 * Boolean indicating that files smaller than the dimensions will be scalled 216 * up. This generally results in a low quality image. 217 * @return 218 * TRUE or FALSE, based on success. 219 */ 220 function imageapi_image_scale(&$image, $width = NULL, $height = NULL, $upscale = FALSE) { 221 $aspect = $image->info['height'] / $image->info['width']; 222 223 if ($upscale) { 224 // Set width/height according to aspect ratio if either is empty. 225 $width = !empty($width) ? $width : $height / $aspect; 226 $height = !empty($height) ? $height : $width / $aspect; 227 } 228 else { 229 // Set impossibly large values if the width and height aren't set. 230 $width = !empty($width) ? $width : 9999999; 231 $height = !empty($height) ? $height : 9999999; 232 233 // Don't scale up. 234 if (round($width) >= $image->info['width'] && round($height) >= $image->info['height']) { 235 return TRUE; 236 } 237 } 238 239 if ($aspect < $height / $width) { 240 $height = $width * $aspect; 241 } 242 else { 243 $width = $height / $aspect; 244 } 245 246 return imageapi_image_resize($image, $width, $height); 247 } 248 249 /** 250 * Resize an image to the given dimensions (ignoring aspect ratio). 251 * 252 * @param $image 253 * An image object returned by imageapi_image_open(). 254 * @param $width 255 * The target width, in pixels. 256 * @param $height 257 * The target height, in pixels. 258 * @return 259 * TRUE or FALSE, based on success. 260 */ 261 function imageapi_image_resize(&$image, $width, $height) { 262 $width = (int) round($width); 263 $height = (int) round($height); 264 265 return imageapi_toolkit_invoke('resize', $image, array($width, $height)); 266 } 267 268 /** 269 * Rotate an image by the given number of degrees. 270 * 271 * @param $image 272 * An image object returned by imageapi_image_open(). 273 * @param $degrees 274 * The number of (clockwise) degrees to rotate the image. 275 * @param $background 276 * An hexadecimal integer specifying the background color to use for the 277 * uncovered area of the image after the rotation. E.g. 0x000000 for black, 278 * 0xff00ff for magenta, and 0xffffff for white. For images that support 279 * transparency, this will default to transparent. Otherwise it will 280 * be white. 281 * @return 282 * TRUE or FALSE, based on success. 283 */ 284 function imageapi_image_rotate(&$image, $degrees, $background = NULL) { 285 return imageapi_toolkit_invoke('rotate', $image, array($degrees, $background)); 286 } 287 288 /** 289 * Sharpen an image given some sharpening parameters. 290 * 291 * NOTE: These parameters only have an effect when Imagemagick is used. 292 * GD will used a fixed convolution matrix as described in imageapi_gd.module 293 * 294 * @param $image 295 * An imageapi image object returned by imageapi_image_open(). 296 * @param $radius 297 * The radius of the gaussian, in pixels, not counting the center pixel. (default 0.5) 298 * @param $sigma 299 * The standard deviation of the gaussian, in pixels. (default 0.5) 300 * @param $amount 301 * The percentage of the difference between the original and the blur image that is 302 * added back into the original. (default 100) 303 * @param $threshold 304 * The threshold, as a fraction of max RGB levels, needed to apply the difference 305 * amount. (default 0.05) 306 * @return 307 * True or FALSE, based on success. 308 */ 309 function imageapi_image_sharpen(&$image, $radius, $sigma, $amount, $threshold) { 310 return imageapi_toolkit_invoke('sharpen', $image, array($radius, $sigma, $amount, $threshold)); 311 } 312 313 /** 314 * Crop an image to the rectangle specified by the given rectangle. 315 * 316 * @param $image 317 * An image object returned by imageapi_image_open(). 318 * @param $x 319 * The top left coordinate, in pixels, of the crop area (x axis value). 320 * @param $y 321 * The top left coordinate, in pixels, of the crop area (y axis value). 322 * @param $width 323 * The target width, in pixels. 324 * @param $height 325 * The target height, in pixels. 326 * @return 327 * TRUE or FALSE, based on success. 328 */ 329 function imageapi_image_crop(&$image, $x, $y, $width, $height) { 330 $aspect = $image->info['height'] / $image->info['width']; 331 if (empty($height)) $height = $width / $aspect; 332 if (empty($width)) $width = $height * $aspect; 333 334 $width = (int) round($width); 335 $height = (int) round($height); 336 337 return imageapi_toolkit_invoke('crop', $image, array($x, $y, $width, $height)); 338 } 339 340 /** 341 * Convert an image to grayscale. 342 * 343 * @param $image 344 * An image object returned by imageapi_image_open(). 345 * @return 346 * TRUE or FALSE, based on success. 347 */ 348 function imageapi_image_desaturate(&$image) { 349 return imageapi_toolkit_invoke('desaturate', $image); 350 } 351 352 /** 353 * Open an image file and return an image object. 354 * 355 * Any changes to the file are not saved until imageapi_image_close() is called. 356 * 357 * @param $file 358 * Path to an image file. 359 * @param $toolkit 360 * An optional, image toolkit name to override the default. 361 * @return 362 * An image object or FALSE if there was a problem loading the file. The 363 * image object has the following properties: 364 * - 'source' - The original file path. 365 * - 'info' - The array of information returned by image_get_info() 366 * - 'toolkit' - The name of the image toolkit requested when the image was 367 * loaded. 368 * Image tookits may add additional properties. The caller is advised not to 369 * monkey about with them. 370 */ 371 function imageapi_image_open($file, $toolkit = FALSE) { 372 if (!$toolkit) { 373 $toolkit = imageapi_default_toolkit(); 374 } 375 if ($toolkit) { 376 $image = new stdClass(); 377 $image->source = $file; 378 $image->info = image_get_info($file); 379 $image->toolkit = $toolkit; 380 if (imageapi_toolkit_invoke('open', $image)) { 381 return $image; 382 } 383 } 384 return FALSE; 385 } 386 387 /** 388 * Close the image and save the changes to a file. 389 * 390 * @param $image 391 * An image object returned by imageapi_image_open(). The object's 'info' 392 * property will be updated if the file is saved successfully. 393 * @param $destination 394 * Destination path where the image should be saved. If it is empty the 395 * original image file will be overwritten. 396 * @return 397 * TRUE or FALSE, based on success. 398 */ 399 function imageapi_image_close($image, $destination = NULL) { 400 if (empty($destination)) { 401 $destination = $image->source; 402 } 403 if ($return = imageapi_toolkit_invoke('close', $image, array($destination))) { 404 // Clear the cached file size and refresh the image information. 405 clearstatcache(); 406 $image->info = image_get_info($destination); 407 408 if (@chmod($destination, 0664)) { 409 return $return; 410 } 411 watchdog('imageapi', 'Could not set permissions on destination file: %file', array('%file' => $destination)); 412 } 413 return FALSE; 414 } 415 416 417 /** 418 * Convert a hex string to its RGBA (Red, Green, Blue, Alpha) integer 419 * components. 420 * 421 * @param $hex 422 * A string specifing an RGB color in the formats: 423 * '#ABC','ABC','#ABCD','ABCD','#AABBCC','AABBCC','#AABBCCDD','AABBCCDD' 424 * @return 425 * An array with four elements for red, green, blue, and alpha. 426 */ 427 function imageapi_hex2rgba($hex) { 428 $hex = ltrim($hex, '#'); 429 if (preg_match('/^[0-9a-f]{3}$/i', $hex)) { 430 // 'FA3' is the same as 'FFAA33' so r=FF, g=AA, b=33 431 $r = str_repeat($hex{0}, 2); 432 $g = str_repeat($hex{1}, 2); 433 $b = str_repeat($hex{2}, 2); 434 $a = '0'; 435 } 436 elseif (preg_match('/^[0-9a-f]{6}$/i', $hex)) { 437 // #FFAA33 or r=FF, g=AA, b=33 438 list($r, $g, $b) = str_split($hex, 2); 439 $a = '0'; 440 } 441 elseif (preg_match('/^[0-9a-f]{8}$/i', $hex)) { 442 // #FFAA33 or r=FF, g=AA, b=33 443 list($r, $g, $b, $a) = str_split($hex, 2); 444 } 445 elseif (preg_match('/^[0-9a-f]{4}$/i', $hex)) { 446 // 'FA37' is the same as 'FFAA3377' so r=FF, g=AA, b=33, a=77 447 $r = str_repeat($hex{0}, 2); 448 $g = str_repeat($hex{1}, 2); 449 $b = str_repeat($hex{2}, 2); 450 $a = str_repeat($hex{3}, 2); 451 } 452 else { 453 //error: invalide hex string, TODO: set form error.. 454 return FALSE; 455 } 456 457 $r = hexdec($r); 458 $g = hexdec($g); 459 $b = hexdec($b); 460 $a = hexdec($a); 461 return array($r, $g, $b, $a); 462 } 463
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |