Source for file Image.php
Documentation is available at Image.php
6: * Copyright (c) 2004, 2009 David Grudl (http://davidgrudl.com)
8: * This source file is subject to the "Nette license" that is bundled
9: * with this package in the file license.txt.
11: * For more information please see http://nettephp.com
13: * @copyright Copyright (c) 2004, 2009 David Grudl
14: * @license http://nettephp.com/license Nette license
15: * @link http://nettephp.com
22: require_once dirname(__FILE__) .
'/Object.php';
27: * Basic manipulation with images.
30: * $image = Image::fromFile('nette.jpg');
31: * $image->resize(150, 100);
36: * @author David Grudl
37: * @copyright Copyright (c) 2004, 2009 David Grudl
40: * @property-read int $width
41: * @property-read int $height
42: * @property-read resource $imageResource
46: /** {@link resize()} allows enlarging image (it only shrinks images by default) */
49: /** {@link resize()} will ignore aspect ratio */
52: /** {@link resize()} fills (and even overflows) given area */
55: /**#@+ @int image types {@link send()} */
57: const PNG =
IMAGETYPE_PNG;
58: const GIF =
IMAGETYPE_GIF;
61: const EMPTY_GIF =
"GIF89a\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\x00\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;";
64: public static $useImageMagick =
FALSE;
73: * @param int red 0..255
74: * @param int green 0..255
75: * @param int blue 0..255
76: * @param int transparency 0..127
79: public static function rgb($red, $green, $blue, $transparency =
0)
83: 'green' =>
max(0, min(255, (int)
$green)),
85: 'alpha' =>
max(0, min(127, (int)
$transparency)),
92: * Opens image from file.
94: * @param mixed detected image format
97: public static function fromFile($file, & $format =
NULL)
100: throw new Exception("PHP extension GD is not loaded.");
104: if (self::$useImageMagick &&
(empty($info) ||
$info[0] *
$info[1] >
2e6)) {
105: return new ImageMagick($file, $format);
108: switch ($format =
$info[2]) {
119: if (self::$useImageMagick) {
120: return new ImageMagick($file, $format);
122: throw new Exception("Unknown image type or file '$file' not found.");
129: * Create a new image from the image stream in the string.
131: * @param mixed detected image format
137: throw new Exception("PHP extension GD is not loaded.");
141: $format =
self::JPEG;
144: $format =
self::PNG;
147: $format =
self::GIF;
158: * Creates blank image.
164: public static function fromBlank($width, $height, $color =
NULL)
167: throw new Exception("PHP extension GD is not loaded.");
170: $width = (int)
$width;
171: $height = (int)
$height;
172: if ($width <
1 ||
$height <
1) {
173: throw new InvalidArgumentException('Image width and height must be greater than zero.');
178: $color +=
array('alpha' =>
0);
184: return new self($image);
201: * Returns image width.
212: * Returns image height.
223: * Sets image resource.
225: * @return Image provides a fluent interface
230: throw new InvalidArgumentException('Image is not valid.');
232: $this->image =
$image;
239: * Returns image GD resource.
244: return $this->image;
251: * @param mixed width in pixels or percent
252: * @param mixed height in pixels or percent
254: * @return Image provides a fluent interface
256: public function resize($newWidth, $newHeight, $flags =
0)
258: list($newWidth, $newHeight) =
$this->calculateSize($newWidth, $newHeight, $flags);
259: $newImage =
self::fromBlank($newWidth, $newHeight, self::RGB(0, 0, 0, 127))->getImageResource();
261: $this->image =
$newImage;
268: * Calculates dimensions of resized image.
269: * @param mixed width in pixels or percent
270: * @param mixed height in pixels or percent
280: $newWidth =
round($width /
100 *
$newWidth);
281: $flags |=
self::ENLARGE;
284: $newWidth = (int)
$newWidth;
288: $newHeight =
round($height /
100 *
$newHeight);
289: $flags |=
empty($percents) ?
self::ENLARGE :
self::STRETCH;
291: $newHeight = (int)
$newHeight;
294: if ($flags & self::STRETCH) { // non-proportional
295: if ($newWidth <
1 ||
$newHeight <
1) {
296: throw new InvalidArgumentException('For stretching must be both width and height specified.');
299: if (($flags & self::ENLARGE) ===
0) {
300: $newWidth =
round($width *
min(1, $newWidth /
$width));
301: $newHeight =
round($height *
min(1, $newHeight /
$height));
304: } else { // proportional
305: if ($newWidth <
1 &&
$newHeight <
1) {
306: throw new InvalidArgumentException('At least width or height must be specified.');
310: if ($newWidth >
0) { // fit width
311: $scale[] =
$newWidth /
$width;
314: if ($newHeight >
0) { // fit height
315: $scale[] =
$newHeight /
$height;
318: if ($flags & self::FILL) {
322: if (($flags & self::ENLARGE) ===
0) {
331: return array($newWidth, $newHeight);
338: * @param mixed x-offset in pixels or percent
339: * @param mixed y-offset in pixels or percent
342: * @return Image provides a fluent interface
344: public function crop($left, $top, $width, $height)
359: $newImage =
self::fromBlank($width, $height, self::RGB(0, 0, 0, 127))->getImageResource();
361: $this->image =
$newImage;
369: * @return Image provides a fluent interface
374: array( -
1, -
1, -
1 ),
375: array( -
1, 24, -
1 ),
376: array( -
1, -
1, -
1 ),
384: * Puts another image into this image.
386: * @param mixed x-coordinate in pixels or percent
387: * @param mixed y-coordinate in pixels or percent
388: * @param int opacity 0..100
389: * @return Image provides a fluent interface
391: public function place(Image $image, $left =
0, $top =
0, $opacity =
100)
403: if ($opacity ===
100) {
406: } elseif ($opacity <>
0) {
415: * Saves image to the file.
416: * @param string filename
417: * @param int quality 0..100 (for JPEG and PNG)
418: * @param int optional image type
419: * @return bool TRUE on success or FALSE on failure.
421: public function save($file =
NULL, $quality =
NULL, $type =
NULL)
423: if ($type ===
NULL) {
439: $quality =
$quality ===
NULL ?
85 :
max(0, min(100, (int)
$quality));
443: $quality =
$quality ===
NULL ?
9 :
max(0, min(9, (int)
$quality));
450: throw new Exception("Unsupported image type.");
457: * Outputs image to string.
458: * @param int image type
459: * @param int quality 0..100 (for JPEG and PNG)
462: public function toString($type =
self::JPEG, $quality =
NULL)
465: $this->save(NULL, $quality, $type);
472: * Outputs image to string.
480: } catch (Exception $e) {
489: * Outputs image to browser.
490: * @param int image type
491: * @param int quality 0..100 (for JPEG and PNG)
492: * @return bool TRUE on success or FALSE on failure.
494: public function send($type =
self::JPEG, $quality =
NULL)
496: if ($type !==
self::GIF &&
$type !==
self::PNG &&
$type !==
self::JPEG) {
497: throw new Exception("Unsupported image type.");
500: return $this->save(NULL, $quality, $type);
506: * Call to undefined method.
508: * @param string method name
509: * @param array arguments
511: * @throws MemberAccessException
515: $function =
'image' .
$name;
517: foreach ($args as $key =>
$value) {
518: if ($value instanceof
self) {
519: $args[$key] =
$value->getImageResource();
521: } elseif (is_array($value) &&
isset($value['red'])) { // rgb