function image_gd_perspective in ImageCache Actions 7
GD toolkit specific implementation of the image Perspective effect.
Parameters
stdClass $image: Image object containing the image resource to operate on.
array $data: The current configuration for this image effect, contains the keys: distortion, vanish, symmetry and opposite_distortion options.
Return value
bool True on success, false otherwise.
File
- canvasactions/
canvasactions.inc, line 1465
Code
function image_gd_perspective(stdClass $image, $data) {
$width = $image->info['width'];
$height = $image->info['height'];
$distortion = $data['distortion'];
$opposite_distortion = $data['symmetry'] === 'symmetrical' ? $distortion : $data['opposite_distortion'];
// To reduce distortion, we work with a temporary hires version of the image.
// @todo: during processing we have 2 resources this size: this might crash on memory limits: warn and/or prevent.
$multiplier = 3;
$hires_width = $width * $multiplier;
$hires_height = $height * $multiplier;
$hires_source_image = imagecreatetruecolor($hires_width, $hires_height);
$transparent_white = imagecolorallocatealpha($hires_source_image, 255, 255, 255, 127);
imagealphablending($hires_source_image, FALSE);
imagefilledrectangle($hires_source_image, 0, 0, $hires_width, $hires_height, $transparent_white);
imagesavealpha($hires_source_image, TRUE);
imagecopyresized($hires_source_image, $image->resource, 0, 0, 0, 0, $hires_width, $hires_height, $width, $height);
imagedestroy($image->resource);
// Creating a hires target canvas to apply the perspective effect on.
$hires_target_image = imagecreatetruecolor($hires_width, $hires_height);
$transparent_white = imagecolorallocatealpha($hires_target_image, 255, 255, 255, 127);
// We don't want to blend: the transparent background we set is only for the
// parts that do not get covered.
imagealphablending($hires_target_image, FALSE);
imagefilledrectangle($hires_target_image, 0, 0, $hires_width, $hires_height, $transparent_white);
// Building perspective effect with help four point distortion methods.
// On each step found new distortion point by right triangle formula.
switch ($data['vanish']) {
case 'top':
$left = round($hires_width * $distortion / 100);
$right = round($hires_width - $hires_width * (100 - $opposite_distortion) / 100);
$tg_beta_left = $left / $hires_height;
$tg_beta_right = $right / $hires_height;
for ($y = 0; $y < $hires_height; $y++) {
$new_left = ($hires_height - $y) * $tg_beta_left;
$new_right = ($hires_height - $y) * $tg_beta_right;
$new_width = $hires_width - $new_left - $new_right;
imagecopyresampled($hires_target_image, $hires_source_image, $new_left, $y, 0, $y, $new_width, 1, $hires_width, 1);
}
break;
case 'bottom':
$left = round($hires_width * $distortion / 100);
$right = round($hires_width - $hires_width * (100 - $opposite_distortion) / 100);
$tg_beta_left = $left / $hires_height;
$tg_beta_right = $right / $hires_height;
for ($y = $hires_height; $y > 0; $y--) {
$new_left = $y * $tg_beta_left;
$new_right = $y * $tg_beta_right;
$new_width = $hires_width - $new_left - $new_right;
imagecopyresampled($hires_target_image, $hires_source_image, $new_left, $y, 0, $y, $new_width, 1, $hires_width, 1);
}
break;
case 'right':
$top = round($hires_height * $distortion / 100);
$bottom = round($hires_height - $hires_height * (100 - $opposite_distortion) / 100);
$tg_beta_top = $top / $hires_width;
$tg_beta_bottom = $bottom / $hires_width;
for ($x = $hires_width; $x > 0; $x--) {
$new_top = $x * $tg_beta_top;
$new_bottom = $x * $tg_beta_bottom;
$new_height = $hires_height - $new_top - $new_bottom;
imagecopyresampled($hires_target_image, $hires_source_image, $x, $new_top, $x, 0, 1, $new_height, 1, $hires_height);
}
break;
case 'left':
$top = round($hires_height * $distortion / 100);
$bottom = round($hires_height - $hires_height * (100 - $opposite_distortion) / 100);
$tg_beta_top = $top / $hires_width;
$tg_beta_bottom = $bottom / $hires_width;
for ($x = 0; $x < $hires_width; $x++) {
$new_top = ($hires_width - $x) * $tg_beta_top;
$new_bottom = ($hires_width - $x) * $tg_beta_bottom;
$new_height = $hires_height - $new_top - $new_bottom;
imagecopyresampled($hires_target_image, $hires_source_image, $x, $new_top, $x, 0, 1, $new_height, 1, $hires_height);
}
break;
}
imagedestroy($hires_source_image);
imagealphablending($hires_target_image, FALSE);
imagesavealpha($hires_target_image, TRUE);
// Return image with perspective effect to original size.
$target_image = imagecreatetruecolor($width, $height);
imagealphablending($target_image, FALSE);
imagecopyresampled($target_image, $hires_target_image, 0, 0, 0, 0, $width, $height, $hires_width, $hires_height);
imagedestroy($hires_target_image);
imagesavealpha($target_image, TRUE);
$image->resource = $target_image;
return TRUE;
}