'textfield', '#title' => t('Compression Quality'), '#description' => t('Ranges from 1 to 100. Higher values mean better image quality, but bigger files.'), '#size' => 10, '#maxlength' => 3, '#default_value' => variable_get('imageapi_imagemagick_quality', 75), '#field_suffix' => '%', '#validate' => array('imageapi_imagemagick_quality_element_validate' => array()), ); $form['imageapi_imagemagick_binary'] = array( '#type' => 'fieldset', '#title' => t('ImageMagick Binary'), '#collapsible' => FALSE, '#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.'), ); $form['imageapi_imagemagick_binary']['version'] = array('#weight' => -1); $form['imageapi_imagemagick_binary']['#after_build'] = array('_imageapi_imagemagick_build_version'); $form['imageapi_imagemagick_binary']['imageapi_imagemagick_convert'] = array( '#type' => 'textfield', '#title' => t('Path to the "convert" binary'), '#default_value' => variable_get('imageapi_imagemagick_convert', '/usr/bin/convert'), '#required' => TRUE, '#description' => t('Specify the complete path to the ImageMagic convert binary. For example: /usr/bin/convert or C:\Program Files\ImageMagick-6.3.4-Q16\convert.exe'), '#validate' => array('_imageapi_imagemagick_validate_path' => array()), ); $form['imageapi_imagemagick_binary']['imageapi_imagemagick_debugging'] = array( '#type' => 'checkbox', '#title' => t('Display debugging information'), '#default_value' => variable_get('imageapi_imagemagick_debugging', 0), '#description' => t('Checking this option will display the ImageMagick commands and ouput to users with the administer site configuration permission.'), ); return system_settings_form($form); } function _imageapi_imagemagick_build_version($form_element, $form_values) { // make sure path is set and valid before running after build. if ($path_errors = _imageapi_imagemagick_check_path($form_values['imageapi_imagemagick_convert'])) { // check here is primarily for pre-existing bad settings... // the #validate should prevent users from adding bad paths. $form_element['imageapi_imagemagick_binary'] = array( '#value' => '

'. implode('
', $path_errors) .'

', ); } else { _imageapi_imagemagick_convert_exec('-version', $output, $errors); $form_element['imageapi_imagemagick_binary']['version'] = array( '#title' => t('Version information'), '#value' => '
'. check_plain(trim($output)) .'
', '#description' => t('The ImageMagick convert binary was located and return this version information.'), ); } $form_element['imageapi_imagemagick_binary']['version']['#type'] = 'item'; $form_element['imageapi_imagemagick_binary']['version']['#weight'] = -1; return $form_element; } function _imageapi_imagemagick_validate_path($element) { if ($errors = _imageapi_imagemagick_check_path($element['#value'])) { form_set_error($element['#parents'][0], implode('
', $errors)); //form_set_value($element['#parents'][0], variable_get('imageapi_imagemagick_convert', '/usr/bin/convert')); return FALSE; } return TRUE; } function imageapi_imagemagick_quality_element_validate($element) { if ($element['#value'] < 0 || $element['#value'] > 100) { form_set_error($element['#name'], t('Compression Quality must be a value between 1 and 100.')); } } function imageapi_imagemagick_image_open($image) { $ext = array_pop(explode('.', $image->source)); $image->res = tempnam(file_directory_temp(), 'imageapi_imagemagick_') .".$ext"; if (!file_copy($image->source, $image->res)) { return FALSE; } $image->ops = array(); register_shutdown_function('file_delete', $image->res); return $image; } function imageapi_imagemagick_image_close($image, $dst) { if (!_imageapi_imagemagick_convert($image->res, $image->res, $image->ops)) { return FALSE; } return file_move($image->res, $dst); } function imageapi_imagemagick_image_crop(&$image, $x, $y, $width, $height) { $image->ops[] = '-crop '. (int) $width .'x'. (int) $height .'+'. (int) $x .'+'. (int) $y .'!'; $image->info['width'] = $width; $image->info['height'] = $height; return TRUE; } function imageapi_imagemagick_image_resize(&$image, $width, $height) { $image->ops[] = '-resize '. (int) $width .'x'. (int) $height .'!'; $image->info['width'] = $width; $image->info['height'] = $height; return TRUE; } function imageapi_imagemagick_image_rotate(&$image, $degrees, $bgcolor) { $image->ops[] = '-rotate '. (float) $degrees .' -background #'. str_pad(dechex($bg_color), 6, 0); return TRUE; } function imageapi_imagemagick_image_desaturate(&$image) { $image->ops[] = '-colorspace GRAY'; return TRUE; } /** * Calls the convert executable with the specified filter. */ function _imageapi_imagemagick_convert($source, $dest, $args) { $args['quality'] = '-quality '. variable_get('imageapi_imagemagick_quality', 75); $command = implode(' ', array( preg_replace("/[^A-Za-z0-9\!\.\-\+\_\/\040]/", '', implode(' ', $args)), escapeshellarg($source), escapeshellarg($dest), )); if (0 != _imageapi_imagemagick_convert_exec($command, $output, $errors)) { return FALSE; } return file_exists($dest); } function _imageapi_imagemagick_check_path($path) { $errors = array(); if (!is_file($path)) { $errors[] = t('The specified ImageMagick path %file does not exist.', array('%file' => $path)); } if (!$errors && !is_executable($path)) { $errors[] = t('The specified ImageMagick path %file is not executable.', array('%file' => $path)); } if ($errors && $open_basedir = ini_get('open_basedir')) { $errors[] = t("PHP's open_basedir security resriction 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'))); } return $errors; } function _imageapi_imagemagick_convert_exec($command_args, &$output, &$errors) { $convert_path = variable_get('imageapi_imagemagick_convert', '/usr/bin/convert'); if ($errors = _imageapi_imagemagick_check_path($convert_path)) { // When updating an invalid path this function throws an error. array_unshift($errors, t("If the referrer is the settings page this error can most likely be ignored.")); array_unshift($errors, t("ImageMagick could not be found. The admin will need to set the path on the image toolkit page.", array('@image-toolkit-settings' => url('admin/settings/image-toolkit')))); watchdog('imageapi imagemagick', implode('
', $errors), WATCHDOG_ERRROR); return FALSE; } if (strstr($_SERVER['SERVER_SOFTWARE'], 'Win32') || strstr($_SERVER['SERVER_SOFTWARE'], 'IIS')) { // Use Window's start command to avoid the "black window" from showing up: // http://us3.php.net/manual/en/function.exec.php#56599 // Use /D to run the command from PHP's current working directory so the // file paths don't have to be absolute. $convert_path = 'start "window title" /D'. getcwd() .' /b '. escapeshellarg($convert_path); } $descriptors = array( 0 => array('pipe', 'r'), // stdin 1 => array('pipe', 'w'), // stdout 2 => array('pipe', 'w') // stderr ); if ($h = proc_open($convert_path .' '. $command_args, $descriptors, $pipes)) { $output = ''; while (!feof($pipes[1])) { $output .= fgets($pipes[1]); } $errors = ''; while (!feof($pipes[2])) { $errors .= fgets($pipes[2]); } // Display debugging information to authorized users. if (variable_get('imageapi_imagemagick_debugging', FALSE) && user_access('administer site configuration')) { drupal_set_message(t("ImageMagick command: @command", array('@command' => $convert_path .' '. $command_args))); drupal_set_message(t("ImageMagick output: @output", array('@output' => $output))); } if ($errors) { drupal_set_message(t("ImageMagick reported an error: %error", array('%error' => $errors)), 'error'); } fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); return proc_close($h); } return FALSE; }