imagecache_reflect.module in ImageCache Reflect 7
Same filename and directory in other branches
Adds a reflection action for images.
File
imagecache_reflect.moduleView source
<?php
/**
* @file
* Adds a reflection action for images.
*/
/**
* Implements hook_image_effect_info().
*/
function imagecache_reflect_image_effect_info() {
$effects = array();
$effects['imagecache_reflect'] = array(
'label' => t('Reflect'),
'help' => t('Creates a reflection-like effect.'),
'effect callback' => 'imagecache_reflect_image',
'form callback' => 'imagecache_reflect_form',
'summary theme' => 'imagecache_reflect_summary',
);
return $effects;
}
/**
* Implements hook_theme().
*/
function imagecache_reflect_theme() {
return array(
'imagecache_reflect_summary' => array(
'variables' => array(
'data' => NULL,
),
),
);
}
/**
* Implements imagecache_hook_form()
*
* Config form for reflect action.
*/
function imagecache_reflect_form($action) {
$action = (array) $action;
$default = array(
'imagecache_reflect_color' => 'White',
'imagecache_reflect_position' => 'bottom',
'imagecache_reflect_size' => '50%',
'imagecache_reflect_transparent_source' => FALSE,
);
$action = array_merge($default, (array) $action);
$form = array();
$form['imagecache_reflect_color'] = array(
'#type' => 'textfield',
'#title' => t('Background color'),
'#description' => t('A hexadecimal color code preceded by a # or the name of the color can be used. eg. <em>white, blue, green, black, etc</em>'),
'#default_value' => $action['imagecache_reflect_color'],
'#size' => 10,
'#maxlength' => 20,
'#suffix' => '<div class="imagecache-reflect-color"></div>',
'#attributes' => array(
'class' => array(
'edit-imagecache-reflect-colorpicker',
),
),
'#element_validate' => array(
'_imagecache_reflect_validate_color',
),
'#attached' => array(
'library' => array(
array(
'system',
'farbtastic',
),
),
'js' => array(
drupal_get_path('module', 'imagecache_reflect') . '/imagecache_reflect.js',
),
),
);
$form['imagecache_reflect_transparent_source'] = array(
'#type' => 'checkbox',
'#title' => t('Transparent source image'),
'#default_value' => $action['imagecache_reflect_transparent_source'],
'#description' => t('If the image that you are reflecting uses alpha transparency, optionally use a much slower algorithm for creating the images, but one that will preserve the transparency.'),
);
$form['imagecache_reflect_position'] = array(
'#type' => 'radios',
'#title' => t('Position'),
'#default_value' => $action['imagecache_reflect_position'],
'#options' => array(
'top' => t('Top'),
'right' => t('Right'),
'bottom' => t('Bottom'),
'left' => t('Left'),
),
'#description' => t('The position of the image reflection. Default is bottom.'),
'#required' => TRUE,
);
$form['imagecache_reflect_size'] = array(
'#type' => 'textfield',
'#title' => t('Size'),
'#default_value' => $action['imagecache_reflect_size'],
'#description' => t('The size of the reflection in pixels. You may append % to the integer to represent percentages.'),
'#required' => TRUE,
);
return $form;
}
/**
* Validates the form color.
*/
function _imagecache_reflect_validate_color($form, &$form_state) {
$c = $form_state['values']['data']['imagecache_reflect_color'];
if (!empty($c) || $c == '0') {
if (drupal_substr($c, 0, 1) == '#') {
if (!preg_match('/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/i', $c)) {
form_error($form, t('Not a valid hex color.'));
}
}
else {
$c = strtolower($c);
$colors = (array) array_change_key_case(_imagecache_reflect_colors());
if (!array_key_exists($c, $colors)) {
form_error($form, t('Not a valid color name.'));
}
}
}
}
/**
* Formats a summary of the reflection-like effect.
*
* @param array $variables
* An associative array containing:
* - data: The current configuration for this reflection-like effect.
*/
function theme_imagecache_reflect_summary($variables) {
$data = $variables['data'];
return t('Background Color: !color, Preserve transparency: @preserve, Position: !position, Size: @size', array(
'!color' => !empty($data['imagecache_reflect_color']) ? $data['imagecache_reflect_color'] : t('White'),
'@preserve' => $data['imagecache_reflect_transparent_source'] ? t('Yes') : t('No'),
'!position' => $data['imagecache_reflect_position'],
'@size' => $data['imagecache_reflect_size'],
));
}
/**
* Implements hook_image().
*
* Creates the reflection-like effect.
*/
function imagecache_reflect_image(&$image, $data) {
$data = array_merge(array(
'imagecache_reflect_color' => 'white',
'imagecache_reflect_position' => 'bottom',
'imagecache_reflect_transparent_source' => FALSE,
'imagecache_reflect_size' => '50%',
), $data);
$is_vertical = in_array($data['imagecache_reflect_position'], array(
'top',
'bottom',
));
if (preg_match('/^\\d{1,3}%$/', $data['imagecache_reflect_size'])) {
$image_size = $is_vertical ? $image->info['height'] : $image->info['width'];
$data['imagecache_reflect_size'] = $image_size * (floatval($data['imagecache_reflect_size']) / 100);
}
else {
$data['imagecache_reflect_size'] = intval($data['imagecache_reflect_size']);
}
if (!empty($data['imagecache_reflect_color'])) {
$data['imagecache_reflect_color'] = _imagecache_reflect_color($data['imagecache_reflect_color']);
}
$width = $image->info['width'] + ($is_vertical ? 0 : $data['imagecache_reflect_size']);
$height = $image->info['height'] + ($is_vertical ? $data['imagecache_reflect_size'] : 0);
$x = $data['imagecache_reflect_position'] == 'left' ? $data['imagecache_reflect_size'] : 0;
$y = $data['imagecache_reflect_position'] == 'top' ? $data['imagecache_reflect_size'] : 0;
$background = imagecreatetruecolor($width, $height);
// If $data['imagecache_reflect_color'] is empty,
// we're trying for a transparent canvas:
if (empty($data['imagecache_reflect_color'])) {
imagesavealpha($background, TRUE);
imagealphablending($background, FALSE);
}
else {
imagefill($background, 0, 0, $data['imagecache_reflect_color']);
}
imagecopy($background, $image->resource, $x, $y, 0, 0, $image->info['width'], $image->info['height']);
// If the user has said that the source image might contain
// transparency, use the slower, but working algorithm to merge
// the images:
if ($data['imagecache_reflect_transparent_source']) {
$min_alpha = _imagecache_reflect_alpha_get_min($image->resource);
}
else {
$min_alpha = 0;
}
$return = FALSE;
switch ($data['imagecache_reflect_position']) {
case 'top':
$steps = min($data['imagecache_reflect_size'], $image->info['height']);
for ($i = 0, $opacity = 50; $i < $steps; ++$i, $opacity = ceil(($steps - $i) / $steps * 100 / 2)) {
_imagecache_reflect_imagecopymerge_alpha($background, $image->resource, 0, $y - $i, 0, $i, $image->info['width'], 1, $opacity, $min_alpha);
}
$return = TRUE;
break;
case 'bottom':
$steps = min($data['imagecache_reflect_size'], $image->info['height']);
for ($i = 0, $opacity = 50; $i < $steps; ++$i, $opacity = ceil(($steps - $i) / $steps * 100 / 2)) {
_imagecache_reflect_imagecopymerge_alpha($background, $image->resource, 0, $image->info['height'] + $i, 0, $image->info['height'] - $i - 1, $image->info['width'], 1, $opacity, $min_alpha);
}
$return = TRUE;
break;
case 'left':
$steps = min($data['imagecache_reflect_size'], $image->info['width']);
for ($i = 0, $opacity = 50; $i < $steps; ++$i, $opacity = ceil(($steps - $i) / $steps * 100 / 2)) {
_imagecache_reflect_imagecopymerge_alpha($background, $image->resource, $x - $i, 0, $i, 0, 1, $image->info['height'], $opacity, $min_alpha);
}
$return = TRUE;
break;
case 'right':
$steps = min($data['imagecache_reflect_size'], $image->info['height']);
for ($i = 0, $opacity = 50; $i < $steps; ++$i, $opacity = ceil(($steps - $i) / $steps * 100 / 2)) {
_imagecache_reflect_imagecopymerge_alpha($background, $image->resource, $image->info['width'] + $i, 0, $image->info['width'] - $i - 1, 0, 1, $image->info['height'], $opacity, $min_alpha);
}
$return = TRUE;
break;
}
if ($return) {
imagedestroy($image->resource);
$image->resource = $background;
$image->info['width'] = $width;
$image->info['height'] = $height;
}
else {
imagedestroy($background);
}
return $return;
}
/**
* A fix to get a function like imagecopymerge with alpha blending.
*
* Main script by aiden dot mail at freemail dot hu.
* Transformed to imagecopymerge_alpha() by rodrigo dot polo at gmail dot com
* @see http://uk3.php.net/manual/en/function.imagecopymerge.php#88456
*/
function _imagecache_reflect_imagecopymerge_alpha(&$dst_im, &$src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct, $minalpha = NULL) {
if (!isset($pct)) {
return FALSE;
}
$pct /= 100;
// Get image width and height.
$w = imagesx($src_im);
$h = imagesy($src_im);
// Turn alpha blending off.
imagealphablending($src_im, FALSE);
if (is_null($minalpha)) {
// Find the most opaque pixel in the image (smallest alpha value).
$minalpha = 127;
for ($x = 0; $x < $w; $x++) {
for ($y = 0; $y < $h; $y++) {
$alpha = imagecolorat($src_im, $x, $y) >> 24 & 0xff;
if ($alpha < $minalpha) {
$minalpha = $alpha;
}
}
}
}
// Loop through image pixels and modify alpha for each.
for ($x = $src_x; $x < $src_x + $src_w; $x++) {
for ($y = $src_y; $y < $src_y + $src_h; $y++) {
// Get current alpha value (represents the transparency).
$colorxy = imagecolorat($src_im, $x, $y);
$alpha = $colorxy >> 24 & 0xff;
// Calculate new alpha.
if ($minalpha !== 127) {
$alpha = 127 + 127 * $pct * ($alpha - 127) / (127 - $minalpha);
}
else {
$alpha += 127 * $pct;
}
// Get the color index with new alpha.
$alphacolorxy = imagecolorallocatealpha($src_im, $colorxy >> 16 & 0xff, $colorxy >> 8 & 0xff, $colorxy & 0xff, $alpha);
// Set pixel with the new color + opacity.
if (!imagesetpixel($src_im, $x, $y, $alphacolorxy)) {
return FALSE;
}
}
}
// The image copy.
imagecopy($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h);
}
/**
* Compute the minimum alpha value of the pixels of a given image resource.
*
* Warning, this function is very expensive.
*/
function _imagecache_reflect_alpha_get_min($src_im) {
$w = imagesx($src_im);
$h = imagesy($src_im);
// Turn alpha blending off.
imagealphablending($src_im, FALSE);
// Find the most opaque pixel in the image (smallest alpha value).
$minalpha = 127;
for ($x = 0; $x < $w; $x++) {
for ($y = 0; $y < $h; $y++) {
$alpha = imagecolorat($src_im, $x, $y) >> 24 & 0xff;
if ($alpha < $minalpha) {
$minalpha = $alpha;
}
}
}
return $minalpha;
}
/**
* Get color indentifier to use in imagefill function.
*
* @param string $c
* The hex value (3 or 6 characters prepended with '#') or name of the color.
*
* @return color
* Returns a color identifier representing the color hex value or name.
*/
function _imagecache_reflect_color($c) {
if (!empty($c)) {
if (drupal_substr($c, 0, 1) == '#') {
$c = drupal_substr($c, 1);
if (drupal_strlen($c) == 6) {
$c = drupal_substr($c, 0, 6);
$c = str_pad($c, 6, '0');
$color = '0x' . $c;
}
else {
$c = drupal_substr($c, 0, 3);
$color = '0x' . $c[0] . $c[0] . $c[1] . $c[1] . $c[2] . $c[2];
}
}
else {
$c = drupal_strtolower(trim($c));
foreach (_imagecache_reflect_colors() as $name => $value) {
if ($c == drupal_strtolower($name)) {
$color = $value;
}
}
}
}
else {
$color = 0xffffff;
}
return $color;
}
/**
* Gets an array of colors with hex equivalent.
*/
function _imagecache_reflect_colors() {
static $colors = array(
'AliceBlue' => '0xF0F8FF',
'AntiqueWhite' => '0xFAEBD7',
'Aqua' => '0x00FFFF',
'Aquamarine' => '0x7FFFD4',
'Azure' => '0xF0FFFF',
'Beige' => '0xF5F5DC',
'Bisque' => '0xFFE4C4',
'Black' => '0x000000',
'BlanchedAlmond' => '0xFFEBCD',
'Blue' => '0x0000FF',
'BlueViolet' => '0x8A2BE2',
'Brown' => '0xA52A2A',
'BurlyWood' => '0xDEB887',
'CadetBlue' => '0x5F9EA0',
'Chartreuse' => '0x7FFF00',
'Chocolate' => '0xD2691E',
'Coral' => '0xFF7F50',
'CornflowerBlue' => '0x6495ED',
'Cornsilk' => '0xFFF8DC',
'Crimson' => '0xDC143C',
'Cyan' => '0x00FFFF',
'DarkBlue' => '0x00008B',
'DarkCyan' => '0x008B8B',
'DarkGoldenRod' => '0xB8860B',
'DarkGray' => '0xA9A9A9',
'DarkGrey' => '0xA9A9A9',
'DarkGreen' => '0x006400',
'DarkKhaki' => '0xBDB76B',
'DarkMagenta' => '0x8B008B',
'DarkOliveGreen' => '0x556B2F',
'Darkorange' => '0xFF8C00',
'DarkOrchid' => '0x9932CC',
'DarkRed' => '0x8B0000',
'DarkSalmon' => '0xE9967A',
'DarkSeaGreen' => '0x8FBC8F',
'DarkSlateBlue' => '0x483D8B',
'DarkSlateGray' => '0x2F4F4F',
'DarkSlateGrey' => '0x2F4F4F',
'DarkTurquoise' => '0x00CED1',
'DarkViolet' => '0x9400D3',
'DeepPink' => '0xFF1493',
'DeepSkyBlue' => '0x00BFFF',
'DimGray' => '0x696969',
'DimGrey' => '0x696969',
'DodgerBlue' => '0x1E90FF',
'FireBrick' => '0xB22222',
'FloralWhite' => '0xFFFAF0',
'ForestGreen' => '0x228B22',
'Fuchsia' => '0xFF00FF',
'Gainsboro' => '0xDCDCDC',
'GhostWhite' => '0xF8F8FF',
'Gold' => '0xFFD700',
'GoldenRod' => '0xDAA520',
'Gray' => '0x808080',
'Grey' => '0x808080',
'Green' => '0x008000',
'GreenYellow' => '0xADFF2F',
'HoneyDew' => '0xF0FFF0',
'HotPink' => '0xFF69B4',
'IndianRed' => '0xCD5C5C',
'Indigo' => '0x4B0082',
'Ivory' => '0xFFFFF0',
'Khaki' => '0xF0E68C',
'Lavender' => '0xE6E6FA',
'LavenderBlush' => '0xFFF0F5',
'LawnGreen' => '0x7CFC00',
'LemonChiffon' => '0xFFFACD',
'LightBlue' => '0xADD8E6',
'LightCoral' => '0xF08080',
'LightCyan' => '0xE0FFFF',
'LightGoldenRodYellow' => '0xFAFAD2',
'LightGray' => '0xD3D3D3',
'LightGrey' => '0xD3D3D3',
'LightGreen' => '0x90EE90',
'LightPink' => '0xFFB6C1',
'LightSalmon' => '0xFFA07A',
'LightSeaGreen' => '0x20B2AA',
'LightSkyBlue' => '0x87CEFA',
'LightSlateGray' => '0x778899',
'LightSlateGrey' => '0x778899',
'LightSteelBlue' => '0xB0C4DE',
'LightYellow' => '0xFFFFE0',
'Lime' => '0x00FF00',
'LimeGreen' => '0x32CD32',
'Linen' => '0xFAF0E6',
'Magenta' => '0xFF00FF',
'Maroon' => '0x800000',
'MediumAquaMarine' => '0x66CDAA',
'MediumBlue' => '0x0000CD',
'MediumOrchid' => '0xBA55D3',
'MediumPurple' => '0x9370D8',
'MediumSeaGreen' => '0x3CB371',
'MediumSlateBlue' => '0x7B68EE',
'MediumSpringGreen' => '0x00FA9A',
'MediumTurquoise' => '0x48D1CC',
'MediumVioletRed' => '0xC71585',
'MidnightBlue' => '0x191970',
'MintCream' => '0xF5FFFA',
'MistyRose' => '0xFFE4E1',
'Moccasin' => '0xFFE4B5',
'NavajoWhite' => '0xFFDEAD',
'Navy' => '0x000080',
'OldLace' => '0xFDF5E6',
'Olive' => '0x808000',
'OliveDrab' => '0x6B8E23',
'Orange' => '0xFFA500',
'OrangeRed' => '0xFF4500',
'Orchid' => '0xDA70D6',
'PaleGoldenRod' => '0xEEE8AA',
'PaleGreen' => '0x98FB98',
'PaleTurquoise' => '0xAFEEEE',
'PaleVioletRed' => '0xD87093',
'PapayaWhip' => '0xFFEFD5',
'PeachPuff' => '0xFFDAB9',
'Peru' => '0xCD853F',
'Pink' => '0xFFC0CB',
'Plum' => '0xDDA0DD',
'PowderBlue' => '0xB0E0E6',
'Purple' => '0x800080',
'Red' => '0xFF0000',
'RosyBrown' => '0xBC8F8F',
'RoyalBlue' => '0x041690',
'SaddleBrown' => '0x8B4513',
'Salmon' => '0xFA8072',
'SandyBrown' => '0xF4A460',
'SeaGreen' => '0x2E8B57',
'SeaShell' => '0xFFF5EE',
'Sienna' => '0xA0522D',
'Silver' => '0xC0C0C0',
'SkyBlue' => '0x87CEEB',
'SlateBlue' => '0x6A5ACD',
'SlateGray' => '0x708090',
'SlateGrey' => '0x708090',
'Snow' => '0xFFFAFA',
'SpringGreen' => '0x00FF7F',
'SteelBlue' => '0x4682B4',
'Tan' => '0xD2B48C',
'Teal' => '0x008080',
'Thistle' => '0xD8BFD8',
'Tomato' => '0xFF6347',
'Turquoise' => '0x40E0D0',
'Violet' => '0xEE82EE',
'Wheat' => '0xF5DEB3',
'White' => '0xFFFFFF',
'WhiteSmoke' => '0xF5F5F5',
'Yellow' => '0xFFFF00',
'YellowGreen' => '0x9ACD32',
);
return $colors;
}
Functions
Name | Description |
---|---|
imagecache_reflect_form | Implements imagecache_hook_form() |
imagecache_reflect_image | Implements hook_image(). |
imagecache_reflect_image_effect_info | Implements hook_image_effect_info(). |
imagecache_reflect_theme | Implements hook_theme(). |
theme_imagecache_reflect_summary | Formats a summary of the reflection-like effect. |
_imagecache_reflect_alpha_get_min | Compute the minimum alpha value of the pixels of a given image resource. |
_imagecache_reflect_color | Get color indentifier to use in imagefill function. |
_imagecache_reflect_colors | Gets an array of colors with hex equivalent. |
_imagecache_reflect_imagecopymerge_alpha | A fix to get a function like imagecopymerge with alpha blending. |
_imagecache_reflect_validate_color | Validates the form color. |