1 <?php
defined('SYSPATH') OR die('No direct access allowed.');
3 * GraphicsMagick Image Driver.
7 * @copyright (c) 2007-2008 Kohana Team
8 * @license http://kohanaphp.com/license.html
10 class Image_GraphicsMagick_Driver
extends Image_Driver
{
12 // Directory that GM is installed in
15 // Command extension (exe for windows)
18 // Temporary image filename
22 * Attempts to detect the GraphicsMagick installation directory.
24 * @throws Kohana_Exception
25 * @param array configuration
28 public function __construct($config)
30 if (empty($config['directory']))
32 // Attempt to locate GM by using "which" (only works for *nix!)
33 if ( ! is_file($path = exec('which gm')))
34 throw new Kohana_Exception('image.graphicsmagick.not_found');
36 $config['directory'] = dirname($path);
39 // Set the command extension
40 $this->ext
= (PHP_SHLIB_SUFFIX
=== 'dll') ?
'.exe' : '';
42 // Check to make sure the provided path is correct
43 if ( ! is_file(realpath($config['directory']).'/gm'.$this->ext
))
44 throw new Kohana_Exception('image.graphicsmagick.not_found', 'gm'.$this->ext
);
47 // Set the installation directory
48 $this->dir
= str_replace('\\', '/', realpath($config['directory'])).'/';
52 * Creates a temporary image and executes the given actions. By creating a
53 * temporary copy of the image before manipulating it, this process is atomic.
55 public function process($image, $actions, $dir, $file, $render = FALSE)
57 // We only need the filename
58 $image = $image['file'];
60 // Unique temporary filename
61 $this->tmp_image
= $dir.'k2img--'.sha1(time().$dir.$file).substr($file, strrpos($file, '.'));
63 // Copy the image to the temporary file
64 copy($image, $this->tmp_image
);
66 // Quality change is done last
67 $quality = (int) arr
::remove('quality', $actions);
69 // Use 95 for the default quality
70 empty($quality) and $quality = 95;
72 // All calls to these will need to be escaped, so do it now
73 $this->cmd_image
= escapeshellarg($this->tmp_image
);
74 $this->new_image
= ($render)?
$this->cmd_image
: escapeshellarg($dir.$file);
76 if ($status = $this->execute($actions))
78 // Use convert to change the image into its final version. This is
79 // done to allow the file type to change correctly, and to handle
80 // the quality conversion in the most effective way possible.
81 if ($error = exec(escapeshellcmd($this->dir
.'gm'.$this->ext
.' convert').' -quality '.$quality.'% '.$this->cmd_image
.' '.$this->new_image
))
83 $this->errors
[] = $error;
87 // Output the image directly to the browser
88 if ($render !== FALSE)
90 $contents = file_get_contents($this->tmp_image
);
91 switch (substr($file, strrpos($file, '.') +
1))
95 header('Content-Type: image/jpeg');
98 header('Content-Type: image/gif');
101 header('Content-Type: image/png');
109 // Remove the temporary image
110 unlink($this->tmp_image
);
111 $this->tmp_image
= '';
116 public function crop($prop)
118 // Sanitize and normalize the properties into geometry
119 $this->sanitize_geometry($prop);
121 // Set the IM geometry based on the properties
122 $geometry = escapeshellarg($prop['width'].'x'.$prop['height'].'+'.$prop['left'].'+'.$prop['top']);
124 if ($error = exec(escapeshellcmd($this->dir
.'gm'.$this->ext
.' convert').' -crop '.$geometry.' '.$this->cmd_image
.' '.$this->cmd_image
))
126 $this->errors
[] = $error;
133 public function flip($dir)
135 // Convert the direction into a GM command
136 $dir = ($dir === Image
::HORIZONTAL
) ?
'-flop' : '-flip';
138 if ($error = exec(escapeshellcmd($this->dir
.'gm'.$this->ext
.' convert').' '.$dir.' '.$this->cmd_image
.' '.$this->cmd_image
))
140 $this->errors
[] = $error;
147 public function resize($prop)
149 switch ($prop['master'])
151 case Image
::WIDTH
: // Wx
152 $dim = escapeshellarg($prop['width'].'x');
154 case Image
::HEIGHT
: // xH
155 $dim = escapeshellarg('x'.$prop['height']);
157 case Image
::AUTO
: // WxH
158 $dim = escapeshellarg($prop['width'].'x'.$prop['height']);
160 case Image
::NONE
: // WxH!
161 $dim = escapeshellarg($prop['width'].'x'.$prop['height'].'!');
165 // Use "convert" to change the width and height
166 if ($error = exec(escapeshellcmd($this->dir
.'gm'.$this->ext
.' convert').' -resize '.$dim.' '.$this->cmd_image
.' '.$this->cmd_image
))
168 $this->errors
[] = $error;
175 public function rotate($amt)
177 if ($error = exec(escapeshellcmd($this->dir
.'gm'.$this->ext
.' convert').' -rotate '.escapeshellarg($amt).' -background transparent '.$this->cmd_image
.' '.$this->cmd_image
))
179 $this->errors
[] = $error;
186 public function sharpen($amount)
188 // Set the sigma, radius, and amount. The amount formula allows a nice
189 // spread between 1 and 100 without pixelizing the image badly.
191 $radius = $sigma * 2;
192 $amount = round(($amount / 80) * 3.14, 2);
194 // Convert the amount to an GM command
195 $sharpen = escapeshellarg($radius.'x'.$sigma.'+'.$amount.'+0');
197 if ($error = exec(escapeshellcmd($this->dir
.'gm'.$this->ext
.' convert').' -unsharp '.$sharpen.' '.$this->cmd_image
.' '.$this->cmd_image
))
199 $this->errors
[] = $error;
206 protected function properties()
208 return array_slice(getimagesize($this->tmp_image
), 0, 2, FALSE);
211 } // End Image GraphicsMagick Driver