From: Michael J. Rubinsky Date: Thu, 28 May 2009 14:27:48 +0000 (-0400) Subject: Remove imagick related code from the Im driver and effects. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=c2a499a1ec30a7a556376b5cc66e8c73600872bd;p=horde.git Remove imagick related code from the Im driver and effects. --- diff --git a/framework/Image/lib/Horde/Image.php b/framework/Image/lib/Horde/Image.php index 6caf45ad4..267102e44 100644 --- a/framework/Image/lib/Horde/Image.php +++ b/framework/Image/lib/Horde/Image.php @@ -62,23 +62,19 @@ class Horde_Image */ protected $_logger; - // @TODO: width/height should be protected since they aren't reliable - // (should use ::getDimensions()) but we need a way to set them - // to zero from Effects... leaving public until a clearGeometry() - // method is implemented. /** * The current width of the image data. * * @var integer */ - public $_width = 0; + protected $_width = 0; /** * The current height of the image data. * * @var integer */ - public $_height = 0; + protected $_height = 0; /** * A directory for temporary files. diff --git a/framework/Image/lib/Horde/Image/Effect/Im/Border.php b/framework/Image/lib/Horde/Image/Effect/Im/Border.php index f2bebe6be..edebc5122 100755 --- a/framework/Image/lib/Horde/Image/Effect/Im/Border.php +++ b/framework/Image/lib/Horde/Image/Effect/Im/Border.php @@ -29,19 +29,11 @@ class Horde_Image_Effect_Im_Border extends Horde_Image_Effect */ public function apply() { - if (!is_null($this->_image->_imagick)) { - $this->_image->_imagick->borderImage( - $this->_params['bordercolor'], - $this->_params['borderwidth'], - $this->_params['borderwidth']); - } else { - $this->_image->addPostSrcOperation(sprintf( - " -bordercolor \"%s\" %s -border %s", - $this->_params['bordercolor'], - (!empty($this->_params['preserve']) ? '-compose Copy' : ''), - $this->_params['borderwidth'])); - } - + $this->_image->addPostSrcOperation(sprintf( + " -bordercolor \"%s\" %s -border %s", + $this->_params['bordercolor'], + (!empty($this->_params['preserve']) ? '-compose Copy' : ''), + $this->_params['borderwidth'])); return true; } diff --git a/framework/Image/lib/Horde/Image/Effect/Im/Composite.php b/framework/Image/lib/Horde/Image/Effect/Im/Composite.php index 15bf20734..3b5bf1359 100755 --- a/framework/Image/lib/Horde/Image/Effect/Im/Composite.php +++ b/framework/Image/lib/Horde/Image/Effect/Im/Composite.php @@ -36,47 +36,28 @@ class Horde_Image_Effect_Im_Composite extends Horde_Image_Effect */ public function apply() { - $this->_image->_imagick = null; - if (!is_null($this->_image->_imagick)) { - foreach ($this->_params['images'] as $image) { - $topimg = new Horde_Image_ImagickProxy(); - $topimg->clear(); - $topimg->readImageBlob($image->raw()); - - /* Calculate center for composite (gravity center)*/ - $geometry = $this->_image->_imagick->getImageGeometry(); - $x = $geometry['width'] / 2; - $y = $geometry['height'] / 2; - - if (isset($this->_params['x']) && isset($this->_params['y'])) { - $x = $this->_params['x']; - $y = $this->_params['y']; - } - $this->_image->_imagick->compositeImage($topimg, constant('Imagick::COMPOSITE_OVER'), $x, $y); - } - } else { - $ops = $geometry = $gravity = ''; - if (isset($this->_params['gravity'])) { - $gravity = ' -gravity ' . $this->_params['gravity']; - } + $ops = $geometry = $gravity = ''; + if (isset($this->_params['gravity'])) { + $gravity = ' -gravity ' . $this->_params['gravity']; + } - if (isset($this->_params['x']) && isset($this->_params['y'])) { - $geometry = ' -geometry +' . $this->_params['x'] . '+' . $this->_params['y'] . ' '; - } - if (isset($this->_params['compose'])) { - // The -matte ensures that the destination (background) image - // has an alpha channel - to avoid black holes in the image. - $compose = ' -compose ' . $this->_params['compose'] . ' -matte'; - } + if (isset($this->_params['x']) && isset($this->_params['y'])) { + $geometry = ' -geometry +' . $this->_params['x'] . '+' . $this->_params['y'] . ' '; + } + if (isset($this->_params['compose'])) { + // The -matte ensures that the destination (background) image + // has an alpha channel - to avoid black holes in the image. + $compose = ' -compose ' . $this->_params['compose'] . ' -matte'; + } - foreach($this->_params['images'] as $image) { - $temp = $image->toFile(); - $this->_image->addFileToClean($temp); - $ops .= ' ' . $temp . $gravity . $compose . ' -composite'; - } - $this->_image->addOperation($geometry); - $this->_image->addPostSrcOperation($ops); + foreach($this->_params['images'] as $image) { + $temp = $image->toFile(); + $this->_image->addFileToClean($temp); + $ops .= ' ' . $temp . $gravity . $compose . ' -composite'; } + $this->_image->addOperation($geometry); + $this->_image->addPostSrcOperation($ops); + return true; } diff --git a/framework/Image/lib/Horde/Image/Effect/Im/DropShadow.php b/framework/Image/lib/Horde/Image/Effect/Im/DropShadow.php index 83a504a64..f95de762a 100644 --- a/framework/Image/lib/Horde/Image/Effect/Im/DropShadow.php +++ b/framework/Image/lib/Horde/Image/Effect/Im/DropShadow.php @@ -32,51 +32,9 @@ class Horde_Image_Effect_Im_DropShadow extends Horde_Image_Effect */ public function apply() { - if (!is_null($this->_image->_imagick)) { - // $shadow is_a ImagickProxy object - $shadow = $this->_image->_imagick->cloneIM(); - $shadow->setImageBackgroundColor('black'); - $shadow->shadowImage(80, $this->_params['fade'], - $this->_params['distance'], - $this->_params['distance']); - - - // If we have an actual background color, we need to explicitly - // create a new background image with that color to be sure there - // *is* a background color. - if ($this->_params['background'] != 'none') { - $size = $shadow->getImageGeometry(); - $new = new Horde_Image_ImagickProxy($size['width'], - $size['height'], - $this->_params['background'], - $this->_image->getType()); - - $new->compositeImage($shadow, - constant('Imagick::COMPOSITE_OVER'), 0, 0); - $shadow->clear(); - $shadow->addImage($new); - $new->destroy(); - } - - if ($this->_params['padding']) { - $shadow->borderImage($this->_params['background'], - $this->_params['padding'], - $this->_params['padding']); - } - $shadow->compositeImage($this->_image->_imagick, - constant('Imagick::COMPOSITE_OVER'), - 0, 0); - $this->_image->_imagick->clear(); - $this->_image->_imagick->addImage($shadow); - $shadow->destroy(); - } else { - $size = $this->_image->getDimensions(); -// $this->_image->addPostSrcOperation("-size {$size['width']}x{$size['height']} xc:{$this->_params['background']} " -// . "-fill {$this->_params['background']} -draw \"matte 0,0 reset\""); - $this->_image->addPostSrcOperation('\( +clone -background black -shadow 80x' . $this->_params['fade'] . '+' . $this->_params['distance'] . '+' . $this->_params['distance'] . ' \) +swap -background none -flatten +repage -bordercolor ' . $this->_params['background'] . ' -border ' . $this->_params['padding']); - } - $this->_image->_width = 0; - $this->_image->_height = 0; + $size = $this->_image->getDimensions(); + $this->_image->addPostSrcOperation('\( +clone -background black -shadow 80x' . $this->_params['fade'] . '+' . $this->_params['distance'] . '+' . $this->_params['distance'] . ' \) +swap -background none -flatten +repage -bordercolor ' . $this->_params['background'] . ' -border ' . $this->_params['padding']); + $this->_image->clearGeometry(); return true; } diff --git a/framework/Image/lib/Horde/Image/Effect/Im/PhotoStack.php b/framework/Image/lib/Horde/Image/Effect/Im/PhotoStack.php index 1ccf6e8c7..1f2b8f8fc 100644 --- a/framework/Image/lib/Horde/Image/Effect/Im/PhotoStack.php +++ b/framework/Image/lib/Horde/Image/Effect/Im/PhotoStack.php @@ -61,81 +61,60 @@ class Horde_Image_Effect_Im_PhotoStack extends Horde_Image_Effect $i = 1; $cnt = count($this->_params['images']); if ($cnt <=0) { - return PEAR::raiseError('No images provided'); + throw new Horde_Image_Exception('No Images provided.'); } - if (!is_null($this->_image->_imagick) && - $this->_image->_imagick->methodExists('polaroidImage') && - $this->_image->_imagick->methodExists('trimImage')) { - $imgs = array(); - $length = 0; + // Start out fresh. + $this->_image->raw(); + + switch ($this->_params['type']) { + case 'plain': + case 'rounded': + // Get top image dimensions, then force each bottom image to the + // same dimensions. + $this->_params['images'][$cnt - 1]->resize($this->_params['resize_height'], + $this->_params['resize_height'], + true); + $size = $this->_params['images'][$cnt - 1]->getDimensions(); + //$this->_image->resize(2 * $this->_params['resize_height'], 2 * $this->_params['resize_height']); + for ($i = 0; $i < $cnt; $i++) { + $this->_params['images'][$i]->resize($size['height'], $size['width'], false); + } + $xo = $yo = (count($this->_params['images']) + 1) * $this->_params['offset']; + $ops = ''; + $haveBottom = false; + foreach ($this->_params['images'] as $image) { + $xo -= $this->_params['offset']; + $yo -= $this->_params['offset']; - switch ($this->_params['type']) { - case 'plain': - case 'rounded': - $haveBottom = false; - // First, we need to resize the top image to get the dimensions - // for the rest of the stack. - $topimg = new Horde_Image_ImagickProxy(); - $topimg->clear(); - $topimg->readImageBlob($this->_params['images'][$cnt - 1]->raw()); - $topimg->thumbnailImage( - $this->_params['resize_height'], - $this->_params['resize_height'], - true); if ($this->_params['type'] == 'rounded') { - $topimg = $this->_roundBorder($topimg); + $temp = $this->_roundBorder($image); + } else { + $temp = $image->toFile(); } + $this->_image->addFileToClean($temp); + $ops .= ' \( ' . $temp . ' -background none -thumbnail ' . $size['width'] . 'x' . $size['height'] . '! -repage +' . $xo . '+' . $yo . ($this->_params['type'] == 'plain' ? ' -bordercolor "#333" -border 1 ' : ' ' ) . ((!$haveBottom) ? '\( +clone -shadow 80x4+0+0 \) +swap -mosaic' : '') . ' \) '; + $haveBottom = true; + } - $size = $topimg->getImageGeometry(); - foreach ($this->_params['images'] as $image) { - $imgk= new Horde_Image_ImagickProxy(); - $imgk->clear(); - $imgk->readImageBlob($image->raw()); - if ($i++ <= $cnt) { - $imgk->thumbnailImage($size['width'], $size['height'], - false); - } else { - $imgk->destroy(); - $imgk = $topimg->cloneIM(); - } + // The first -background none option below is only honored in + // convert versions before 6.4 it seems. Without it specified as + // none here, all stacks come out with a white background. + $this->_image->addPostSrcOperation($ops . ' -background ' . $this->_params['background'] . ' -mosaic -bordercolor ' . $this->_params['background'] . ' -border ' . $this->_params['padding']); - if ($this->_params['type'] == 'rounded') { - $imgk = $this->_roundBorder($imgk); - } else { - $imgk->borderImage($this->_params['bordercolor'], 1, 1); - } - // Only shadow the bottom image for 'plain' stacks - if (!$haveBottom) { - $shad = $imgk->cloneIM(); - $shad->setImageBackgroundColor('black'); - $shad->shadowImage(80, 4, 0, 0); - $shad->compositeImage($imgk, - constant('Imagick::COMPOSITE_OVER'), - 0, 0); - $imgk->clear(); - $imgk->addImage($shad); - $shad->destroy(); - $haveBottom = true; - } - // Get the geometry of the image and remember the largest. - $geo = $imgk->getImageGeometry(); - $length = max( - $length, - sqrt(pow($geo['height'], 2) + pow($geo['width'], 2))); + break; - $imgs[] = $imgk; - } - break; - case 'polaroid': + case 'polaroid': + // Check for im version > 6.3.2 + $ver = $this->_image->getIMVersion(); + if (is_array($ver) && version_compare($ver[0], '6.3.2') >= 0) { + $ops = ''; foreach ($this->_params['images'] as $image) { - $imgk= new Horde_Image_ImagickProxy(); - $imgk->clear(); - $imgk->readImageBlob($image->raw()); - $imgk->thumbnailImage($this->_params['resize_height'], - $this->_params['resize_height'], - true); - $imgk->setImageBackgroundColor('black'); + $temp = $image->toFile(); + // Remember the temp files so we can nuke them later. + $this->_image->addFileToClean($temp); + + // Don't rotate the top image. if ($i++ == $cnt) { $angle = 0; } else { @@ -144,155 +123,30 @@ class Horde_Image_Effect_Im_PhotoStack extends Horde_Image_Effect $angle = $angle * -1; } } - $result = $imgk->polaroidImage($angle); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - // Get the geometry of the image and remember the largest. - $geo = $imgk->getImageGeometry(); - $length = max( - $length, - sqrt(pow($geo['height'], 2) + pow($geo['width'], 2))); - - $imgs[] = $imgk; - } - break; - } - - // Make sure the background canvas is large enough to hold it all. - $this->_image->_imagick->thumbnailImage($length * 1.5 + 20, - $length * 1.5 + 20); - - // x and y offsets. - $xo = $yo = (count($imgs) + 1) * $this->_params['offset']; - foreach ($imgs as $image) { - if ($this->_params['type'] == 'polaroid') { - $xo = mt_rand(1, $this->_params['resize_height'] / 2); - $yo = mt_rand(1, $this->_params['resize_height'] / 2); - } elseif ($this->_params['type'] == 'plain' || - $this->_params['type'] == 'rounded') { - $xo -= $this->_params['offset']; - $yo -= $this->_params['offset']; + $ops .= ' \( ' . $temp . ' -geometry +' . mt_rand(1, $this->_params['resize_height']) . '+' . mt_rand(1, $this->_params['resize_height']) . ' -thumbnail \'' . $this->_params['resize_height'] . 'x' . $this->_params['resize_height'] . '>\' -bordercolor Snow -border 1 -polaroid ' . $angle . ' \) '; } - - $this->_image->_imagick->compositeImage( - $image, constant('Imagick::COMPOSITE_OVER'), $xo, $yo); - $image->removeImage(); - $image->destroy(); - } - // If we have a background other than 'none' we need to - // compose two images together to make sure we *have* a background. - if ($this->_params['background'] != 'none') { - $size = $this->_image->getDimensions(); - $new = new Horde_Image_ImagickProxy($length * 1.5 + 20, - $length * 1.5 + 20, - $this->_params['background'], - $this->_image->getType()); - - - - $new->compositeImage($this->_image->_imagick, - constant('Imagick::COMPOSITE_OVER'), 0, 0); - $this->_image->_imagick->clear(); - $this->_image->_imagick->addImage($new); - $new->destroy(); - } - // Trim the canvas before resizing to keep the thumbnails as large - // as possible. - $this->_image->_imagick->trimImage(0); - if ($this->_params['padding']) { - $this->_image->_imagick->borderImage($this->_params['background'], - $this->_params['padding'], - $this->_params['padding']); - } - - } else { - // No Imagick installed - use im, but make sure we don't mix imagick - // and convert. - $this->_image->_imagick = null; - $this->_image->raw(); - - switch ($this->_params['type']) { - case 'plain': - case 'rounded': - // Get top image dimensions, then force each bottom image to the - // same dimensions. - $this->_params['images'][$cnt - 1]->resize($this->_params['resize_height'], - $this->_params['resize_height'], - true); - $size = $this->_params['images'][$cnt - 1]->getDimensions(); - //$this->_image->resize(2 * $this->_params['resize_height'], 2 * $this->_params['resize_height']); - for ($i = 0; $i < $cnt; $i++) { - $this->_params['images'][$i]->resize($size['height'], $size['width'], false); - } - $xo = $yo = (count($this->_params['images']) + 1) * $this->_params['offset']; + $this->_image->addPostSrcOperation('-background none' . $ops . '-mosaic -bordercolor ' . $this->_params['background'] . ' -border ' . $this->_params['padding']); + } else { + // An attempt at a -polaroid command free version of this + // effect based on various examples and ideas at + // http://imagemagick.org $ops = ''; - $haveBottom = false; foreach ($this->_params['images'] as $image) { - $xo -= $this->_params['offset']; - $yo -= $this->_params['offset']; - - if ($this->_params['type'] == 'rounded') { - $temp = $this->_roundBorder($image); - } else { - $temp = $image->toFile(); - } + $temp = $image->toFile(); $this->_image->addFileToClean($temp); - $ops .= ' \( ' . $temp . ' -background none -thumbnail ' . $size['width'] . 'x' . $size['height'] . '! -repage +' . $xo . '+' . $yo . ($this->_params['type'] == 'plain' ? ' -bordercolor "#333" -border 1 ' : ' ' ) . ((!$haveBottom) ? '\( +clone -shadow 80x4+0+0 \) +swap -mosaic' : '') . ' \) '; - $haveBottom = true; - } - - // The first -background none option below is only honored in - // convert versions before 6.4 it seems. Without it specified as - // none here, all stacks come out with a white background. - $this->_image->addPostSrcOperation($ops . ' -background ' . $this->_params['background'] . ' -mosaic -bordercolor ' . $this->_params['background'] . ' -border ' . $this->_params['padding']); - - break; - - case 'polaroid': - // Check for im version > 6.3.2 - $ver = $this->_image->getIMVersion(); - if (is_array($ver) && version_compare($ver[0], '6.3.2') >= 0) { - $ops = ''; - foreach ($this->_params['images'] as $image) { - $temp = $image->toFile(); - // Remember the temp files so we can nuke them later. - $this->_image->addFileToClean($temp); - - // Don't rotate the top image. - if ($i++ == $cnt) { - $angle = 0; - } else { - $angle = mt_rand(1, 45); - if (mt_rand(1, 2) % 2 === 0) { - $angle = $angle * -1; - } - } - $ops .= ' \( ' . $temp . ' -geometry +' . mt_rand(1, $this->_params['resize_height']) . '+' . mt_rand(1, $this->_params['resize_height']) . ' -thumbnail \'' . $this->_params['resize_height'] . 'x' . $this->_params['resize_height'] . '>\' -bordercolor Snow -border 1 -polaroid ' . $angle . ' \) '; - } - $this->_image->addPostSrcOperation('-background none' . $ops . '-mosaic -bordercolor ' . $this->_params['background'] . ' -border ' . $this->_params['padding']); - } else { - // An attempt at a -polaroid command free version of this - // effect based on various examples and ideas at - // http://imagemagick.org - $ops = ''; - foreach ($this->_params['images'] as $image) { - $temp = $image->toFile(); - $this->_image->addFileToClean($temp); - if ($i++ == $cnt) { - $angle = 0; - } else { - $angle = mt_rand(1, 45); - if (mt_rand(1, 2) % 2 === 0) { - $angle = $angle * -1; - } + if ($i++ == $cnt) { + $angle = 0; + } else { + $angle = mt_rand(1, 45); + if (mt_rand(1, 2) % 2 === 0) { + $angle = $angle * -1; } - $ops .= '\( ' . $temp . ' -thumbnail \'' . $this->_params['resize_height'] . 'x' . $this->_params['resize_height']. '>\' -bordercolor "#eee" -border 4 -bordercolor grey90 -border 1 -bordercolor none -background none -rotate ' . $angle . ' -background none \( +clone -shadow 60x4+4+4 \) +swap -background none -flatten \) '; } - $this->_image->addPostSrcOperation('-background none ' . $ops . '-mosaic -trim +repage -bordercolor ' . $this->_params['background'] . ' -border ' . $this->_params['padding']); + $ops .= '\( ' . $temp . ' -thumbnail \'' . $this->_params['resize_height'] . 'x' . $this->_params['resize_height']. '>\' -bordercolor "#eee" -border 4 -bordercolor grey90 -border 1 -bordercolor none -background none -rotate ' . $angle . ' -background none \( +clone -shadow 60x4+4+4 \) +swap -background none -flatten \) '; } - break; + $this->_image->addPostSrcOperation('-background none ' . $ops . '-mosaic -trim +repage -bordercolor ' . $this->_params['background'] . ' -border ' . $this->_params['padding']); } + break; } return true; @@ -302,27 +156,13 @@ class Horde_Image_Effect_Im_PhotoStack extends Horde_Image_Effect { $context = array('tmpdir' => $this->_image->getTmpDir(), 'convert' => $this->_image->getConvertPath()); - if (!is_null($this->_image->_imagick)) { - $size = $image->getImageGeometry(); - $new = Horde_Image::factory('im', array('context' => $context)); - $new->loadString('somestring', $image->getImageBlob()); - $image->destroy(); - $new->addEffect('RoundCorners', array('border' => 2, 'bordercolor' => '#111')); - $new->applyEffects(); - $return = new Horde_Image_ImagickProxy($size['width'] + $this->_params['borderwidth'], - $size['height'] + $this->_params['borderwidth'], - $this->_params['bordercolor'], - $this->_image->getType()); - $return->clear(); - $return->readImageBlob($new->raw()); - return $return; - } else { - $size = $image->getDimensions(); - $new = Horde_Image::factory('im', array('data' => $image->raw(), 'context' => $context)); - $new->addEffect('RoundCorners', array('border' => 2, 'bordercolor' => '#111', 'background' => 'none')); - $new->applyEffects(); - return $new->toFile(); - } + + $size = $image->getDimensions(); + $new = Horde_Image::factory('im', array('data' => $image->raw(), 'context' => $context)); + $new->addEffect('RoundCorners', array('border' => 2, 'bordercolor' => '#111', 'background' => 'none')); + $new->applyEffects(); + + return $new->toFile(); } } \ No newline at end of file diff --git a/framework/Image/lib/Horde/Image/Effect/Im/PolaroidImage.php b/framework/Image/lib/Horde/Image/Effect/Im/PolaroidImage.php index cd93d8972..38450195f 100755 --- a/framework/Image/lib/Horde/Image/Effect/Im/PolaroidImage.php +++ b/framework/Image/lib/Horde/Image/Effect/Im/PolaroidImage.php @@ -35,52 +35,19 @@ class Horde_Image_Effect_Im_PolaroidImage extends Horde_Image_Effect */ public function apply() { - if (!is_null($this->_image->_imagick) && - $this->_image->_imagick->methodExists('polaroidImage') && - $this->_image->_imagick->methodExists('trimImage')) { - - // This determines the color of the underlying shadow. - $this->_image->_imagick->setImageBackgroundColor($this->_params['shadowcolor']); - - $result = $this->_image->_imagick->polaroidImage($this->_params['angle']); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - - // We need to create a new image to composite the polaroid over. - // (yes, even if it's a transparent background evidently) - $size = $this->_image->getDimensions(); - $imk = new Horde_Image_ImagickProxy($size['width'], - $size['height'], - $this->_params['background'], - $this->_image->getType()); - - $result = $imk->compositeImage($this->_image->_imagick, - constant('Imagick::COMPOSITE_OVER'), - 0, 0); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - $this->_image->_imagick->clear(); - $this->_image->_imagick->addImage($imk); - $imk->destroy(); - + // Check for im version > 6.3.2 + $this->_image->_imagick = null; + $ver = $this->_image->getIMVersion(); + if (is_array($ver) && version_compare($ver[0], '6.3.2') >= 0) { + $this->_image->addPostSrcOperation(sprintf("-bordercolor \"#eee\" -background none -polaroid %s \( +clone -fill %s -draw 'color 0,0 reset' \) +swap +flatten", + $this->_params['angle'], $this->_params['background'])); } else { - - // Check for im version > 6.3.2 - $this->_image->_imagick = null; - $ver = $this->_image->getIMVersion(); - if (is_array($ver) && version_compare($ver[0], '6.3.2') >= 0) { - $this->_image->addPostSrcOperation(sprintf("-bordercolor \"#eee\" -background none -polaroid %s \( +clone -fill %s -draw 'color 0,0 reset' \) +swap +flatten", - $this->_params['angle'], $this->_params['background'])); - } else { - $size = $this->_image->getDimensions(); - $this->_image->addPostSrcOperation(sprintf("-bordercolor \"#eee\" -border 8 bordercolor grey90 -border 1 -bordercolor none -background none -rotate %s \( +clone -shadow 60x1.5+1+1 -rotate 90 -wave 1x%s -rotate 90 \) +swap -rotate 90 -wave 1x%s -rotate -90 -flatten \( +clone -fill %s -draw 'color 0,0 reset ' \) +swap -flatten", - $this->_params['angle'], $size['height'] * 2, $size['height'] * 2, $this->_params['background'])); - } - - return true; + $size = $this->_image->getDimensions(); + $this->_image->addPostSrcOperation(sprintf("-bordercolor \"#eee\" -border 8 bordercolor grey90 -border 1 -bordercolor none -background none -rotate %s \( +clone -shadow 60x1.5+1+1 -rotate 90 -wave 1x%s -rotate 90 \) +swap -rotate 90 -wave 1x%s -rotate -90 -flatten \( +clone -fill %s -draw 'color 0,0 reset ' \) +swap -flatten", + $this->_params['angle'], $size['height'] * 2, $size['height'] * 2, $this->_params['background'])); } + + return true; } } \ No newline at end of file diff --git a/framework/Image/lib/Horde/Image/Effect/Im/RoundCorners.php b/framework/Image/lib/Horde/Image/Effect/Im/RoundCorners.php index c56e7f469..c1b4de007 100644 --- a/framework/Image/lib/Horde/Image/Effect/Im/RoundCorners.php +++ b/framework/Image/lib/Horde/Image/Effect/Im/RoundCorners.php @@ -25,79 +25,25 @@ class Horde_Image_Effect_Im_RoundCorners extends Horde_Image_Effect { /* Use imagick extension if available */ $round = $this->_params['radius']; - // Apparently roundCorners() requires imagick to be compiled against - // IM > 6.2.8. - if (!is_null($this->_image->_imagick) && - $this->_image->_imagick->methodExists('roundCorners')) { - $result = $this->_image->_imagick->roundCorners($round, $round); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - // Using a border? - if ($this->_params['bordercolor'] != 'none' && - $this->_params['border'] > 0) { + // Get image dimensions + $dimensions = $this->_image->getDimensions(); + $height = $dimensions['height']; + $width = $dimensions['width']; - $size = $this->_image->getDimensions(); + $this->_image->addOperation("-size {$width}x{$height} xc:{$this->_params['background']} " + . "-fill {$this->_params['background']} -draw \"matte 0,0 reset\" -tile"); - $new = new Horde_Image_ImagickProxy($size['width'] + $this->_params['border'], - $size['height'] + $this->_params['border'], - $this->_params['bordercolor'], - $this->_image->getType()); - - $result = $new->roundCorners($round, $round); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - $new->compositeImage($this->_image->_imagick, - constant('Imagick::COMPOSITE_OVER'), 1, 1); - $this->_image->_imagick->clear(); - $this->_image->_imagick->addImage($new); - $new->destroy(); - } - - // If we have a background other than 'none' we need to - // compose two images together to make sure we *have* a background. - if ($this->_params['background'] != 'none') { - $size = $this->_image->getDimensions(); - $new = new Horde_Image_ImagickProxy($size['width'], - $size['height'], - $this->_params['background'], - $this->_image->getType()); - - - - $new->compositeImage($this->_image->_imagick, - constant('Imagick::COMPOSITE_OVER'), 0, 0); - $this->_image->_imagick->clear(); - $this->_image->_imagick->addImage($new); - $new->destroy(); - } - } else { - // Get image dimensions - $dimensions = $this->_image->getDimensions(); - $height = $dimensions['height']; - $width = $dimensions['width']; - - // Make sure we don't attempt to use Imagick for any other effects - // to make sure we do them in the proper order. - $this->_image->_imagick = null; - - $this->_image->addOperation("-size {$width}x{$height} xc:{$this->_params['background']} " - . "-fill {$this->_params['background']} -draw \"matte 0,0 reset\" -tile"); - - $this->_image->roundedRectangle(round($round / 2), - round($round / 2), - $width - round($round / 2) - 2, - $height - round($round / 2) - 2, - $round + 2, - 'none', - 'white'); - } + $this->_image->roundedRectangle(round($round / 2), + round($round / 2), + $width - round($round / 2) - 2, + $height - round($round / 2) - 2, + $round + 2, + 'none', + 'white'); // Reset width/height since these might have changed - $this->_image->_width = 0; - $this->_image->_height = 0; + $this->_image->clearGeometry(); return true; } diff --git a/framework/Image/lib/Horde/Image/Im.php b/framework/Image/lib/Horde/Image/Im.php index 7055a6afd..b07e9cc2f 100644 --- a/framework/Image/lib/Horde/Image/Im.php +++ b/framework/Image/lib/Horde/Image/Im.php @@ -45,17 +45,6 @@ class Horde_Image_Im extends Horde_Image protected $_postSrcOperations = array(); /** - * Reference to an Horde_Image_ImagickProxy object. - * - * @TODO: This needs to be public since some of the Effects need to - * access this and possibly null it out. This will be resolved - * when Imagick is pulled out into it's own driver. - * - * @var Imagick - */ - public $_imagick = null; - - /** * An array of temporary filenames that need to be unlinked at the end of * processing. Use addFileToClean() from client code (Effects) to add files * to this array. @@ -82,86 +71,13 @@ class Horde_Image_Im extends Horde_Image throw new InvalidArgumentException('A path to the convert binary is required.'); } $this->_convert = $context['convert']; - - // TODO: Will be breaking out Imagick into it's own driver. - - // Imagick library doesn't play nice with outputting data for 0x0 - // images, so use 1x1 for our default if needed. - if (Util::loadExtension('imagick')) { - ini_set('imagick.locale_fix', 1); - $this->_width = max(array($this->_width, 1)); - $this->_height = max(array($this->_height, 1)); - // Use a proxy for the Imagick calls to keep exception catching - // code out of PHP4 compliant code. - $this->_imagick = new Horde_Image_ImagickProxy($this->_width, - $this->_height, - $this->_background, - $this->_type); - // Yea, it's wasteful to create the proxy (which creates a blank - // image) then overwrite it if we're passing in an image, but this - // will be fixed in Horde 4 when imagick is broken out into it's own - // proper driver. - if (!empty($params['filename'])) { - $this->loadFile($params['filename']); - } elseif(!empty($params['data'])) { - $this->loadString(md5($params['data']), $params['data']); - } else { - $this->_data = $this->_imagick->getImageBlob(); - } - - $this->_imagick->setImageFormat($this->_type); + if (!empty($params['filename'])) { + $this->loadFile($params['filename']); + } elseif (!empty($params['data'])) { + $this->loadString(md5($params['data']), $params['data']); } else { - if (!empty($params['filename'])) { - $this->loadFile($params['filename']); - } elseif (!empty($params['data'])) { - $this->loadString(md5($params['data']), $params['data']); - } else { - $cmd = "-size {$this->_width}x{$this->_height} xc:{$this->_background} +profile \"*\" {$this->_type}:__FILEOUT__"; - $this->executeConvertCmd($cmd); - } - } - } - - /** - * Load the image data from a string. Need to override this method - * in order to load the imagick object if we need to. - * - * @TODO: This can be nuked when imagick is broken out. - * - * @param string $id An arbitrary id for the image. - * @param string $image_data The data to use for the image. - */ - public function loadString($id, $image_data) - { - parent::loadString($id, $image_data); - if (!is_null($this->_imagick)) { - $this->_imagick->clear(); - $this->_imagick->readImageBlob($image_data); - $this->_imagick->setFormat($this->_type); - $this->_imagick->setIteratorIndex(0); - } - } - - /** - * Load the image data from a file. Need to override this method - * in order to load the imagick object if we need to. - * - * @TODO: Nuke when imagick is broken out. - * - * @param string $filename The full path and filename to the file to load - * the image data from. The filename will also be - * used for the image id. - * - * @return mixed PEAR Error if file does not exist or could not be loaded - * otherwise NULL if successful or already loaded. - */ - public function loadFile($filename) - { - parent::loadFile($filename); - if (!is_null($this->_imagick)) { - $this->_imagick->clear(); - $this->_imagick->readImageBlob($this->_data); - $this->_imagick->setIteratorIndex(0); + $cmd = "-size {$this->_width}x{$this->_height} xc:{$this->_background} +profile \"*\" {$this->_type}:__FILEOUT__"; + $this->executeConvertCmd($cmd); } } @@ -178,11 +94,6 @@ class Horde_Image_Im extends Horde_Image */ public function raw($convert = false) { - // Make sure _data is sync'd with imagick object - if (!is_null($this->_imagick)) { - $this->_data = $this->_imagick->getImageBlob(); - } - if (!empty($this->_data)) { // If there are no operations, and we already have data, don't // bother writing out files, just return the current data. @@ -214,16 +125,7 @@ class Horde_Image_Im extends Horde_Image /* Load the result */ $this->_data = file_get_contents($tmpout); - - // Keep imagick object in sync if we need to. - // @TODO: Might be able to stop doing this once all operations - // are doable through imagick api. - if (!is_null($this->_imagick)) { - $this->_imagick->clear(); - $this->_imagick->readImageBlob($this->_data); - } } - @unlink($tmpin); @unlink($tmpout); @@ -238,11 +140,7 @@ class Horde_Image_Im extends Horde_Image parent::reset(); $this->_operations = array(); $this->_postSrcOperations = array(); - if (is_object($this->_imagick)) { - $this->_imagick->clear(); - } - $this->_width = 0; - $this->_height = 0; + $this->clearGeometry(); } /** @@ -255,50 +153,20 @@ class Horde_Image_Im extends Horde_Image */ public function resize($width, $height, $ratio = true, $keepProfile = false) { - if (!is_null($this->_imagick)) { - $this->_imagick->thumbnailImage($width, $height, $ratio); + $resWidth = $width * 2; + $resHeight = $height * 2; + $this->_operations[] = "-size {$resWidth}x{$resHeight}"; + if ($ratio) { + $this->_postSrcOperations[] = (($keepProfile) ? "-resize" : "-thumbnail") . " {$width}x{$height}"; } else { - $resWidth = $width * 2; - $resHeight = $height * 2; - $this->_operations[] = "-size {$resWidth}x{$resHeight}"; - if ($ratio) { - $this->_postSrcOperations[] = (($keepProfile) ? "-resize" : "-thumbnail") . " {$width}x{$height}"; - } else { - $this->_postSrcOperations[] = (($keepProfile) ? "-resize" : "-thumbnail") . " {$width}x{$height}!"; - } + $this->_postSrcOperations[] = (($keepProfile) ? "-resize" : "-thumbnail") . " {$width}x{$height}!"; } // Reset the width and height instance variables since after resize // we don't know the *exact* dimensions yet (especially if we maintained // aspect ratio. // Refresh the data $this->raw(); - $this->_width = 0; - $this->_height = 0; - } - - /** - * More efficient way of getting size if using imagick library. - * *ALWAYS* use getDimensions() to get image geometry...instance - * variables only cache geometry until it changes, then they go - * to zero. - * - */ - public function getDimensions() - { - if (!is_null($this->_imagick)) { - if ($this->_height == 0 && $this->_width == 0) { - $size = $this->_imagick->getImageGeometry(); - if (is_a($size, 'PEAR_Error')) { - return $size; - } - $this->_height = $size['height']; - $this->_width = $size['width']; - } - return array('width' => $this->_width, - 'height' => $this->_height); - } else { - return parent::getDimensions(); - } + $this->clearGeometry(); } /** @@ -311,24 +179,16 @@ class Horde_Image_Im extends Horde_Image */ public function crop($x1, $y1, $x2, $y2) { - if (!is_null($this->_imagick)) { - $result = $this->_imagick->cropImage($x2 - $x1, $y2 - $y1, $x1, $y1); - $this->_imagick->setImagePage(0, 0, 0, 0); - } else { - $line = ($x2 - $x1) . 'x' . ($y2 - $y1) . '+' . $x1 . '+' . $y1; - $this->_operations[] = '-crop ' . $line . ' +repage'; - $result = true; - } + $line = ($x2 - $x1) . 'x' . ($y2 - $y1) . '+' . $x1 . '+' . $y1; + $this->_operations[] = '-crop ' . $line . ' +repage'; + // Reset width/height since these might change $this->raw(); - $this->_width = 0; - $this->_height = 0; - - return $result; + $this->clearGeometry(); } /** - * Rotate the current image. + * Rotate the current image. This is an atomic operation. * * @param integer $angle The angle to rotate the image by, * in the clockwise direction. @@ -336,16 +196,12 @@ class Horde_Image_Im extends Horde_Image */ public function rotate($angle, $background = 'white') { - if (!is_null($this->_imagick)) { - return $this->_imagick->rotateImage($background, $angle); - } else { - $this->raw(); - $this->_operations[] = "-background $background -rotate {$angle}"; - $this->raw(); - } + $this->raw(); + $this->_operations[] = "-background $background -rotate {$angle}"; + $this->raw(); + // Reset width/height since these might have changed - $this->_width = 0; - $this->_height = 0; + $this->clearGeometry(); } /** @@ -353,11 +209,7 @@ class Horde_Image_Im extends Horde_Image */ public function flip() { - if (!is_null($this->_imagick)) { - $this->_imagick->flipImage(); - } else { - $this->_operations[] = '-flip'; - } + $this->_operations[] = '-flip'; } /** @@ -365,11 +217,7 @@ class Horde_Image_Im extends Horde_Image */ public function mirror() { - if (!is_null($this->_imagick)) { - $this->_imagick->flopImage(); - } else { - $this->_operations[] = '-flop'; - } + $this->_operations[] = '-flop'; } /** @@ -377,11 +225,7 @@ class Horde_Image_Im extends Horde_Image */ public function grayscale() { - if (!is_null($this->_imagick)) { - $this->_imagick->setImageColorSpace(constant('Imagick::COLORSPACE_GRAY')); - } else { - $this->_postSrcOperations[] = '-colorspace GRAY'; - } + $this->_postSrcOperations[] = '-colorspace GRAY'; } /** @@ -391,14 +235,10 @@ class Horde_Image_Im extends Horde_Image */ public function sepia($threshold = 85) { - if (!is_null($this->_imagick)) { - $this->_imagick->sepiaToneImage($threshold); - } else { - $this->_operations[] = '-sepia-tone ' . $threshold . '%'; - } + $this->_operations[] = '-sepia-tone ' . $threshold . '%'; } - /** + /** * Draws a text string on the image in a specified location, with * the specified style information. * @@ -415,15 +255,9 @@ class Horde_Image_Im extends Horde_Image */ public function text($string, $x, $y, $font = '', $color = 'black', $direction = 0, $fontsize = 'small') { - if (!is_null($this->_imagick)) { - $fontsize = self::getFontSize($fontsize); - - return $this->_imagick->text($string, $x, $y, $font, $color, $direction, $fontsize); - } else { - $string = addslashes('"' . $string . '"'); - $fontsize = self::getFontSize($fontsize); - $this->_postSrcOperations[] = "-fill $color " . (!empty($font) ? "-font $font" : '') . " -pointsize $fontsize -gravity northwest -draw \"text $x,$y $string\" -fill none"; - } + $string = addslashes('"' . $string . '"'); + $fontsize = self::getFontSize($fontsize); + $this->_postSrcOperations[] = "-fill $color " . (!empty($font) ? "-font $font" : '') . " -pointsize $fontsize -gravity northwest -draw \"text $x,$y $string\" -fill none"; } /** @@ -437,12 +271,8 @@ class Horde_Image_Im extends Horde_Image */ public function circle($x, $y, $r, $color, $fill = 'none') { - if (!is_null($this->_imagick)) { - return $this->_imagick->circle($x, $y, $r, $color, $fill); - } else { - $xMax = $x + $r; - $this->_postSrcOperations[] = "-stroke $color -fill $fill -draw \"circle $x,$y $xMax,$y\" -stroke none -fill none"; - } + $xMax = $x + $r; + $this->_postSrcOperations[] = "-stroke $color -fill $fill -draw \"circle $x,$y $xMax,$y\" -stroke none -fill none"; } /** @@ -455,17 +285,11 @@ class Horde_Image_Im extends Horde_Image */ public function polygon($verts, $color, $fill = 'none') { - // TODO: For now, use only convert since ::polygon is called from other - // methods that are convert-only for now. - //if (!is_null($this->_imagick)) { - //return $this->_imagick->polygon($verts, $color, $fill); - //} else { - $command = ''; - foreach ($verts as $vert) { - $command .= sprintf(' %d,%d', $vert['x'], $vert['y']); - } - $this->_postSrcOperations[] = "-stroke $color -fill $fill -draw \"polygon $command\" -stroke none -fill none"; - //} + $command = ''; + foreach ($verts as $vert) { + $command .= sprintf(' %d,%d', $vert['x'], $vert['y']); + } + $this->_postSrcOperations[] = "-stroke $color -fill $fill -draw \"polygon $command\" -stroke none -fill none"; } /** @@ -480,13 +304,9 @@ class Horde_Image_Im extends Horde_Image */ public function rectangle($x, $y, $width, $height, $color, $fill = 'none') { - if (!is_null($this->_imagick)) { - $this->_imagick->rectangle($x, $y, $width, $height, $color, $fill); - } else { - $xMax = $x + $width; - $yMax = $y + $height; - $this->_postSrcOperations[] = "-stroke $color -fill $fill -draw \"rectangle $x,$y $xMax,$yMax\" -stroke none -fill none"; - } + $xMax = $x + $width; + $yMax = $y + $height; + $this->_postSrcOperations[] = "-stroke $color -fill $fill -draw \"rectangle $x,$y $xMax,$yMax\" -stroke none -fill none"; } /** @@ -502,14 +322,9 @@ class Horde_Image_Im extends Horde_Image */ public function roundedRectangle($x, $y, $width, $height, $round, $color, $fill) { - if (!is_null($this->_imagick)) { - $this->_imagick->roundedRectangle($x, $y, $width, $height, $round, $color, $fill); - } else { - $x1 = $x + $width; - $y1 = $y + $height; - $this->_postSrcOperations[] = "-stroke $color -fill $fill -draw \"roundRectangle $x,$y $x1,$y1 $round,$round\" -stroke none -fill none"; - - } + $x1 = $x + $width; + $y1 = $y + $height; + $this->_postSrcOperations[] = "-stroke $color -fill $fill -draw \"roundRectangle $x,$y $x1,$y1 $round,$round\" -stroke none -fill none"; } /** @@ -524,11 +339,7 @@ class Horde_Image_Im extends Horde_Image */ public function line($x0, $y0, $x1, $y1, $color = 'black', $width = 1) { - if (!is_null($this->_imagick)) { - return $this->_imagick->line($x0, $y0, $x1, $y1, $color, $width); - } else { - $this->_operations[] = "-stroke $color -strokewidth $width -draw \"line $x0,$y0 $x1,$y1\""; - } + $this->_operations[] = "-stroke $color -strokewidth $width -draw \"line $x0,$y0 $x1,$y1\""; } /** @@ -545,13 +356,7 @@ class Horde_Image_Im extends Horde_Image */ public function dashedLine($x0, $y0, $x1, $y1, $color = 'black', $width = 1, $dash_length = 2, $dash_space = 2) { - if (!is_null($this->_imagick)) { - return $this->_imagick->dashedLine($x0, $y0, $x1, $y1, $color, - $width, $dash_length, - $dash_space); - } else { - $this->_operations[] = "-stroke $color -strokewidth $width -draw \"line $x0,$y0 $x1,$y1\""; - } + $this->_operations[] = "-stroke $color -strokewidth $width -draw \"line $x0,$y0 $x1,$y1\""; } /** @@ -565,15 +370,11 @@ class Horde_Image_Im extends Horde_Image */ public function polyline($verts, $color, $width = 1) { - if (!is_null($this->_imagick)) { - return $this->_imagick->polyline($verts, $color, $width); - } else { - $command = ''; - foreach ($verts as $vert) { - $command .= sprintf(' %d,%d', $vert['x'], $vert['y']); - } - $this->_operations[] = "-stroke $color -strokewidth $width -fill none -draw \"polyline $command\" -strokewidth 1 -stroke none -fill none"; + $command = ''; + foreach ($verts as $vert) { + $command .= sprintf(' %d,%d', $vert['x'], $vert['y']); } + $this->_operations[] = "-stroke $color -strokewidth $width -fill none -draw \"polyline $command\" -strokewidth 1 -stroke none -fill none"; } /** @@ -703,13 +504,8 @@ class Horde_Image_Im extends Horde_Image { static $version = null; if (!is_array($version)) { - if (!is_null($this->_imagick)) { - $output = $this->_imagick->getVersion(); - $output[0] = $output['versionString']; - } else { - $commandline = $this->_convert . ' --version'; - exec($commandline, $output, $retval); - } + $commandline = $this->_convert . ' --version'; + exec($commandline, $output, $retval); if (preg_match('/([0-9])\.([0-9])\.([0-9])/', $output[0], $matches)) { $version = $matches; return $matches; @@ -717,6 +513,7 @@ class Horde_Image_Im extends Horde_Image return false; } } + return $version; }