* @TODO: - Can we depend on the Horde_Util:: class or some other solution needed?
* - Exceptions
*/
-class Horde_Image_Base Implements Iterator
+abstract class Horde_Image_Base Implements Iterator
{
/**
* Background color.
protected $_type = 'png';
/**
+ * Cache the context
+ *
+ * @param array
+ */
+ protected $_context;
+
+ /**
* Constructor.
*
* @param string $rgb The base color for generated pixels/images.
*/
protected function __construct($params, $context = array())
{
-
+ $this->_params = $params;
+ $this->_context = $context;
+
if (empty($context['tmpdir'])) {
throw new InvalidArgumentException('A path to a temporary directory is required.');
}
public function display()
{
$this->headers();
- echo $this->raw();
+ echo $this->raw(true);
}
/**
}
/**
- * Iterator interface
+ * Request a specific image from the collection of images.
+ *
+ * @param integer $index The index to return
+ *
+ * @return Horde_Image_Base
*/
- public function rewind()
- {
-
- }
-
- public function current()
-
- {
-
- }
-
- public function key()
- {
-
- }
-
- public function next()
- {
-
- }
-
- public function valid()
- {
-
- }
+ abstract function getImageAtIndex($index);
+ /**
+ * Return the number of image pages available in the image object.
+ *
+ * @return integer
+ */
+ abstract function getImagePageCount();
+
}
protected $_convert = '';
/**
+ * Path to the identify binary
+ *
+ * @string
+ */
+ protected $_identify;
+
+ /**
+ * Cache the number of image pages
+ *
+ * @var integer
+ */
+ private $_pages;
+
+ /**
+ * Track current page for the iterator
+ *
+ * @var integer
+ */
+ private $_currentPage = 0;
+
+ /**
* Constructor.
*/
public function __construct($params, $context = array())
throw new InvalidArgumentException('A path to the convert binary is required.');
}
$this->_convert = $context['convert'];
+
+ if (!empty($context['identify'])) {
+ $this->_identify = $context['identify'];
+ }
if (!empty($params['filename'])) {
$this->loadFile($params['filename']);
} elseif (!empty($params['data'])) {
}
/**
+ * Publically visible raw method. Hides the extra parameters from client
+ * code.
+ *
+ * @see self::_raw
+ */
+ public function raw($convert = false)
+ {
+ return $this->_raw($convert);
+ }
+
+ /**
* Returns the raw data for this image.
*
* @param boolean $convert If true, the image data will be returned in the
*
* @return string The raw image data.
*/
- public function raw($convert = false)
+ private function _raw($convert = false, $index = 0, $preserve_data = false)
{
if (empty($this->_data) ||
// If there are no operations, and we already have data, don't
if (count($this->_operations) || count($this->_postSrcOperations) || $convert) {
$tmpout = Horde_Util::getTempFile('img', false, $this->_tmpdir);
$command = $this->_convert . ' ' . implode(' ', $this->_operations)
- . ' "' . $tmpin . '"\'[0]\' '
+ . ' "' . $tmpin . '"\'[' . $index . ']\' '
. implode(' ', $this->_postSrcOperations)
. ' +profile "*" ' . $this->_type . ':"' . $tmpout . '" 2>&1';
$this->_logDebug(sprintf("convert command executed by Horde_Image_im::raw(): %s", $command));
$this->_postSrcOperations = array();
/* Load the result */
- $this->_data = file_get_contents($tmpout);
+ $return = file_get_contents($tmpout);
+ if (!$preserve_data) {
+ $this->_data = $return;
+ }
}
@unlink($tmpin);
@unlink($tmpout);
- return $this->_data;
+ return $return;
}
/**
return $this->_convert;
}
+ /**
+ * Reset the imagick iterator to the first image in the set.
+ *
+ * @return void
+ */
+ public function rewind()
+ {
+ $this->_logDebug('Horde_Image_Im#rewind');
+ $this->_currentPage = 0;
+ }
+
+ /**
+ * Return the current image from the internal iterator.
+ *
+ * @return Horde_Image_Imagick
+ */
+ public function current()
+ {
+ $this->_logDebug('Horde_Image_Im#current');
+ return $this->getImageAtIndex($this->_currentPage);
+ }
+
+ /**
+ * Get the index of the internal iterator.
+ *
+ * @return integer
+ */
+ public function key()
+ {
+ $this->_logDebug('Horde_Image_Im#key');
+ return $this->_currentPage;
+ }
+
+ /**
+ * Advance the iterator
+ *
+ * @return Horde_Image_Im
+ */
+ public function next()
+ {
+ $this->_logDebug('Horde_Image_Im#next');
+ $this->_currentPage++;
+ if ($this->valid()) {
+ return $this->getImageAtIndex($this->_currentPage);
+ }
+ }
+
+ /**
+ * Deterimines if the current iterator item is valid.
+ *
+ * @return boolean
+ */
+ public function valid()
+ {
+ return $this->_currentPage < $this->getImagePageCount();
+ }
+
+ /**
+ * Request a specific image from the collection of images.
+ *
+ * @param integer $index The index to return
+ *
+ * @return Horde_Image_Base
+ */
+ public function getImageAtIndex($index)
+ {
+ $this->_logDebug('Horde_Image_Im#getImageAtIndex: ' . $index);
+ if ($index >= $this->getImagePageCount()) {
+ throw new Horde_Image_Exception('Image index out of bounds.');
+ }
+ $rawImage = $this->_raw(true, $index, true);
+ $image = new Horde_Image_Im(array('data' => $rawImage), $this->_context);
+
+ return $image;
+ }
+
+ /**
+ * Return the number of image pages available in the image object.
+ *
+ * @return integer
+ */
+ public function getImagePageCount()
+ {
+ if (is_null($this->_pages)) {
+ $pages = $this->_getImagePages();
+ $this->_pages = array_pop($pages);
+ }
+ $this->_logDebug('Horde_Image_Im#getImagePageCount: ' . $this->_pages);
+
+ return $this->_pages;
+
+ }
+
+ private function _getImagePages()
+ {
+ $this->_logDebug('Horde_Image_Im#_getImagePages');
+ $filename = $this->toFile();
+ $cmd = $this->_identify . ' -format "%n" ' . $filename;
+ exec($cmd, $output, $retval);
+ if ($retval) {
+ $this->_logErr(sprintf("Error running command: %s", $cmd . "\n" . implode("\n", $output)));
+ }
+ unlink($filename);
+
+ return $output;
+ }
}
throw new Horde_Image_Exception($e);
}
$this->_imagick->setFormat($this->_type);
- $this->_imagick->setIteratorIndex(0);
+ //$this->_imagick->setIteratorIndex(0);
unset($this->_data);
}
{
$this->_logDebug('Horde_Image_Imagick#current');
$params = array('data' => $this->raw());
- $context = array('tmpdir' => $this->_tmpdir,
- 'logger' => $this->_logger);
- $image = new Horde_Image_Imagick($params, $context);
- $this->_logDebug(print_r($image, true));
+ $image = new Horde_Image_Imagick($params, $this->_context);
+
return $image;
}
}
}
+ /**
+ * Deterimines if the current iterator item is valid.
+ *
+ * @return boolean
+ */
public function valid()
{
$this->_logDebug('Horde_Image_Imagick#valid:' . print_r(!$this->moreImages, true));
return !$this->_noMoreImages;
}
+
+ /**
+ * Request a specific image from the collection of images.
+ *
+ * @param integer $index The index to return
+ *
+ * @return Horde_Image_Base
+ */
+ public function getImageAtIndex($index)
+ {
+ if ($index >= $this->_imagick->getNumberImages()) {
+ throw Horde_Image_Exception('Image index out of bounds.');
+ }
+
+ $currentIndex = $this->_imagick->getIteratorIndex();
+ $this->_imagick->setIteratorIndex($index);
+ $image = $this->current();
+ $this->_imagick->setIteratorIndex($currentIndex);
+
+ return $image;
+ }
+
+ /**
+ * Return the number of image pages available in the image object.
+ *
+ * @return integer
+ */
+ public function getImagePageCount()
+ {
+ return $this->_imagick->getNumberImages();
+ }
}