1. <?php
2. /**
3. * This file contains the ezcImageImagemagickHandler class.
4. *
5. * @package ImageConversion
6. * @version //autogentag//
7. * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
8. * @license http://ez.no/licenses/new_bsd New BSD License
9. * @filesource
10. */
11.
12. /**
13. * ezcImageHandler implementation for ImageMagick.
14. *
15. * @see ezcImageConverter
16. * @see ezcImageHandler
17. *
18. * @package ImageConversion
19. * @version //autogentag//
20. */
21. class ezcImageImagemagickHandler extends ezcImageImagemagickBaseHandler
22. implements ezcImageGeometryFilters,
23. ezcImageColorspaceFilters,
24. ezcImageEffectFilters,
25. ezcImageWatermarkFilters,
26. ezcImageThumbnailFilters
27. {
28.
29. /**
30. * Scale filter.
31. * General scale filter. Scales the image to fit into a given box size,
32. * determined by a given width and height value, measured in pixel. This
33. * method maintains the aspect ratio of the given image. Depending on the
34. * given direction value, this method performs the following scales:
35. *
36. * - ezcImageGeometryFilters::SCALE_BOTH:
37. * The image will be scaled to fit exactly into the given box
38. * dimensions, no matter if it was smaller or larger as the box
39. * before.
40. * - ezcImageGeometryFilters::SCALE_DOWN:
41. * The image will be scaled to fit exactly into the given box
42. * only if it was larger than the given box dimensions before. If it
43. * is smaller, the image will not be scaled at all.
44. * - ezcImageGeometryFilters::SCALE_UP:
45. * The image will be scaled to fit exactly into the given box
46. * only if it was smaller than the given box dimensions before. If it
47. * is larger, the image will not be scaled at all. ATTENTION:
48. * In this case, the image does not necessarily fit into the given box
49. * afterwards.
50. *
51. * ATTENTION: Using this filter method directly results in the filter being
52. * applied to the image which is internally marked as "active" (most
53. * commonly this is the last recently loaded one). It is highly recommended
54. * to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
55. * method, which enables you to specify the image a filter is applied to.
56. *
57. * @param int $width Scale to width
58. * @param int $height Scale to height
59. * @param int $direction Scale to which direction.
60. * @return void
61. *
62. * @throws ezcImageInvalidReferenceException
63. * No loaded file could be found or an error destroyed a loaded reference.
64. * @throws ezcBaseValueException
65. * If a submitted parameter was out of range or type.
66. */
67. public function scale( $width, $height, $direction = ezcImageGeometryFilters::SCALE_BOTH )
68. {
69. if ( !is_int( $width ) || $width < 1 )
70. {
71. throw new ezcBaseValueException( 'width', $width, 'int > 0' );
72. }
73. if ( !is_int( $height ) || $height < 1 )
74. {
75. throw new ezcBaseValueException( 'height', $height, 'int > 0' );
76. }
77.
78. $dirMod = $this->getDirectionModifier( $direction );
79. $this->addFilterOption(
80. $this->getActiveReference(),
81. '-resize',
82. $width.$dirMod.'x'.$height.$dirMod
83. );
84. }
85.
86. /**
87. * Scale after width filter.
88. * Scales the image to a give width, measured in pixel. Scales the height
89. * automatically while keeping the ratio. The direction dictates, if an
90. * image may only be scaled {@link self::SCALE_UP}, {@link self::SCALE_DOWN}
91. * or if the scale may work in {@link self::SCALE_BOTH} directions.
92. *
93. * ATTENTION: Using this filter method directly results in the filter being
94. * applied to the image which is internally marked as "active" (most
95. * commonly this is the last recently loaded one). It is highly recommended
96. * to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
97. * method, which enables you to specify the image a filter is applied to.
98. *
99. * @param int $width Scale to width
100. * @param int $direction Scale to which direction
101. * @return void
102. *
103. * @throws ezcImageInvalidReferenceException
104. * No loaded file could be found or an error destroyed a loaded reference
105. * @throws ezcBaseValueException
106. * If a submitted parameter was out of range or type.
107. */
108. public function scaleWidth( $width, $direction )
109. {
110. if ( !is_int( $width ) || $width < 1 )
111. {
112. throw new ezcBaseValueException( 'width', $width, 'int > 0' );
113. }
114.
115. $dirMod = $this->getDirectionModifier( $direction );
116. $this->addFilterOption(
117. $this->getActiveReference(),
118. '-resize ',
119. $width.$dirMod
120. );
121. }
122.
123. /**
124. * Scale after height filter.
125. * Scales the image to a give height, measured in pixel. Scales the width
126. * automatically while keeping the ratio. The direction dictates, if an
127. * image may only be scaled {@link self::SCALE_UP}, {@link self::SCALE_DOWN}
128. * or if the scale may work in {@link self::SCALE_BOTH} directions.
129. *
130. * ATTENTION: Using this filter method directly results in the filter being
131. * applied to the image which is internally marked as "active" (most
132. * commonly this is the last recently loaded one). It is highly recommended
133. * to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
134. * method, which enables you to specify the image a filter is applied to.
135. *
136. * @param int $height Scale to height
137. * @param int $direction Scale to which direction
138. * @return void
139. *
140. * @throws ezcImageInvalidReferenceException
141. * No loaded file could be found or an error destroyed a loaded reference
142. * @throws ezcBaseValueException
143. * If a submitted parameter was out of range or type.
144. */
145. public function scaleHeight( $height, $direction )
146. {
147. if ( !is_int( $height ) || $height < 1 )
148. {
149. throw new ezcBaseValueException( 'height', $height, 'int > 0' );
150. }
151. $dirMod = $this->getDirectionModifier( $direction );
152. $this->addFilterOption(
153. $this->getActiveReference(),
154. '-resize ',
155. 'x'.$height.$dirMod
156. );
157. }
158.
159. /**
160. * Scale percent measures filter.
161. * Scale an image to a given percentage value size.
162. *
163. * ATTENTION: Using this filter method directly results in the filter being
164. * applied to the image which is internally marked as "active" (most
165. * commonly this is the last recently loaded one). It is highly recommended
166. * to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
167. * method, which enables you to specify the image a filter is applied to.
168. *
169. * @param int $width Scale to width
170. * @param int $height Scale to height
171. * @return void
172. *
173. * @throws ezcImageInvalidReferenceException
174. * No loaded file could be found or an error destroyed a loaded reference
175. * @throws ezcBaseValueException
176. * If a submitted parameter was out of range or type.
177. */
178. public function scalePercent( $width, $height )
179. {
180. if ( !is_int( $height ) || $height < 1 )
181. {
182. throw new ezcBaseValueException( 'height', $height, 'int > 0' );
183. }
184. if ( !is_int( $width ) || $width < 1 || $width > 100 )
185. {
186. throw new ezcBaseValueException( 'width', $width, 'int > 0' );
187. }
188. $this->addFilterOption(
189. $this->getActiveReference(),
190. '-resize',
191. $width.'%x'.$height.'%'
192. );
193. }
194.
195. /**
196. * Scale exact filter.
197. * Scale the image to a fixed given pixel size, no matter to which
198. * direction.
199. *
200. * ATTENTION: Using this filter method directly results in the filter being
201. * applied to the image which is internally marked as "active" (most
202. * commonly this is the last recently loaded one). It is highly recommended
203. * to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
204. * method, which enables you to specify the image a filter is applied to.
205. *
206. * @param int $width Scale to width
207. * @param int $height Scale to height
208. * @return void
209. *
210. * @throws ezcImageInvalidReferenceException
211. * No loaded file could be found or an error destroyed a loaded reference.
212. * @throws ezcBaseValueException
213. * If a submitted parameter was out of range or type.
214. */
215. public function scaleExact( $width, $height )
216. {
217. if ( !is_int( $height ) || $height < 1 )
218. {
219. throw new ezcBaseValueException( 'height', $height, 'int > 0' );
220. }
221. if ( !is_int( $width ) || $width < 1 )
222. {
223. throw new ezcBaseValueException( 'width', $width, 'int > 0' );
224. }
225. $this->addFilterOption(
226. $this->getActiveReference(),
227. '-resize',
228. $width.'!x'.$height.'!'
229. );
230. }
231.
232. /**
233. * Crop filter.
234. * Crop an image to a given size. This takes cartesian coordinates of a
235. * rect area to crop from the image. The cropped area will replace the old
236. * image resource (not the input image immediately, if you use the
237. * {@link ezcImageConverter}). Coordinates are given as integer values and
238. * are measured from the top left corner.
239. *
240. * ATTENTION: Using this filter method directly results in the filter being
241. * applied to the image which is internally marked as "active" (most
242. * commonly this is the last recently loaded one). It is highly recommended
243. * to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
244. * method, which enables you to specify the image a filter is applied to.
245. *
246. * @param int $x X offset of the cropping area.
247. * @param int $y Y offset of the cropping area.
248. * @param int $width Width of cropping area.
249. * @param int $height Height of cropping area.
250. * @return void
251. *
252. * @throws ezcImageInvalidReferenceException
253. * No loaded file could be found or an error destroyed a loaded reference.
254. * @throws ezcBaseValueException
255. * If a submitted parameter was out of range or type.
256. */
257. public function crop( $x, $y, $width, $height )
258. {
259. if ( !is_int( $x ) )
260. {
261. throw new ezcBaseValueException( 'x', $x, 'int' );
262. }
263. if ( !is_int( $y ) )
264. {
265. throw new ezcBaseValueException( 'y', $y, 'int' );
266. }
267. if ( !is_int( $height ) )
268. {
269. throw new ezcBaseValueException( 'height', $height, 'int' );
270. }
271. if ( !is_int( $width ) )
272. {
273. throw new ezcBaseValueException( 'width', $width, 'int' );
274. }
275.
276. $data = getimagesize( $this->getActiveResource() );
277. $x = ( $x >= 0 ) ? $x : $data[0] + $x;
278. $y = ( $y >= 0 ) ? $y : $data[1] + $y;
279.
280. $xStart = ( $xStart = min( $x, $x + $width ) ) >= 0 ? '+'.$xStart : $xStart;
281. $yStart = ( $yStart = min( $y, $y + $height ) ) >= 0 ? '+'.$yStart : $yStart;
282. $this->addFilterOption(
283. $this->getActiveReference(),
284. '-crop ',
285. abs( $width ).'x'.abs( $height ).$xStart.$yStart.'!'
286. );
287. }
288.
289. /**
290. * Colorspace filter.
291. * Transform the color space of the picture. The following color space are
292. * supported:
293. *
294. * - {@link self::COLORSPACE_GREY} - 255 grey colors
295. * - {@link self::COLORSPACE_SEPIA} - Sepia colors
296. * - {@link self::COLORSPACE_MONOCHROME} - 2 colors black and white
297. *
298. * ATTENTION: Using this filter method directly results in the filter being
299. * applied to the image which is internally marked as "active" (most
300. * commonly this is the last recently loaded one). It is highly recommended
301. * to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
302. * method, which enables you to specify the image a filter is applied to.
303. *
304. * @param int $space Colorspace, one of self::COLORSPACE_* constants.
305. * @return void
306. *
307. * @throws ezcImageInvalidReferenceException
308. * No loaded file could be found or an error destroyed a loaded reference
309. * @throws ezcBaseValueException
310. * If the parameter submitted as the colorspace was not within the
311. * self::COLORSPACE_* constants.
312. */
313. public function colorspace( $space )
314. {
315. switch ( $space )
316. {
317. case self::COLORSPACE_GREY:
318. $this->addFilterOption(
319. $this->getActiveReference(),
320. '-colorspace',
321. 'GRAY'
322. );
323. $this->addFilterOption(
324. $this->getActiveReference(),
325. '-colors',
326. '255'
327. );
328. break;
329. case self::COLORSPACE_MONOCHROME:
330. $this->addFilterOption(
331. $this->getActiveReference(),
332. '-monochrome'
333. );
334. break;
335. case self::COLORSPACE_SEPIA:
336. $this->addFilterOption(
337. $this->getActiveReference(),
338. '-sepia-tone',
339. '80%'
340. );
341. break;
342. return;
343. default:
344. throw new ezcBaseValueException( 'space', $space, 'self::COLORSPACE_GREY, self::COLORSPACE_SEPIA, self::COLORSPACE_MONOCHROME' );
345. break;
346. }
347. }
348.
349. /**
350. * Noise filter.
351. * Apply a noise transformation to the image. Valid values are the following
352. * strings:
353. * - 'Uniform'
354. * - 'Gaussian'
355. * - 'Multiplicative'
356. * - 'Impulse'
357. * - 'Laplacian'
358. * - 'Poisson'
359. *
360. * ATTENTION: Using this filter method directly results in the filter being
361. * applied to the image which is internally marked as "active" (most
362. * commonly this is the last recently loaded one). It is highly recommended
363. * to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
364. * method, which enables you to specify the image a filter is applied to.
365. *
366. * @param strings $value Noise value as described above.
367. * @return void
368. *
369. * @throws ezcBaseValueException
370. * If the noise value is out of range.
371. * @throws ezcImageInvalidReferenceException
372. * No loaded file could be found or an error destroyed a loaded reference.
373. */
374. public function noise( $value )
375. {
376. $value = ucfirst( strtolower( $value ) );
377. $possibleValues = array(
378. 'Uniform',
379. 'Gaussian',
380. 'Multiplicative',
381. 'Impulse',
382. 'Laplacian',
383. 'Poisson',
384. );
385. if ( !in_array( $value, $possibleValues ) )
386. {
387. throw new ezcBaseValueException( 'value', $value, 'Uniform, Gaussian, Multiplicative, Impulse, Laplacian, Poisson' );
388. }
389. $this->addFilterOption(
390. $this->getActiveReference(),
391. '+noise',
392. $value
393. );
394. }
395.
396. /**
397. * Swirl filter.
398. * Applies a swirl with the given intense to the image.
399. *
400. * ATTENTION: Using this filter method directly results in the filter being
401. * applied to the image which is internally marked as "active" (most
402. * commonly this is the last recently loaded one). It is highly recommended
403. * to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
404. * method, which enables you to specify the image a filter is applied to.
405. *
406. * @param int $value Intense of swirl.
407. * @return void
408. *
409. * @throws ezcImageInvalidReferenceException
410. * No loaded file could be found or an error destroyed a loaded reference.
411. * @throws ezcBaseValueException
412. * If the swirl value is out of range.
413. */
414. public function swirl( $value )
415. {
416. if ( !is_int( $value ) || $value < 0 )
417. {
418. throw new ezcBaseValueException( 'value', $value, 'int >= 0' );
419. }
420. $this->addFilterOption(
421. $this->getActiveReference(),
422. '-swirl',
423. $value
424. );
425. }
426.
427. /**
428. * Border filter.
429. * Adds a border to the image. The width is measured in pixel. The color is
430. * defined in an array of hex values:
431. *
432. * <code>
433. * array(
434. * 0 => <red value>,
435. * 1 => <green value>,
436. * 2 => <blue value>,
437. * );
438. * </code>
439. *
440. * ATTENTION: Using this filter method directly results in the filter being
441. * applied to the image which is internally marked as "active" (most
442. * commonly this is the last recently loaded one). It is highly recommended
443. * to apply filters through the {@link ezcImageImagemagickHandler::applyFilter()}
444. * method, which enables you to specify the image a filter is applied to.
445. *
446. * @param int $width Width of the border.
447. * @param array(int) $color Color.
448. * @return void
449. *
450. * @throws ezcImageInvalidReferenceException
451. * No loaded file could be found or an error destroyed a loaded reference.
452. * @throws ezcBaseValueException
453. * If a submitted parameter was out of range or type.
454. */
455. public function border( $width, array $color )
456. {
457. if ( !is_int( $width ) )
458. {
459. throw new ezcBaseValueException( 'width', $width, 'int' );
460. }
461. $colorString = $this->colorArrayToString( $color );
462. $this->addFilterOption(
463. $this->getActiveReference(),
464. '-bordercolor',
465. $colorString
466. );
467. $this->addFilterOption(
468. $this->getActiveReference(),
469. '-border',
470. $width
471. );
472. }
473.
474. /**
475. * Watermark filter.
476. * Places a watermark on the image. The file to use as the watermark image
477. * is given as $image. The $posX, $posY and $size values are given in
478. * percent, related to the destination image. A $size value of 10 will make
479. * the watermark appear in 10% of the destination image size.
480. * $posX = $posY = 10 will make the watermark appear in the top left corner
481. * of the destination image, 10% of its size away from its borders. If
482. * $size is ommitted, the watermark image will not be resized.
483. *
484. * @param string $image The image file to use as the watermark
485. * @param int $posX X position in the destination image in percent.
486. * @param int $posY Y position in the destination image in percent.
487. * @param int|bool$size Percentage size of the watermark, false for none.
488. * @return void
489. *
490. * @throws ezcImageInvalidReferenceException
491. * If no valid resource for the active reference could be found.
492. * @throws ezcImageFilterFailedException
493. * If the operation performed by the the filter failed.
494. * @throws ezcBaseValueException
495. * If a submitted parameter was out of range or type.
496. */
497. public function watermarkPercent( $image, $posX, $posY, $size = false )
498. {
499. if ( !is_string( $image ) || !file_exists( $image ) || !is_readable( $image ) )
500. {
501. throw new ezcBaseValueException( 'image', $image, 'string, path to an image file' );
502. }
503. if ( !is_int( $posX ) || $posX < 0 || $posX > 100 )
504. {
505. throw new ezcBaseValueException( 'posX', $posX, 'int percentage value' );
506. }
507. if ( !is_int( $posY ) || $posY < 0 || $posY > 100 )
508. {
509. throw new ezcBaseValueException( 'posY', $posY, 'int percentage value' );
510. }
511. if ( !is_bool( $size ) && ( !is_int( $size ) || $size < 0 || $size > 100 ) )
512. {
513. throw new ezcBaseValueException( 'size', $size, 'int percentage value / bool' );
514. }
515.
516. $data = getimagesize( $this->getReferenceData( $this->getActiveReference(), "resource" ) );
517.
518. $originalWidth = $data[0];
519. $originalHeight = $data[1];
520.
521. $watermarkWidth = false;
522. $watermarkHeight = false;
523.
524. if ( $size !== false )
525. {
526. $watermarkWidth = (int) round( $originalWidth * $size / 100 );
527. $watermarkHeight = (int) round( $originalHeight * $size / 100 );
528. }
529.
530. $watermarkPosX = (int) round( $originalWidth * $posX / 100 );
531. $watermarkPosY = (int) round( $originalHeight * $posY / 100 );
532.
533. $this->watermarkAbsolute( $image, $watermarkPosX, $watermarkPosY, $watermarkWidth, $watermarkHeight );
534.
535. }
536.
537. /**
538. * Watermark filter.
539. * Places a watermark on the image. The file to use as the watermark image
540. * is given as $image. The $posX, $posY and $size values are given in
541. * pixel. The watermark appear at $posX, $posY in the destination image
542. * with a size of $size pixel. If $size is ommitted, the watermark image
543. * will not be resized.
544. *
545. * @param string $image The image file to use as the watermark
546. * @param int $posX X position in the destination image in pixel.
547. * @param int $posY Y position in the destination image in pixel.
548. * @param int|bool$width Pixel size of the watermark, false to keep size.
549. * @param int|bool$height Pixel size of the watermark, false to keep size.
550. * @return void
551. *
552. * @throws ezcImageInvalidReferenceException
553. * If no valid resource for the active reference could be found.
554. * @throws ezcImageFilterFailedException
555. * If the operation performed by the the filter failed.
556. * @throws ezcBaseValueException
557. * If a submitted parameter was out of range or type.
558. */
559. public function watermarkAbsolute( $image, $posX, $posY, $width = false, $height = false )
560. {
561. if ( !is_string( $image ) || !file_exists( $image ) || !is_readable( $image ) )
562. {
563. throw new ezcBaseValueException( 'image', $image, 'string, path to an image file' );
564. }
565. if ( !is_int( $posX ) )
566. {
567. throw new ezcBaseValueException( 'posX', $posX, 'int' );
568. }
569. if ( !is_int( $posY ) )
570. {
571. throw new ezcBaseValueException( 'posY', $posY, 'int' );
572. }
573. if ( !is_int( $width ) && !is_bool( $width ) )
574. {
575. throw new ezcBaseValueException( 'width', $width, 'int/bool' );
576. }
577. if ( !is_int( $height ) && !is_bool( $height ) )
578. {
579. throw new ezcBaseValueException( 'height', $height, 'int/bool' );
580. }
581.
582. $data = getimagesize( $this->getActiveResource() );
583.
584. // Negative offsets
585. $posX = ( $posX >= 0 ) ? $posX : $data[0] + $posX;
586. $posY = ( $posY >= 0 ) ? $posY : $data[1] + $posY;
587.
588. $this->addFilterOption(
589. $this->getActiveReference(),
590. '-composite',
591. ''
592. );
593.
594. $this->addFilterOption(
595. $this->getActiveReference(),
596. '-geometry',
597. ( $width !== false ? $width : "" ) . ( $height !== false ? "x$height" : "" ) . "+$posX+$posY"
598. );
599.
600. $this->addCompositeImage( $this->getActiveReference(), $image );
601. }
602.
603. /**
604. * Creates a thumbnail, and crops parts of the given image to fit the range best.
605. * This filter creates a thumbnail of the given image. The image is scaled
606. * down, keeping the original ratio and keeping the image larger as the
607. * given range, if necessary. Overhead for the target range is cropped from
608. * both sides equally.
609. *
610. * If you are looking for a filter that just resizes your image to
611. * thumbnail size, you should consider the {@link }
612. * ezcImageImagemagickHandler::scale()} filter.
613. *
614. * @param int $width Width of the thumbnail.
615. * @param int $height Height of the thumbnail.
616. */
617. public function croppedThumbnail( $width, $height )
618. {
619. if ( !is_int( $width ) || $width < 1 )
620. {
621. throw new ezcBaseValueException( 'width', $width, 'int > 0' );
622. }
623. if ( !is_int( $height ) || $height < 1 )
624. {
625. throw new ezcBaseValueException( 'height', $height, 'int > 0' );
626. }
627. $data = getimagesize( $this->getReferenceData( $this->getActiveReference(), "resource" ) );
628.
629. $scaleRatio = max( $width / $data[0], $height / $data[1] );
630. $scaleWidth = round( $data[0] * $scaleRatio );
631. $scaleHeight = round( $data[1] * $scaleRatio );
632.
633. $cropOffsetX = ( $scaleWidth > $width ) ? "+" . round( ( $scaleWidth - $width ) / 2 ) : "+0";
634. $cropOffsetY = ( $scaleHeight > $height ) ? "+" . round( ( $scaleHeight - $height ) / 2 ) : "+0";
635.
636. $this->addFilterOption(
637. $this->getActiveReference(),
638. '-resize',
639. $scaleWidth . "x" . $scaleHeight
640. );
641. $this->addFilterOption(
642. $this->getActiveReference(),
643. '-crop',
644. $width . "x" . $height . $cropOffsetX . $cropOffsetY . "!"
645. );
646. }
647.
648. /**
649. * Creates a thumbnail, and fills up the image to fit the given range.
650. * This filter creates a thumbnail of the given image. The image is scaled
651. * down, keeping the original ratio and scaling the image smaller as the
652. * given range, if necessary. Overhead for the target range is filled with the given
653. * color on both sides equally.
654. *
655. * The color is defined by the following array format (integer values 0-255):
656. *
657. * <code>
658. * array(
659. * 0 => <red value>,
660. * 1 => <green value>,
661. * 2 => <blue value>,
662. * );
663. * </code>
664. *
665. * If you are looking for a filter that just resizes your image to
666. * thumbnail size, you should consider the {@link }
667. * ezcImageImagemagickHandler::scale()} filter.
668. *
669. * @param int $width Width of the thumbnail.
670. * @param int $height Height of the thumbnail.
671. * @param array $color Fill color.
672. * @return void
673. */
674. public function filledThumbnail( $width, $height, $color = array() )
675. {
676. if ( !is_int( $width ) || $width < 1 )
677. {
678. throw new ezcBaseValueException( 'width', $width, 'int > 0' );
679. }
680. if ( !is_int( $height ) || $height < 1 )
681. {
682. throw new ezcBaseValueException( 'height', $height, 'int > 0' );
683. }
684. $data = getimagesize( $this->getReferenceData( $this->getActiveReference(), "resource" ) );
685.
686. $scaleRatio = min( $width / $data[0], $height / $data[1] );
687. $scaleWidth = round( $data[0] * $scaleRatio );
688. $scaleHeight = round( $data[1] * $scaleRatio );
689.
690. $cropOffsetX = ( $scaleWidth < $width ) ? "-" . round( ( $width - $scaleWidth ) / 2 ) : "+0";
691. $cropOffsetY = ( $scaleHeight < $height ) ? "-" . round( ( $height - $scaleHeight ) / 2 ) : "+0";
692.
693. $colorString = '#';
694. $i = 0;
695. foreach ( $color as $id => $colorVal )
696. {
697. if ( $i++ > 2 )
698. {
699. break;
700. }
701. if ( !is_int( $colorVal ) || $colorVal < 0 || $colorVal > 255 )
702. {
703. throw new ezcBaseValueException( "color[$id]", $color[$id], 'int > 0 and < 256' );
704. }
705. $colorString .= sprintf( '%02x', $colorVal );
706. }
707.
708. $this->addFilterOption(
709. $this->getActiveReference(),
710. '-resize',
711. $width . "x" . $height
712. );
713. $this->addFilterOption(
714. $this->getActiveReference(),
715. '-crop',
716. $width . "x" . $height . $cropOffsetX . $cropOffsetY . "!"
717. );
718. $this->addFilterOption(
719. $this->getActiveReference(),
720. '-background',
721. $colorString
722. );
723. $this->addFilterOption(
724. $this->getActiveReference(),
725. '-flatten'
726. );
727. }
728.
729. /**
730. * Returns the ImageMagick direction modifier for a direction constant.
731. * ImageMagick supports the following modifiers to determine if an
732. * image should be scaled up only, down only or in both directions:
733. *
734. * <code>
735. * SCALE_UP: >
736. * SCALE_DOWN: <
737. * </code>
738. *
739. * This method returns the correct modifier for the internal direction
740. * constants.
741. *
742. * @param int $direction One of ezcImageGeometryFilters::SCALE_*
743. * @return string The correct modifier.
744. *
745. * @throws ezcBaseValueException
746. * If a submitted parameter was out of range or type.
747. */
748. protected function getDirectionModifier( $direction )
749. {
750. $dirMod = '';
751. switch ( $direction )
752. {
753. case self::SCALE_DOWN:
754. $dirMod = '>';
755. break;
756. case self::SCALE_UP:
757. $dirMod = '<';
758. break;
759. case self::SCALE_BOTH:
760. $dirMod = '';
761. break;
762. default:
763. throw new ezcBaseValueException( 'direction', $direction, 'self::SCALE_BOTH, self::SCALE_UP, self::SCALE_DOWN' );
764. break;
765. }
766. return $dirMod;
767. }
768. }
769. ?>