diff -u -p -r paint-funcs.orig/scale-funcs.c paint-funcs/scale-funcs.c
--- paint-funcs.orig/scale-funcs.c	Fri Jun  8 14:21:03 2007
+++ paint-funcs/scale-funcs.c	Fri Jun  8 14:44:47 2007
@@ -377,6 +377,19 @@ rotate_pointers (guchar  **p,
   p[i] = tmp;
 }
 
+static inline void
+rotate_pointers_r(guchar **p,
+                  guint32  n)
+{
+    guchar *tmp = p[n-1];
+    guint32 i;
+
+    for (i = n-1; i > 0; i--)
+        p[i] = p[i-1];
+
+    p[0] = tmp;
+}
+
 static void
 get_scaled_row (gdouble              **src,
                 gint                   y,
@@ -845,13 +858,14 @@ lanczos_sum (guchar         *ptr,
              const gdouble  *kernel,  /* 1-D kernel of transform coeffs */
              gint            u,
              gint            bytes,
-             gint            byte)
+             gint            byte,
+             gint            hlw)     /* Horizontal lanczos sampling width */
 {
   gdouble sum = 0;
   gint    i;
 
-  for (i = 0; i < LANCZOS_WIDTH2 ; i++)
-    sum += kernel[i] * ptr[ (u + i - LANCZOS_WIDTH) * bytes + byte ];
+  for (i = 0; i < LANCZOS_WIDTH2_F(hlw); i++)
+    sum += kernel[i] * ptr[ (u + i - hlw) * bytes + byte ];
 
   return sum;
 }
@@ -862,14 +876,15 @@ lanczos_sum_mul (guchar         *ptr,
                  gint            u,
                  gint            bytes,
                  gint            byte,
-                 gint            alpha)
+                 gint            alpha,
+                 gint            hlw)    /* Horizontal lanczos sampling width */
 {
   gdouble sum = 0;
   gint    i;
 
-  for (i = 0; i < LANCZOS_WIDTH2 ; i++ )
-    sum += kernel[i] * ptr[ (u + i - LANCZOS_WIDTH) * bytes + byte ]
-                 * ptr[ (u + i - LANCZOS_WIDTH) * bytes + alpha];
+  for (i = 0; i < LANCZOS_WIDTH2_F(hlw) ; i++ )
+    sum += kernel[i] * ptr[ (u + i - hlw) * bytes + byte ]
+      * ptr[ (u + i - hlw) * bytes + alpha];
 
   return sum;
 }
@@ -901,7 +916,7 @@ inv_lin_trans (const gdouble *t,
 gfloat *
 create_lanczos_lookup (void)
 {
-  const gdouble dx = LANCZOS_WIDTH / (gdouble) (LANCZOS_SAMPLES - 1);
+  const gdouble dx = LANCZOS_WIDTH / (gdouble) (LANCZOS_SAMPLES2 - 1);
 
   gfloat  *lookup = g_new (gfloat, LANCZOS_SAMPLES);
   gdouble  x      = 0.0;
@@ -924,14 +939,15 @@ scale_region_lanczos (PixelRegion      *
                       gpointer          progress_data)
 
 {
-  gfloat        *kernel_lookup  = NULL;             /* Lanczos lookup table                */
-  gdouble        x_kernel[LANCZOS_WIDTH2],    /* 1-D kernels of Lanczos window coeffs */
-                 y_kernel[LANCZOS_WIDTH2];
+  gfloat        *kernel_lookup = NULL;        /* Lanczos lookup table */
+
+  gdouble        *x_kernel = NULL,    /* 1-D kernels of Lanczos window coeffs */
+                 *y_kernel = NULL;
 
   gdouble        newval;                      /* new interpolated RGB value          */
 
   guchar        *win_buf = NULL;              /* Sliding window buffer               */
-  guchar        *win_ptr[LANCZOS_WIDTH2];     /* Ponters to sliding window rows      */
+  guchar        **win_ptr = NULL;     /* Ponters to sliding window rows      */
 
   guchar        *dst_buf = NULL;              /* Pointer to destination image data   */
 
@@ -949,11 +965,22 @@ scale_region_lanczos (PixelRegion      *
 
   const gint     src_row_span  = src_width * bytes;
   const gint     dst_row_span  = dst_width * bytes;
-  const gint     win_row_span  = (src_width + LANCZOS_WIDTH2) * bytes;
 
   const gdouble  scale_x       = dst_width / (gdouble) src_width;
   const gdouble  scale_y       = dst_height / (gdouble) src_height;
 
+  const gint     x_lanczos_width = src_width<=dst_width ?
+                    LANCZOS_WIDTH :
+                    (gint)(LANCZOS_WIDTH*src_width/dst_width),
+                 y_lanczos_width = src_height<=dst_height ?
+                    LANCZOS_WIDTH :
+                    (gint)(LANCZOS_WIDTH*src_height/dst_height);
+
+  const gint    x_lanczos_width2 = LANCZOS_WIDTH2_F(x_lanczos_width),
+                y_lanczos_width2 = LANCZOS_WIDTH2_F(y_lanczos_width);
+
+
+
   for (i = 0; i < 6; i++)
     trans[i] = 0.0;
 
@@ -966,6 +993,13 @@ scale_region_lanczos (PixelRegion      *
       return;
     }
 
+
+
+  x_kernel = g_new0(gdouble, x_lanczos_width2);
+  y_kernel = g_new0(gdouble, y_lanczos_width2);
+
+  win_ptr = g_new0(guchar*, y_lanczos_width2);
+
   /* allocate buffer for destination row */
   dst_buf = g_new0 (guchar, dst_row_span);
 
@@ -984,16 +1018,20 @@ scale_region_lanczos (PixelRegion      *
   /* allocate and fill kernel_lookup lookup table */
   kernel_lookup = create_lanczos_lookup ();
 
-  /* allocate buffer for source rows */
-  win_buf = g_new0 (guchar, win_row_span * LANCZOS_WIDTH2);
+    {
+      const gint    win_row_span = (src_width + x_lanczos_width2) * bytes;
+
+      /* allocate buffer for source rows */
+      win_buf = g_new0(guchar, win_row_span * y_lanczos_width2);
 
-  /* Set the window pointers */
-  for ( i = 0 ; i < LANCZOS_WIDTH2 ; i++ )
-    win_ptr[i] = win_buf + (win_row_span * i) + LANCZOS_WIDTH * bytes;
+      /* Set the window pointers */
+      for ( i = 0 ; i < y_lanczos_width2 ; i++ )
+        win_ptr[i] = win_buf + (win_row_span * i) + x_lanczos_width * bytes;
+    }
 
   /* fill the data for the first loop */
-  for ( i = 0 ; i <= LANCZOS_WIDTH && i < src_height ; i++)
-    pixel_region_get_row (srcPR, 0, i, src_width, win_ptr[i + LANCZOS_WIDTH], 1);
+  for ( i = 0 ; i <= y_lanczos_width && i < src_height ; i++)
+    pixel_region_get_row (srcPR, 0, i, src_width, win_ptr[i + y_lanczos_width], 1);
 
   for (row = y = 0; y < dst_height; y++)
     {
@@ -1043,27 +1081,34 @@ scale_region_lanczos (PixelRegion      *
            */
           kx_sum = ky_sum = 0.0;
 
-          for (i = LANCZOS_WIDTH; i >= -LANCZOS_WIDTH; i--)
+          for (i = x_lanczos_width; i >= -x_lanczos_width; i--)
             {
-              gint pos = i * LANCZOS_SPP;
+              gint pos = i * LANCZOS_SPP * LANCZOS_WIDTH/x_lanczos_width;
 
               if ( int_src_x + i >= 0 && int_src_x + i < src_width)
-                kx_sum += x_kernel[LANCZOS_WIDTH + i] = kernel_lookup[ABS (x_shift - pos)];
+                kx_sum += x_kernel[x_lanczos_width + i] 
+                  = kernel_lookup[ABS (x_shift - pos)];
               else
-                x_kernel[LANCZOS_WIDTH + i] = 0.0;
+                x_kernel[x_lanczos_width + i] = 0.0;
+            }
+
+          for(i = y_lanczos_width; i >= -y_lanczos_width; i--)
+            {
+              gint pos = i * LANCZOS_SPP * LANCZOS_WIDTH/y_lanczos_width;
 
               if ( int_src_y + i >= 0 && int_src_y + i < src_height)
-                ky_sum += y_kernel[LANCZOS_WIDTH + i] = kernel_lookup[ABS (y_shift - pos)];
+                ky_sum += y_kernel[y_lanczos_width + i] 
+                  = kernel_lookup[ABS (y_shift - pos)];
               else
-                y_kernel[LANCZOS_WIDTH + i] = 0.0;
+                y_kernel[y_lanczos_width + i] = 0.0;
             }
 
           /* normalise the kernel arrays */
-          for (i = -LANCZOS_WIDTH; i <= LANCZOS_WIDTH; i++)
-          {
-             x_kernel[LANCZOS_WIDTH + i] /= kx_sum;
-             y_kernel[LANCZOS_WIDTH + i] /= ky_sum;
-          }
+          for (i = -x_lanczos_width; i <= x_lanczos_width; i++)
+            x_kernel[x_lanczos_width + i] /= kx_sum;
+
+          for (i = -y_lanczos_width; i<= y_lanczos_width; i++)
+            y_kernel[y_lanczos_width + i] /= ky_sum;
 
           /*
             Scaling up
@@ -1075,23 +1120,22 @@ scale_region_lanczos (PixelRegion      *
           for ( ; row < int_src_y ; )
             {
               row++;
-              rotate_pointers (win_ptr, LANCZOS_WIDTH2);
-              if ( row + LANCZOS_WIDTH < src_height)
+              rotate_pointers (win_ptr, y_lanczos_width2);
+              if ( row + y_lanczos_width < src_height)
                 pixel_region_get_row (srcPR, 0,
-                                      row + LANCZOS_WIDTH, src_width,
-                                      win_ptr[LANCZOS_WIDTH2 - 1], 1);
+                                      row + y_lanczos_width, src_width,
+                                      win_ptr[y_lanczos_width2 - 1], 1);
               else
-                memset (win_ptr[LANCZOS_WIDTH2 - 1], 0,
+                memset (win_ptr[y_lanczos_width2 - 1], 0,
                         sizeof (guchar) * src_row_span);
             }
            /*
               Scaling down
             */
-            for ( ; row > int_src_y ; )
+          for ( ; row > int_src_y ; )
             {
               row--;
-              for ( i = 0 ; i < LANCZOS_WIDTH2 - 1 ; i++ )
-                 rotate_pointers (win_ptr, LANCZOS_WIDTH2);
+              rotate_pointers_r(win_ptr, y_lanczos_width2);
               if ( row >=  0)
                 pixel_region_get_row (srcPR, 0,
                                       row, src_width,
@@ -1111,9 +1155,10 @@ scale_region_lanczos (PixelRegion      *
                gdouble    aval;
 
                aval = 0.0;
-               for (i = 0; i < LANCZOS_WIDTH2 ; i++ )
+               for (i = 0; i < y_lanczos_width2 ; i++ )
                  aval += y_kernel[i] * lanczos_sum (win_ptr[i], x_kernel,
-                         int_src_x, bytes, alpha);
+                                                    int_src_x, bytes, alpha,
+                                                    x_lanczos_width);
 
                if (aval <= 0.0)
                  {
@@ -1134,9 +1179,10 @@ scale_region_lanczos (PixelRegion      *
                for (byte = 0; byte < alpha; byte++)
                  {
                    newval = 0.0;
-                   for (i = 0; i < LANCZOS_WIDTH2; i++ )
+                   for (i = 0; i < y_lanczos_width2; i++ )
                      newval += y_kernel[i] * lanczos_sum_mul (win_ptr[i], x_kernel,
-                               int_src_x, bytes, byte, alpha);
+                                                              int_src_x, bytes, byte, alpha,
+                                                              x_lanczos_width);
                    newval *= arecip;
                    dst_buf[x * bytes + byte] = CLAMP (newval, 0, 255);
                  }
@@ -1147,9 +1193,10 @@ scale_region_lanczos (PixelRegion      *
                  {
                    /* Calculate new value */
                    newval = 0.0;
-                   for (i = 0; i < LANCZOS_WIDTH2; i++ )
+                   for (i = 0; i < y_lanczos_width2; i++ )
                      newval += y_kernel[i] * lanczos_sum (win_ptr[i], x_kernel,
-                               int_src_x, bytes, byte);
+                                                          int_src_x, bytes, byte,
+                                                          x_lanczos_width);
                    dst_buf[x * bytes + byte] = CLAMP ((gint) newval, 0, 255);
                  }
              }
@@ -1161,4 +1208,7 @@ scale_region_lanczos (PixelRegion      *
   g_free (dst_buf);
   g_free (win_buf);
   g_free (kernel_lookup);
+  g_free (x_kernel);
+  g_free (y_kernel);
+  g_free (win_ptr);
 }
diff -u -p -r paint-funcs.orig/scale-funcs.h paint-funcs/scale-funcs.h
--- paint-funcs.orig/scale-funcs.h	Fri Jun  8 14:21:03 2007
+++ paint-funcs/scale-funcs.h	Fri Jun  8 14:18:59 2007
@@ -24,7 +24,9 @@
 #define LANCZOS_MIN      (1.0/LANCZOS_SPP)
 #define LANCZOS_WIDTH    (3)                    /* 3 for Lanczos3 code, for L4 prefer DUAL_LANCZOS below */
 #define LANCZOS_WIDTH2   (1 + (LANCZOS_WIDTH * 2))
+#define LANCZOS_WIDTH2_F(w) (1 + ((w) * 2)) 
 #define LANCZOS_SAMPLES  (LANCZOS_SPP * (LANCZOS_WIDTH + 1))
+#define LANCZOS_SAMPLES2 (LANCZOS_SPP * (LANCZOS_WIDTH))
 
 
 void     scale_region          (PixelRegion           *srcPR,
