--- gimp-1.3.12.orig/plug-ins/common/waves.c	2003-02-01 23:27:18.000000000 +0100
+++ gimp-1.3.12/plug-ins/common/waves.c	2003-03-02 02:12:24.000000000 +0100
@@ -80,6 +80,7 @@
 		  gint     width,
 		  gint     height,
 		  gint     bypp,
+		  gboolean has_alpha,
 		  gdouble  amplitude,
 		  gdouble  wavelength,
 		  gdouble  phase,
@@ -216,11 +217,12 @@
   gint retval=0;
   GimpPixelRgn srcPr, dstPr;
   guchar *src, *dst;
-  guint width, height, bpp;
+  guint width, height, bpp, has_alpha;
 
   width = drawable->width;
   height = drawable->height;
   bpp = drawable->bpp;
+  has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
 
   src = g_new (guchar, width * height * bpp);
   dst = g_new (guchar, width * height * bpp);
@@ -228,8 +230,9 @@
   gimp_pixel_rgn_init (&dstPr, drawable, 0, 0, width, height, TRUE, TRUE);
   gimp_pixel_rgn_get_rect (&srcPr, src, 0, 0, width, height);
 
-  wave (src, dst, width, height, bpp, argp->amplitude, argp->wavelength,
-        argp->phase, argp->type==0, argp->reflective, 1);
+  wave (src, dst, width, height, bpp, has_alpha,
+        argp->amplitude, argp->wavelength, argp->phase,
+        argp->type==0, argp->reflective, 1);
   gimp_pixel_rgn_set_rect (&dstPr, dst, 0, 0, width, height);
 
   g_free (src);
@@ -416,6 +419,7 @@
   dst = g_new (guchar, preview->width * preview->height * preview->bpp);
 
   wave (preview->cache, dst, preview->width, preview->height, preview->bpp,
+        preview->bpp == 2 || preview->bpp == 4,
 	argp->amplitude * preview->scale_x, 
 	argp->wavelength * preview->scale_x,
 	argp->phase, argp->type == 0, argp->reflective, 0);
@@ -464,6 +468,8 @@
   gtk_widget_show (pframe);
 
   preview = gimp_fixme_preview_new (drawable, FALSE);
+  /* FIXME: this forces gimp_fixme_preview to set its alpha correctly */
+  gimp_fixme_preview_fill_scaled (preview, drawable);
   gtk_container_add (GTK_CONTAINER (pframe), preview->widget);
   gtk_widget_show (preview->widget);
 
@@ -479,6 +485,68 @@
   return preview->widget;
 }
 
+/*
+ * gimp_bilinear_8 () equivalent, but on whole pixels.
+ * FIXME: this shouldn't be called gimp_*
+ *        OTOH something like this should probably go to libgimpcolor
+ */
+static void
+gimp_bilinear_pixels_8 (guchar *dest,
+                        gdouble x,
+                        gdouble y,
+                        guint bpp,
+                        gboolean has_alpha,
+                        guchar **values)
+{
+  guint i;
+
+  g_assert (dest != NULL);
+  g_assert (values != NULL);
+  for (i = 0; i < bpp; i++)
+    g_assert (values[i]);
+
+  x = fmod (x, 1.0);
+  y = fmod (y, 1.0);
+
+  if (x < 0.0)
+    x += 1.0;
+  if (y < 0.0)
+    y += 1.0;
+
+  if (has_alpha)
+    {
+      guint ai = bpp-1;
+      gdouble alpha0 = values[0][ai];
+      gdouble alpha1 = values[1][ai];
+      gdouble alpha2 = values[2][ai];
+      gdouble alpha3 = values[3][ai];
+      gdouble alpha = (1.0 - y) * ((1.0 - x) * alpha0 + x * alpha1)
+                      + y * ((1.0 - x) * alpha2 + x * alpha3);
+
+      dest[ai] = (guchar) alpha;
+      if (dest[ai])
+        {
+          for (i = 0; i < ai; i++)
+            {
+              gdouble m0 = (1.0 - x) * values[0][i] * alpha0
+                          + x * values[1][i] * alpha1;
+              gdouble m1 = (1.0 - x) * values[2][i] * alpha2
+                          + x * values[3][i] * alpha3;
+              dest[i] = (guchar) (((1.0 - y) * m0 + y * m1) / alpha);
+            }
+        }
+    }
+  else
+    {
+      for (i = 0; i < bpp; i++)
+        {
+          gdouble m0 = (1.0 - x) * values[0][i] + x * values[1][i];
+          gdouble m1 = (1.0 - x) * values[2][i] + x * values[3][i];
+          dest[i] = (guchar) ((1.0 - y) * m0 + y * m1);
+        }
+    }
+}
+
 /* Wave the image.  For each pixel in the destination image
  * which is inside the selection, we compute the corresponding
  * waved location in the source image.  We use bilinear
@@ -501,6 +569,7 @@
       gint     width,
       gint     height,
       gint     bypp,
+      gboolean has_alpha,
       gdouble  amplitude,
       gdouble  wavelength,
       gdouble  phase,
@@ -526,10 +595,8 @@
 
   gint xi, yi;
 
-  guchar  values[4];
-  guchar  val;
-
-  gint k;
+  guchar *values[4];
+  guchar  zeroes[4] = { 0, 0, 0, 0 };
 
   phase = phase * G_PI / 180;
   rowsiz   = width * bypp;
@@ -643,32 +710,28 @@
 	  x2_in = WITHIN (0, xi + 1, width - 1);
 	  y2_in = WITHIN (0, yi + 1, height - 1);
 
-	  for (k = 0; k < bypp; k++)
-	    {
-	      if (x1_in && y1_in)
-		values[0] = *(p + k);
-	      else
-		values[0] = 0;
-
-	      if (x2_in && y1_in)
-		values[1] = *(p + bypp + k);
-	      else
-		values[1] = 0;
-
-	      if (x1_in && y2_in)
-		values[2] = *(p + rowsiz + k);
-	      else
-		values[2] = 0;
-
-	      if (x2_in && y2_in)
-		values[3] = *(p + bypp + k + rowsiz);
-	      else
-		values[3] = 0;
-
-	      val = gimp_bilinear_8 (needx, needy, values);
+          if (x1_in && y1_in)
+            values[0] = p;
+          else
+            values[0] = zeroes;
+
+          if (x2_in && y1_in)
+            values[1] = p + bypp;
+          else
+            values[1] = zeroes;
+
+          if (x1_in && y2_in)
+            values[2] = p + rowsiz;
+          else
+            values[2] = zeroes;
+
+          if (x2_in && y2_in)
+            values[3] = p + bypp + rowsiz;
+          else
+            values[3] = zeroes;
 
-	      *dest++ = val;
-	    }
+          gimp_bilinear_pixels_8 (dest, needx, needy, bypp, has_alpha, values);
+          dest += bypp;
 	}
 
       dst += rowsiz;
