PageRenderTime 47ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/www/libs/nette-dev/ImageMagick.php

https://github.com/bazo/Mokuji
PHP | 249 lines | 119 code | 48 blank | 82 comment | 21 complexity | 75570f82dbf56bbca09557c800d2974f MD5 | raw file
Possible License(s): BSD-3-Clause, MIT
  1. <?php
  2. /**
  3. * Nette Framework
  4. *
  5. * @copyright Copyright (c) 2004, 2010 David Grudl
  6. * @license http://nettephp.com/license Nette license
  7. * @link http://nettephp.com
  8. * @category Nette
  9. * @package Nette
  10. */
  11. /**
  12. * Manipulation with large images using ImageMagick.
  13. *
  14. * <code>
  15. * $image = Image::fromFile('bigphoto.jpg');
  16. * $image->resize(150, 100);
  17. * $image->sharpen();
  18. * $image->send();
  19. * </code>
  20. *
  21. * @copyright Copyright (c) 2004, 2010 David Grudl
  22. * @package Nette
  23. */
  24. class ImageMagick extends Image
  25. {
  26. /** @var string path to ImageMagick library */
  27. public static $path = '';
  28. /** @var string */
  29. public static $tempDir;
  30. /** @var string */
  31. private $file;
  32. /** @var bool */
  33. private $isTemporary = FALSE;
  34. /** @var int */
  35. private $width;
  36. /** @var int */
  37. private $height;
  38. /**
  39. * Wraps image file.
  40. * @param string detected image format
  41. * @param string
  42. */
  43. public function __construct($file, & $format = NULL)
  44. {
  45. if (!is_file($file)) {
  46. throw new InvalidArgumentException("File '$file' not found.");
  47. }
  48. $format = $this->setFile(realpath($file));
  49. if ($format === 'JPEG') $format = self::JPEG;
  50. elseif ($format === 'PNG') $format = self::PNG;
  51. elseif ($format === 'GIF') $format = self::GIF;
  52. }
  53. /**
  54. * Returns image width.
  55. * @return int
  56. */
  57. public function getWidth()
  58. {
  59. return $this->file === NULL ? parent::getWidth() : $this->width;
  60. }
  61. /**
  62. * Returns image height.
  63. * @return int
  64. */
  65. public function getHeight()
  66. {
  67. return $this->file === NULL ? parent::getHeight() : $this->height;
  68. }
  69. /**
  70. * Returns image GD resource.
  71. * @return resource
  72. */
  73. public function getImageResource()
  74. {
  75. if ($this->file !== NULL) {
  76. if (!$this->isTemporary) {
  77. $this->execute("convert -strip %input %output", self::PNG);
  78. }
  79. $this->setImageResource(imagecreatefrompng($this->file));
  80. if ($this->isTemporary) {
  81. unlink($this->file);
  82. }
  83. $this->file = NULL;
  84. }
  85. return parent::getImageResource();
  86. }
  87. /**
  88. * Resizes image.
  89. * @param mixed width in pixels or percent
  90. * @param mixed height in pixels or percent
  91. * @param int flags
  92. * @return ImageMagick provides a fluent interface
  93. */
  94. public function resize($width, $height, $flags = self::FIT)
  95. {
  96. if ($this->file === NULL) {
  97. return parent::resize($newWidth, $newHeight, $flags);
  98. }
  99. $mirror = '';
  100. if ($width < 0) $mirror .= ' -flop';
  101. if ($height < 0) $mirror .= ' -flip';
  102. list($newWidth, $newHeight) = self::calculateSize($this->getWidth(), $this->getHeight(), $width, $height, $flags);
  103. $this->execute("convert -resize {$newWidth}x{$newHeight}! {$mirror} -strip %input %output", self::PNG);
  104. return $this;
  105. }
  106. /**
  107. * Crops image.
  108. * @param int x-coordinate
  109. * @param int y-coordinate
  110. * @param int width
  111. * @param int height
  112. * @return ImageMagick provides a fluent interface
  113. */
  114. public function crop($left, $top, $width, $height)
  115. {
  116. if ($this->file === NULL) {
  117. return parent::crop($left, $top, $width, $height);
  118. }
  119. $left = max(0, (int) $left);
  120. $top = max(0, (int) $top);
  121. $width = min((int) $width, $this->getWidth() - $left);
  122. $height = min((int) $height, $this->getHeight() - $top);
  123. $this->execute("convert -crop {$width}x{$height}+{$left}+{$top} -strip %input %output", self::PNG);
  124. return $this;
  125. }
  126. /**
  127. * Saves image to the file.
  128. * @param string filename
  129. * @param int quality 0..100 (for JPEG and PNG)
  130. * @param int optional image type
  131. * @return bool TRUE on success or FALSE on failure.
  132. */
  133. public function save($file = NULL, $quality = NULL, $type = NULL)
  134. {
  135. if ($this->file === NULL) {
  136. return parent::save($file, $quality, $type);
  137. }
  138. $quality = $quality === NULL ? '' : '-quality ' . max(0, min(100, (int) $quality));
  139. if ($file === NULL) {
  140. $this->execute("convert $quality -strip %input %output", $type === NULL ? self::PNG : $type);
  141. readfile($this->file);
  142. } else {
  143. $this->execute("convert $quality -strip %input %output", (string) $file);
  144. }
  145. return TRUE;
  146. }
  147. /**
  148. * Change and identify image file.
  149. * @param string filename
  150. * @return string detected image format
  151. */
  152. private function setFile($file)
  153. {
  154. $this->file = $file;
  155. $res = $this->execute('identify -format "%w,%h,%m" ' . escapeshellarg($this->file));
  156. if (!$res) {
  157. throw new Exception("Unknown image type in file '$file' or ImageMagick not available.");
  158. }
  159. list($this->width, $this->height, $format) = explode(',', $res, 3);
  160. return $format;
  161. }
  162. /**
  163. * Executes command.
  164. * @param string command
  165. * @param string|bool process output?
  166. * @return string
  167. */
  168. private function execute($command, $output = NULL)
  169. {
  170. $command = str_replace('%input', escapeshellarg($this->file), $command);
  171. if ($output) {
  172. $newFile = is_string($output)
  173. ? $output
  174. : (self::$tempDir ? self::$tempDir : dirname($this->file)) . '/' . uniqid('_tempimage', TRUE) . image_type_to_extension($output);
  175. $command = str_replace('%output', escapeshellarg($newFile), $command);
  176. }
  177. $lines = array();
  178. exec(self::$path . $command, $lines, $status); // $status: 0 - ok, 1 - error, 127 - command not found?
  179. if ($output) {
  180. if ($status != 0) {
  181. throw new Exception("Unknown error while calling ImageMagick.");
  182. }
  183. if ($this->isTemporary) {
  184. unlink($this->file);
  185. }
  186. $this->setFile($newFile);
  187. $this->isTemporary = !is_string($output);
  188. }
  189. return $lines ? $lines[0] : FALSE;
  190. }
  191. /**
  192. * Delete temporary files.
  193. * @return void
  194. */
  195. public function __destruct()
  196. {
  197. if ($this->file !== NULL && $this->isTemporary) {
  198. unlink($this->file);
  199. }
  200. }
  201. }