/[drupal]/contributions/modules/imageapi/imageapi_imagemagick.module
ViewVC logotype

Contents of /contributions/modules/imageapi/imageapi_imagemagick.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.23 - (show annotations) (download) (as text)
Fri May 29 17:48:48 2009 UTC (5 months, 4 weeks ago) by drewish
Branch: MAIN
CVS Tags: HEAD
Changes since 1.22: +7 -3 lines
File MIME type: text/x-php
#360193 Paul Kishimoto and drewish: Get ImageMagick working with relative paths in subdirectories.
1 <?php // $Id: imageapi_imagemagick.module,v 1.22 2009/04/17 17:57:53 drewish Exp $
2
3 /**
4 * @file
5 * ImageMagick toolkit functions
6 */
7
8
9 /**
10 * Implementation of hook_image_toolkits().
11 */
12 function imageapi_imagemagick_image_toolkits() {
13 return array(
14 'imageapi_imagemagick' => array(
15 'title' => t('ImageMagick toolkit'),
16 'available' => TRUE,
17 ),
18 );
19 }
20
21 /**
22 * Settings form for the toolkit.
23 */
24 function image_imageapi_imagemagick_settings() {
25 $form['imageapi_imagemagick_quality'] = array(
26 '#type' => 'textfield',
27 '#title' => t('Compression Quality'),
28 '#description' => t('Ranges from 0 to 100. Higher values mean better image quality, but bigger files.'),
29 '#size' => 10,
30 '#maxlength' => 3,
31 '#default_value' => variable_get('imageapi_imagemagick_quality', 75),
32 '#field_suffix' => '%',
33 '#element_validate' => array('imageapi_imagemagick_quality_element_validate'),
34 );
35
36 $form['imageapi_imagemagick_binary'] = array(
37 '#type' => 'fieldset',
38 '#title' => t('ImageMagick Binary'),
39 '#collapsible' => FALSE,
40 '#description' => t('ImageMagick is a standalone program used to manipulate images. To use it, it must be installed on your server and you need to know where it is located. If you are unsure of the exact path consult your ISP or server administrator.'),
41 );
42 $form['imageapi_imagemagick_binary']['imageapi_imagemagick_convert'] = array(
43 '#type' => 'textfield',
44 '#title' => t('Path to the "convert" binary'),
45 '#default_value' => variable_get('imageapi_imagemagick_convert', '/usr/bin/convert'),
46 '#required' => TRUE,
47 '#description' => t('Specify the complete path to the ImageMagic <kbd>convert</kbd> binary. For example: <kbd>/usr/bin/convert</kbd> or <kbd>C:\Program Files\ImageMagick-6.3.4-Q16\convert.exe</kbd>'),
48 '#element_validate' => array('imageapi_imagemagick_validate_path'),
49 );
50 $form['imageapi_imagemagick_binary']['imageapi_imagemagick_debugging'] = array(
51 '#type' => 'checkbox',
52 '#title' => t('Display debugging information'),
53 '#default_value' => variable_get('imageapi_imagemagick_debugging', 0),
54 '#description' => t('Checking this option will display the ImageMagick commands and output to users with the <em>administer site configuration</em> permission.'),
55 '#weight' => 2,
56 );
57 $form['imageapi_imagemagick_binary']['version'] = array('#weight' => -1);
58 $form['imageapi_imagemagick_binary']['#after_build'] = array('_imageapi_imagemagick_build_version');
59
60 return $form;
61 }
62
63 function _imageapi_imagemagick_build_version($form_element, $form_state) {
64 // make sure path is set and valid before running after build.
65 if ($path_errors = _imageapi_imagemagick_check_path($form_state['values']['imageapi_imagemagick_convert'])) {
66 // check here is primarily for pre-existing bad settings...
67 // the #validate should prevent users from adding bad paths.
68 $form_element['imageapi_imagemagick_binary'] = array(
69 '#markup' => '<p class="error">'. implode('<br />', $path_errors) .'</p>',
70 );
71 }
72 else {
73 _imageapi_imagemagick_convert_exec('-version', $output, $errors);
74 $form_element['imageapi_imagemagick_binary']['version'] = array(
75 '#title' => t('Version information'),
76 '#markup' => '<pre>'. check_plain(trim($output)) .'</pre>',
77 '#description' => t('The ImageMagick <kbd>convert</kbd> binary was located and return this version information.'),
78 );
79 }
80 $form_element['imageapi_imagemagick_binary']['version']['#type'] = 'item';
81 $form_element['imageapi_imagemagick_binary']['version']['#weight'] = -1;
82 return $form_element;
83 }
84
85 function imageapi_imagemagick_validate_path($element) {
86 if ($element['#post'] == 'imageapi_imagemagick' && $errors = _imageapi_imagemagick_check_path($element['#value'])) {
87 form_set_error($element['#parents'][0], implode('<br />', $errors));
88 //form_set_value($element['#parents'][0], variable_get('imageapi_imagemagick_convert', '/usr/bin/convert'));
89 return FALSE;
90 }
91 return TRUE;
92 }
93
94 function imageapi_imagemagick_quality_element_validate($element) {
95 if ($element['#value'] < 0 || $element['#value'] > 100) {
96 form_set_error($element['#name'], t('Compression Quality must be a value between 0 and 100.'));
97 }
98 }
99
100 function image_imageapi_imagemagick_load(stdClass $image) {
101 $image->ops = array();
102 return $image;
103 }
104
105 function image_imageapi_imagemagick_save(stdClass $image, $destination) {
106 return _imageapi_imagemagick_convert($image->source, $destination, $image->ops);
107 }
108
109 function image_imageapi_imagemagick_crop(stdClass $image, $x, $y, $width, $height) {
110 $image->ops[] = '-crop '. (int) $width .'x'. (int) $height .'+'. (int) $x .'+'. (int) $y .'!';
111 $image->info['width'] = $width;
112 $image->info['height'] = $height;
113 return TRUE;
114 }
115
116 function image_imageapi_imagemagick_resize(stdClass $image, $width, $height) {
117 $image->ops[] = '-resize '. (int) $width .'x'. (int) $height .'!';
118 $image->info['width'] = $width;
119 $image->info['height'] = $height;
120 return TRUE;
121 }
122
123 function image_imageapi_imagemagick_rotate(stdClass $image, $degrees, $background = NULL) {
124 if (is_null($background)) {
125 $image->ops[] = ' -rotate '. (float) $degrees;
126 }
127 else {
128 if (is_int($bgcolor)) {
129 $bgcolor = '#'. str_pad(dechex($bgcolor), 6, 0);
130 }
131 else {
132 $bgcolor = str_replace('0x', '#', $bgcolor);
133 }
134 $image->ops[] = '-background '. escapeshellarg($bgcolor) .' -rotate '. (float) $degrees;
135 }
136 return TRUE;
137 }
138
139 function image_imageapi_imagemagick_sharpen(stdClass $image, $radius, $sigma, $amount, $threshold) {
140 $unsharp_arg = $radius .'x'. $sigma .'+'. $amount/100 .'+'. $threshold;
141 $image->ops[] = '-unsharp '. $unsharp_arg;
142 return TRUE;
143 }
144
145 function image_imageapi_imagemagick_desaturate(stdClass $image) {
146 $image->ops[] = '-colorspace GRAY';
147 return TRUE;
148 }
149
150 /**
151 * Calls the convert executable with the specified filter.
152 */
153 function _imageapi_imagemagick_convert($source, $dest, $args) {
154 $args['quality'] = '-quality '. escapeshellarg(variable_get('imageapi_imagemagick_quality', 75));
155 // To make use of ImageMagick 6's parenthetical command grouping we need to make
156 // the $source image the first parameter and $dest the last.
157 // See http://www.imagemagick.org/Usage/basics/#cmdline for more info.
158 $command = escapeshellarg($source) .' '. implode(' ', $args) .' '. escapeshellarg($dest);
159
160 if (0 != _imageapi_imagemagick_convert_exec($command, $output, $errors)) {
161 return FALSE;
162 }
163 return file_exists($dest);
164 }
165
166 function _imageapi_imagemagick_check_path($path) {
167 $errors = array();
168 if (!is_file($path)) {
169 $errors[] = t('The specified ImageMagick path %file does not exist.', array('%file' => $path));
170 }
171 if (!$errors && !is_executable($path)) {
172 $errors[] = t('The specified ImageMagick path %file is not executable.', array('%file' => $path));
173 }
174 if ($errors && $open_basedir = ini_get('open_basedir')) {
175 $errors[] = t("PHP's <a href='!open-basedir'>open_basedir</a> security restriction is set to %open-basedir, which may be interfering with attempts to locate ImageMagick.", array('%file' => $path, '%open-basedir' => $open_basedir, '!info-link' => url('http://php.net/features.safe-mode#ini.open-basedir')));
176 }
177 return $errors;
178 }
179
180 function _imageapi_imagemagick_convert_exec($command_args, &$output, &$errors) {
181 $convert_path = variable_get('imageapi_imagemagick_convert', '/usr/bin/convert');
182 if ($errors = _imageapi_imagemagick_check_path($convert_path)) {
183 watchdog('imageapi imagemagick', '!errors', array('!errors' => implode('<br />', $errors)), WATCHDOG_ERROR);
184 return FALSE;
185 }
186
187 // Specify Drupal's root as the working a working directory so that relative
188 // paths are interpreted correctly.
189 $drupal_path = $_SERVER['DOCUMENT_ROOT'] . dirname($_SERVER['SCRIPT_NAME'] ? $_SERVER['SCRIPT_NAME'] : $_SERVER['SCRIPT_FILENAME']);
190
191 if (strstr($_SERVER['SERVER_SOFTWARE'], 'Win32') || strstr($_SERVER['SERVER_SOFTWARE'], 'IIS')) {
192 // Use Window's start command to avoid the "black window" from showing up:
193 // http://us3.php.net/manual/en/function.exec.php#56599
194 // Use /D to run the command from PHP's current working directory so the
195 // file paths don't have to be absolute.
196 $convert_path = 'start "window title" /D'. escapeshellarg($drupal_path) .' /B '. escapeshellarg($convert_path);
197 }
198
199 $descriptors = array(
200 0 => array('pipe', 'r'), // stdin
201 1 => array('pipe', 'w'), // stdout
202 2 => array('pipe', 'w') // stderr
203 );
204 if ($h = proc_open($convert_path .' '. $command_args, $descriptors, $pipes, $drupal_path)) {
205 $output = '';
206 while (!feof($pipes[1])) {
207 $output .= fgets($pipes[1]);
208 }
209
210 $errors = '';
211 while (!feof($pipes[2])) {
212 $errors .= fgets($pipes[2]);
213 }
214
215 // Display debugging information to authorized users.
216 if (variable_get('imageapi_imagemagick_debugging', FALSE) && user_access('administer site configuration')) {
217 drupal_set_message(t('ImageMagick command: @command', array('@command' => $convert_path .' '. $command_args)));
218 drupal_set_message(t('ImageMagick output: @output', array('@output' => $output)));
219 }
220
221 if ($errors) {
222 drupal_set_message(t('ImageMagick reported an error: %error', array('%error' => $errors)), 'error');
223 }
224
225 fclose($pipes[0]);
226 fclose($pipes[1]);
227 fclose($pipes[2]);
228 return proc_close($h);
229 }
230 return FALSE;
231 }

  ViewVC Help
Powered by ViewVC 1.1.2