From 683fbbe6f44edc6fa4b8360dccecf23f69f38bf2 Mon Sep 17 00:00:00 2001 From: Chauncey McAskill Date: Thu, 13 Jul 2017 19:20:37 -0400 Subject: [PATCH] Crop Effect: Added support for ImageMagick Changes: - Abstract: Added support for "gravity", "repage", and "geometry" - Imagick: Added (untested) support for gravity - ImageMagick: Added support for crop --- .../Image/Effect/AbstractCropEffect.php | 131 +++++++++++++++--- .../Effect/ImagemagickCropEffect.php | 44 ++++++ .../Imagick/Effect/ImagickCropEffect.php | 4 +- 3 files changed, 159 insertions(+), 20 deletions(-) create mode 100644 src/Charcoal/Image/Imagemagick/Effect/ImagemagickCropEffect.php diff --git a/src/Charcoal/Image/Effect/AbstractCropEffect.php b/src/Charcoal/Image/Effect/AbstractCropEffect.php index c300a0b..a57f545 100644 --- a/src/Charcoal/Image/Effect/AbstractCropEffect.php +++ b/src/Charcoal/Image/Effect/AbstractCropEffect.php @@ -16,23 +16,41 @@ abstract class AbstractCropEffect extends AbstractEffect * @var integer $x */ private $x = 0; + /** * @var integer $y */ private $y = 0; + /** * @var integer $width */ private $width = 0; + /** * @var integer $height */ private $height = 0; /** - * @param integer $width The crop width. + * @var mixed $geometry + */ + private $geometry; + + /** + * @var string $gravity + */ + private $gravity = 'center'; + + /** + * @var boolean $repage + */ + private $repage = false; + + /** + * @param integer $width The crop width. * @throws InvalidArgumentException If the width argument is not valid. - * @return Rotate Chainable + * @return AbstractCropEffect */ public function setWidth($width) { @@ -46,7 +64,7 @@ public function setWidth($width) } /** - * @return float + * @return integer */ public function width() { @@ -54,9 +72,9 @@ public function width() } /** - * @param integer $height The crop height. + * @param integer $height The crop height. * @throws InvalidArgumentException If the height argument is not valid. - * @return $this Chainable + * @return AbstractCropEffect */ public function setHeight($height) { @@ -70,7 +88,7 @@ public function setHeight($height) } /** - * @return float + * @return integer */ public function height() { @@ -80,9 +98,9 @@ public function height() /** * The X coordinate of the cropped region's top left corner * - * @param integer $x The x-position (in pixel) of the crop. + * @param integer $x The x-position (in pixel) of the crop. * @throws InvalidArgumentException If the x argument is not valid. - * @return $this Chainable + * @return AbstractCropEffect */ public function setX($x) { @@ -96,7 +114,7 @@ public function setX($x) } /** - * @return float + * @return integer */ public function x() { @@ -106,9 +124,9 @@ public function x() /** * The Y coordinate of the cropped region's top left corner * - * @param integer $y The y-position (in pixel) of the crop. + * @param integer $y The y-position (in pixel) of the crop. * @throws InvalidArgumentException If the y argumnet is not valid. - * @return $this Chainable + * @return AbstractCropEffect */ public function setY($y) { @@ -122,7 +140,7 @@ public function setY($y) } /** - * @return float + * @return integer */ public function y() { @@ -130,8 +148,78 @@ public function y() } /** - * @param array $data The effect data. - * @return AbstractResizeEffect Chainable + * Set a complex geometry value. + * + * @param mixed $geometry The image geometry. + * @throws InvalidArgumentException If the geometry argument is not valid. + * @return AbstractCropEffect + */ + public function setGeometry($geometry) + { + if ($geometry !== null && !is_string($geometry) && !is_numeric($geometry)) { + throw new InvalidArgumentException( + 'Geometry must be a valid crop' + ); + } + $this->geometry = $geometry; + return $this; + } + + /** + * Retrieve the complex geometry value. + * + * @return mixed + */ + public function geometry() + { + return $this->geometry; + } + + /** + * @param string $gravity The crop gravity. + * @throws InvalidArgumentException If the argument is not a valid gravity name. + * @return AbstractCropEffect + */ + public function setGravity($gravity) + { + if (!in_array($gravity, $this->image()->availableGravities())) { + throw new InvalidArgumentException( + 'Gravity is not valid' + ); + } + $this->gravity = $gravity; + return $this; + } + + /** + * @return string + */ + public function gravity() + { + return $this->gravity; + } + + /** + * @param boolean $repage The repage image flag. + * @return AbstractCropEffect + */ + public function setRepage($repage) + { + $this->repage = !!$repage; + return $this; + } + + /** + * @return boolean + */ + public function repage() + { + return $this->repage; + } + + /** + * @param array $data The effect data. + * @return AbstractCropEffect */ public function process(array $data = null) { @@ -139,9 +227,14 @@ public function process(array $data = null) $this->setData($data); } + if ($this->geometry()) { + $this->doCrop(0, 0, 0, 0); + return $this; + } + $y = $this->y(); $x = $this->x(); - $width = $this->width(); + $width = $this->width(); $height = $this->height(); $this->doCrop($width, $height, $x, $y); @@ -150,10 +243,10 @@ public function process(array $data = null) } /** - * @param integer $width The crop width. - * @param integer $height The crop height. - * @param integer $x The x-position (in pixel) of the crop. - * @param integer $y The y-position (in pixel) of the crop. + * @param integer $width The crop width. + * @param integer $height The crop height. + * @param integer $x The x-position (in pixel) of the crop. + * @param integer $y The y-position (in pixel) of the crop. * @return void */ abstract protected function doCrop($width, $height, $x, $y); diff --git a/src/Charcoal/Image/Imagemagick/Effect/ImagemagickCropEffect.php b/src/Charcoal/Image/Imagemagick/Effect/ImagemagickCropEffect.php new file mode 100644 index 0000000..c42b746 --- /dev/null +++ b/src/Charcoal/Image/Imagemagick/Effect/ImagemagickCropEffect.php @@ -0,0 +1,44 @@ +geometry(); + if ($geometry) { + $params = [ $option.' '.$geometry ]; + } else { + $params = [ '-gravity "'.$this->gravity().'"' ]; + + $size = $width.'x'.$height.($x >= 0 ? '+' : '').$x.($y >= 0 ? '+' : '').$y; + $params[] = $option.' '.$size; + } + + if ($this->repage()) { + $params[] = '+repage'; + } + + $this->image()->applyCmd(implode(' ', $params)); + } +} diff --git a/src/Charcoal/Image/Imagick/Effect/ImagickCropEffect.php b/src/Charcoal/Image/Imagick/Effect/ImagickCropEffect.php index 115a78d..b564ab3 100644 --- a/src/Charcoal/Image/Imagick/Effect/ImagickCropEffect.php +++ b/src/Charcoal/Image/Imagick/Effect/ImagickCropEffect.php @@ -20,6 +20,8 @@ class ImagickCropEffect extends AbstractCropEffect */ protected function doCrop($width, $height, $x, $y) { - $this->image()->imagick()->cropImage($width, $height, $x, $y); + $gravity = $this->image()->imagickGravity($this->gravity()); + + $this->image()->imagick()->setGravity($gravity)->cropImage($width, $height, $x, $y); } }