Overview

Packages

  • Image
  • None

Classes

  • Horde_Image
  • Horde_Image_Base
  • Horde_Image_Effect
  • Horde_Image_Effect_Border
  • Horde_Image_Effect_Gd_DropShadow
  • Horde_Image_Effect_Gd_RoundCorners
  • Horde_Image_Effect_Gd_TextWatermark
  • Horde_Image_Effect_Gd_Unsharpmask
  • Horde_Image_Effect_Im_Border
  • Horde_Image_Effect_Im_CenterCrop
  • Horde_Image_Effect_Im_Composite
  • Horde_Image_Effect_Im_DropShadow
  • Horde_Image_Effect_Im_LiquidResize
  • Horde_Image_Effect_Im_PhotoStack
  • Horde_Image_Effect_Im_PolaroidImage
  • Horde_Image_Effect_Im_RoundCorners
  • Horde_Image_Effect_Im_TextWatermark
  • Horde_Image_Effect_Im_Unsharpmask
  • Horde_Image_Effect_Imagick_Border
  • Horde_Image_Effect_Imagick_CenterCrop
  • Horde_Image_Effect_Imagick_Composite
  • Horde_Image_Effect_Imagick_DropShadow
  • Horde_Image_Effect_Imagick_LiquidResize
  • Horde_Image_Effect_Imagick_PhotoStack
  • Horde_Image_Effect_Imagick_PolaroidImage
  • Horde_Image_Effect_Imagick_RoundCorners
  • Horde_Image_Effect_Imagick_SmartCrop
  • Horde_Image_Effect_Imagick_TextWatermark
  • Horde_Image_Effect_Imagick_Unsharpmask
  • Horde_Image_Exception
  • Horde_Image_Exif
  • Horde_Image_Exif_Base
  • Horde_Image_Exif_Bundled
  • Horde_Image_Exif_Exiftool
  • Horde_Image_Exif_Parser_Base
  • Horde_Image_Exif_Php
  • Horde_Image_Gd
  • Horde_Image_Im
  • Horde_Image_Imagick
  • Horde_Image_Png
  • Horde_Image_Svg
  • Horde_Image_Swf
  • Horde_Image_Translation
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Effect for composing multiple images into a single image.
  4:  *
  5:  * Copyright 2007-2012 Horde LLC (http://www.horde.org/)
  6:  *
  7:  * The technique for the Polaroid-like stack using the Imagick extension is
  8:  * credited to Mikko Koppanen and is documented at http://valokuva.org
  9:  *
 10:  * @author  Michael J. Rubinsky <mrubinsk@horde.org>
 11:  * @package Image
 12:  */
 13: class Horde_Image_Effect_Im_PhotoStack extends Horde_Image_Effect
 14: {
 15:     /**
 16:      * Valid parameters for the stack effect
 17:      *
 18:      * images           -    An array of Horde_Image objects to stack. Images
 19:      *                       are stacked in a FIFO manner, so that the top-most
 20:      *                       image is the last one in this array.
 21:      *
 22:      * type             -    Determines the style for the composition.
 23:      *                       'plain' or 'polaroid' are supported.
 24:      *
 25:      * resize_height    -    The height that each individual thumbnail
 26:      *                       should be resized to before composing on the image.
 27:      *
 28:      * padding          -    How much padding should we ensure is left around
 29:      *                       the active image area?
 30:      *
 31:      * background       -    The background canvas color - this is used as the
 32:      *                       color to set any padding to.
 33:      *
 34:      * bordercolor      -    If using type 'plain' this sets the color of the
 35:      *                       border that each individual thumbnail gets.
 36:      *
 37:      * borderwidth      -    If using type 'plain' this sets the width of the
 38:      *                       border on each individual thumbnail.
 39:      *
 40:      * offset           -    If using type 'plain' this determines the amount of
 41:      *                       x and y offset to give each successive image when
 42:      *                       it is placed on the top of the stack.
 43:      *
 44:      * @var array
 45:      */
 46:     protected $_params = array('type' => 'plain',
 47:                                'resize_height' => '150',
 48:                                'padding' => 0,
 49:                                'background' => 'none',
 50:                                'bordercolor' => '#333',
 51:                                'borderwidth' => 1,
 52:                                'borderrounding' => 10,
 53:                                'offset' => 5);
 54: 
 55:     /**
 56:      * Create the photo_stack
 57:      *
 58:      */
 59:     public function apply()
 60:     {
 61:         $i = 1;
 62:         $cnt = count($this->_params['images']);
 63:         if ($cnt <=0) {
 64:             throw new Horde_Image_Exception('No Images provided.');
 65:         }
 66: 
 67:         // Start out fresh.
 68:         $this->_image->raw();
 69: 
 70:         switch ($this->_params['type']) {
 71:         case 'plain':
 72:         case 'rounded':
 73:             // Get top image dimensions, then force each bottom image to the
 74:             // same dimensions.
 75:             $this->_params['images'][$cnt - 1]->resize($this->_params['resize_height'],
 76:                                                        $this->_params['resize_height'],
 77:                                                        true);
 78:             $size = $this->_params['images'][$cnt - 1]->getDimensions();
 79:             $xo = $yo = (count($this->_params['images'])) * $this->_params['offset'];
 80:             $ops = '';
 81:             $haveBottom = false;
 82:             foreach ($this->_params['images'] as $image) {
 83:                 $image->resize($size['height'], $size['width'], false);
 84:                 $xo -= $this->_params['offset'];
 85:                 $yo -= $this->_params['offset'];
 86: 
 87:                 if ($this->_params['type'] == 'rounded') {
 88:                     $temp = $this->_roundBorder($image);
 89:                 } else {
 90:                     $temp = $image->toFile();
 91:                 }
 92:                 $this->_image->addFileToClean($temp);
 93:                 $ops .= ' \( ' . $temp . ' -background none -thumbnail ' . $size['width'] . 'x' . $size['height'] . '! -repage +' . $xo . '+' . $yo . ($this->_params['type'] == 'plain' ? ' -bordercolor "#333" -border 1 ' : ' ' ) . ((!$haveBottom) ? '\( +clone -shadow 80x3+4+4 \) +swap -mosaic' : '') . ' \) ';
 94:                 $haveBottom = true;
 95:             }
 96: 
 97:             // The first -background none option below is only honored in
 98:             // convert versions before 6.4 it seems. Without it specified as
 99:             // none here, all stacks come out with a white background.
100:             $this->_image->addPostSrcOperation($ops . ' -background ' . $this->_params['background'] . ' -mosaic -bordercolor ' . $this->_params['background'] . ' -border ' . $this->_params['padding']);
101:             break;
102: 
103:         case 'polaroid':
104:             // Check for im version > 6.3.2
105:             $ver = $this->_image->getIMVersion();
106:             if (is_array($ver) && version_compare($ver[0], '6.3.2') >= 0) {
107:                 $ops = '';
108:                 foreach ($this->_params['images'] as $image) {
109:                     $temp = $image->toFile();
110:                     // Remember the temp files so we can nuke them later.
111:                     $this->_image->addFileToClean($temp);
112: 
113:                     // Don't rotate the top image.
114:                     if ($i++ == $cnt) {
115:                         $angle = 0;
116:                     } else {
117:                         $angle = mt_rand(1, 45);
118:                         if (mt_rand(1, 2) % 2 === 0) {
119:                             $angle = $angle * -1;
120:                         }
121:                     }
122:                     $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 . ' \) ';
123:                 }
124:                 $this->_image->addPostSrcOperation('-background none' . $ops . '-mosaic -bordercolor ' . $this->_params['background'] . ' -border ' . $this->_params['padding']);
125:             } else {
126:                 // An attempt at a -polaroid command free version of this
127:                 // effect based on various examples and ideas at
128:                 // http://imagemagick.org
129:                 $ops = '';
130:                 foreach ($this->_params['images'] as $image) {
131:                     $temp = $image->toFile();
132:                     $this->_image->addFileToClean($temp);
133:                     if ($i++ == $cnt) {
134:                         $angle = 0;
135:                     } else {
136:                         $angle = mt_rand(1, 45);
137:                         if (mt_rand(1, 2) % 2 === 0) {
138:                             $angle = $angle * -1;
139:                         }
140:                     }
141:                     $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 \) ';
142:                 }
143:                 $this->_image->addPostSrcOperation('-background none ' . $ops . '-mosaic -trim +repage -bordercolor ' . $this->_params['background'] . ' -border ' . $this->_params['padding']);
144:             }
145:             break;
146:         }
147: 
148:         return true;
149:     }
150: 
151:     private function _roundBorder($image)
152:     {
153:         $context = array('tmpdir' => $this->_image->getTmpDir(),
154:                          'convert' => $this->_image->getConvertPath());
155: 
156:         $size = $image->getDimensions();
157:         $new = new Horde_Image_Im(array('data' => $image->raw()), $context);
158:         $new->addEffect('RoundCorners', array('border' => 2, 'bordercolor' => '#111', 'background' => 'none'));
159:         $new->applyEffects();
160: 
161:         return $new->toFile();
162:     }
163: 
164: }
API documentation generated by ApiGen