PageRenderTime 40ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/system/classes/libraries/image/driver/imagemagick.php

http://github.com/enormego/EightPHP
PHP | 190 lines | 159 code | 8 blank | 23 comment | 3 complexity | 4ca2aad934fb3c971881d8c6fc00dce8 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * ImageMagick Image Driver.
  4. *
  5. * @package System
  6. * @subpackage Libraries.Image
  7. * @author EightPHP Development Team
  8. * @copyright (c) 2009-2010 EightPHP
  9. * @license http://license.eightphp.com
  10. */
  11. class Image_Driver_ImageMagick_Core extends Image_Driver {
  12. // Directory that IM is installed in
  13. protected $dir = '';
  14. // Command extension (exe for windows)
  15. protected $ext = '';
  16. // Temporary image filename
  17. protected $tmp_image;
  18. /**
  19. * Attempts to detect the ImageMagick installation directory.
  20. *
  21. * @throws Eight_Exception
  22. * @param array configuration
  23. * @return void
  24. */
  25. public function __construct($config) {
  26. if(empty($config['directory'])) {
  27. // Attempt to locate IM by using "which" (only works for *nix!)
  28. if(!is_file($path = exec('which convert')))
  29. throw new Eight_Exception('image.imagemagick.not_found');
  30. $config['directory'] = dirname($path);
  31. }
  32. // Set the command extension
  33. $this->ext = (PHP_SHLIB_SUFFIX === 'dll') ? '.exe' : '';
  34. // Check to make sure the provided path is correct
  35. if(!is_file(realpath($config['directory']).'/convert'.$this->ext))
  36. throw new Eight_Exception('image.imagemagick.not_found', 'convert'.$this->ext);
  37. // Set the installation directory
  38. $this->dir = str_replace('\\', '/', realpath($config['directory'])).'/';
  39. }
  40. /**
  41. * Creates a temporary image and executes the given actions. By creating a
  42. * temporary copy of the image before manipulating it, this process is atomic.
  43. */
  44. public function process($image, $actions, $dir, $file, $render = NO) {
  45. // We only need the filename
  46. $image = $image['file'];
  47. // Unique temporary filename
  48. $this->tmp_image = $dir.'k2img--'.sha1(time().$dir.$file).substr($file, strrpos($file, '.'));
  49. // Copy the image to the temporary file
  50. copy($image, $this->tmp_image);
  51. // Quality change is done last
  52. $quality = (int) arr::remove('quality', $actions);
  53. // Use 95 for the default quality
  54. empty($quality) and $quality = 95;
  55. // All calls to these will need to be escaped, so do it now
  56. $this->cmd_image = escapeshellarg($this->tmp_image);
  57. $this->new_image = ($render)? $this->cmd_image : escapeshellarg($dir.$file);
  58. if($status = $this->execute($actions)) {
  59. // Use convert to change the image into its final version. This is
  60. // done to allow the file type to change correctly, and to handle
  61. // the quality conversion in the most effective way possible.
  62. if($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -quality '.$quality.'% '.$this->cmd_image.' '.$this->new_image)) {
  63. $this->errors[] = $error;
  64. } else {
  65. // Output the image directly to the browser
  66. if($render !== NO) {
  67. $contents = file_get_contents($this->tmp_image);
  68. switch (substr($file, strrpos($file, '.') + 1)) {
  69. case 'jpg':
  70. case 'jpeg':
  71. header('Content-Type: image/jpeg');
  72. break;
  73. case 'gif':
  74. header('Content-Type: image/gif');
  75. break;
  76. case 'png':
  77. header('Content-Type: image/png');
  78. break;
  79. }
  80. echo $contents;
  81. }
  82. }
  83. }
  84. // Remove the temporary image
  85. unlink($this->tmp_image);
  86. $this->tmp_image = '';
  87. return $status;
  88. }
  89. public function crop($prop) {
  90. // Sanitize and normalize the properties into geometry
  91. $this->sanitize_geometry($prop);
  92. // Set the IM geometry based on the properties
  93. $geometry = escapeshellarg($prop['width'].'x'.$prop['height'].'+'.$prop['left'].'+'.$prop['top']);
  94. if($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -crop '.$geometry.' '.$this->cmd_image.' '.$this->cmd_image)) {
  95. $this->errors[] = $error;
  96. return NO;
  97. }
  98. return YES;
  99. }
  100. public function flip($dir) {
  101. // Convert the direction into a IM command
  102. $dir = ($dir === Image::HORIZONTAL) ? '-flop' : '-flip';
  103. if($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' '.$dir.' '.$this->cmd_image.' '.$this->cmd_image)) {
  104. $this->errors[] = $error;
  105. return NO;
  106. }
  107. return YES;
  108. }
  109. public function resize($prop) {
  110. switch ($prop['master']) {
  111. case Image::WIDTH: // Wx
  112. $dim = escapeshellarg($prop['width'].'x');
  113. break;
  114. case Image::HEIGHT: // xH
  115. $dim = escapeshellarg('x'.$prop['height']);
  116. break;
  117. case Image::AUTO: // WxH
  118. $dim = escapeshellarg($prop['width'].'x'.$prop['height']);
  119. break;
  120. case Image::NONE: // WxH!
  121. $dim = escapeshellarg($prop['width'].'x'.$prop['height'].'!');
  122. break;
  123. }
  124. // Use "convert" to change the width and height
  125. if($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -resize '.$dim.' '.$this->cmd_image.' '.$this->cmd_image)) {
  126. $this->errors[] = $error;
  127. return NO;
  128. }
  129. return YES;
  130. }
  131. public function rotate($amt) {
  132. if($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -rotate '.escapeshellarg($amt).' -background transparent '.$this->cmd_image.' '.$this->cmd_image)) {
  133. $this->errors[] = $error;
  134. return NO;
  135. }
  136. return YES;
  137. }
  138. public function sharpen($amount) {
  139. // Set the sigma, radius, and amount. The amount formula allows a nice
  140. // spread between 1 and 100 without pixelizing the image badly.
  141. $sigma = 0.5;
  142. $radius = $sigma * 2;
  143. $amount = round(($amount / 80) * 3.14, 2);
  144. // Convert the amount to an IM command
  145. $sharpen = escapeshellarg($radius.'x'.$sigma.'+'.$amount.'+0');
  146. if($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -unsharp '.$sharpen.' '.$this->cmd_image.' '.$this->cmd_image)) {
  147. $this->errors[] = $error;
  148. return NO;
  149. }
  150. return YES;
  151. }
  152. protected function properties() {
  153. return array_slice(getimagesize($this->tmp_image), 0, 2, NO);
  154. }
  155. } // End Image ImageMagick Driver