721 lines
21 KiB
Plaintext
721 lines
21 KiB
Plaintext
<?php
|
|
// $Id$
|
|
|
|
/**
|
|
* @file
|
|
* Exposes global functionality for creating image styles.
|
|
*/
|
|
|
|
/**
|
|
* Implement hook_menu().
|
|
*/
|
|
function image_menu() {
|
|
$items = array();
|
|
|
|
$items['image/generate/%image_style'] = array(
|
|
'title' => 'Generate image style',
|
|
'page callback' => 'image_style_generate',
|
|
'page arguments' => array(2),
|
|
'access callback' => TRUE,
|
|
'type' => MENU_CALLBACK,
|
|
);
|
|
|
|
return $items;
|
|
}
|
|
|
|
/**
|
|
* Implement hook_theme().
|
|
*/
|
|
function image_theme() {
|
|
return array(
|
|
'image_style' => array(
|
|
'arguments' => array('style' => NULL, 'path' => NULL, 'alt' => '', 'title' => '', 'attributes' => NULL, 'getsize' => TRUE),
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Implement hook_flush_caches().
|
|
*/
|
|
function image_flush_caches() {
|
|
return array('cache_image');
|
|
}
|
|
|
|
/**
|
|
* Implement hook_file_download().
|
|
*
|
|
* Control the access to files underneath the styles directory.
|
|
*/
|
|
function image_file_download($filepath) {
|
|
if (strpos($filepath, 'styles/') === 0) {
|
|
$args = explode('/', $filepath);
|
|
// Discard the first part of the path (styles).
|
|
array_shift($args);
|
|
// Get the style name from the second part.
|
|
$style_name = array_shift($args);
|
|
// Then the remaining parts are the path to the image.
|
|
$original_path = implode('/', $args);
|
|
|
|
// Check that the file exists and is an image.
|
|
if ($info = image_get_info(file_create_path($filepath))) {
|
|
// Check the permissions of the original to grant access to this image.
|
|
$headers = module_invoke_all('file_download', $original_path);
|
|
if (!in_array(-1, $headers)) {
|
|
return array(
|
|
'Content-Type: ' . $info['mime_type'],
|
|
'Content-Length: ' . $info['file_size'],
|
|
);
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implement hook_file_move().
|
|
*/
|
|
function image_file_move($file, $source) {
|
|
// Delete any image derivatives at the original image path.
|
|
image_path_flush($file->filepath);
|
|
}
|
|
|
|
/**
|
|
* Implement hook_file_delete().
|
|
*/
|
|
function image_file_delete($file) {
|
|
// Delete any image derivatives of this image.
|
|
image_path_flush($file->filepath);
|
|
}
|
|
|
|
/**
|
|
* Clear cached versions of a specific file in all styles.
|
|
*
|
|
* @param $path
|
|
* The Drupal file path to the original image.
|
|
*/
|
|
function image_path_flush($path) {
|
|
$path = file_directory_strip($path);
|
|
$styles = image_styles();
|
|
foreach ($styles as $style) {
|
|
if ($path = file_create_path('styles/' . $style['name'] . '/' . $path)) {
|
|
file_unmanaged_delete($path);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get an array of all styles and their settings.
|
|
*
|
|
* @return
|
|
* An array of styles keyed by the image style ID (isid).
|
|
* @see image_style_load()
|
|
*/
|
|
function image_styles() {
|
|
$styles = &drupal_static(__FUNCTION__);
|
|
|
|
// Grab from cache or build the array.
|
|
if (!isset($styles)) {
|
|
if ($cache = cache_get('image_styles', 'cache')) {
|
|
$styles = $cache->data;
|
|
}
|
|
else {
|
|
$styles = array();
|
|
$result = db_select('image_styles', NULL, array('fetch' => PDO::FETCH_ASSOC))
|
|
->fields('image_styles')
|
|
->orderBy('name')
|
|
->execute();
|
|
foreach ($result as $style) {
|
|
$styles[$style['name']] = $style;
|
|
$styles[$style['name']]['effects'] = image_style_effects($style);
|
|
}
|
|
|
|
cache_set('image_styles', $styles);
|
|
}
|
|
}
|
|
|
|
return $styles;
|
|
}
|
|
|
|
/**
|
|
* Load a style by style name or ID. May be used as a loader for menu items.
|
|
*
|
|
* @param $name
|
|
* The name of the style.
|
|
* @param $isid
|
|
* Optional. The numeric id of a style if the name is not known.
|
|
* @return
|
|
* An image style array containing the following keys:
|
|
* - "isid": The unique image style ID.
|
|
* - "name": The unique image style name.
|
|
* - "effects": An array of effects within this style.
|
|
* If the style name or ID is not valid, an empty array is returned.
|
|
* @see image_effect_load()
|
|
*/
|
|
function image_style_load($name = NULL, $isid = NULL) {
|
|
$styles = image_styles();
|
|
|
|
// If retrieving by name.
|
|
if (isset($name) && isset($styles[$name])) {
|
|
return $styles[$name];
|
|
}
|
|
|
|
// If retrieving by image style id.
|
|
if (isset($isid)) {
|
|
foreach ($styles as $name => $style) {
|
|
if ($style['isid'] == $isid) {
|
|
return $style;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Otherwise the style was not found.
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* Save an image style.
|
|
*
|
|
* @param style
|
|
* An image style array.
|
|
* @return
|
|
* A style array. In the case of a new style, 'isid' will be populated.
|
|
*/
|
|
function image_style_save($style) {
|
|
if (isset($style['isid']) && is_numeric($style['isid'])) {
|
|
// Load the existing style to make sure we account for renamed styles.
|
|
$old_style = image_style_load(NULL, $style['isid']);
|
|
image_style_flush($old_style);
|
|
drupal_write_record('image_styles', $style, 'isid');
|
|
if ($old_style['name'] != $style['name']) {
|
|
$style['old_name'] = $old_style['name'];
|
|
}
|
|
}
|
|
else {
|
|
drupal_write_record('image_styles', $style);
|
|
$style['is_new'] = TRUE;
|
|
}
|
|
|
|
// Let other modules update as necessary on save.
|
|
module_invoke_all('image_style_save', $style);
|
|
|
|
// Clear all caches and flush.
|
|
image_style_flush($style);
|
|
|
|
return $style;
|
|
}
|
|
|
|
/**
|
|
* Delete an image style.
|
|
*
|
|
* @param $style
|
|
* An image style array.
|
|
* @param $replacement_style_name
|
|
* (optional) When deleting a style, specify a replacement style name so
|
|
* that existing settings (if any) may be converted to a new style.
|
|
* @return
|
|
* TRUE on success.
|
|
*/
|
|
function image_style_delete($style, $replacement_style_name = '') {
|
|
image_style_flush($style);
|
|
|
|
db_delete('image_effects')->condition('isid', $style['isid'])->execute();
|
|
db_delete('image_styles')->condition('isid', $style['isid'])->execute();
|
|
|
|
// Let other modules update as necessary on save.
|
|
$style['old_name'] = $style['name'];
|
|
$style['name'] = $replacement_style_name;
|
|
module_invoke_all('image_style_delete', $style);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* Load all the effects for an image style.
|
|
*
|
|
* @param $style
|
|
* An image style array.
|
|
* @return
|
|
* An array of effects associated with specified style in the format
|
|
* array('isid' => array()), or an empty array if the specified style has
|
|
* no effects.
|
|
*/
|
|
function image_style_effects($style) {
|
|
$effects = image_effects();
|
|
$style_effects = array();
|
|
foreach ($effects as $effect) {
|
|
if ($style['isid'] == $effect['isid']) {
|
|
$style_effects[$effect['ieid']] = $effect;
|
|
}
|
|
}
|
|
|
|
return $style_effects;
|
|
}
|
|
|
|
/**
|
|
* Get an array of image styles suitable for using as select list options.
|
|
*
|
|
* @param $include_empty
|
|
* If TRUE a <none> option will be inserted in the options array.
|
|
* @return
|
|
* Array of image styles both key and value are set to style name.
|
|
*/
|
|
function image_style_options($include_empty = TRUE) {
|
|
$styles = image_styles();
|
|
$options = array();
|
|
if ($include_empty && !empty($styles)) {
|
|
$options[''] = t('<none>');
|
|
}
|
|
$options = array_merge($options, drupal_map_assoc(array_keys($styles)));
|
|
if (empty($options)) {
|
|
$options[''] = t('No defined styles');
|
|
}
|
|
return $options;
|
|
}
|
|
|
|
/**
|
|
* Menu callback; Given a style and image path, generate a derivative.
|
|
*
|
|
* This menu callback is always served after checking a token to prevent
|
|
* generation of unnecessary images. After generating an image transfer it to
|
|
* the requesting agent via file_transfer().
|
|
*/
|
|
function image_style_generate() {
|
|
$args = func_get_args();
|
|
$style = array_shift($args);
|
|
$style_name = $style['name'];
|
|
$path = implode('/', $args);
|
|
|
|
$source = file_create_path($path);
|
|
$path_md5 = md5($path);
|
|
$destination = image_style_path($style['name'], $path);
|
|
|
|
// Check that it's a defined style and that access was granted by
|
|
// image_style_generate_url().
|
|
if (!$style || !cache_get('access:' . $style_name . ':' . $path_md5, 'cache_image')) {
|
|
drupal_access_denied();
|
|
exit();
|
|
}
|
|
|
|
// Don't start generating the image if it is already in progress.
|
|
$cid = 'generate:' . $style_name . ':' . $path_md5;
|
|
if (cache_get($cid, 'cache_image')) {
|
|
print t('Image generation in progress, please try again shortly.');
|
|
exit();
|
|
}
|
|
|
|
// If the image has already been generated then send it.
|
|
if ($image = image_load($destination)) {
|
|
file_transfer($image->source, array('Content-type: ' . $image->info['mime_type'], 'Content-length: ' . $image->info['file_size']));
|
|
}
|
|
|
|
// Set a cache entry designating this image as being in-process.
|
|
cache_set($cid, $destination, 'cache_image');
|
|
|
|
// Try to generate the image.
|
|
if (image_style_create_derivative($style, $source, $destination)) {
|
|
$image = image_load($destination);
|
|
cache_clear_all($cid, 'cache_image');
|
|
file_transfer($image->source, array('Content-type: ' . $image->info['mime_type'], 'Content-length: ' . $image->info['file_size']));
|
|
}
|
|
else {
|
|
cache_clear_all($cid, 'cache_image');
|
|
watchdog('image', 'Unable to generate the derived image located at %path.', $destination);
|
|
print t('Error generating image.');
|
|
exit();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a new image based on an image style.
|
|
*
|
|
* @param $style
|
|
* An image style array.
|
|
* @param $source
|
|
* Path of the source file.
|
|
* @param $destination
|
|
* Path of the destination file.
|
|
* @return
|
|
* TRUE if an image derivative is generated, FALSE if no image derivative
|
|
* is generated. NULL if the derivative is being generated.
|
|
*/
|
|
function image_style_create_derivative($style, $source, $destination) {
|
|
// Get the folder for the final location of this style.
|
|
$directory = dirname($destination);
|
|
|
|
// Build the destination folder tree if it doesn't already exist.
|
|
if (!file_check_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
|
|
watchdog('image', 'Failed to create style directory: %directory', array('%directory' => $directory), WATCHDOG_ERROR);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!$image = image_load($source)) {
|
|
return FALSE;
|
|
}
|
|
|
|
foreach ($style['effects'] as $effect) {
|
|
image_effect_apply($image, $effect);
|
|
}
|
|
|
|
if (!image_save($image, $destination)) {
|
|
if (file_exists($destination)) {
|
|
watchdog('image', 'Cached image file %destination already exists. There may be an issue with your rewrite configuration.', array('%destination' => $destination), WATCHDOG_ERROR);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* Flush cached media for a style.
|
|
*
|
|
* @param $style
|
|
* An image style array.
|
|
*/
|
|
function image_style_flush($style) {
|
|
$style_directory = realpath(file_directory_path() . '/styles/' . $style['name']);
|
|
if (is_dir($style_directory)) {
|
|
file_unmanaged_delete_recursive($style_directory);
|
|
}
|
|
|
|
// Let other modules update as necessary on flush.
|
|
module_invoke_all('image_style_flush', $style);
|
|
|
|
// Clear image style and effect caches.
|
|
cache_clear_all('image_styles', 'cache');
|
|
cache_clear_all('image_effects', 'cache');
|
|
drupal_static_reset('image_styles');
|
|
drupal_static_reset('image_effects');
|
|
|
|
// Clear page caches when flushing.
|
|
if (module_exists('block')) {
|
|
cache_clear_all('*', 'cache_block', TRUE);
|
|
}
|
|
cache_clear_all('*', 'cache_page', TRUE);
|
|
}
|
|
|
|
/**
|
|
* Return the complete URL to an image when using a style.
|
|
*
|
|
* If the image has already been created then its location will be returned. If
|
|
* it does not then image_style_generate_url() will be called.
|
|
*
|
|
* @param $style_name
|
|
* The name of the style to be used with this image.
|
|
* @param $path
|
|
* The path to the image.
|
|
* @return
|
|
* The absolute URL where a style image can be downloaded, suitable for use
|
|
* in an <img> tag. If the site is using the default method for generating
|
|
* images, the image may not yet exist and will only be created when a
|
|
* visitor's browser requests the file.
|
|
* @see image_style_generate_url()
|
|
* @see image_style_path()
|
|
*/
|
|
function image_style_url($style_name, $path) {
|
|
$style_path = image_style_path($style_name, $path);
|
|
if (file_exists($style_path)) {
|
|
return file_create_url($style_path);
|
|
}
|
|
return image_style_generate_url($style_name, $path);
|
|
}
|
|
|
|
/**
|
|
* Return the URL for an image derivative given a style and image path.
|
|
*
|
|
* This function is the default image generation method. It returns a URL for
|
|
* an image that can be used in an <img> tag. When the browser requests the
|
|
* image at image/generate/[style_name]/[path] the image is generated if it does
|
|
* not already exist and then served to the browser. This allows each image to
|
|
* have its own PHP instance (and memory limit) for generation of the new image.
|
|
*
|
|
* @param $style_name
|
|
* The name of the style to be used with this image.
|
|
* @param $path
|
|
* The path to the image.
|
|
* @return
|
|
* The absolute URL where a style image can be downloaded, suitable for use
|
|
* in an <img> tag. Requesting the URL will cause the image to be created.
|
|
* @see image_style_generate()
|
|
* @see image_style_url()
|
|
*/
|
|
function image_style_generate_url($style_name, $path) {
|
|
$destination = image_style_path($style_name, $path);
|
|
|
|
// If the image already exists use that rather than regenerating it.
|
|
if (file_exists($destination)) {
|
|
return image_style_url($style_name, $path);
|
|
}
|
|
|
|
// Disable page cache for this request. This prevents anonymous users from
|
|
// needlessly hitting the image generation URL when the image already exists.
|
|
$GLOBALS['conf']['cache'] = CACHE_DISABLED;
|
|
|
|
// Set a cache entry to grant access to this style/image path. This will be
|
|
// checked by image_style_generate().
|
|
cache_set('access:' . $style_name . ':' . md5($path), 1, 'cache_image', time() + 600);
|
|
|
|
// Generate a callback path for the image.
|
|
$url = url('image/generate/' . $style_name . '/' . $path, array('absolute' => TRUE));
|
|
return $url;
|
|
}
|
|
|
|
/**
|
|
* Return a relative path to an image when using a style.
|
|
*
|
|
* The path returned by this function may not exist. The default generation
|
|
* method only creates images when they are requested by a user's browser.
|
|
*
|
|
* @param $style_name
|
|
* The name of the style to be used with this image.
|
|
* @param $path
|
|
* The path to the image.
|
|
* @return
|
|
* The path to an image style image relative to Drupal's root.
|
|
* @see image_style_url()
|
|
*/
|
|
function image_style_path($style_name, $path) {
|
|
return file_directory_path() . '/styles/' . $style_name . '/' . file_directory_strip($path);
|
|
}
|
|
|
|
/**
|
|
* Pull in effects exposed by other modules using hook_image_effect_info().
|
|
*
|
|
* @return
|
|
* An array of effects to be used when transforming images.
|
|
* @see hook_image_effect_info()
|
|
* @see image_effect_definition_load()
|
|
*/
|
|
function image_effect_definitions() {
|
|
$effects = &drupal_static(__FUNCTION__);
|
|
|
|
if (!isset($effects)) {
|
|
if ($cache = cache_get('image_effects') && !empty($cache->data)) {
|
|
$effects = $cache->data;
|
|
}
|
|
else {
|
|
$effects = array();
|
|
foreach (module_implements('image_effect_info') as $module) {
|
|
foreach (module_invoke($module, 'image_effect_info') as $name => $effect) {
|
|
// Ensure the current toolkit supports the effect.
|
|
$effect['module'] = $module;
|
|
$effect['name'] = $name;
|
|
$effect['data'] = isset($effect['data']) ? $effect['data'] : array();
|
|
$effects[$name] = $effect;
|
|
};
|
|
}
|
|
uasort($effects, '_image_effect_definitions_sort');
|
|
cache_set('image_effects', $effects);
|
|
}
|
|
}
|
|
|
|
return $effects;
|
|
}
|
|
|
|
/**
|
|
* Load the definition for an effect.
|
|
*
|
|
* The effect definition is a set of core properties for an effect, not
|
|
* containing any user-settings. The definition defines various functions to
|
|
* call when configuring or executing an effect. This loader is mostly for
|
|
* internal use within image.module. Use image_effect_load() or
|
|
* image_style_load() to get effects that contain configuration.
|
|
*
|
|
* @param $effect
|
|
* The name of the effect definition to load.
|
|
* @return
|
|
* An array containing the image effect definition with the following keys:
|
|
* - "effect": The unique name for the effect being performed. Usually prefixed
|
|
* with the name of the module providing the effect.
|
|
* - "module": The module providing the effect.
|
|
* - "help": A description of the effect.
|
|
* - "function": The name of the function that will execute the effect.
|
|
* - "form": i'm (optional) The name of a function to configure the effect.
|
|
* - "summary": (optional) The name of a theme function that will display a
|
|
* one-line summary of the effect. Does not include the "theme_" prefix.
|
|
*/
|
|
function image_effect_definition_load($effect) {
|
|
$definitions = image_effect_definitions();
|
|
return isset($definitions[$effect]) ? $definitions[$effect] : FALSE;
|
|
}
|
|
|
|
/**
|
|
* Load all image effects from the database.
|
|
*
|
|
* @return
|
|
* An array of all image effects.
|
|
* @see image_effect_load()
|
|
*/
|
|
function image_effects() {
|
|
$effects = &drupal_static(__FUNCTION__);
|
|
|
|
if (!isset($effects)) {
|
|
$effects = array();
|
|
|
|
// Add database image effects.
|
|
$result = db_select('image_effects', NULL, array('fetch' => PDO::FETCH_ASSOC))
|
|
->fields('image_effects')
|
|
->orderBy('image_effects.weight', 'ASC')
|
|
->execute();
|
|
foreach ($result as $effect) {
|
|
$effect['data'] = unserialize($effect['data']);
|
|
$definition = image_effect_definition_load($effect['name']);
|
|
// Do not load effects whose definition cannot be found.
|
|
if ($definition) {
|
|
$effect = array_merge($definition, $effect);
|
|
$effects[$effect['ieid']] = $effect;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $effects;
|
|
}
|
|
|
|
/**
|
|
* Load a single image effect.
|
|
*
|
|
* @param $ieid
|
|
* The image effect ID.
|
|
* @return
|
|
* An image effect array, consisting of the following keys:
|
|
* - "ieid": The unique image effect ID.
|
|
* - "isid": The unique image style ID that contains this effect.
|
|
* - "weight": The weight of this effect within the image style.
|
|
* - "effect": The name of the effect definition that powers this effect.
|
|
* - "data": An associative array of configuration options for this effect.
|
|
* Besides these keys, the entirety of the image definition is merged into
|
|
* the image effect array. Returns FALSE if the specified effect cannot be
|
|
* found.
|
|
* @see image_style_load()
|
|
* @see image_effect_definition_load()
|
|
*/
|
|
function image_effect_load($ieid) {
|
|
$effects = image_effects();
|
|
return isset($effects[$ieid]) ? $effects[$ieid] : FALSE;
|
|
}
|
|
|
|
/**
|
|
* Save an image effect.
|
|
*
|
|
* @param $effect
|
|
* An image effect array.
|
|
* @return
|
|
* An image effect array. In the case of a new effect 'ieid' will be set.
|
|
*/
|
|
function image_effect_save($effect) {
|
|
if (!empty($effect['ieid'])) {
|
|
drupal_write_record('image_effects', $effect, 'ieid');
|
|
}
|
|
else {
|
|
drupal_write_record('image_effects', $effect);
|
|
}
|
|
$style = image_style_load(NULL, $effect['isid']);
|
|
image_style_flush($style);
|
|
return $effect;
|
|
}
|
|
|
|
/**
|
|
* Delete an image effect.
|
|
*
|
|
* @param $effect
|
|
* An image effect array.
|
|
*/
|
|
function image_effect_delete($effect) {
|
|
db_delete('image_effects')->condition('ieid', $effect['ieid'])->execute();
|
|
$style = image_style_load(NULL, $effect['isid']);
|
|
image_style_flush($style);
|
|
}
|
|
|
|
/**
|
|
* Given an image object and effect, perform the effect on the file.
|
|
*
|
|
* @param $image
|
|
* An image object returned by image_load().
|
|
* @param $effect
|
|
* An image effect array.
|
|
* @return
|
|
* TRUE on success. FALSE if unable to perform effect on image.
|
|
*/
|
|
function image_effect_apply(&$image, $effect) {
|
|
if (drupal_function_exists($effect['effect callback'])) {
|
|
return call_user_func($effect['effect callback'], $image, $effect['data']);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* Return a themed image using a specific image style.
|
|
*
|
|
* @param $style_name
|
|
* The name of the style to be used to alter the original image.
|
|
* @param $path
|
|
* The path of the image file relative to the Drupal files directory.
|
|
* This function does not work with images outside the files directory nor
|
|
* with remotely hosted images.
|
|
* @param $alt
|
|
* The alternative text for text-based browsers.
|
|
* @param $title
|
|
* The title text is displayed when the image is hovered in some popular
|
|
* browsers.
|
|
* @param $attributes
|
|
* Associative array of attributes to be placed in the img tag.
|
|
* @param $getsize
|
|
* If set to TRUE, the image's dimension are fetched and added as
|
|
* width/height attributes.
|
|
* @return
|
|
* A string containing the image tag.
|
|
* @ingroup themeable
|
|
*/
|
|
function theme_image_style($style_name, $path, $alt = '', $title = '', $attributes = NULL, $getsize = TRUE) {
|
|
// theme_image() can only honor the $getsize parameter with local file paths.
|
|
// The derivative image is not created until it has been requested so the file
|
|
// may not yet exist, in this case we just fallback to the URL.
|
|
$style_path = image_style_path($style_name, $path);
|
|
if (!file_exists($style_path)) {
|
|
$style_path = image_style_url($style_name, $path);
|
|
}
|
|
return theme('image', $style_path, $alt, $title, $attributes, $getsize);
|
|
}
|
|
|
|
/**
|
|
* Accept a percentage and return it in pixels.
|
|
*/
|
|
function image_filter_percent($value, $current_pixels) {
|
|
if (strpos($value, '%') !== FALSE) {
|
|
$value = str_replace('%', '', $value) * 0.01 * $current_pixels;
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Accept a keyword (center, top, left, etc) and return it as a pixel offset.
|
|
*
|
|
* @param $value
|
|
* @param $current_pixels
|
|
* @param $new_pixels
|
|
*/
|
|
function image_filter_keyword($value, $current_pixels, $new_pixels) {
|
|
switch ($value) {
|
|
case 'top':
|
|
case 'left':
|
|
return 0;
|
|
|
|
case 'bottom':
|
|
case 'right':
|
|
return $current_pixels - $new_pixels;
|
|
|
|
case 'center':
|
|
return $current_pixels / 2 - $new_pixels / 2;
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Internal function for sorting image effect definitions through uasort().
|
|
*
|
|
* @see image_effect_definitions()
|
|
*/
|
|
function _image_effect_definitions_sort($a, $b) {
|
|
return strcasecmp($a['name'], $b['name']);
|
|
}
|