1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
13: class Horde_Image_Effect_Imagick_PhotoStack extends Horde_Image_Effect
14: {
15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 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: 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: if (!method_exists($this->_image->imagick, 'polaroidImage') ||
67: !method_exists($this->_image->imagick, 'trimImage')) {
68: throw new Horde_Image_Exception('Your version of Imagick is not compiled against a recent enough ImageMagick library to use the PhotoStack effect.');
69: }
70:
71: $imgs = array();
72: $length = 0;
73:
74: switch ($this->_params['type']) {
75: case 'plain':
76: case 'rounded':
77: $haveBottom = false;
78:
79:
80: $topimg = new Imagick();
81: $topimg->clear();
82: $topimg->readImageBlob($this->_params['images'][$cnt - 1]->raw());
83: $topimg->thumbnailImage(
84: $this->_params['resize_height'],
85: $this->_params['resize_height'],
86: true);
87: if ($this->_params['type'] == 'rounded') {
88: $topimg = $this->_roundBorder($topimg);
89: }
90:
91: $size = $topimg->getImageGeometry();
92: foreach ($this->_params['images'] as $image) {
93: $imgk= new Imagick();
94: $imgk->clear();
95: $imgk->readImageBlob($image->raw());
96:
97:
98: if ($i++ <= $cnt) {
99: $imgk->thumbnailImage($size['width'], $size['height'], false);
100: } else {
101: $imgk->destroy();
102: $imgk = $topimg->clone();
103: }
104: if ($this->_params['type'] == 'rounded') {
105: $imgk = $this->_roundBorder($imgk);
106: } else {
107: $imgk->borderImage($this->_params['bordercolor'],
108: $this->_params['borderwidth'],
109: $this->_params['borderwidth']);
110: }
111:
112: if (!$haveBottom) {
113: $shad = $imgk->clone();
114: $shad->setImageBackgroundColor(new ImagickPixel('black'));
115: $shad->shadowImage(80, 4, 0, 0);
116: $shad->compositeImage($imgk, Imagick::COMPOSITE_OVER, 0, 0);
117: $imgk->clear();
118: $imgk->addImage($shad);
119: $shad->destroy();
120: $haveBottom = true;
121: }
122:
123: $geo = $imgk->getImageGeometry();
124: $length = max(
125: $length,
126: sqrt(pow($geo['height'], 2) + pow($geo['width'], 2)));
127:
128: $imgs[] = $imgk;
129: }
130: break;
131: case 'polaroid':
132: foreach ($this->_params['images'] as $image) {
133:
134:
135:
136: $imgk= new Imagick();
137: $imgk->clear();
138: $imgk->readImageBlob($image->raw());
139: $imgk->thumbnailImage($this->_params['resize_height'],
140: $this->_params['resize_height'],
141: true);
142: $imgk->setImageBackgroundColor('black');
143: if ($i++ == $cnt) {
144: $angle = 0;
145: } else {
146: $angle = mt_rand(1, 45);
147: if (mt_rand(1, 2) % 2 === 0) {
148: $angle = $angle * -1;
149: }
150: }
151: $result = $imgk->polaroidImage(new ImagickDraw(), $angle);
152:
153:
154: $geo = $imgk->getImageGeometry();
155: $length = max(
156: $length,
157: sqrt(pow($geo['height'], 2) + pow($geo['width'], 2)));
158:
159: $imgs[] = $imgk;
160: }
161: break;
162: }
163:
164:
165: $this->_image->imagick->thumbnailImage($length * 1.5 + 20,
166: $length * 1.5 + 20);
167:
168:
169: $xo = $yo = (count($imgs) + 1) * $this->_params['offset'];
170: foreach ($imgs as $image) {
171: if ($this->_params['type'] == 'polaroid') {
172: $xo = mt_rand(1, $this->_params['resize_height'] / 2);
173: $yo = mt_rand(1, $this->_params['resize_height'] / 2);
174: } elseif ($this->_params['type'] == 'plain' ||
175: $this->_params['type'] == 'rounded') {
176: $xo -= $this->_params['offset'];
177: $yo -= $this->_params['offset'];
178: }
179: $this->_image->imagick->compositeImage($image, Imagick::COMPOSITE_OVER, $xo, $yo);
180: $image->removeImage();
181: $image->destroy();
182: }
183:
184:
185:
186: $this->_image->imagick->trimImage(0);
187: if ($this->_params['padding'] || $this->_params['background'] != 'none') {
188: $this->_image->imagick->borderImage(
189: new ImagickPixel($this->_params['background']),
190: $this->_params['padding'],
191: $this->_params['padding']);
192: }
193:
194: return true;
195: }
196:
197: private function _roundBorder($image)
198: {
199: $context = array('tmpdir' => $this->_image->getTmpDir());
200: $size = $image->getImageGeometry();
201: $new = new Horde_Image_Imagick(array(), $context);
202: $new->loadString($image->getImageBlob());
203: $image->destroy();
204: $new->addEffect('RoundCorners', array('border' => 2, 'bordercolor' => '#111'));
205: $new->applyEffects();
206: $return = new Imagick();
207: $return->newImage($size['width'] + $this->_params['borderwidth'],
208: $size['height'] + $this->_params['borderwidth'],
209: $this->_params['bordercolor']);
210: $return->setImageFormat($this->_image->getType());
211: $return->clear();
212: $return->readImageBlob($new->raw());
213:
214: return $return;
215: }
216:
217: }