From a6f59b31d22901a38204c3e9a162818458b92014 Mon Sep 17 00:00:00 2001 From: Claudiu Cristea Date: Sun, 6 Oct 2013 03:04:28 +0300 Subject: [PATCH] Issue #2103635 by claudiu.cristea | fietserwin: Remove image effect code from Image and ImageInterface. --- core/lib/Drupal/Core/Image/Image.php | 75 ++------------- core/lib/Drupal/Core/Image/ImageInterface.php | 104 +-------------------- .../lib/Drupal/image/Tests/ImageEffectsTest.php | 14 ++- .../system/Plugin/ImageToolkit/GDToolkit.php | 36 +++++++ .../Drupal/system/Plugin/ImageToolkitInterface.php | 39 ++++++++ .../lib/Drupal/system/Tests/Image/ToolkitTest.php | 14 ++- .../image_test/Plugin/ImageToolkit/TestToolkit.php | 16 ++++ 7 files changed, 114 insertions(+), 184 deletions(-) diff --git a/core/lib/Drupal/Core/Image/Image.php b/core/lib/Drupal/Core/Image/Image.php index 0f2fc85..0de3520 100644 --- a/core/lib/Drupal/Core/Image/Image.php +++ b/core/lib/Drupal/Core/Image/Image.php @@ -8,7 +8,6 @@ namespace Drupal\Core\Image; use Drupal\system\Plugin\ImageToolkitInterface; -use Drupal\Component\Utility\Image as ImageUtility; /** * Defines an image object to represent an image file. @@ -284,73 +283,19 @@ protected function processInfo() { } /** - * {@inheritdoc} + * Calls specific toolkit operation to be performed against the image. */ - public function scale($width = NULL, $height = NULL, $upscale = FALSE) { - $dimensions = array( - 'width' => $this->getWidth(), - 'height' => $this->getHeight(), - ); - - // Scale the dimensions - if they don't change then just return success. - if (!ImageUtility::scaleDimensions($dimensions, $width, $height, $upscale)) { - return TRUE; + public function __call($name, $arguments) { + try { + $arguments = is_array($arguments) ? $arguments : array(); + // @todo In https://drupal.org/node/2073759, call_user_func_array() will + // be replaced by $this->toolkit->process($name, $this, $arguments). + array_unshift($arguments, $this); + return call_user_func_array(array($this->toolkit, $name), $arguments); } - - return $this->resize($dimensions['width'], $dimensions['height']); - - } - - /** - * {@inheritdoc} - */ - public function scaleAndCrop($width, $height) { - $scale = max($width / $this->getWidth(), $height / $this->getHeight()); - $x = ($this->getWidth() * $scale - $width) / 2; - $y = ($this->getHeight() * $scale - $height) / 2; - - if ($this->resize($this->getWidth() * $scale, $this->getHeight() * $scale)) { - return $this->crop($x, $y, $width, $height); + catch (\BadMethodCallException $e) { + throw $e; } - return FALSE; - } - - /** - * {@inheritdoc} - */ - public function crop($x, $y, $width, $height) { - $aspect = $this->getHeight() / $this->getWidth(); - if (empty($height)) $height = $width * $aspect; - if (empty($width)) $width = $height / $aspect; - - $width = (int) round($width); - $height = (int) round($height); - - return $this->toolkit->crop($this, $x, $y, $width, $height); - } - - /** - * {@inheritdoc} - */ - public function resize($width, $height) { - $width = (int) round($width); - $height = (int) round($height); - - return $this->toolkit->resize($this, $width, $height); - } - - /** - * {@inheritdoc} - */ - public function desaturate() { - return $this->toolkit->desaturate($this); - } - - /** - * {@inheritdoc} - */ - public function rotate($degrees, $background = NULL) { - return $this->toolkit->rotate($this, $degrees, $background); } /** diff --git a/core/lib/Drupal/Core/Image/ImageInterface.php b/core/lib/Drupal/Core/Image/ImageInterface.php index 5966ab2..827aa3f 100644 --- a/core/lib/Drupal/Core/Image/ImageInterface.php +++ b/core/lib/Drupal/Core/Image/ImageInterface.php @@ -2,7 +2,7 @@ /** * @file - * Contains Drupal\Core\Image\ImageInterface. + * Contains \Drupal\Core\Image\ImageInterface. */ namespace Drupal\Core\Image; @@ -157,106 +157,4 @@ public function getToolkitId(); */ public function save($destination = NULL); - /** - * Scales an image while maintaining aspect ratio. - * - * The resulting image can be smaller for one or both target dimensions. - * - * @param int $width - * (optional) The target width, in pixels. This value is omitted then the - * scaling will based only on the height value. - * @param int $height - * (optional) The target height, in pixels. This value is omitted then the - * scaling will based only on the width value. - * @param bool $upscale - * (optional) Boolean indicating that files smaller than the dimensions will - * be scaled up. This generally results in a low quality image. - * - * @return bool - * TRUE on success, FALSE on failure. - */ - public function scale($width = NULL, $height = NULL, $upscale = FALSE); - - /** - * Scales an image to the exact width and height given. - * - * This function achieves the target aspect ratio by cropping the original image - * equally on both sides, or equally on the top and bottom. This function is - * useful to create uniform sized avatars from larger images. - * - * The resulting image always has the exact target dimensions. - * - * @param int $width - * The target width, in pixels. - * @param int $height - * The target height, in pixels. - * - * @return bool - * TRUE on success, FALSE on failure. - */ - public function scaleAndCrop($width, $height); - - /** - * Crops an image to a rectangle specified by the given dimensions. - * - * @param int $x - * The top left coordinate, in pixels, of the crop area (x axis value). - * @param int $y - * The top left coordinate, in pixels, of the crop area (y axis value). - * @param int $width - * The target width, in pixels. - * @param int $height - * The target height, in pixels. - * - * @return bool - * TRUE on success, FALSE on failure. - * - * @see \Drupal\system\Plugin\ImageToolkitInterface::crop() - */ - public function crop($x, $y, $width, $height); - - /** - * Resizes an image to the given dimensions (ignoring aspect ratio). - * - * @param int $width - * The target width, in pixels. - * @param int $height - * The target height, in pixels. - * - * @return bool - * TRUE on success, FALSE on failure. - * - * @see \Drupal\system\Plugin\ImageToolkitInterface::resize() - */ - public function resize($width, $height); - - /** - * Converts an image to grayscale. - * - * @return bool - * TRUE on success, FALSE on failure. - * - * @see \Drupal\system\Plugin\ImageToolkitInterface::desaturate() - */ - public function desaturate(); - - /** - * Rotates an image by the given number of degrees. - * - * @param int $degrees - * The number of (clockwise) degrees to rotate the image. - * @param string $background - * (optional) An hexadecimal 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. For images that - * support transparency, this will default to transparent. Otherwise it will - * be white. - * - * @return bool - * TRUE on success, FALSE on failure. - * - * @see \Drupal\system\Plugin\ImageToolkitInterface::rotate() - */ - public function rotate($degrees, $background = NULL); - } diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageEffectsTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageEffectsTest.php index 74f41ec..8afcb22 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageEffectsTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageEffectsTest.php @@ -67,12 +67,12 @@ function testScaleEffect() { 'width' => 10, 'height' => 10, )); - $this->assertToolkitOperationsCalled(array('resize')); + $this->assertToolkitOperationsCalled(array('scale')); // Check the parameters. $calls = $this->imageTestGetAllCalls(); - $this->assertEqual($calls['resize'][0][1], 10, 'Width was passed correctly'); - $this->assertEqual($calls['resize'][0][2], 5, 'Height was based off aspect ratio and passed correctly'); + $this->assertEqual($calls['scale'][0][1], 10, 'Width was passed correctly'); + $this->assertEqual($calls['scale'][0][2], 10, 'Height was based off aspect ratio and passed correctly'); } /** @@ -103,14 +103,12 @@ function testScaleAndCropEffect() { 'width' => 5, 'height' => 10, )); - $this->assertToolkitOperationsCalled(array('resize', 'crop')); + $this->assertToolkitOperationsCalled(array('scaleAndCrop')); // Check the parameters. $calls = $this->imageTestGetAllCalls(); - $this->assertEqual($calls['crop'][0][1], 7.5, 'X was computed and passed correctly'); - $this->assertEqual($calls['crop'][0][2], 0, 'Y was computed and passed correctly'); - $this->assertEqual($calls['crop'][0][3], 5, 'Width was computed and passed correctly'); - $this->assertEqual($calls['crop'][0][4], 10, 'Height was computed and passed correctly'); + $this->assertEqual($calls['scaleAndCrop'][0][1], 5, 'Width was computed and passed correctly'); + $this->assertEqual($calls['scaleAndCrop'][0][2], 10, 'Height was computed and passed correctly'); } /** diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/GDToolkit.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/GDToolkit.php index cf13884..e118fd1 100644 --- a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/GDToolkit.php +++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/GDToolkit.php @@ -12,6 +12,7 @@ use Drupal\Core\Annotation\Translation; use Drupal\Core\Image\ImageInterface; use Drupal\system\Plugin\ImageToolkitInterface; +use Drupal\Component\Utility\Image; /** * Defines the GD2 toolkit for image manipulation within Drupal. @@ -123,6 +124,10 @@ public function rotate(ImageInterface $image, $degrees, $background = NULL) { * {@inheritdoc} */ public function crop(ImageInterface $image, $x, $y, $width, $height) { + $aspect = $image->getHeight() / $image->getWidth(); + $height = empty($height) ? $width * $aspect : $height; + $width = empty($width) ? $height / $aspect : $width; + $res = $this->createTmp($image, $width, $height); if (!imagecopyresampled($res, $image->getResource(), 0, 0, $x, $y, $width, $height, $width, $height)) { @@ -154,6 +159,37 @@ public function desaturate(ImageInterface $image) { /** * {@inheritdoc} */ + public function scale(ImageInterface $image, $width = NULL, $height = NULL, $upscale = FALSE) { + $dimensions = array( + 'width' => $image->getWidth(), + 'height' => $image->getHeight(), + ); + + // Scale the dimensions - if they don't change then just return success. + if (!Image::scaleDimensions($dimensions, $width, $height, $upscale)) { + return TRUE; + } + + return $this->resize($image, $dimensions['width'], $dimensions['height']); + } + + /** + * {@inheritdoc} + */ + public function scaleAndCrop(ImageInterface $image, $width, $height) { + $scale = max($width / $image->getWidth(), $height / $image->getHeight()); + $x = ($image->getWidth() * $scale - $width) / 2; + $y = ($image->getHeight() * $scale - $height) / 2; + + if ($this->resize($image, $image->getWidth() * $scale, $image->getHeight() * $scale)) { + return $this->crop($image, $x, $y, $width, $height); + } + return FALSE; + } + + /** + * {@inheritdoc} + */ public function load(ImageInterface $image) { $function = 'imagecreatefrom' . image_type_to_extension($image->getType(), FALSE); if (function_exists($function) && $resource = $function($image->getSource())) { diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkitInterface.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkitInterface.php index 5918160..5a4d86c 100644 --- a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkitInterface.php +++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkitInterface.php @@ -132,6 +132,45 @@ public function crop(ImageInterface $image, $x, $y, $width, $height); public function desaturate(ImageInterface $image); /** + * Scales an image while maintaining aspect ratio. + * + * The resulting image can be smaller for one or both target dimensions. + * + * @param int $width + * (optional) The target width, in pixels. This value is omitted then the + * scaling will based only on the height value. + * @param int $height + * (optional) The target height, in pixels. This value is omitted then the + * scaling will based only on the width value. + * @param bool $upscale + * (optional) Boolean indicating that files smaller than the dimensions will + * be scaled up. This generally results in a low quality image. + * + * @return bool + * TRUE on success, FALSE on failure. + */ + public function scale(ImageInterface $image, $width = NULL, $height = NULL, $upscale = FALSE); + + /** + * Scales an image to the exact width and height given. + * + * This function achieves the target aspect ratio by cropping the original + * image equally on both sides, or equally on the top and bottom. This + * function is useful to create uniform sized avatars from larger images. + * + * The resulting image always has the exact target dimensions. + * + * @param int $width + * The target width, in pixels. + * @param int $height + * The target height, in pixels. + * + * @return bool + * TRUE on success, FALSE on failure. + */ + public function scaleAndCrop(ImageInterface $image, $width, $height); + + /** * Creates an image resource from a file. * * @param \Drupal\Core\Image\ImageInterface $image diff --git a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTest.php b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTest.php index 5f6c4dc..84b34f0 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTest.php @@ -70,12 +70,12 @@ function testResize() { function testScale() { // TODO: need to test upscaling $this->assertTrue($this->image->scale(10, 10), 'Function returned the expected value.'); - $this->assertToolkitOperationsCalled(array('resize')); + $this->assertToolkitOperationsCalled(array('scale')); // Check the parameters. $calls = $this->imageTestGetAllCalls(); - $this->assertEqual($calls['resize'][0][1], 10, 'Width was passed correctly'); - $this->assertEqual($calls['resize'][0][2], 5, 'Height was based off aspect ratio and passed correctly'); + $this->assertEqual($calls['scale'][0][1], 10, 'Width was passed correctly'); + $this->assertEqual($calls['scale'][0][2], 10, 'Height was based off aspect ratio and passed correctly'); } /** @@ -83,15 +83,13 @@ function testScale() { */ function testScaleAndCrop() { $this->assertTrue($this->image->scaleAndCrop(5, 10), 'Function returned the expected value.'); - $this->assertToolkitOperationsCalled(array('resize', 'crop')); + $this->assertToolkitOperationsCalled(array('scaleAndCrop')); // Check the parameters. $calls = $this->imageTestGetAllCalls(); - $this->assertEqual($calls['crop'][0][1], 7.5, 'X was computed and passed correctly'); - $this->assertEqual($calls['crop'][0][2], 0, 'Y was computed and passed correctly'); - $this->assertEqual($calls['crop'][0][3], 5, 'Width was computed and passed correctly'); - $this->assertEqual($calls['crop'][0][4], 10, 'Height was computed and passed correctly'); + $this->assertEqual($calls['scaleAndCrop'][0][1], 5, 'Width was computed and passed correctly'); + $this->assertEqual($calls['scaleAndCrop'][0][2], 10, 'Height was computed and passed correctly'); } /** diff --git a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/TestToolkit.php b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/TestToolkit.php index 778e9e2..82c3081 100644 --- a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/TestToolkit.php +++ b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/TestToolkit.php @@ -108,6 +108,22 @@ public function desaturate(ImageInterface $image) { } /** + * {@inheritdoc} + */ + public function scale(ImageInterface $image, $width = NULL, $height = NULL, $upscale = FALSE) { + $this->logCall('scale', array($image, $width, $height, $upscale)); + return TRUE; + } + + /** + * {@inheritdoc} + */ + public function scaleAndCrop(ImageInterface $image, $width, $height) { + $this->logCall('scaleAndCrop', array($image, $width, $height)); + return TRUE; + } + + /** * Stores the values passed to a toolkit call. * * @param string $op -- 1.8.3.1