Index: imageapi_imagemagick.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/imageapi/imageapi_imagemagick.module,v
retrieving revision 1.23
diff -u -p -r1.23 imageapi_imagemagick.module
--- imageapi_imagemagick.module	29 May 2009 17:48:48 -0000	1.23
+++ imageapi_imagemagick.module	29 Jul 2009 00:00:40 -0000
@@ -35,17 +35,35 @@ function image_imageapi_imagemagick_sett
 
   $form['imageapi_imagemagick_binary'] = array(
     '#type' => 'fieldset',
-    '#title' => t('ImageMagick Binary'),
+    '#title' => t('ImageMagick Binaries'),
     '#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.'),
+    '#description' => t('ImageMagick is a collection of  standalone programs used to manipulate images. To use it, it must be installed on your server and you need to know where the programs are located. If you are unsure of the exact paths consult your ISP or server administrator.'),
   );
   $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 <kbd>convert</kbd> binary. For example: <kbd>/usr/bin/convert</kbd> or <kbd>C:\Program Files\ImageMagick-6.3.4-Q16\convert.exe</kbd>'),
+    '#description' => t('Specify the complete path to the ImageMagick <kbd>convert</kbd> binary. For example: <kbd>/usr/bin/convert</kbd> or <kbd>C:\Program Files\ImageMagick-6.3.4-Q16\convert.exe</kbd>'),
     '#element_validate' => array('imageapi_imagemagick_validate_path'),
+    '#weight' => -2,
+  );
+  $form['imageapi_imagemagick_binary']['imageapi_imagemagick_convert_version'] = array(
+    '#type' => 'textfield',
+    '#weight' => -1,
+  );
+  $form['imageapi_imagemagick_binary']['imageapi_imagemagick_identify'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Path to the "identify" binary'),
+    '#default_value' => variable_get('imageapi_imagemagick_identify', '/usr/bin/identify'),
+    '#required' => TRUE,
+    '#description' => t('Specify the complete path to the ImageMagick <kbd>identify</kbd> binary. This is usually in the same directory as the <kbd>convert</kbd> binary.'),
+    '#element_validate' => array('imageapi_imagemagick_validate_path'),
+    '#weight' => 0,
+   );
+  $form['imageapi_imagemagick_binary']['imageapi_imagemagick_identify_version'] = array(
+    '#type' => 'item',
+    '#weight' => 1,
   );
   $form['imageapi_imagemagick_binary']['imageapi_imagemagick_debugging'] = array(
     '#type' => 'checkbox',
@@ -54,7 +72,6 @@ function image_imageapi_imagemagick_sett
     '#description' => t('Checking this option will display the ImageMagick commands and output to users with the <em>administer site configuration</em> permission.'),
     '#weight' => 2,
   );
-  $form['imageapi_imagemagick_binary']['version'] = array('#weight' => -1);
   $form['imageapi_imagemagick_binary']['#after_build'] = array('_imageapi_imagemagick_build_version');
 
   return $form;
@@ -65,20 +82,29 @@ function _imageapi_imagemagick_build_ver
   if ($path_errors = _imageapi_imagemagick_check_path($form_state['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(
-      '#markup' => '<p class="error">'. implode('<br />', $path_errors) .'</p>',
-    );
+    $form_element['imageapi_imagemagick_binary']['convert_version']['#markup'] =  '<p class="error">'. implode('<br />', $path_errors) .'</p>';
   }
   else {
     _imageapi_imagemagick_convert_exec('-version', $output, $errors);
-    $form_element['imageapi_imagemagick_binary']['version'] = array(
+    $form_element['imageapi_imagemagick_binary']['convert_version'] = array(
       '#title' => t('Version information'),
       '#markup' => '<pre>'. check_plain(trim($output)) .'</pre>',
-      '#description' => t('The ImageMagick <kbd>convert</kbd> binary was located and return this version information.'),
+      '#description' => t('The ImageMagick <kbd>convert</kbd> binary was located and returned this version information.'),
     );
   }
-  $form_element['imageapi_imagemagick_binary']['version']['#type'] = 'item';
-  $form_element['imageapi_imagemagick_binary']['version']['#weight'] = -1;
+  $form_element['imageapi_imagemagick_binary']['convert_version']['#type'] = 'item';
+  $form_element['imageapi_imagemagick_binary']['convert_version']['#weight'] = -1;
+  if ($path_errors = _imageapi_imagemagick_check_path($form_state['values']['imageapi_imagemagick_identify'])) {
+    $form_element['imageapi_imagemagick_binary']['imageapi_imagemagick_identify_version']['#markup'] = '<p class="error">'. implode('<br />', $path_errors) .'</p>';
+  }
+  else {
+    _imageapi_imagemagick_identify_exec('-version', $output, $errors);
+    $form_element['imageapi_imagemagick_binary']['imageapi_imagemagick_identify_version']['#title'] = t('Version information');
+    $form_element['imageapi_imagemagick_binary']['imageapi_imagemagick_identify_version']['#markup'] = '<pre>'. check_plain(trim($output)) .'</pre>';
+    $form_element['imageapi_imagemagick_binary']['imageapi_imagemagick_identify_version']['#description'] = t('The ImageMagick <kbd>identify</kbd> binary was located and returned this version information.');
+  }
+  $form_element['imageapi_imagemagick_binary']['imageapi_imagemagick_identify_version']['#type'] = 'item';
+  $form_element['imageapi_imagemagick_binary']['imageapi_imagemagick_identify_version']['#weight'] = 1;
   return $form_element;
 }
 
@@ -99,11 +125,15 @@ function imageapi_imagemagick_quality_el
 
 function image_imageapi_imagemagick_load(stdClass $image) {
   $image->ops = array();
-  return $image;
+  return TRUE;
 }
 
 function image_imageapi_imagemagick_save(stdClass $image, $destination) {
-  return _imageapi_imagemagick_convert($image->source, $destination, $image->ops);
+  $type = '';
+  if (!strncmp($image->info['mime_type'], 'image/', 6)) {
+    $type = substr($image->info['mime_type'], 6) . ':';
+  }
+  return _imageapi_imagemagick_convert($image->source, $type . $destination, $image->ops);
 }
 
 function image_imageapi_imagemagick_crop(stdClass $image, $x, $y, $width, $height) {
@@ -148,14 +178,51 @@ function image_imageapi_imagemagick_desa
 }
 
 /**
+ * Get details about an image.
+ *
+ * Imagemagick supports a number of file formats.
+ *
+ * @param $image
+ *   An image object.
+ * @return
+ *   FALSE, if the file could not be found or is not an image. Otherwise, a
+ *   keyed array containing information about the image:
+ *    'width'     - Width in pixels.
+ *    'height'    - Height in pixels.
+ *    'extension' - Commonly used file extension for the image.
+ *    'mime_type' - MIME type, e.g. 'image/jpeg', 'image/gif', 'image/png'.
+ *    'file_size' - File size in bytes.
+ */
+function image_imageapi_imagemagick_get_info($image) {
+  $info = FALSE;
+  _imageapi_imagemagick_identify_exec("-format \"%w %h %m\" " . escapeshellarg($image->source), $output, $errors);
+  $results = explode(' ', $output);
+  if (count($results)) {
+    $extension = strtolower($results[2]); 
+    $info = array('width' => $results[0],
+                  'height' => $results[1],
+                  'extension' => $extension,
+                  'file_size' => @filesize($image->source),
+                  'mime_type' => file_get_mimetype($image->source));
+  }
+  return $info;
+}
+
+/**
  * Calls the convert executable with the specified filter.
  */
 function _imageapi_imagemagick_convert($source, $dest, $args) {
   $args['quality'] = '-quality '. escapeshellarg(variable_get('imageapi_imagemagick_quality', 75));
+
+  // When an image contains more than one layer, ImageMagick normally converts
+  // to more than one image. But we don't want this, so we pass the -append
+  // argument. This has no effect on single-layered images.
+  $args['append'] = '-append';
+
   // To make use of ImageMagick 6's parenthetical command grouping we need to make
   // the $source image the first parameter and $dest the last.
   // See http://www.imagemagick.org/Usage/basics/#cmdline for more info.
-  $command = escapeshellarg($source) .' '. implode(' ', $args) .' '. escapeshellarg($dest);
+  $command = escapeshellarg($source . '[0]') .' '. implode(' ', $args) .' '. escapeshellarg($dest);
 
   if (0 != _imageapi_imagemagick_convert_exec($command, $output, $errors)) {
     return FALSE;
@@ -179,7 +246,16 @@ function _imageapi_imagemagick_check_pat
 
 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)) {
+  return _imageapi_imagemagick_exec($convert_path, $command_args, $output, $errors);
+}
+
+function _imageapi_imagemagick_identify_exec($command_args, &$output, &$errors) {
+  $identify_path = variable_get('imageapi_imagemagick_identify', '/usr/bin/identify');
+  return _imageapi_imagemagick_exec($identify_path, $command_args, $output, $errors);
+}
+
+function _imageapi_imagemagick_exec($command_path, $command_args, &$output, &$errors) {
+  if ($errors = _imageapi_imagemagick_check_path($command_path)) {
     watchdog('imageapi imagemagick', '!errors', array('!errors' => implode('<br />', $errors)), WATCHDOG_ERROR);
     return FALSE;
   }
@@ -193,7 +269,7 @@ function _imageapi_imagemagick_convert_e
     // 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'. escapeshellarg($drupal_path) .' /B '. escapeshellarg($convert_path);
+    $command_path = 'start "window title" /D'. escapeshellarg($drupal_path) .' /B '. escapeshellarg($command_path);
   }
 
   $descriptors = array(
@@ -201,7 +277,7 @@ function _imageapi_imagemagick_convert_e
     1 => array('pipe', 'w'), // stdout
     2 => array('pipe', 'w')  // stderr
   );
-  if ($h = proc_open($convert_path .' '. $command_args, $descriptors, $pipes, $drupal_path)) {
+  if ($h = proc_open($command_path .' '. $command_args, $descriptors, $pipes, $drupal_path)) {
     $output = '';
     while (!feof($pipes[1])) {
       $output .= fgets($pipes[1]);
@@ -214,7 +290,7 @@ function _imageapi_imagemagick_convert_e
 
     // 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 command: @command', array('@command' => $command_path .' '. $command_args)));
       drupal_set_message(t('ImageMagick output: @output', array('@output' => $output)));
     }
 
