--- /dev/null
+<?php
+/**
+ * Image border Effect for the Horde_Image package.
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @package Horde_Image
+ */
+class Horde_Image_Effect_Imagick_Border extends Horde_Image_Effect
+{
+ /**
+ * Valid parameters for border effects:
+ *
+ * bordercolor - Border color. Defaults to black.
+ * borderwidth - Border thickness, defaults to 1 pixel.
+ * preserve - Preserves the alpha transparency layer (if present)
+ *
+ * @var array
+ */
+ protected $_params = array('bordercolor' => 'black',
+ 'borderwidth' => 1,
+ 'preserve' => true);
+
+ /**
+ * Draw the border.
+ *
+ * This draws the configured border to the provided image. Beware,
+ * that every pixel inside the border clipping will be overwritten
+ * with the background color.
+ */
+ public function apply()
+ {
+ Horde_Image_Imagick::borderImage($this->_image->imagick,
+ $this->_params['bordercolor'],
+ $this->_params['borderwidth'],
+ $this->_params['borderwidth']);
+ return true;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Simple composite effect for composing multiple images. This effect assumes
+ * that all images being passed in are already the desired size.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org)
+ *
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Horde_Image
+ */
+class Horde_Image_Effect_Imagick_Composite extends Horde_Image_Effect
+{
+ /**
+ * Valid parameters for border effects:
+ *
+ * 'images' - an array of Horde_Image objects to overlay.
+ *
+ * ...and ONE of the following. If both are provided, the behaviour is
+ * undefined.
+ *
+ * 'gravity' - the ImageMagick gravity constant describing placement
+ * (IM driver only so far, not imagick)
+ *
+ * 'x' and 'y' - coordinates for the overlay placement.
+ *
+ * @var array
+ */
+ protected $_params = array();
+
+ /**
+ * Draw the border.
+ *
+ * This draws the configured border to the provided image. Beware,
+ * that every pixel inside the border clipping will be overwritten
+ * with the background color.
+ */
+ public function apply()
+ {
+ foreach ($this->_params['images'] as $image) {
+ $topimg = new Imagick();
+ $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, Imagick::COMPOSITE_OVER, $x, $y);
+ }
+ return true;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Image effect for adding a drop shadow.
+ *
+ * Copyright 2007-2009 The Horde Project (http://www.horde.org/)
+ *
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Horde_Image
+ */
+class Horde_Image_Effect_Imagick_DropShadow extends Horde_Image_Effect
+{
+ /**
+ * Valid parameters: Most are currently ignored for the im version
+ * of this effect.
+ *
+ * @TODO
+ *
+ * @var array
+ */
+ protected $_params = array('distance' => 5, // This is used as the x and y offset
+ 'width' => 2,
+ 'hexcolor' => '000000',
+ 'angle' => 215,
+ 'fade' => 3, // Sigma value
+ 'padding' => 0,
+ 'background' => 'none');
+
+ /**
+ * Apply the effect.
+ *
+ * @return mixed true | PEAR_Error
+ */
+ public function apply()
+ {
+ $shadow = $this->_image->imagick->clone();
+ $shadow->setImageBackgroundColor(new ImagickPixel('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 Imagick();
+ $new->newImage($size['width'], $size['height'], new ImagickPixel($this->_params['background']));
+ $new->setImageFormat($this->_image->getType());
+
+ $new->compositeImage($shadow, Imagick::COMPOSITE_OVER, 0, 0);
+ $shadow->clear();
+ $shadow->addImage($new);
+ $new->destroy();
+ }
+
+ if ($this->_params['padding']) {
+ Horde_Image_Imagick::borderImage($shadow,
+ $this->_params['background'],
+ $this->_params['padding'],
+ $this->_params['padding']);
+ }
+
+ $shadow->compositeImage($this->_image->imagick, Imagick::COMPOSITE_OVER, 0, 0);
+ $this->_image->imagick->clear();
+ $this->_image->imagick->addImage($shadow);
+ $shadow->destroy();
+
+ $this->_image->clearGeometry();
+
+ return true;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Effect for composing multiple images into a single image.
+ *
+ * Copyright 2007-2009 The Horde Project (http://www.horde.org/)
+ *
+ * The technique for the Polaroid-like stack using the Imagick extension is
+ * credited to Mikko Koppanen and is documented at http://valokuva.org
+ *
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Horde_Image
+ */
+class Horde_Image_Effect_Imagick_PhotoStack extends Horde_Image_Effect
+{
+ /**
+ * Valid parameters for the stack effect
+ *
+ * images - An array of Horde_Image objects to stack. Images
+ * are stacked in a FIFO manner, so that the top-most
+ * image is the last one in this array.
+ *
+ * type - Determines the style for the composition.
+ * 'plain' or 'polaroid' are supported.
+ *
+ * resize_height - The height that each individual thumbnail
+ * should be resized to before composing on the image.
+ *
+ * padding - How much padding should we ensure is left around
+ * the active image area?
+ *
+ * background - The background canvas color - this is used as the
+ * color to set any padding to.
+ *
+ * bordercolor - If using type 'plain' this sets the color of the
+ * border that each individual thumbnail gets.
+ *
+ * borderwidth - If using type 'plain' this sets the width of the
+ * border on each individual thumbnail.
+ *
+ * offset - If using type 'plain' this determines the amount of
+ * x and y offset to give each successive image when
+ * it is placed on the top of the stack.
+ *
+ * @var array
+ */
+ protected $_params = array('type' => 'plain',
+ 'resize_height' => '150',
+ 'padding' => 0,
+ 'background' => 'none',
+ 'bordercolor' => '#333',
+ 'borderwidth' => 1,
+ 'borderrounding' => 10,
+ 'offset' => 5);
+
+ /**
+ * Create the photo_stack
+ *
+ */
+ public function apply()
+ {
+ $i = 1;
+ $cnt = count($this->_params['images']);
+ if ($cnt <=0) {
+ throw new Horde_Image_Exception('No Images provided.');
+ }
+ if (!method_exists($this->_image->imagick, 'polaroidImage') ||
+ !method_exists($this->_image->imagick, 'trimImage')) {
+ throw new Horde_Image_Exception('Your version of Imagick is not compiled against a recent enough ImageMagick library to use the PhotoStack effect.');
+ }
+
+ $imgs = array();
+ $length = 0;
+
+ 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 Imagick();
+ $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);
+ }
+
+ $size = $topimg->getImageGeometry();
+ foreach ($this->_params['images'] as $image) {
+ $imgk= new Imagick();
+ $imgk->clear();
+ $imgk->readImageBlob($image->raw());
+ if ($i++ <= $cnt) {
+ $imgk->thumbnailImage($size['width'], $size['height'],
+ false);
+ } else {
+ $imgk->destroy();
+ $imgk = $topimg->clone();
+ }
+
+ if ($this->_params['type'] == 'rounded') {
+ $imgk = $this->_roundBorder($imgk);
+ } else {
+ Horde_Image_Imagick::borderImage($imgk, $this->_params['bordercolor'], 1, 1);
+ }
+ // Only shadow the bottom image for 'plain' stacks
+ if (!$haveBottom) {
+ $shad = $imgk->clone();
+ $shad->setImageBackgroundColor(new ImagickPixel('black'));
+ $shad->shadowImage(80, 4, 0, 0);
+ $shad->compositeImage($imgk, 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)));
+
+ $imgs[] = $imgk;
+ }
+ break;
+ case 'polaroid':
+ foreach ($this->_params['images'] as $image) {
+ //@TODO: instead of doing $image->raw(), we might be able to clone
+ // the imagick object if we can do it cleanly might
+ // be faster, less memory intensive?
+ $imgk= new Imagick();
+ $imgk->clear();
+ $imgk->readImageBlob($image->raw());
+ $imgk->thumbnailImage($this->_params['resize_height'],
+ $this->_params['resize_height'],
+ true);
+ $imgk->setImageBackgroundColor('black');
+ if ($i++ == $cnt) {
+ $angle = 0;
+ } else {
+ $angle = mt_rand(1, 45);
+ if (mt_rand(1, 2) % 2 === 0) {
+ $angle = $angle * -1;
+ }
+ }
+ $result = $imgk->polaroidImage(new ImagickDraw(), $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'];
+ }
+ $this->_image->imagick->compositeImage($image, 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 Imagick();
+ $new->newImage($length * 1.5 + 20, $length * 1.5 + 20, new ImagickPixel($this->_params['background']));
+ $new->setImageFormat($this->_image->getType());
+ $new->compositeImage($this->_image->imagick, 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']) {
+ Horde_Image_Imagick::borderImage($this->_image->imagick,
+ $this->_params['background'],
+ $this->_params['padding'],
+ $this->_params['padding']);
+ }
+
+ return true;
+ }
+
+ private function _roundBorder($image)
+ {
+ $context = array('tmpdir' => $this->_image->getTmpDir());
+ $size = $image->getImageGeometry();
+ $new = Horde_Image::factory('Imagick', array('context' => $context));
+ $new->loadString('somestring', $image->getImageBlob());
+ $image->destroy();
+ $new->addEffect('RoundCorners', array('border' => 2, 'bordercolor' => '#111'));
+ $new->applyEffects();
+ $return = new Imagick();
+ $return->newImage($size['width'] + $this->_params['borderwidth'],
+ $size['height'] + $this->_params['borderwidth'],
+ $this->_params['bordercolor']);
+ $return->setImageFormat($this->_image->getType());
+ $return->clear();
+ $return->readImageBlob($new->raw());
+
+ return $return;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Effect for creating a polaroid looking image.
+ *
+ * Copyright 2007-2009 The Horde Project (http://www.horde.org/)
+ *
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Horde_Image
+ */
+class Horde_Image_Effect_Imagick_PolaroidImage extends Horde_Image_Effect
+{
+ /**
+ * Valid parameters for the polaroid effect
+ *
+ * resize_height - The height that each individual thumbnail
+ * should be resized to before composing on the image.
+ *
+ * background - The color of the image background.
+ *
+ * angle - Angle to rotate the image.
+ *
+ * shadowcolor - The color of the image shadow.
+ */
+
+ /**
+ * @var array
+ */
+ protected $_params = array('background' => 'none',
+ 'angle' => 0,
+ 'shadowcolor' => 'black');
+
+ /**
+ * Create the effect
+ *
+ */
+ public function apply()
+ {
+ if (!method_exists($this->_image->imagick, 'polaroidImage') ||
+ !method_exists($this->_image->imagick, 'trimImage')) {
+ throw new Horde_Image_Exception('Your version of Imagick is not compiled against a recent enough ImageMagick library to use the PolaroidImage effect.');
+ }
+
+ // This determines the color of the underlying shadow.
+ $this->_image->imagick->setImageBackgroundColor(new ImagickPixel($this->_params['shadowcolor']));
+ $this->_image->imagick->polaroidImage(new ImagickDraw(), $this->_params['angle']);
+
+
+ // 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 Imagick();
+ $imk->newImage($size['width'], $size['height'], $this->_params['background']);
+ $imk->setImageFormat($this->_image->getType());
+ $result = $imk->compositeImage($this->_image->imagick, Imagick::COMPOSITE_OVER, 0, 0);
+ $this->_image->imagick->clear();
+ $this->_image->imagick->addImage($imk);
+ $imk->destroy();
+
+ return true;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Image effect for rounding image corners.
+ *
+ * Copyright 2007-2009 The Horde Project (http://www.horde.org/)
+ *
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Horde_Image
+ */
+class Horde_Image_Effect_Imagick_RoundCorners extends Horde_Image_Effect
+{
+ /**
+ * Valid parameters:
+ *
+ * radius - Radius of rounded corners.
+ *
+ * @var array
+ */
+ protected $_params = array('radius' => 10,
+ 'background' => 'none',
+ 'border' => 0,
+ 'bordercolor' => 'none');
+
+ public function apply()
+ {
+ if (!method_exists($this->_image->imagick, 'roundCorners')) {
+ throw new Horde_Image_Exception('Your version of Imagick is not compiled against a recent enough ImageMagick library (> 6.2.8) to use the RoundCorners effect.');
+ }
+
+ $round = $this->_params['radius'];
+ $result = $this->_image->imagick->roundCorners($round, $round);
+
+ // Using a border?
+ if ($this->_params['bordercolor'] != 'none' &&
+ $this->_params['border'] > 0) {
+
+ $size = $this->_image->getDimensions();
+
+ $new = new Imagick();
+ $new->newImage($size['width'] + $this->_params['border'],
+ $size['height'] + $this->_params['border'],
+ $this->_params['bordercolor']);
+ $new->setImageFormat($this->_image->getType());
+
+ $new->roundCorners($round, $round);
+ $new->compositeImage($this->_image->imagick, 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 Imagick();
+ $new->newImage($size['width'],
+ $size['height'],
+ $this->_params['background']);
+ $new->setImageFormat($this->_image->getType());
+ $new->compositeImage($this->_image->imagick, Imagick::COMPOSITE_OVER, 0, 0);
+ $this->_image->imagick->clear();
+ $this->_image->imagick->addImage($new);
+ $new->destroy();
+ }
+
+ // Reset width/height since these might have changed
+ $this->_image->clearGeometry();
+
+ return true;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Image effect for watermarking images with text for the im driver..
+ *
+ * Copyright 2007-2009 The Horde Project (http://www.horde.org/)
+ *
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Horde_Image
+ */
+class Horde_Image_Effect_Imagick_TextWatermark extends Horde_Image_Effect
+{
+ /**
+ * Valid parameters for watermark effects:
+ *
+ * text (required) - The text of the watermark.
+ * halign - The horizontal placement
+ * valign - The vertical placement
+ * font - The font name or family to use
+ * fontsize - The size of the font to use
+ * (small, medium, large, giant)
+ *
+ * @var array
+ */
+ protected $_params = array('halign' => 'right',
+ 'valign' => 'bottom',
+ 'font' => 'courier',
+ 'fontsize' => 'small');
+
+ /**
+ * Add the watermark
+ *
+ */
+ public function apply()
+ {
+ /* Determine placement on image */
+ switch ($this->_params['valign']) {
+ case 'bottom':
+ $v = 'south';
+ break;
+ case 'center':
+ $v = 'center';
+ break;
+ default:
+ $v = 'north';
+ }
+
+ switch ($this->_params['halign']) {
+ case 'right':
+ $h = 'east';
+ break;
+ case 'center':
+ $h = 'center';
+ break;
+ default:
+ $h = 'west';
+
+ }
+ if (($v == 'center' && $h != 'center') ||
+ ($v == 'center' && $h == 'center')) {
+ $gravity = $h;
+ } elseif ($h == 'center' && $v != 'center') {
+ $gravity = $v;
+ } else {
+ $gravity = $v . $h;
+ }
+ /* Determine font point size */
+ $point = $this->_image->getFontSize($this->_params['fontsize']);
+
+ //@TODO:
+ throw new Horde_Image_Exception('Not Yet Implemented.');
+ }
+
+}
\ No newline at end of file
if (Util::loadExtension('imagick')) {
ini_set('imagick.locale_fix', 1);
$this->_imagick = new Imagick();
- $this->_width = max(array($this->_width, 1));
- $this->_height = max(array($this->_height, 1));
if (!empty($params['filename'])) {
$this->loadFile($params['filename']);
} elseif(!empty($params['data'])) {
$this->loadString(md5($params['data']), $params['data']);
} else {
+ $this->_width = max(array($this->_width, 1));
+ $this->_height = max(array($this->_height, 1));
$this->_imagick->newImage($this->_width, $this->_height, $this->_background);
- $this->_data = $this->_imagick->getImageBlob();
}
$this->_imagick->setImageFormat($this->_type);
}
public function loadFile($filename)
{
// parent function loads image data into $this->_data
- // @TODO: Can we clear the _data variable to save memory?
parent::loadFile($filename);
- $this->loadFile($this->_data);
+ $this->_imagick->clear();
+ $this->_imagick->readImageBlob($this->_data);
+ $this->_imagick->setFormat($this->_type);
+ $this->_imagick->setIteratorIndex(0);
+ unset($this->_data);
}
/*
} else {
$this->_imagick->thumbnailImage($width, $height, $ratio);
}
- $this->_width = 0;
- $this->_height = 0;
+ $this->clearGeometry();
}
/**
* variables only cache geometry until it changes, then they go
* to zero.
*
+ * @return array of geometry information.
*/
public function getDimensions()
{
if ($this->_height == 0 && $this->_width == 0) {
try {
$size = $this->_imagick->getImageGeometry();
- catch (ImagickException $e) {
+ } catch (ImagickException $e) {
//@TODO - Rethrow as Horde_Image_Exception
}
}
-}
\ No newline at end of file
+ /**
+ * Crop the current image.
+ *
+ * @param integer $x1 x for the top left corner
+ * @param integer $y1 y for the top left corner
+ * @param integer $x2 x for the bottom right corner of the cropped image.
+ * @param integer $y2 y for the bottom right corner of the cropped image.
+ */
+ public function crop($x1, $y1, $x2, $y2)
+ {
+ $result = $this->_imagick->cropImage($x2 - $x1, $y2 - $y1, $x1, $y1);
+ $this->_imagick->setImagePage(0, 0, 0, 0);
+ $this->clearGeometry();
+ }
+
+ /**
+ * Rotate the current image.
+ *
+ * @param integer $angle The angle to rotate the image by,
+ * in the clockwise direction.
+ * @param integer $background The background color to fill any triangles.
+ */
+ public function rotate($angle, $background = 'white')
+ {
+ $this->_imagick->rotateImage($background, $angle);
+ $this->clearGeometry();
+ }
+
+ /**
+ * Flip the current image.
+ */
+ public function flip()
+ {
+ $this->_imagick->flipImage();
+ }
+
+ /**
+ * Mirror the current image.
+ */
+ public function mirror()
+ {
+ $this->_imagick->flopImage();
+ }
+
+ /**
+ * Convert the current image to grayscale.
+ */
+ public function grayscale()
+ {
+ $this->_imagick->setImageColorSpace(Imagick::COLORSPACE_GRAY);
+ }
+
+ /**
+ * Sepia filter.
+ *
+ * @param integer $threshold Extent of sepia effect.
+ */
+ public function sepia($threshold = 85)
+ {
+ $this->_imagick->sepiaToneImage($threshold);
+ }
+
+ /**
+ * Draws a text string on the image in a specified location, with
+ * the specified style information.
+ *
+ * @TODO: Need to differentiate between the stroke (border) and the fill color,
+ * but this is a BC break, since we were just not providing a border.
+ *
+ * @param string $text The text to draw.
+ * @param integer $x The left x coordinate of the start of the text string.
+ * @param integer $y The top y coordinate of the start of the text string.
+ * @param string $font The font identifier you want to use for the text.
+ * @param string $color The color that you want the text displayed in.
+ * @param integer $direction An integer that specifies the orientation of the text.
+ * @param string $fontsize Size of the font (small, medium, large, giant)
+ */
+ public function text($string, $x, $y, $font = '', $color = 'black', $direction = 0, $fontsize = 'small')
+ {
+ $fontsize = self::getFontSize($fontsize);
+ $pixel = new ImagickPixel($color);
+ $draw = new ImagickDraw();
+ $draw->setFillColor($pixel);
+ if (!empty($font)) {
+ $draw->setFont($font);
+ }
+ $draw->setFontSize($fontsize);
+ $draw->setGravity(Imagick::GRAVITY_NORTHWEST);
+ $res = $this->_imagick->annotateImage($draw, $x, $y, $direction, $string);
+ $draw->destroy();
+ }
+
+ /**
+ * Draw a circle.
+ *
+ * @param integer $x The x coordinate of the centre.
+ * @param integer $y The y coordinate of the centre.
+ * @param integer $r The radius of the circle.
+ * @param string $color The line color of the circle.
+ * @param string $fill The color to fill the circle.
+ */
+ public function circle($x, $y, $r, $color, $fill = 'none')
+ {
+ $draw = new ImagickDraw();
+ $draw->setFillColor(new ImagickPixel($fill));
+ $draw->setStrokeColor(new ImagickPixel($color));
+ $draw->circle($x, $y, $r + $x, $y);
+ $res = $this->_imagick->drawImage($draw);
+ $draw->destroy();
+ }
+
+ /**
+ * Draw a polygon based on a set of vertices.
+ *
+ * @param array $vertices An array of x and y labeled arrays
+ * (eg. $vertices[0]['x'], $vertices[0]['y'], ...).
+ * @param string $color The color you want to draw the polygon with.
+ * @param string $fill The color to fill the polygon.
+ */
+ public function polygon($verts, $color, $fill = 'none')
+ {
+ $draw = new ImagickDraw();
+ $draw->setFillColor(new ImagickPixel($fill));
+ $draw->setStrokeColor(new ImagickPixel($color));
+ $draw->polygon($verts);
+ $res = $this->_imagick->drawImage($draw);
+ $draw->destroy();
+ }
+
+ /**
+ * Draw a rectangle.
+ *
+ * @param integer $x The left x-coordinate of the rectangle.
+ * @param integer $y The top y-coordinate of the rectangle.
+ * @param integer $width The width of the rectangle.
+ * @param integer $height The height of the rectangle.
+ * @param string $color The line color of the rectangle.
+ * @param string $fill The color to fill the rectangle.
+ */
+ public function rectangle($x, $y, $width, $height, $color, $fill = 'none')
+ {
+ $draw = new ImagickDraw();
+ $draw->setStrokeColor(new ImagickPixel($color));
+ $draw->setFillColor(new ImagickPixel($fill));
+ $draw->rectangle($x, $y, $x + $width, $y + $height);
+ $res = $this->_imagick->drawImage($draw);
+ $draw->destroy();
+ }
+
+ /**
+ * Draw a rounded rectangle.
+ *
+ * @param integer $x The left x-coordinate of the rectangle.
+ * @param integer $y The top y-coordinate of the rectangle.
+ * @param integer $width The width of the rectangle.
+ * @param integer $height The height of the rectangle.
+ * @param integer $round The width of the corner rounding.
+ * @param string $color The line color of the rectangle.
+ * @param string $fill The color to fill the rounded rectangle with.
+ */
+ public function roundedRectangle($x, $y, $width, $height, $round, $color, $fill)
+ {
+ $draw = new ImagickDraw();
+ $draw->setStrokeColor(new ImagickPixel($color));
+ $draw->setFillColor(new ImagickPixel($fill));
+ $draw->roundRectangle($x, $y, $x + $width, $y + $height, $round, $round);
+ $res = $this->_imagick->drawImage($draw);
+ }
+
+ /**
+ * Draw a line.
+ *
+ * @param integer $x0 The x coordinate of the start.
+ * @param integer $y0 The y coordinate of the start.
+ * @param integer $x1 The x coordinate of the end.
+ * @param integer $y1 The y coordinate of the end.
+ * @param string $color The line color.
+ * @param string $width The width of the line.
+ */
+ public function line($x0, $y0, $x1, $y1, $color = 'black', $width = 1)
+ {
+ $draw = new ImagickDraw();
+ $draw->setStrokeColor(new ImagickPixel($color));
+ $draw->setStrokeWidth($width);
+ $draw->line($x0, $y0, $x1, $y1);
+ $res = $this->_imagick->drawImage($draw);
+ $draw->destroy();
+ }
+
+ /**
+ * Draw a dashed line.
+ *
+ * @param integer $x0 The x co-ordinate of the start.
+ * @param integer $y0 The y co-ordinate of the start.
+ * @param integer $x1 The x co-ordinate of the end.
+ * @param integer $y1 The y co-ordinate of the end.
+ * @param string $color The line color.
+ * @param string $width The width of the line.
+ * @param integer $dash_length The length of a dash on the dashed line
+ * @param integer $dash_space The length of a space in the dashed line
+ */
+ public function dashedLine($x0, $y0, $x1, $y1, $color = 'black', $width = 1, $dash_length = 2, $dash_space = 2)
+ {
+ $draw = new ImagickDraw();
+ $draw->setStrokeColor(new ImagickPixel($color));
+ $draw->setStrokeWidth($width);
+ $draw->setStrokeDashArray(array($dash_length, $dash_space));
+ $draw->line($x0, $y0, $x1, $y1);
+ $res = $this->_imagick->drawImage($draw);
+ $draw->destroy();
+ }
+
+ /**
+ * Draw a polyline (a non-closed, non-filled polygon) based on a
+ * set of vertices.
+ *
+ * @param array $vertices An array of x and y labeled arrays
+ * (eg. $vertices[0]['x'], $vertices[0]['y'], ...).
+ * @param string $color The color you want to draw the line with.
+ * @param string $width The width of the line.
+ */
+ public function polyline($verts, $color, $width = 1)
+ {
+ $draw = new ImagickDraw();
+ $draw->setStrokeColor(new ImagickPixel($color));
+ $draw->setStrokeWidth($width);
+ $draw->setFillColor(new ImagickPixel('none'));
+ $draw->polyline($verts);
+ $res = $this->_imagick->drawImage($draw);
+ $draw->destroy();
+ }
+
+ /**
+ * Draw an arc.
+ *
+ * @TODO
+ *
+ * @param integer $x The x coordinate of the centre.
+ * @param integer $y The y coordinate of the centre.
+ * @param integer $r The radius of the arc.
+ * @param integer $start The start angle of the arc.
+ * @param integer $end The end angle of the arc.
+ * @param string $color The line color of the arc.
+ * @param string $fill The fill color of the arc (defaults to none).
+ */
+ public function arc($x, $y, $r, $start, $end, $color = 'black', $fill = 'none')
+ {
+ throw new Horde_Image_Exception('Not Yet Implemented.');
+ }
+
+ public function applyEffects()
+ {
+ // noop for this driver.
+ }
+
+ public function __get($property)
+ {
+ switch ($property) {
+ case "imagick":
+ return $this->_imagick;
+ }
+ }
+
+ /**
+ * Utility function to wrap Imagick::borderImage so we can preserve any
+ * transparency in the image.
+ *
+ * @param Imagick &$image The Imagick object to border.
+ * @param integer $width
+ * @param integer $height
+ *
+ * @return void
+ */
+ static public function borderImage(&$image, $color, $width, $height)
+ {
+ // Need to jump through these hoops in order to preserve any
+ // transparency.
+ $border = $image->clone();
+ $border->borderImage(new ImagickPixel($color), $width, $height);
+ $border->compositeImage($image, Imagick::COMPOSITE_COPY, $width, $height);
+ $image->clear();
+ $image->addImage($border);
+ $border->destroy();
+ }
+
+ }
\ No newline at end of file
<file name="Border.php" role="php" />
<file name="Composite.php" role="php" />
</dir> <!-- /Horde/Image/Effect/im -->
+ <dir name="Imagick">
+ <file name="DropShadow.php" role="php" />
+ <file name="RoundCorners.php" role="php" />
+ <file name="TextWatermark.php" role="php" />
+ <file name="PhotoStack.php" role="php" />
+ <file name="PolaroidImage.php" role="php" />
+ <file name="Border.php" role="php" />
+ <file name="Composite.php" role="php" />
+ </dir> <!-- /Horde/Image/Effect/Imagick -->
<dir name="Gd">
<file name="DropShadow.php" role="php" />
<file name="RoundCorners.php" role="php" />
<file name="rgb.php" role="php" />
<file name="Svg.php" role="php" />
<file name="Swf.php" role="php" />
+ <file name="Exception.php" role="php" />
</dir> <!-- /Horde/Image -->
<dir name="tests">
<file name="gd.php" role="test" />
<file name="swf.php" role="test" />
</dir> <!-- /tests -->
<file name="Image.php" role="php" />
- <file name="Exception.php" role="php" />
</dir> <!-- /Horde -->
</dir> <!-- /lib -->
</dir> <!-- / -->
<install name="lib/Horde/Image/Effect/Im/PolaroidImage.php" as="Horde/Image/Effect/Im/PolaroidImage.php" />
<install name="lib/Horde/Image/Effect/Im/Border.php" as="Horde/Image/Effect/Im/Border.php" />
<install name="lib/Horde/Image/Effect/Im/Composite.php" as="Horde/Image/Effect/Im/Composite.php" />
+ <install name="lib/Horde/Image/Effect/Imagick/DropShadow.php" as="Horde/Image/Effect/Imagick/DropShadow.php" />
+ <install name="lib/Horde/Image/Effect/Imagick/RoundCorners.php" as="Horde/Image/Effect/Imagick/RoundCorners.php" />
+ <install name="lib/Horde/Image/Effect/Imagick/TextWatermark.php" as="Horde/Image/Effect/Imagick/TextWatermark.php" />
+ <install name="lib/Horde/Image/Effect/Imagick/PhotoStack.php" as="Horde/Image/Effect/Imagick/PhotoStack.php" />
+ <install name="lib/Horde/Image/Effect/Imagick/PolaroidImage.php" as="Horde/Image/Effect/Imagick/PolaroidImage.php" />
+ <install name="lib/Horde/Image/Effect/Imagick/Border.php" as="Horde/Image/Effect/Imagick/Border.php" />
+ <install name="lib/Horde/Image/Effect/Imagick/Composite.php" as="Horde/Image/Effect/Imagick/Composite.php" />
<install name="lib/Horde/Image/Effect/Gd/DropShadow.php" as="Horde/Image/Effect/Gd/DropShadow.php" />
<install name="lib/Horde/Image/Effect/Gd/RoundCorners.php" as="Horde/Image/Effect/Gd/RoundCorners.php" />
<install name="lib/Horde/Image/Effect/Gd/TextWatermark.php" as="Horde/Image/Effect/Gd/TextWatermark.php" />
<install name="lib/Horde/Image/rgb.php" as="Horde/Image/rgb.php" />
<install name="lib/Horde/Image/Svg.php" as="Horde/Image/Svg.php" />
<install name="lib/Horde/Image/Swf.php" as="Horde/Image/Swf.php" />
+ <install name="lib/Horde/Image/Exception.php" as="Horde/Image/Exception.php" />
<install name="lib/Horde/Image.php" as="Horde/Image.php" />
</filelist>
</phprelease>