## Apache Zeta Components Manual :: File Source for gd.php

## Source for file gd.php

Documentation is available at gd.php

1. <?php
2. /**
3. * This file contains the ezcImageGdHandler class.
4. *
5. * Licensed to the Apache Software Foundation (ASF) under one
6. * or more contributor license agreements. See the NOTICE file
7. * distributed with this work for additional information
8. * regarding copyright ownership. The ASF licenses this file
9. * to you under the Apache License, Version 2.0 (the
10. * "License"); you may not use this file except in compliance
11. * with the License. You may obtain a copy of the License at
12. *
13. * http://www.apache.org/licenses/LICENSE-2.0
14. *
15. * Unless required by applicable law or agreed to in writing,
16. * software distributed under the License is distributed on an
17. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18. * KIND, either express or implied. See the License for the
19. * specific language governing permissions and limitations
20. * under the License.
21. *
22. * @package ImageConversion
23. * @version //autogentag//
24. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
25. * @filesource
26. */
28. /**
29. * ezcImageHandler implementation for the GD2 extension of PHP, including filters.
30. *
31. * This ezcImageHandler is used when you want to manipulate images using ext/GD
32. * in your application.
33. *
34. * Note: If you experience problems with loading some JPEG files that work in
35. * your image viewer, please set the php.ini directive 'gd.jpeg_ignore_warning'
36. * to true (possible via {@link ini_set()}).
37. *
38. * @see ezcImageConverter
39. * @see ezcImageHandler
40. *
41. * @package ImageConversion
42. * @version //autogentag//
43. */
44. class ezcImageGdHandler extends ezcImageGdBaseHandler
45. implements ezcImageGeometryFilters ,
46. ezcImageColorspaceFilters ,
47. ezcImageWatermarkFilters ,
48. ezcImageThumbnailFilters
49. {
50. /**
51. * Scale filter.
52. * General scale filter. Scales the image to fit into a given box size,
53. * determined by a given width and height value, measured in pixel. This
54. * method maintains the aspect ratio of the given image. Depending on the
55. * given direction value, this method performs the following scales:
56. *
57. * - ezcImageGeometryFilters::SCALE_BOTH:
58. * The image will be scaled to fit exactly into the given box
59. * dimensions, no matter if it was smaller or larger as the box
60. * before.
61. * - ezcImageGeometryFilters::SCALE_DOWN:
62. * The image will be scaled to fit exactly into the given box
63. * only if it was larger than the given box dimensions before. If it
64. * is smaller, the image will not be scaled at all.
65. * - ezcImageGeometryFilters::SCALE_UP:
66. * The image will be scaled to fit exactly into the given box
67. * only if it was smaller than the given box dimensions before. If it
68. * is larger, the image will not be scaled at all. ATTENTION:
69. * In this case, the image does not necessarily fit into the given box
70. * afterwards.
71. *
72. * ATTENTION: Using this filter method directly results in the filter being
73. * applied to the image which is internally marked as "active" (most
74. * commonly this is the last recently loaded one). It is highly recommended
75. * to apply filters through the {@link ezcImageGdHandler::applyFilter()} method,
76. * which enables you to specify the image a filter is applied to.
77. *
78. * @param int $width Scale to width
79. * @param int $height Scale to height
80. * @param int $direction Scale to which direction.
81. * @return void
82. *
83. * @throws ezcImageInvalidReferenceException
84. * If no valid resource for the active reference could be found.
85. * @throws ezcImageFilterFailedException
86. * If the operation performed by the the filter failed.
87. * @throws ezcBaseValueException
88. * If a submitted parameter was out of range or type.
89. */
90. public function scale ( $width, $height, $direction = ezcImageGeometryFilters::SCALE_BOTH )
91. {
93. if ( ! is_int ( $width ) || $width < 1 )
94. {
95. throw new ezcBaseValueException ( 'width', $width, 'int > 0' );
96. }
97. if ( ! is_int ( $height ) || $height < 1 )
98. {
99. throw new ezcBaseValueException ( 'height', $height, 'int > 0' );
100. }
102. $resource = $this->getActiveResource();
103. $oldDim = array( 'x' => imagesx ( $resource ), 'y' => imagesy ( $resource ) );
105. $widthRatio = $width / $oldDim['x'];
106. $heighRatio = $height / $oldDim['y'];
108. $ratio = min ( $widthRatio, $heighRatio );
110. switch ( $direction )
111. {
112. case self::SCALE_DOWN:
113. $ratio = $ratio < 1 ? $ratio : 1;
114. break;
115. case self::SCALE_UP:
116. $ratio = $ratio > 1 ? $ratio : 1;
117. break;
118. case self::SCALE_BOTH:
119. break;
120. default:
121. throw new ezcBaseValueException ( 'direction', $direction, 'self::SCALE_BOTH, self::SCALE_UP, self::SCALE_DOWN' );
122. break;
123. }
124. $this-> performScale ( round ( $oldDim['x'] * $ratio ), round ( $oldDim['y'] * $ratio ) );
125. }
127. /**
128. * Scale after width filter.
129. * Scales the image to a give width, measured in pixel. Scales the height
130. * automatically while keeping the ratio. The direction dictates, if an
131. * image may only be scaled {@link self::SCALE_UP}, {@link self::SCALE_DOWN}
132. * or if the scale may work in {@link self::SCALE_BOTH} directions.
133. *
134. * ATTENTION: Using this filter method directly results in the filter being
135. * applied to the image which is internally marked as "active" (most
136. * commonly this is the last recently loaded one). It is highly recommended
137. * to apply filters through the {@link ezcImageGdHandler::applyFilter()} method,
138. * which enables you to specify the image a filter is applied to.
139. *
140. * @param int $width Scale to width
141. * @param int $direction Scale to which direction
142. * @return void
143. *
144. * @throws ezcImageInvalidReferenceException
145. * If no valid resource for the active reference could be found.
146. * @throws ezcImageFilterFailedException
147. * If the operation performed by the the filter failed.
148. * @throws ezcBaseValueException
149. * If a submitted parameter was out of range or type.
150. */
151. public function scaleWidth ( $width, $direction )
152. {
153. if ( ! is_int ( $width ) || $width < 1 )
154. {
155. throw new ezcBaseValueException ( 'width', $width, 'int > 0' );
156. }
158. $resource = $this->getActiveResource();
159. $oldDim = array(
160. 'x' => imagesx ( $resource ),
161. 'y' => imagesy ( $resource ),
162. );
163. switch ( $direction )
164. {
165. case self::SCALE_BOTH:
166. $newDim = array(
167. 'x' => $width,
168. 'y' => $width / $oldDim['x'] * $oldDim['y']
169. );
170. break;
171. case self::SCALE_UP:
172. $newDim = array(
173. 'x' => max ( $width, $oldDim['x'] ),
174. 'y' => $width > $oldDim['x'] ? round ( $width / $oldDim['x'] * $oldDim['y'] ) : $oldDim['y'],
175. );
176. break;
177. case self::SCALE_DOWN:
178. $newDim = array(
179. 'x' => min ( $width, $oldDim['x'] ),
180. 'y' => $width < $oldDim['x'] ? round ( $width / $oldDim['x'] * $oldDim['y'] ) : $oldDim['y'],
181. );
182. break;
183. default:
184. throw new ezcBaseValueException ( 'direction', $direction, 'self::SCALE_BOTH, self::SCALE_UP, self::SCALE_DOWN' );
185. break;
186. }
187. $this-> performScale ( $newDim["x"], $newDim["y"] );
188. }
190. /**
191. * Scale after height filter.
192. * Scales the image to a give height, measured in pixel. Scales the width
193. * automatically while keeping the ratio. The direction dictates, if an
194. * image may only be scaled {@link self::SCALE_UP}, {@link self::SCALE_DOWN}
195. * or if the scale may work in {@link self::SCALE_BOTH} directions.
196. *
197. * ATTENTION: Using this filter method directly results in the filter being
198. * applied to the image which is internally marked as "active" (most
199. * commonly this is the last recently loaded one). It is highly recommended
200. * to apply filters through the {@link ezcImageGdHandler::applyFilter()} method,
201. * which enables you to specify the image a filter is applied to.
202. *
203. * @param int $height Scale to height
204. * @param int $direction Scale to which direction
205. * @return void
206. *
207. * @throws ezcImageInvalidReferenceException
208. * If no valid resource for the active reference could be found.
209. * @throws ezcImageFilterFailedException
210. * If the operation performed by the the filter failed.
211. * @throws ezcBaseValueException
212. * If a submitted parameter was out of range or type.
213. */
214. public function scaleHeight ( $height, $direction )
215. {
216. if ( ! is_int ( $height ) || $height < 1 )
217. {
218. throw new ezcBaseValueException ( 'height', $height, 'int > 0' );
219. }
221. $resource = $this->getActiveResource();
222. $oldDim = array(
223. 'x' => imagesx ( $resource ),
224. 'y' => imagesy ( $resource ),
225. );
226. switch ( $direction )
227. {
228. case self::SCALE_BOTH:
229. $newDim = array(
230. 'x' => $height / $oldDim['y'] * $oldDim['x'],
231. 'y' => $height,
232. );
233. break;
234. case self::SCALE_UP:
235. $newDim = array(
236. 'x' => $height > $oldDim['y'] ? round ( $height / $oldDim['y'] * $oldDim['x'] ) : $oldDim['x'],
237. 'y' => max ( $height, $oldDim['y'] ),
238. );
239. break;
240. case self::SCALE_DOWN:
241. $newDim = array(
242. 'x' => $height < $oldDim['y'] ? round ( $height / $oldDim['y'] * $oldDim['x'] ) : $oldDim['x'],
243. 'y' => min ( $height, $oldDim['y'] ),
244. );
245. break;
246. default:
247. throw new ezcBaseValueException ( 'direction', $direction, 'self::SCALE_BOTH, self::SCALE_UP, self::SCALE_DOWN' );
248. break;
249. }
250. $this-> performScale ( $newDim["x"], $newDim["y"] );
251. }
253. /**
254. * Scale percent measures filter.
255. * Scale an image to a given percentage value size.
256. *
257. * ATTENTION: Using this filter method directly results in the filter being
258. * applied to the image which is internally marked as "active" (most
259. * commonly this is the last recently loaded one). It is highly recommended
260. * to apply filters through the {@link ezcImageGdHandler::applyFilter()} method,
261. * which enables you to specify the image a filter is applied to.
262. *
263. * @param int $width Scale to width
264. * @param int $height Scale to height
265. * @return void
266. *
267. * @throws ezcImageInvalidReferenceException
268. * If no valid resource for the active reference could be found.
269. * @throws ezcImageFilterFailedException
270. * If the operation performed by the the filter failed.
271. * @throws ezcBaseValueException
272. * If a submitted parameter was out of range or type.
273. */
274. public function scalePercent ( $width, $height )
275. {
276. if ( ! is_int ( $height ) || $height < 1 )
277. {
278. throw new ezcBaseValueException ( 'height', $height, 'int > 0' );
279. }
280. if ( ! is_int ( $width ) || $width < 1 )
281. {
282. throw new ezcBaseValueException ( 'width', $width, 'int > 0' );
283. }
285. $resource = $this->getActiveResource();
286. $this-> performScale ( round ( imagesx ( $resource ) * $width / 100 ), round ( imagesy ( $resource ) * $height / 100 ) );
287. }
289. /**
290. * Scale exact filter.
291. * Scale the image to a fixed given pixel size, no matter to which
292. * direction.
293. *
294. * ATTENTION: Using this filter method directly results in the filter being
295. * applied to the image which is internally marked as "active" (most
296. * commonly this is the last recently loaded one). It is highly recommended
297. * to apply filters through the {@link ezcImageGdHandler::applyFilter()} method,
298. * which enables you to specify the image a filter is applied to.
299. *
300. * @param int $width Scale to width
301. * @param int $height Scale to height
302. * @return void
303. *
304. * @throws ezcImageInvalidReferenceException
305. * If no valid resource for the active reference could be found.
306. * @throws ezcBaseValueException
307. * If a submitted parameter was out of range or type.
308. */
309. public function scaleExact ( $width, $height )
310. {
311. if ( ! is_int ( $height ) || $height < 1 )
312. {
313. throw new ezcBaseValueException ( 'height', $height, 'int > 0' );
314. }
315. if ( ! is_int ( $width ) || $width < 1 )
316. {
317. throw new ezcBaseValueException ( 'width', $width, 'int > 0' );
318. }
319. $this-> performScale ( $width, $height );
320. }
322. /**
323. * Crop filter.
324. * Crop an image to a given size. This takes cartesian coordinates of a
325. * rect area to crop from the image. The cropped area will replace the old
326. * image resource (not the input image immediately, if you use the
327. * {@link ezcImageConverter}). Coordinates are given as integer values and
328. * are measured from the top left corner.
329. *
330. * ATTENTION: Using this filter method directly results in the filter being
331. * applied to the image which is internally marked as "active" (most
332. * commonly this is the last recently loaded one). It is highly recommended
333. * to apply filters through the {@link ezcImageGdHandler::applyFilter()} method,
334. * which enables you to specify the image a filter is applied to.
335. *
336. * @param int $x X offset of the cropping area.
337. * @param int $y Y offset of the cropping area.
338. * @param int $width Width of cropping area.
339. * @param int $height Height of cropping area.
340. * @return void
341. *
342. * @throws ezcImageInvalidReferenceException
343. * If no valid resource for the active reference could be found.
344. * @throws ezcImageFilterFailedException
345. * If the operation performed by the the filter failed.
346. * @throws ezcBaseValueException
347. * If a submitted parameter was out of range or type.
348. */
349. public function crop ( $x, $y, $width, $height )
350. {
351. if ( ! is_int ( $x ) )
352. {
353. throw new ezcBaseValueException ( 'x', $x, 'int' );
354. }
355. if ( ! is_int ( $y ) )
356. {
357. throw new ezcBaseValueException ( 'y', $y, 'int' );
358. }
359. if ( ! is_int ( $height ) )
360. {
361. throw new ezcBaseValueException ( 'height', $height, 'int' );
362. }
363. if ( ! is_int ( $width ) )
364. {
365. throw new ezcBaseValueException ( 'width', $width, 'int' );
366. }
368. $oldResource = $this->getActiveResource();
370. $sourceWidth = imagesx ( $oldResource );
371. $sourceHeight = imagesy ( $oldResource );
373. $x = ( $x >= 0 ) ? $x : $sourceWidth + $x;
374. $y = ( $y >= 0 ) ? $y : $sourceHeight + $y;
376. $x = abs ( min ( $x, $x + $width ) );
377. $y = abs ( min ( $y, $y + $height ) );
379. $width = abs ( $width );
380. $height = abs ( $height );
382. if ( $x + $width > $sourceWidth )
383. {
384. $width = $sourceWidth - $x;
385. }
386. if ( $y + $height > $sourceHeight )
387. {
388. $height = $sourceHeight - $y;
389. }
391. $this->performCrop( $x, $y, $width, $height );
393. }
395. /**
396. * Colorspace filter.
397. * Transform the colorspace of the picture. The following colorspaces are
398. * supported:
399. *
400. * - {@link self::COLORSPACE_GREY} - 255 grey colors
401. * - {@link self::COLORSPACE_SEPIA} - Sepia colors
402. * - {@link self::COLORSPACE_MONOCHROME} - 2 colors black and white
403. *
404. * ATTENTION: Using this filter method directly results in the filter being
405. * applied to the image which is internally marked as "active" (most
406. * commonly this is the last recently loaded one). It is highly recommended
407. * to apply filters through the {@link ezcImageGdHandler::applyFilter()} method,
408. * which enables you to specify the image a filter is applied to.
409. *
410. * @param int $space Colorspace, one of self::COLORSPACE_* constants.
411. *
412. * @throws ezcImageInvalidReferenceException
413. * If no valid resource for the active reference could be found.
414. * @throws ezcBaseValueException
415. * If the parameter submitted as the colorspace was not within the
416. * self::COLORSPACE_* constants.
417. * @throws ezcImageFilterFailedException
418. * If the operation performed by the the filter failed.
419. */
420. public function colorspace ( $space )
421. {
422. switch ( $space )
423. {
424. case self::COLORSPACE_GREY:
425. $this-> luminanceColorScale ( array( 1.0, 1.0, 1.0 ) );
426. break;
427. case self::COLORSPACE_MONOCHROME:
428. $this-> thresholdColorScale (
429. array(
430. 127 => array( 0, 0, 0 ),
431. 255 => array( 255, 255, 255 ),
432. )
433. );
434. break;
435. return;
436. case self::COLORSPACE_SEPIA:
437. $this-> luminanceColorScale ( array( 1.0, 0.89, 0.74 ) );
438. break;
439. default:
440. throw new ezcBaseValueException ( 'space', $space, 'self::COLORSPACE_GREY, self::COLORSPACE_SEPIA, self::COLORSPACE_MONOCHROME' );
441. break;
442. }
444. }
446. /**
447. * Watermark filter.
448. * Places a watermark on the image. The file to use as the watermark image
449. * is given as $image. The $posX, $posY and $size values are given in
450. * percent, related to the destination image. A $size value of 10 will make
451. * the watermark appear in 10% of the destination image size.
452. * $posX = $posY = 10 will make the watermark appear in the top left corner
453. * of the destination image, 10% of its size away from its borders. If
454. * $size is ommitted, the watermark image will not be resized.
455. *
456. * @param string $image The image file to use as the watermark
457. * @param int $posX X position in the destination image in percent.
458. * @param int $posY Y position in the destination image in percent.
459. * @param int|bool$size Percentage size of the watermark, false for none.
460. * @return void
461. *
462. * @throws ezcImageInvalidReferenceException
463. * If no valid resource for the active reference could be found.
464. * @throws ezcImageFilterFailedException
465. * If the operation performed by the the filter failed.
466. * @throws ezcBaseValueException
467. * If a submitted parameter was out of range or type.
468. */
469. public function watermarkPercent ( $image, $posX, $posY, $size = false )
470. {
471. if ( ! is_string ( $image ) || ! file_exists ( $image ) || ! is_readable ( $image ) )
472. {
473. throw new ezcBaseValueException ( 'image', $image, 'string, path to an image file' );
474. }
475. if ( ! is_int ( $posX ) || $posX < 0 || $posX > 100 )
476. {
477. throw new ezcBaseValueException ( 'posX', $posX, 'int percentage value' );
478. }
479. if ( ! is_int ( $posY ) || $posY < 0 || $posY > 100 )
480. {
481. throw new ezcBaseValueException ( 'posY', $posY, 'int percentage value' );
482. }
483. if ( ! is_bool ( $size ) && ( ! is_int ( $size ) || $size < 0 || $size > 100 ) )
484. {
485. throw new ezcBaseValueException ( 'size', $size, 'int percentage value / bool' );
486. }
488. $imgWidth = imagesx ( $this->getActiveResource() );
489. $imgHeight = imagesy ( $this->getActiveResource() );
491. $watermarkWidth = false;
492. $watermarkHeight = false;
493. if ( $size !== false )
494. {
495. $watermarkWidth = (int) round ( $imgWidth * $size / 100 );
496. $watermarkHeight = (int) round ( $imgHeight * $size / 100 );
497. }
499. $watermarkPosX = (int) round ( $imgWidth * $posX / 100 );
500. $watermarkPosY = (int) round ( $imgHeight * $posY / 100 );
502. $this-> watermarkAbsolute ( $image, $watermarkPosX, $watermarkPosY, $watermarkWidth, $watermarkHeight );
503. }
505. /**
506. * Watermark filter.
507. * Places a watermark on the image. The file to use as the watermark image
508. * is given as $image. The $posX, $posY and $size values are given in
509. * pixel. The watermark appear at $posX, $posY in the destination image
510. * with a size of $size pixel. If $size is ommitted, the watermark image
511. * will not be resized.
512. *
513. * @param string $image The image file to use as the watermark
514. * @param int $posX X position in the destination image in pixel.
515. * @param int $posY Y position in the destination image in pixel.
516. * @param int|bool$width Pixel size of the watermark, false to keep size.
517. * @param int|bool$height Pixel size of the watermark, false to keep size.
518. * @return void
519. *
520. * @throws ezcImageInvalidReferenceException
521. * If no valid resource for the active reference could be found.
522. * @throws ezcImageFilterFailedException
523. * If the operation performed by the the filter failed.
524. * @throws ezcBaseValueException
525. * If a submitted parameter was out of range or type.
526. * @throws ezcImageFileNotProcessableException
527. * If the given watermark image could not be loaded.
528. */
529. public function watermarkAbsolute ( $image, $posX, $posY, $width = false, $height = false )
530. {
531. if ( ! is_string ( $image ) || ! file_exists ( $image ) || ! is_readable ( $image ) )
532. {
533. throw new ezcBaseValueException ( 'image', $image, 'string, path to an image file' );
534. }
535. if ( ! is_int ( $posX ) )
536. {
537. throw new ezcBaseValueException ( 'posX', $posX, 'int' );
538. }
539. if ( ! is_int ( $posY ) )
540. {
541. throw new ezcBaseValueException ( 'posY', $posY, 'int' );
542. }
543. if ( ! is_int ( $width ) && ! is_bool ( $width ) )
544. {
545. throw new ezcBaseValueException ( 'width', $width, 'int/bool' );
546. }
547. if ( ! is_int ( $height ) && ! is_bool ( $height ) )
548. {
549. throw new ezcBaseValueException ( 'height', $height, 'int/bool' );
550. }
552. // Backup original image reference
553. $originalRef = $this->getActiveReference();
555. $originalWidth = imagesx ( $this->getActiveResource() );
556. $originalHeight = imagesy ( $this->getActiveResource() );
558. $watermarkRef = $this-> load ( $image );
559. if ( $width !== false && $height !== false && ( $originalWidth !== $width || $originalHeight !== $height ) )
560. {
561. $this-> scale ( $width, $height, ezcImageGeometryFilters ::SCALE_BOTH );
562. }
564. // Negative offsets
565. $posX = ( $posX >= 0 ) ? $posX : $originalWidth + $posX;
566. $posY = ( $posY >= 0 ) ? $posY : $originalHeight + $posY;
568. imagecopy (
569. $this->getReferenceData( $originalRef, "resource" ), // resource $dst_im
570. $this->getReferenceData( $watermarkRef, "resource" ), // resource $src_im
571. $posX, // int $dst_x
572. $posY, // int $dst_y
573. 0, // int $src_x
574. 0, // int $src_y
575. imagesx ( $this->getReferenceData( $watermarkRef, "resource" ) ), // int $src_w
576. imagesy ( $this->getReferenceData( $watermarkRef, "resource" ) ) // int $src_h
577. );
579. $this-> close ( $watermarkRef );
581. // Restore original image reference
582. $this->setActiveReference( $originalRef );
583. }
585. /**
586. * Creates a thumbnail, and crops parts of the given image to fit the range best.
587. * This filter creates a thumbnail of the given image. The image is scaled
588. * down, keeping the original ratio and keeping the image larger as the
589. * given range, if necessary. Overhead for the target range is cropped from
590. * both sides equally.
591. *
592. * If you are looking for a filter that just resizes your image to
593. * thumbnail size, you should consider the {@link }
594. * ezcImageGdHandler::scale()} filter.
595. *
596. * @param int $width Width of the thumbnail.
597. * @param int $height Height of the thumbnail.
598. */
599. public function croppedThumbnail ( $width, $height )
600. {
601. if ( ! is_int ( $width ) || $width < 1 )
602. {
603. throw new ezcBaseValueException ( 'width', $width, 'int > 0' );
604. }
605. if ( ! is_int ( $height ) || $height < 1 )
606. {
607. throw new ezcBaseValueException ( 'height', $height, 'int > 0' );
608. }
609. $resource = $this->getActiveResource();
610. $data[0] = imagesx ( $resource );
611. $data[1] = imagesy ( $resource );
613. $scaleRatio = max ( $width / $data[0], $height / $data[1] );
614. $scaleWidth = round ( $data[0] * $scaleRatio );
615. $scaleHeight = round ( $data[1] * $scaleRatio );
617. $cropOffsetX = ( $scaleWidth > $width ) ? round ( ( $scaleWidth - $width ) / 2 ) : 0;
618. $cropOffsetY = ( $scaleHeight > $height ) ? round ( ( $scaleHeight - $height ) / 2 ) : 0;
620. $this-> performScale ( $scaleWidth, $scaleHeight );
621. $this->performCrop( $cropOffsetX, $cropOffsetY, $width, $height );
622. }
624. /**
625. * Creates a thumbnail, and fills up the image to fit the given range.
626. * This filter creates a thumbnail of the given image. The image is scaled
627. * down, keeping the original ratio and scaling the image smaller as the
628. * given range, if necessary. Overhead for the target range is filled with the given
629. * color on both sides equally.
630. *
631. * The color is defined by the following array format (integer values 0-255):
632. *
633. * <code>
634. * array(
635. * 0 => <red value>,
636. * 1 => <green value>,
637. * 2 => <blue value>,
638. * );
639. * </code>
640. *
641. * If you are looking for a filter that just resizes your image to
642. * thumbnail size, you should consider the {@link }
643. * ezcImageGdHandler::scale()} filter.
644. *
645. * @param int $width Width of the thumbnail.
646. * @param int $height Height of the thumbnail.
647. * @param array $color Fill color.
648. *
649. * @return void
650. */
651. public function filledThumbnail ( $width, $height, $color = array() )
652. {
653. $i = 0;
654. foreach ( $color as $id => $colorVal )
655. {
656. if ( $i++ > 2 )
657. {
658. break;
659. }
660. if ( ! is_int ( $colorVal ) || $colorVal < 0 || $colorVal > 255 )
661. {
662. throw new ezcBaseValueException ( "color[$id]", $color[$id], 'int > 0 and < 256' );
663. }
664. }
666. // Sanity checks for $width and $height performed by scale() method.
667. $this-> scale ( $width, $height, ezcImageGeometryFilters ::SCALE_BOTH );
669. $oldResource = $this->getActiveResource();
671. $realWidth = imagesx ( $oldResource );
672. $realHeight = imagesy ( $oldResource );
673. $xOffset = ( $width > $realWidth ) ? round ( ( $width - $realWidth ) / 2 ) : 0;
674. $yOffset = ( $height > $realHeight ) ? round ( ( $height - $realHeight ) / 2 ) : 0;
676. $newResource = imagecreatetruecolor ( $width, $height );
677. $bgColor = $this-> getColor ( $newResource, $color[0], $color[1], $color[2] );
678. if ( imagefill ( $newResource, 0, 0, $bgColor ) === false )
679. {
680. throw new ezcImageFilterFailedException ( "filledThumbnail", "Color fill failed." );
681. }
683. imagecopy (
684. $newResource,
685. $oldResource,
686. $xOffset,
687. $yOffset,
688. 0,
689. 0,
690. $realWidth,
691. $realHeight
692. );
694. $this->setActiveResource( $newResource );
695. imagedestroy ( $oldResource );
696. }
698. // private
700. /**
701. * Retrieve luminance value for a specific pixel.
702. *
703. * @param resource(GD) $resource Image resource
704. * @param int $x Pixel x coordinate.
705. * @param int $y Pixel y coordinate.
706. * @return float Luminance value.
707. */
708. private function getLuminanceAt( $resource, $x, $y )
709. {
710. $currentColor = imagecolorat ( $resource, $x, $y );
711. $rgbValues = array(
712. 'r' => ( $currentColor >> 16 ) & 0xff,
713. 'g' => ( $currentColor >> 8 ) & 0xff,
714. 'b' => $currentColor & 0xff,
715. );
716. return $rgbValues['r'] * 0.299 + $rgbValues['g'] * 0.587 + $rgbValues['b'] * 0.114;
717. }
719. /**
720. * Scale colors by threshold values.
721. * Thresholds are defined by the following array structures:
722. *
723. * <code>
724. * array(
725. * <int threshold value> => array(
726. * 0 => <int red value>,
727. * 1 => <int green value>,
728. * 2 => <int blue value>,
729. * ),
730. * )
731. * </code>
732. *
733. * @param array $thresholds
734. * @return void
735. *
736. * @throws ezcImageInvalidReferenceException
737. * If no valid resource for the active reference could be found.
738. * @throws ezcImageFilterFailedException
739. * If the operation performed by the the filter failed.
740. *
741. * @todo Optimization as described here: http://lists.ez.no/pipermail/components/2005-November/000566.html
742. */
743. protected function thresholdColorScale ( $thresholds )
744. {
745. $resource = $this->getActiveResource();
746. $dimensions = array( 'x' => imagesx ( $resource ), 'y' => imagesy ( $resource ) );
748. // Check for GIFs and convert them to work properly here.
749. if ( ! imageistruecolor ( $resource ) )
750. {
751. $resource = $this-> paletteToTruecolor ( $resource, $dimensions );
752. }
754. foreach ( $thresholds as $threshold => $colors )
755. {
756. $thresholds[$threshold] = array_merge (
757. $colors,
758. array( 'color' => $this-> getColor ( $resource, $colors[0], $colors[1], $colors[2] ) )
759. );
760. }
761. // Default
762. if ( !isset( $thresholds[255] ) )
763. {
764. $thresholds[255] = end ( $thresholds );
765. reset ( $thresholds );
766. }
768. $colorCache = array();
770. for ( $x = 0; $x < $dimensions['x']; $x++ )
771. {
772. for ( $y = 0; $y < $dimensions['y']; $y++ )
773. {
774. $luminance = $this->getLuminanceAt( $resource, $x, $y );
775. $color = end ( $thresholds );
776. foreach ( $thresholds as $threshold => $colorValues )
777. {
778. if ( $luminance <= $threshold )
779. {
780. $color = $colorValues;
781. break;
782. }
783. }
784. imagesetpixel ( $resource, $x, $y, $color['color'] );
785. }
786. }
788. $this->setActiveResource( $resource );
789. }
791. /**
792. * Perform luminance color scale.
793. *
794. * @param array $scale Array of RGB values (numeric index).
795. *
796. * @throws ezcImageInvalidReferenceException
797. * If no valid resource for the active reference could be found.
798. * @throws ezcImageFilterFailedException
799. * If the operation performed by the the filter failed
800. *
801. * @todo Optimization as described here: http://lists.ez.no/pipermail/components/2005-November/000566.html
802. */
803. protected function luminanceColorScale ( $scale )
804. {
805. $resource = $this->getActiveResource();
806. $dimensions = array( 'x' => imagesx ( $resource ), 'y' => imagesy ( $resource ) );
808. // Check for GIFs and convert them to work properly here.
809. if ( ! imageistruecolor ( $resource ) )
810. {
811. $resource = $this-> paletteToTruecolor ( $resource, $dimensions );
812. }
814. for ( $x = 0; $x < $dimensions['x']; $x++ )
815. {
816. for ( $y = 0; $y < $dimensions['y']; $y++ )
817. {
818. $luminance = $this->getLuminanceAt( $resource, $x, $y );
819. $newRgbValues = array(
820. 'r' => $luminance * $scale[0],
821. 'g' => $luminance * $scale[1],
822. 'b' => $luminance * $scale[2],
823. );
824. $color = $this-> getColor ( $resource, $newRgbValues['r'], $newRgbValues['g'], $newRgbValues['b'] );
825. imagesetpixel ( $resource, $x, $y, $color );
826. }
827. }
828. $this->setActiveResource( $resource );
829. }
831. /**
832. * Convert a palette based image resource to a true color one.
833. * Takes a GD resource that does not represent a true color image and
834. * converts it to a true color based resource. Do not forget, to replace
835. * the actual resource in the handler, if you use this ,method!
836. *
837. * @param resource(GD) $resource The image resource to convert
838. * @param array(string=>int) $dimensions X and Y dimensions.
839. * @return resource(GD) The converted resource.
840. */
841. protected function paletteToTruecolor ( $resource, $dimensions )
842. {
843. $newResource = imagecreatetruecolor ( $dimensions['x'], $dimensions['y'] );
844. imagecopy ( $newResource, $resource, 0, 0, 0, 0, $dimensions['x'], $dimensions['y'] );
845. imagedestroy ( $resource );
846. return $newResource;
847. }
849. /**
850. * Common color determination method.
851. * Returns a color identifier for an RGB value. Avoids problems with palette images.
852. *
853. * @param reource(GD) $resource The image resource to get a color for.
854. * @param int $r Red value.
855. * @param int $g Green value.
856. * @param int $b Blue value.
857. *
858. * @return int The color identifier.
859. *
860. * @throws ezcImageFilterFailedException
861. * If the operation performed by the the filter failed.
862. */
863. protected function getColor ( $resource, $r, $g, $b )
864. {
865. if ( ( $res = imagecolorexact ( $resource, $r, $g, $b ) ) !== -1 )
866. {
867. return $res;
868. }
869. if ( ( $res = imagecolorallocate ( $resource, $r, $g, $b ) ) !== -1 )
870. {
871. return $res;
872. }
873. if ( ( $res = imagecolorclosest ( $resource, $r, $g, $b ) ) !== -1 )
874. {
875. return $res;
876. }
877. throw new ezcImageFilterFailedException ( 'allocatecolor', "Color allocation failed for color r: '{$r}', g: '{$g}', b: '{$b}'." );
878. }
880. /**
881. * General scaling method to perform actual scale to new dimensions.
882. *
883. * @param int $width Width.
884. * @param int $height Height.
885. * @return void
886. *
887. * @throws ezcImageInvalidReferenceException
888. * If no valid resource for the active reference could be found.
889. * @throws ezcImageFilterFailedException.
890. * If the operation performed by the the filter failed.
891. */
892. protected function performScale ( $width, $height )
893. {
894. $oldResource = $this->getActiveResource();
895. if ( imageistruecolor ( $oldResource ) )
896. {
897. $newResource = imagecreatetruecolor ( $width, $height );
898. }
899. else
900. {
901. $newResource = imagecreate ( $width, $height );
902. }
904. // Save transparency, if image has it
905. $bgColor = imagecolorallocatealpha ( $newResource, 255, 255, 255, 127 );
906. imagealphablending ( $newResource, true );
907. imagesavealpha ( $newResource, true );
908. imagefill ( $newResource, 1, 1, $bgColor );
910. $res = imagecopyresampled (
911. $newResource,
912. $oldResource,
913. 0, 0, 0, 0,
914. $width,
915. $height,
916. imagesx ( $this->getActiveResource() ),
917. imagesy ( $this->getActiveResource() )
918. );
919. if ( $res === false )
920. {
921. throw new ezcImageFilterFailedException ( 'scale', 'Resampling of image failed.' );
922. }
923. imagedestroy ( $oldResource );
924. $this->setActiveResource( $newResource );
925. }
927. /**
928. * General method to perform a crop operation.
929. *
930. * @param int $x
931. * @param int $y
932. * @param int $width
933. * @param int $height
934. * @return void
935. */
936. private function performCrop( $x, $y, $width, $height )
937. {
938. $oldResource = $this->getActiveResource();
939. if ( imageistruecolor ( $oldResource ) )
940. {
941. $newResource = imagecreatetruecolor ( $width, $height );
942. }
943. else
944. {
945. $newResource = imagecreate ( $width, $height );
946. }
948. // Save transparency, if image has it
949. $bgColor = imagecolorallocatealpha ( $newResource, 255, 255, 255, 127 );
950. imagealphablending ( $newResource, true );
951. imagesavealpha ( $newResource, true );
952. imagefill ( $newResource, 1, 1, $bgColor );
954. $res = imagecopyresampled (
955. $newResource, // destination resource
956. $oldResource, // source resource
957. 0, // destination x coord
958. 0, // destination y coord
959. $x, // source x coord
960. $y, // source y coord
961. $width, // destination width
962. $height, // destination height
963. $width, // source witdh
964. $height // source height
965. );
966. if ( $res === false )
967. {
968. throw new ezcImageFilterFailedException ( 'crop', 'Resampling of image failed.' );
969. }
970. imagedestroy ( $oldResource );
971. $this->setActiveResource( $newResource );
972. }
973. }
974. ?>

Documentation generated by phpDocumentor 1.4.3