Index: gimpdrawable-transform.c
===================================================================
RCS file: /cvs/gnome/gimp/app/core/gimpdrawable-transform.c,v
retrieving revision 1.116
diff -u -r1.116 gimpdrawable-transform.c
--- gimpdrawable-transform.c	29 Aug 2006 14:46:21 -0000	1.116
+++ gimpdrawable-transform.c	10 Sep 2006 09:49:48 -0000
@@ -292,7 +292,7 @@
   if (interpolation_type == GIMP_INTERPOLATION_LANCZOS &&
       (x2 - x1 < LANCZOS_WIDTH2 || y2 - y1 < LANCZOS_WIDTH2))
     interpolation_type = GIMP_INTERPOLATION_CUBIC;
-
+ 
   /* initialise the pixel_surround and pixel_cache accessors */
   switch (interpolation_type)
     {
@@ -322,6 +322,53 @@
   /* these loops could be rearranged, depending on which bit of code
    * you'd most like to write more than once.
    */
+  if ( interpolation_type == GIMP_INTERPOLATION_LANCZOS ) 
+    {
+       gdouble du;
+       gdouble dv;
+       gdouble dw;
+
+       guchar color[MAX_CHANNELS];
+       gint    b, u, v;
+
+       for (y = y1; y < y2; y++)
+         {
+           if (progress && !(y & 0xf))
+               gimp_progress_set_value (progress,
+                                 (gdouble) (y - y1) / (gdouble) (y2 - y1));
+
+           d = dest;
+
+           for (x = x1; x < x2; x++)
+             {
+               /* set up inverse transform steps */
+               du = uinc * x + m.coeff[0][1] * y + m.coeff[0][2];
+               dv = vinc * x + m.coeff[1][1] * y + m.coeff[1][2];
+               dw = winc * x + m.coeff[2][1] * y + m.coeff[2][2];
+               
+               u = floor(du/dw);
+               v = floor(dv/dw);
+
+               /* Coordinates in source image */
+              if ( !(u <  u1 || v <  v1 ||
+                     u >= u2 || v >= v2 ))
+                {
+                  sample_lanczos (&surround, du/dw, dv/dw, color, bytes, alpha, kernel);
+                }
+               /*  Set the destination pixel  */
+               for (b = 0; b < bytes; b++)
+                 *d++ = color[b];
+               
+             }
+          /*  set the pixel region row  */
+          pixel_region_set_row (&destPR, 0, (y - y1), width, dest);
+       }
+      pixel_surround_clear (&surround);
+      g_free (kernel);
+      g_free (dest);
+      return new_tiles;
+
+    }
 
   for (y = y1; y < y2; y++)
     {
@@ -460,8 +507,6 @@
                                         color, bytes, alpha);
                           break;
                         case GIMP_INTERPOLATION_LANCZOS:
-                          sample_lanczos (&surround, u[0] - u1, v[0] - v1,
-                                          color, bytes, alpha, kernel);
                           break;
                         }
                     }
@@ -479,7 +524,6 @@
               tw[i] += winc;
             }
         }
-
       /*  set the pixel region row  */
       pixel_region_set_row (&destPR, 0, (y - y1), width, dest);
     }
@@ -491,12 +535,10 @@
     case GIMP_INTERPOLATION_CUBIC:
     case GIMP_INTERPOLATION_LINEAR:
       pixel_surround_clear (&surround);
-      break;
+      break; 
     case GIMP_INTERPOLATION_LANCZOS:
-      pixel_surround_clear (&surround);
-      g_free (kernel);
       break;
-    }
+    } 
 
   g_free (dest);
 
@@ -1683,7 +1725,7 @@
 
 
 /* Lanczos */
-
+/* Lanczos */
 static inline gdouble
 sinc (gdouble x)
 {
@@ -1696,51 +1738,50 @@
 }
 
 static inline gdouble
-lanczos_sum (const guchar *data,
-             gdouble      *l,
-             gint          row,
-             gint          bytes,
-             gint          byte)
+lanczos_sum (guchar         *data,
+             const gdouble  *lu,
+             gint            offset,
+             gint            bytes,
+             gint            byte)
 {
   gdouble sum = 0;
-  gint    j, k;
+  gint    i, k;
 
-  for (k = 0, j = 0; j < LANCZOS_WIDTH2; j++, k += bytes)
-    sum += (l[j] * data[row + k + byte]);
+  for (k = i = 0; i < LANCZOS_WIDTH2 ; i++, k+=bytes)
+    sum += lu[i] * data[ offset + k + byte ];
 
   return sum;
 }
 
 static inline gdouble
-lanczos_sum_mul (const guchar  *data,
-                 const gdouble *l,
-                 gint           row,
-                 gint           bytes,
-                 gint           byte,
-                 gint           alpha)
+lanczos_sum_mul (guchar         *data,
+                 const gdouble  *lu,
+                 gint            offset,
+                 gint            bytes,
+                 gint            byte,
+                 gint            alpha)
 {
   gdouble sum = 0;
-  gint    j, k;
+  gint    i, k;
 
-  for (k = 0, j = 0; j < LANCZOS_WIDTH2; j++, k += bytes)
-    sum += (l[j] *
-            data[row + k + byte] *
-            data[row + k + alpha]);
+  for (k = i = 0; i < LANCZOS_WIDTH2 ; i++, k+=bytes )
+    sum += lu[i] * data[ offset + k + byte ]
+                 * data[ offset + k + alpha];
 
   return sum;
 }
 
+
 static gdouble *
 kernel_lanczos (void)
 {
-  gdouble *kernel ;
-  gdouble  x  = 0.0;
-  gdouble  dx = (gdouble) LANCZOS_WIDTH / (gdouble) (LANCZOS_SAMPLES - 1);
-  gint     i;
+  const gdouble dx = (gdouble) LANCZOS_WIDTH / (gdouble) (LANCZOS_SAMPLES - 1);
 
-  kernel = g_new (gdouble, LANCZOS_SAMPLES);
+  gdouble *kernel = g_new (gdouble, LANCZOS_SAMPLES);
+  gdouble  x      = 0.0;
+  gint     i;
 
-  for (i = 0 ;i < LANCZOS_SAMPLES; i++)
+  for (i = 0; i < LANCZOS_SAMPLES; i++)
     {
       kernel[i] = ((ABS (x) < LANCZOS_WIDTH) ?
                    (sinc (x) * sinc (x / LANCZOS_WIDTH)) : 0.0);
@@ -1750,10 +1791,11 @@
   return kernel;
 }
 
+
 static void
 sample_lanczos (PixelSurround *surround,
-                gdouble        u,
-                gdouble        v,
+                gdouble        du,
+                gdouble        dv,
                 guchar        *color,
                 gint           bytes,
                 gint           alpha,
@@ -1763,38 +1805,44 @@
   gdouble  lu[LANCZOS_WIDTH2];      /* Lanczos sample value              */
   gdouble  lv[LANCZOS_WIDTH2];      /* Lanczos sample value              */
   gdouble  lusum, lvsum, weight;    /* Lanczos weighting vars            */
-  gint           i,j,row, byte;           /* loop vars to fill source window   */
-  gint     du,dv;
+  gint     i,j,byte;                /* loop vars to fill source window   */
+  gint     rowstride;               /* pixel surround rowstride          */
+  gint     offset;                  /* offset for pixel surround data    */
+  gint     su,sv;
   guchar  *data;
 
   gdouble  aval, arecip;            /* Handle alpha values               */
   gdouble  newval;                  /* New interpolated RGB value        */
 
-  gint     iu = floor(u);
-  gint     iv = floor(v);
+  gint     u = floor(du);
+  gint     v = floor(dv);
 
   /* lock the pixel surround */
-  data = pixel_surround_lock (surround,
-                              iu - LANCZOS_WIDTH, iv - LANCZOS_WIDTH);
+  data = pixel_surround_lock (surround, u, v);
 
-  row = pixel_surround_rowstride (surround);
+  rowstride = pixel_surround_rowstride (surround);
 
   /* the fractional error */
-  du = (gint)((u - iu) * LANCZOS_SPP);
-  dv = (gint)((v - iv) * LANCZOS_SPP);
+  su = (gint)((du - u) * LANCZOS_SPP);
+  sv = (gint)((dv - v) * LANCZOS_SPP);
+
+  lusum = lvsum = 0.0;
 
-  for (lusum = lvsum = i = 0, j = LANCZOS_WIDTH - 1;
-       j >= - LANCZOS_WIDTH;
-       j--, i++)
+  for (i = LANCZOS_WIDTH; i >= -LANCZOS_WIDTH; i--)
     {
-        lusum += lu[i] = kernel[ABS (j * LANCZOS_SPP + du)];
-        lvsum += lv[i] = kernel[ABS (j * LANCZOS_SPP + dv)];
+       gint pos = i * LANCZOS_SPP;
+       lusum += lu[LANCZOS_WIDTH + i] = kernel[ABS (su - pos)];
+       lvsum += lv[LANCZOS_WIDTH + i] = kernel[ABS (sv - pos)];
     }
 
-  weight = lusum * lvsum;
+  weight = lvsum*lusum;
+
 
   for ( aval = 0, i = 0 ; i < LANCZOS_WIDTH2 ; i ++ )
-    aval += lv[i] * lanczos_sum (data, lu, i * row, bytes, alpha);
+    {
+      offset = i * rowstride;
+      aval += lv[i] * lanczos_sum (data, lu, offset, bytes, alpha);
+    }
 
   /* calculate alpha of result */
   aval /= weight;
@@ -1818,8 +1866,11 @@
   for (byte = 0; byte < alpha; byte++)
     {
       for (newval = 0, i = 0; i < LANCZOS_WIDTH2; i ++)
-        newval += lv[i] * lanczos_sum_mul (data, lu,
-                                           i * row, bytes, byte, alpha);
+        {
+          offset = i * rowstride;
+          newval += lv[i] * lanczos_sum_mul (data, lu,
+                                             offset, bytes, byte, alpha);
+        }
         newval *= arecip;
         color[byte] = CLAMP (newval, 0, 255);
     }
