Index: imageapi.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/imagecache_effects/imageapi.inc,v
retrieving revision 1.1
diff -u -p -r1.1 imageapi.inc
--- imageapi.inc	5 Jan 2009 00:32:38 -0000	1.1
+++ imageapi.inc	8 Jun 2010 20:17:13 -0000
@@ -82,12 +82,12 @@ function imageapi_image_watermark($image
 function imageapi_gd_image_watermark($image, $marker, $options = array()) {
   // because of a bug? in gd with png images, we have to use another function
   if ($marker->info['mime_type'] == 'image/png' && $options['opacity'] == 100) {
-    imagealphablending($image->res, true);
-    imagealphablending($marker->res, true);
-    return imagecopy($image->res, $marker->res, $options['x'], $options['y'], 0, 0, $marker->info['width'], $marker->info['height']);
+    imagealphablending($image->resource, true);
+    imagealphablending($marker->resource, true);
+    return imagecopy($image->resource, $marker->resource, $options['x'], $options['y'], 0, 0, $marker->info['width'], $marker->info['height']);
   }
   else {
-    return imagecopymerge($image->res, $marker->res, $options['x'], $options['y'], 0, 0, $marker->info['width'], $marker->info['height'], $options['opacity']);
+    return imagecopymerge($image->resource, $marker->resource, $options['x'], $options['y'], 0, 0, $marker->info['width'], $marker->info['height'], $options['opacity']);
   }
 }
 
@@ -97,6 +97,7 @@ function imageapi_image_reflection($imag
   $options = array_merge(array(
     'color' => 'white',
     'position' => 'bottom',
+    'transparent_source' => FALSE,
     'size' => 30,
   ), $options);
   
@@ -110,7 +111,9 @@ function imageapi_image_reflection($imag
     $options['size'] = intval($options['size']);
   }
   
-  $options['color'] = imageapi_color($options['color']);
+  if (!empty($options['color'])) {
+    $options['color'] = imageapi_color($options['color']);
+  }
   
   $function = $image->toolkit .'_image_reflection';
   if (function_exists($function)) {
@@ -131,44 +134,63 @@ function imageapi_gd_image_reflection(&$
   $y = $options['position'] == 'top' ? $options['size'] : 0;
   
   $background = imagecreatetruecolor($width, $height);
-  imagefill($background, 0, 0, $options['color']);
-  imagecopy($background, $image->res, $x, $y, 0, 0, $image->info['width'], $image->info['height']);
+  // If $options['color'] is empty, we're trying for a transparent canvas:
+  if (empty($options['color'])) {
+    imagesavealpha($background, TRUE);
+    imagealphablending($background, FALSE); 
+  }
+  else {
+    imagefill($background, 0, 0, $options['color']);
+  }
+  imagecopy($background, $image->resource, $x, $y, 0, 0, $image->info['width'], $image->info['height']);
+  
+  $imagecopymerge = 'imagecopymerge';
+  // If the user has said that the source image might contain
+  // transparency, use the slower, but working algorithm to merge
+  // the images:
+  if ($options['transparent_source']) {
+    $imagecopymerge = '_imageapi_gd_image_reflection_imagecopymerge_alpha';
+    $min_alpha = _imageapi_gd_image_reflection_alpha_get_min($image->resource);
+  }
+  else {
+    $min_alpha = NULL;
+  }
   
   $return = false;
   switch ($options['position']) {
     case 'top':
       $steps = min($options['size'], $image->info['height']);
       for ($i = 0, $opacity = 50; $i < $steps; ++$i, $opacity = ceil(((($steps - $i) / $steps) * 100) / 2)) {
-        imagecopymerge($background, $image->res, 0, $y - $i, 0, $i, $image->info['width'], 1, $opacity);
+        $imagecopymerge($background, $image->resource, 0, $y - $i, 0, $i, $image->info['width'], 1, $opacity, $min_alpha);
       }
       $return = true;
       break;
     case 'bottom':
       $steps = min($options['size'], $image->info['height']);
       for ($i = 0, $opacity = 50; $i < $steps; ++$i, $opacity = ceil(((($steps - $i) / $steps) * 100) / 2)) {
-        imagecopymerge($background, $image->res, 0, $image->info['height'] + $i, 0, $image->info['height'] - $i, $image->info['width'], 1, $opacity);
+        $imagecopymerge($background, $image->resource, 0, $image->info['height'] + $i, 0, $image->info['height'] - $i - 1, $image->info['width'], 1, $opacity, $min_alpha);
       }
       $return = true;
       break;
     case 'left':
       $steps = min($options['size'], $image->info['width']);
       for ($i = 0, $opacity = 50; $i < $steps; ++$i, $opacity = ceil(((($steps - $i) / $steps) * 100) / 2)) {
-        imagecopymerge($background, $image->res, $x - $i, 0, $i, 0, 1, $image->info['height'], $opacity);
+        $imagecopymerge($background, $image->resource, $x - $i, 0, $i, 0, 1, $image->info['height'], $opacity, $min_alpha);
       }
       $return = true;
       break;
     case 'right':
       $steps = min($options['size'], $image->info['height']);
       for ($i = 0, $opacity = 50; $i < $steps; ++$i, $opacity = ceil(((($steps - $i) / $steps) * 100) / 2)) {
-        imagecopymerge($background, $image->res, $image->info['width'] + $i, 0, $image->info['width'] - $i, 0, 1, $image->info['height'], $opacity);
+        $imagecopymerge($background, $image->resource, $image->info['width'] + $i, 0, $image->info['width'] - $i - 1, 0, 1, $image->info['height'], $opacity, $min_alpha);
       }
       $return = true;
       break;
   }
   
   if ($return) {
-    imagedestroy($image->res);
-    $image->res = $background;
+    imagedestroy($image->resource);
+    $image->resource = $background;
     $image->info['width'] = $width;
     $image->info['height'] = $height;
   }
@@ -178,6 +200,82 @@ function imageapi_gd_image_reflection(&$
   return $return;
 }
 
+/**
+ * A fix to get a function like imagecopymerge with alpha blending
+ * 
+ * Main script by aiden dot mail at freemail dot hu.
+ * Transformed to imagecopymerge_alpha() by rodrigo dot polo at gmail dot com
+ * see: http://uk2.php.net/manual/en/function.imagecopymerge.php#88456.
+ */
+function _imageapi_gd_image_reflection_imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct, $minalpha = NULL){
+    if(!isset($pct)){
+        return false;
+    }
+    $pct /= 100;
+    // Get image width and height
+    $w = imagesx( $src_im );
+    $h = imagesy( $src_im );
+    // Turn alpha blending off
+    imagealphablending( $src_im, false );
+    if (is_null($minalpha)) {
+      // Find the most opaque pixel in the image (the one with the smallest alpha value)
+      $minalpha = 127;
+      for( $x = 0; $x < $w; $x++ )
+      for( $y = 0; $y < $h; $y++ ){
+          $alpha = ( imagecolorat( $src_im, $x, $y ) >> 24 ) & 0xFF;
+          if( $alpha < $minalpha ){
+              $minalpha = $alpha;
+          }
+      }
+    }
+    //loop through image pixels and modify alpha for each
+    for( $x = $src_x; $x < $src_x + $src_w; $x++ ){
+        for( $y = $src_y; $y < $src_y + $src_h; $y++ ){
+            //get current alpha value (represents the TANSPARENCY!)
+            $colorxy = imagecolorat( $src_im, $x, $y );
+            $alpha = ( $colorxy >> 24 ) & 0xFF;
+            //calculate new alpha
+            if( $minalpha !== 127 ){
+                $alpha = 127 + 127 * $pct * ( $alpha - 127 ) / ( 127 - $minalpha );
+            } else {
+                $alpha += 127 * $pct;
+            }
+            //get the color index with new alpha
+            $alphacolorxy = imagecolorallocatealpha( $src_im, ( $colorxy >> 16 ) & 0xFF, ( $colorxy >> 8 ) & 0xFF, $colorxy & 0xFF, $alpha );
+            //set pixel with the new color + opacity
+            if( !imagesetpixel( $src_im, $x, $y, $alphacolorxy ) ){
+                return false;
+            }
+        }
+    }
+    // The image copy
+    imagecopy($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h);
+}
+
+/**
+ * Compute the minimum alpha value of the pixels of a given image resource.
+ *
+ * Warning, this function is very expensive.
+ */
+function _imageapi_gd_image_reflection_alpha_get_min($src_im) {
+  $w = imagesx( $src_im );
+  $h = imagesy( $src_im );
+  // Turn alpha blending off
+  imagealphablending( $src_im, false );
+  // Find the most opaque pixel in the image (the one with the smallest alpha value)
+  $minalpha = 127;
+  for( $x = 0; $x < $w; $x++ )
+  for( $y = 0; $y < $h; $y++ ){
+      $alpha = ( imagecolorat( $src_im, $x, $y ) >> 24 ) & 0xFF;
+      if( $alpha < $minalpha ){
+          $minalpha = $alpha;
+      }
+  }
+  return $minalpha;
+}
+
+ 
+
 function _imageapi_colors() {
   static $colors = array(
     'AliceBlue' => 0xF0F8FF,
Index: imagecache_effects.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/imagecache_effects/imagecache_effects.info,v
retrieving revision 1.1
diff -u -p -r1.1 imagecache_effects.info
--- imagecache_effects.info	5 Jan 2009 00:32:38 -0000	1.1
+++ imagecache_effects.info	8 Jun 2010 20:17:13 -0000
@@ -1,7 +1,6 @@
-; created by Netengine - www.netengine.com.au
+; $Id: $
 name = ImageCache Effects
 description = Additional image effects for Image Cache.
 package = ImageCache
 dependencies[] = imagecache
-core = 6.x
-version = 6.x-0.1
\ No newline at end of file
+core = 6.x
\ No newline at end of file
Index: imagecache_effects.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/imagecache_effects/imagecache_effects.module,v
retrieving revision 1.1
diff -u -p -r1.1 imagecache_effects.module
--- imagecache_effects.module	5 Jan 2009 00:32:38 -0000	1.1
+++ imagecache_effects.module	8 Jun 2010 20:17:13 -0000
@@ -36,6 +36,7 @@ function imagecache_effects_imagecache_a
       'data' => array(
         'color' => 'white',
         'position' => 'bottom',
+        'transparent_source' => FALSE,
         'size' => 30,
       ),
     ),
Index: imagecache_effects_reflection.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/imagecache_effects/imagecache_effects_reflection.inc,v
retrieving revision 1.1
diff -u -p -r1.1 imagecache_effects_reflection.inc
--- imagecache_effects_reflection.inc	5 Jan 2009 00:32:38 -0000	1.1
+++ imagecache_effects_reflection.inc	8 Jun 2010 20:17:13 -0000
@@ -1,14 +1,26 @@
 <?php
+
+/**
+ * Form callback for the imagecache preset options.
+ */
 function imagecache_effects_reflection_form($data) {
+
   $form['color'] = array(
     '#type' => 'textfield',
     '#title' => t('Background color'),
     '#default_value' => isset($data['color']) ? $data['color'] : 'white',
-    '#description' => t('A hexadecimal color code preceded by a # or the name of the color can be used. eg. <em>white, blue, green, black, etc</em>'),
-    '#required' => true,
+    '#description' => t('A hexadecimal color code preceded by a # or the name of the color can be used. eg. <em>white, blue, green, black, etc</em>, or leave blank for a transparent background.'),
     '#size' => 10,
     '#maxlength' => 20,
   );
+  
+  $form['transparent_source'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Transparent source image'),
+    '#default_value' => isset($data['transparent_source']) ? $data['transparent_source'] : FALSE,
+    '#description' => t('If the image that you are reflecting uses alpha transparency, optionally use a much slower algorithm for creating the images, but one that will preserve the transparency.'),
+  );
+  
   $form['position'] = array(
     '#type' => 'radios',
     '#title' => t('Position'),
@@ -22,6 +34,7 @@ function imagecache_effects_reflection_f
     '#description' => t('The position of the image reflection. Default is bottom.'),
     '#required' => true,
   );
+  
   $form['size'] = array(
     '#type' => 'textfield',
     '#title' => t('Size'),
@@ -29,13 +42,15 @@ function imagecache_effects_reflection_f
     '#description' => t('The size of the reflection in pixels. You may append % to the integer to represent percentages.'),
     '#required' => true,
   );
+  
   return $form;
 }
 
 function theme_imagecache_effects_reflection($element) {
   $data = $element['#value'];
-  return t('Background Color: !color, Position: !position, Size: @size', array(
-    '!color' => is_numeric($data['color']) ? intval($data['color']) : theme('placeholder', check_plain($data['color'])),
+  return t('Background Color: !color, Preserve transparency: @preserve, Position: !position, Size: @size', array(
+    '!color' => is_numeric($data['color']) ? intval($data['color']) : theme('placeholder', empty($data['color']) ? t('Transparent') : check_plain($data['color'])),
+    '@preserve' => $data['transparent_source'] ? t('Yes') : t('No'),
     '!position' => is_numeric($data['position']) ? intval($data['position']) : theme('placeholder', check_plain($data['position'])),
     '@size' => $data['size'],
   ));
