You are here

public static function GDToolkitReflect::reflect in ImageCache Reflect 8

Creates an image with a reflection-like effect from a provided image.

Parameters

resource $image: The image object to create the reflected image from.

array $configuration: An associative array containing: -color: Hex color of the reflection background. -transparency: Boolean. Whether to preserve alpha transparency. -position: Reflection position (left, right, top, bottom). -size: Size of the reflection in percent or pixels.

Return value

bool Returns TRUE if successful.

1 call to GDToolkitReflect::reflect()
ReflectImageEffect::applyEffect in lib/Drupal/imagecache_reflect/Plugin/ImageEffect/ReflectImageEffect.php
Applies an image effect to the image object.

File

lib/Drupal/imagecache_reflect/Plugin/ImageToolkit/GDToolkitReflect.php, line 34
Contains \Drupal\imagecache_reflect\Plugin\ImageToolkit\GDToolkitReflect.

Class

GDToolkitReflect
Creates a reflect operation for the GD library.

Namespace

Drupal\imagecache_reflect\Plugin\ImageToolkit

Code

public static function reflect(ImageInterface $image, array $configuration) {

  // Verify that Drupal is using the PHP GD library for image manipulations
  // since this effect depends on functions in the GD library.
  if ($image
    ->getToolkitId() != 'gd') {
    watchdog('image', 'Image reflect failed on %path. Using non GD toolkit.', array(
      '%path' => $image
        ->getSource(),
    ), WATCHDOG_ERROR);
    return FALSE;
  }

  // Get config params.
  $color = $configuration['bgcolor'];
  $transparency = $configuration['transparency'];
  $position = $configuration['position'];
  $size = $configuration['size'];

  // Image source for the reflection effect.
  $src_im = $image
    ->getResource();

  // Expand the canvas vertically or horizontally depending on
  // the reflection position.
  $is_vertical = \in_array($position, array(
    'top',
    'bottom',
  ));

  // Determine the reflection size in pixels.
  // Calculate pixels from a percentage if given.
  if (preg_match('/^\\d{1,3}%$/', $size)) {
    $image_size = $is_vertical ? $image
      ->getHeight() : $image
      ->getWidth();
    $size = $image_size * (floatval($size) / 100);
  }
  else {
    $size = intval($size);
  }

  // Calculate the final dimensions of the image with its reflection.
  $width = $image
    ->getWidth() + ($is_vertical ? 0 : $size);
  $height = $image
    ->getHeight() + ($is_vertical ? $size : 0);

  // Creates a new destination canvas.
  $dst_im = imagecreatetruecolor($width, $height);

  // If $color is empty, we're trying for a transparent canvas:
  if (empty($color)) {
    imagesavealpha($dst_im, TRUE);
    imagealphablending($dst_im, FALSE);
  }
  else {

    // Convert short #FFF syntax to full #FFFFFF syntax.
    if (strlen($color) == 4) {
      $c = $color;
      $color = $c[0] . $c[1] . $c[1] . $c[2] . $c[2] . $c[3] . $c[3];
    }

    // Convert #FFFFFF syntax to hexadecimal colors.
    $color = hexdec(str_replace('#', '0x', $color));
    imagefill($dst_im, 0, 0, $color);
  }

  // Determine x,y coordinates where source will be on the new image canvas.
  $x = $position == 'left' ? $size : 0;
  $y = $position == 'top' ? $size : 0;

  // Copy the source image onto the new canvas.
  imagecopy($dst_im, $src_im, $x, $y, 0, 0, $image
    ->getWidth(), $image
    ->getHeight());

  // If the user has said that the source image might contain transparency,
  // use the slower, but working algorithm to merge the images.
  $minalpha = $transparency ? self::alphaGetMin($src_im) : 0;

  // Determines the number of passes for imagecopymergeAlpha().
  $steps = $is_vertical ? min($size, $image
    ->getHeight()) : min($size, $image
    ->getWidth());

  // Creates the reflection on the new canvas.
  switch ($position) {
    case 'top':
      for ($i = 0, $opacity = 50; $i < $steps; ++$i, $opacity = ceil(($steps - $i) / $steps * 100 / 2)) {
        self::imagecopymergeAlpha($dst_im, $src_im, 0, $y - $i, 0, $i, $image
          ->getWidth(), 1, $opacity, $minalpha);
      }
      break;
    case 'bottom':
      for ($i = 0, $opacity = 50; $i < $steps; ++$i, $opacity = ceil(($steps - $i) / $steps * 100 / 2)) {
        self::imagecopymergeAlpha($dst_im, $src_im, 0, $image
          ->getHeight() + $i, 0, $image
          ->getHeight() - $i - 1, $image
          ->getWidth(), 1, $opacity, $minalpha);
      }
      break;
    case 'left':
      for ($i = 0, $opacity = 50; $i < $steps; ++$i, $opacity = ceil(($steps - $i) / $steps * 100 / 2)) {
        self::imagecopymergeAlpha($dst_im, $src_im, $x - $i, 0, $i, 0, 1, $image
          ->getHeight(), $opacity, $minalpha);
      }
      break;
    case 'right':
      for ($i = 0, $opacity = 50; $i < $steps; ++$i, $opacity = ceil(($steps - $i) / $steps * 100 / 2)) {
        self::imagecopymergeAlpha($dst_im, $src_im, $image
          ->getWidth() + $i, 0, $image
          ->getWidth() - $i - 1, 0, 1, $image
          ->getHeight(), $opacity, $minalpha);
      }
      break;
  }

  // Destroy the original image and return the modified image.
  imagedestroy($image
    ->getResource());
  $image
    ->setResource($dst_im)
    ->setWidth($width)
    ->setHeight($height);
  return TRUE;
}