'admin/settings/imageapi', 'title' => t('ImageAPI'), 'description' => t('Configure ImageAPI.'), 'callback' => 'drupal_get_form', 'callback arguments' => array('imageapi_settings'), ); } else { $toolkits = imageapi_get_available_toolkits(); if ($toolkits) { $items[] = array( 'path' => 'admin/settings/imageapi/list', 'title' => 'List', 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -1, ); $items[] = array( 'path' => 'admin/settings/imageapi/config', 'title' => 'Configure', 'type' => MENU_LOCAL_TASK, 'callback' => 'drupal_get_form', 'callback arguments' => array(imageapi_default_toolkit() .'_settings_form'), ); foreach ($toolkits as $module => $info) { $items[] = array( 'path' => 'admin/settings/imageapi/config/'. $module, 'title' => $info['name'], 'callback' => 'drupal_get_form', 'callback arguments' => array($module .'_settings_form'), 'type' => $module == imageapi_default_toolkit() ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK, ); } } } return $items; } function imageapi_settings() { $form = array(); $toolkits = imageapi_get_available_toolkits(); switch (count($toolkits)) { case 0: $form['imageapi_toolkits']['#value'] = t('There are no image toolkit modules enabled. Toolkit modules can be enabled from the module configuration page.', array('!admin-build-modules' => url('admin/build/modules'))); return $form; case 1: $toolkit = key($toolkits); // The variable needs to be manually set. Otherwise, if a user has two // toolkits and disables the selected one they won't be able to select the // remaing toolkit. variable_set('imageapi_image_toolkit', $toolkit); $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'])); return $form; default: $options = array(); foreach ($toolkits as $module => $info) { $options[$module] = $info['name']; } $form['imageapi_image_toolkit'] = array( '#type' => 'radios', '#title' => t('Select a default image processing toolkit'), '#default_value' => imageapi_default_toolkit(), '#options' => $options, '#description' => t('This setting lets you choose which toolkit Drupal uses resizing, cropping and other image manipulations.'), ); } return system_settings_form($form); } /** * Implementation of hook_requirements(). */ function imageapi_requirements($phase) { $requirements = array(); // Ensure translations don't break at install time $t = get_t(); if (version_compare(phpversion(), IMAGEAPI_MINIMUM_PHP) < 0) { $requirements['imageapi_php'] = array( 'title' => $t('ImageAPI PHP'), 'description' => $t('ImageAPI requires at least PHP %version.', array('%version' => IMAGEAPI_MINIMUM_PHP)), 'severity' => REQUIREMENT_ERROR ); } return $requirements; } /** * Return a list of available toolkits. * * @return * An array of the enabled image toolkit modules. The module name is the key * and the value is a sub-array with the module's 'name' and 'description'. */ function imageapi_get_available_toolkits() { static $toolkits; if (!isset($toolkits)) { $toolkits = array(); foreach (module_implements('imageapi_toolkit', TRUE) as $module) { $info = _module_parse_info_file(drupal_get_path('module', $module) .'/'. $module .'.info'); $toolkits[$module] = array('name' => $info['name'], 'description' => $info['description']); } } return $toolkits; } /** * Retrieve the name of the currently used toolkit. * * @return * String containing the name of the toolkit, or FALSE if none is available. */ function imageapi_default_toolkit() { $toolkit = variable_get('imageapi_image_toolkit', 'imageapi_gd'); // Verify that the image toolkit is available. if (isset($toolkit) && module_exists($toolkit)) { return $toolkit; } return FALSE; } /** * Scales an image to the exact width and height given. Achieves the * target aspect ratio by cropping the original image equally on both * sides, or equally on the top and bottom. This function is, for * example, useful to create uniform sized avatars from larger images. * * The resulting image always has the exact target dimensions. * * @param $image * An ImageAPI Image object. * @param $width * The target width in pixels. * @param $height * The target height in pixels. * @return * Modified ImageAPI Image object. */ function imageapi_image_scale_and_crop(&$image, $width, $height) { $scale = max($width / $image->info['width'], $height / $image->info['height']); $x = round(($image->info['width'] * $scale - $width) / 2); $y = round(($image->info['height'] * $scale - $height) / 2); if (imageapi_image_resize($image, $image->info['width'] * $scale, $image->info['height'] * $scale)) { return imageapi_image_crop($image, $x, $y, $width, $height); } return FALSE; } /** * Scales an image to the given width and height while maintaining aspect * ratio. * * The resulting image can be smaller for one or both target dimensions. * * @param $image * An ImageAPI Image object. * @param $width * The target width in pixels. * @param $height * The target height in pixels. * @param $upscale * Allow upscaling. * @return * TRUE or FALSE, based on success. */ function imageapi_image_scale(&$image, $width, $height, $upscale = FALSE) { // Don't scale up. if (!$upscale && $width >= $image->info['width'] && $height >= $image->info['height']) { return TRUE; } $aspect = $image->info['height'] / $image->info['width']; if ($aspect < $height / $width) { $height = (int) round($width * $aspect); } else { $width = (int) round($height / $aspect); } return call_user_func($image->toolkit .'_image_resize', $image, $width, $height); } /** * Resize an image to the given dimensions (ignoring aspect ratio). * * @param $source The filepath of the source image. * @param $source * The filepath of the source image. * @param $destination * The file path of the destination image. * @param $width * The target width in pixels. * @param $height * The target height in pixels. * @param $toolkit * An optional override of the default image toolkit. * @return * TRUE or FALSE, based on success. */ function imageapi_image_resize(&$image, $width, $height) { return call_user_func($image->toolkit .'_image_resize', $image, $width, $height); } /** * Rotate an image by the given number of degrees. * * @param $source * The filepath of the source image. * @param $destination * The file path of the destination image. * @param $degrees * The number of (clockwise) degrees to rotate the image. * @param $bg_color * An hexidecimal integer specifying the background color to use for the * uncovered area of the image after the rotation. E.g. 0x000000 for black, * 0xff00ff for magenta, and 0xffffff for white. * @param $toolkit * An optional override of the default image toolkit. * @return * TRUE or FALSE, based on success. */ function imageapi_image_rotate(&$image, $degrees, $bgcolor = 0x000000) { return call_user_func($image->toolkit .'_image_rotate', $image, $degrees, $bgcolor); } /** * Crop an image to the rectangle specified by the given rectangle. * * @param $image * An imageapi image object. * @param $x * The top left co-ordinate of the crop area (x axis value). * @param $y * The top left co-ordinate of the crop area (y axis value). * @param $width * The target width in pixels. * @param $height * The target height in pixels. * @return * modifed image object. */ function imageapi_image_crop(&$image, $x, $y, $width, $height) { return call_user_func($image->toolkit .'_image_crop', $image, $x, $y, $width, $height); } function imageapi_image_desaturate(&$image) { return call_user_func($image->toolkit .'_image_desaturate', $image); } function imageapi_image_open($file, $toolkit = FALSE) { if (!$toolkit) { $toolkit = imageapi_default_toolkit(); } if ($toolkit) { $image = new StdClass(); $image->source = $file; $image->info = image_get_info($file); $image->toolkit = $toolkit; if ($image = call_user_func($image->toolkit.'_image_open', $image)) { return $image; } } watchdog('imageapi', t('ImageAPI failed to open %file with %toolkit', array('%file' => $file, '%toolkit' => $toolkit)), WATCHDOG_WARNING); return FALSE; } /** * Write an image to a file. * * @param $image * imageAPI image object. * * @param $destination * destination path where image should be saved. If it is empty the original image will * be over written. */ function imageapi_image_close($image, $destination = '') { if (empty($destination)) { $destination = $image->source; } if ($return = call_user_func($image->toolkit .'_image_close', $image, $destination)) { if (@chmod($destination, 0775)) { return $return; } watchdog('imageapi', t('Could not set permissons on destination file: %file', array('%file' => $destination))); } return FALSE; }