1 <?php
defined('SYSPATH') OR die('No direct access allowed.');
3 * ImageMagick Image Driver.
5 * $Id: ImageMagick.php 3917 2009-01-21 03:06:22Z zombor $
9 * @copyright (c) 2007-2008 Kohana Team
10 * @license http://kohanaphp.com/license.html
12 class Image_ImageMagick_Driver
extends Image_Driver
{
14 // Directory that IM is installed in
17 // Command extension (exe for windows)
20 // Temporary image filename
24 * Attempts to detect the ImageMagick installation directory.
26 * @throws Kohana_Exception
27 * @param array configuration
30 public function __construct($config)
32 if (empty($config['directory']))
34 // Attempt to locate IM by using "which" (only works for *nix!)
35 if ( ! is_file($path = exec('which convert')))
36 throw new Kohana_Exception('image.imagemagick.not_found');
38 $config['directory'] = dirname($path);
41 // Set the command extension
42 $this->ext
= (PHP_SHLIB_SUFFIX
=== 'dll') ?
'.exe' : '';
44 // Check to make sure the provided path is correct
45 if ( ! is_file(realpath($config['directory']).'/convert'.$this->ext
))
46 throw new Kohana_Exception('image.imagemagick.not_found', 'convert'.$this->ext
);
48 // Set the installation directory
49 $this->dir
= str_replace('\\', '/', realpath($config['directory'])).'/';
53 * Creates a temporary image and executes the given actions. By creating a
54 * temporary copy of the image before manipulating it, this process is atomic.
56 public function process($image, $actions, $dir, $file, $render = FALSE)
58 // We only need the filename
59 $image = $image['file'];
61 // Unique temporary filename
62 $this->tmp_image
= $dir.'k2img--'.sha1(time().$dir.$file).substr($file, strrpos($file, '.'));
64 // Copy the image to the temporary file
65 copy($image, $this->tmp_image
);
67 // Quality change is done last
68 $quality = (int) arr
::remove('quality', $actions);
70 // Use 95 for the default quality
71 empty($quality) and $quality = 95;
73 // All calls to these will need to be escaped, so do it now
74 $this->cmd_image
= escapeshellarg($this->tmp_image
);
75 $this->new_image
= ($render)?
$this->cmd_image
: escapeshellarg($dir.$file);
77 if ($status = $this->execute($actions))
79 // Use convert to change the image into its final version. This is
80 // done to allow the file type to change correctly, and to handle
81 // the quality conversion in the most effective way possible.
82 if ($error = exec(escapeshellcmd($this->dir
.'convert'.$this->ext
).' -quality '.$quality.'% '.$this->cmd_image
.' '.$this->new_image
))
84 $this->errors
[] = $error;
88 // Output the image directly to the browser
89 if ($render !== FALSE)
91 $contents = file_get_contents($this->tmp_image
);
92 switch (substr($file, strrpos($file, '.') +
1))
96 header('Content-Type: image/jpeg');
99 header('Content-Type: image/gif');
102 header('Content-Type: image/png');
110 // Remove the temporary image
111 unlink($this->tmp_image
);
112 $this->tmp_image
= '';
117 public function crop($prop)
119 // Sanitize and normalize the properties into geometry
120 $this->sanitize_geometry($prop);
122 // Set the IM geometry based on the properties
123 $geometry = escapeshellarg($prop['width'].'x'.$prop['height'].'+'.$prop['left'].'+'.$prop['top']);
125 if ($error = exec(escapeshellcmd($this->dir
.'convert'.$this->ext
).' -crop '.$geometry.' '.$this->cmd_image
.' '.$this->cmd_image
))
127 $this->errors
[] = $error;
134 public function flip($dir)
136 // Convert the direction into a IM command
137 $dir = ($dir === Image
::HORIZONTAL
) ?
'-flop' : '-flip';
139 if ($error = exec(escapeshellcmd($this->dir
.'convert'.$this->ext
).' '.$dir.' '.$this->cmd_image
.' '.$this->cmd_image
))
141 $this->errors
[] = $error;
148 public function resize($prop)
150 switch ($prop['master'])
152 case Image
::WIDTH
: // Wx
153 $dim = escapeshellarg($prop['width'].'x');
155 case Image
::HEIGHT
: // xH
156 $dim = escapeshellarg('x'.$prop['height']);
158 case Image
::AUTO
: // WxH
159 $dim = escapeshellarg($prop['width'].'x'.$prop['height']);
161 case Image
::NONE
: // WxH!
162 $dim = escapeshellarg($prop['width'].'x'.$prop['height'].'!');
166 // Use "convert" to change the width and height
167 if ($error = exec(escapeshellcmd($this->dir
.'convert'.$this->ext
).' -resize '.$dim.' '.$this->cmd_image
.' '.$this->cmd_image
))
169 $this->errors
[] = $error;
176 public function rotate($amt)
178 if ($error = exec(escapeshellcmd($this->dir
.'convert'.$this->ext
).' -rotate '.escapeshellarg($amt).' -background transparent '.$this->cmd_image
.' '.$this->cmd_image
))
180 $this->errors
[] = $error;
187 public function sharpen($amount)
189 // Set the sigma, radius, and amount. The amount formula allows a nice
190 // spread between 1 and 100 without pixelizing the image badly.
192 $radius = $sigma * 2;
193 $amount = round(($amount / 80) * 3.14, 2);
195 // Convert the amount to an IM command
196 $sharpen = escapeshellarg($radius.'x'.$sigma.'+'.$amount.'+0');
198 if ($error = exec(escapeshellcmd($this->dir
.'convert'.$this->ext
).' -unsharp '.$sharpen.' '.$this->cmd_image
.' '.$this->cmd_image
))
200 $this->errors
[] = $error;
207 protected function properties()
209 return array_slice(getimagesize($this->tmp_image
), 0, 2, FALSE);
212 } // End Image ImageMagick Driver