? patchfile.patch
Index: scale-funcs.c
===================================================================
RCS file: /cvs/gnome/gimp/app/paint-funcs/scale-funcs.c,v
retrieving revision 1.2
diff -u -p -r1.2 scale-funcs.c
--- scale-funcs.c	15 Jan 2005 20:46:21 -0000	1.2
+++ scale-funcs.c	19 Jan 2005 11:49:33 -0000
@@ -790,6 +790,28 @@ subsample_region (PixelRegion *srcPR,
 
 
 /* Lanczos */
+static inline void 
+mirror_edge(guchar  *row,
+            gint     width,
+            gint     bytes)
+{
+  gint    i, k;
+
+  guchar *ptr; 
+  ptr = row - LANCZOS_WIDTH * bytes;
+  for ( i = LANCZOS_WIDTH ; i > 0 ; i-- )
+    {
+      for ( k = 0 ; k < bytes ; k++ , ptr++ )
+        *ptr = row[i*bytes+k];
+    }
+
+  ptr   = row + width*bytes;
+  for ( i = 1 ; i <= LANCZOS_WIDTH ; i++ )
+    {
+      for ( k = 0 ; k < bytes ; k++, ptr++ )
+        *ptr = *(ptr-(i*bytes));
+    }
+}
 
 static inline gdouble
 sinc (gdouble x)
@@ -811,8 +833,9 @@ lanczos_sum (guchar        **src,
              gint            byte)
 {
   gdouble sum = 0;
-  gint    j, k;
-
+  gint    k;
+  guchar *ptr; 
+  ptr = src[row] - LANCZOS_WIDTH * bytes;
   /* LANCZOS_WIDTH = 2
      l[*] = kernel coefficients
 
@@ -823,9 +846,8 @@ lanczos_sum (guchar        **src,
 
      sum = d.l[0] +e.l[1] + f.l[2] + g.l[3]
   */
-
-  for (k = 0, j = col - LANCZOS_WIDTH + 1; j <= col + LANCZOS_WIDTH; j++, k++)
-    sum += l[k] * src[row][j * bytes + byte];
+  for (k = 0 ; k < LANCZOS_WIDTH2 ; k++ )
+    sum += l[k] * ptr[(k+col) * bytes + byte ];
 
   return sum;
 }
@@ -840,10 +862,11 @@ lanczos_sum_mul (guchar        **src,
                  gint            alpha)
 {
   gdouble sum = 0;
-  gint    j, k;
-
-  for (k = 0, j = col - LANCZOS_WIDTH + 1; j <= col + LANCZOS_WIDTH; j++, k++)
-    sum += l[k] * src[row][j * bytes + byte] * src[row][j * bytes + alpha];
+  gint    k;
+  guchar *ptr; 
+  ptr = src[row] - LANCZOS_WIDTH * bytes;
+  for (k = 0 ; k < LANCZOS_WIDTH2; k++)
+    sum += l[k] * ptr[(k+col) * bytes + byte] * ptr[(k+col) * bytes + alpha];
 
   return sum;
 }
@@ -906,18 +929,15 @@ scale_region_lanczos (PixelRegion *srcPR
   gint         srcrow;                  /* counter for read src rows         */
   guchar      *src_buf=NULL;            /* Holds sliding window buffer       */
   guchar      *src[LANCZOS_WIDTH2];     /* Array for sliding window pointers */
-  guchar      *cur_buf=NULL;            /* Current line in sliding window    */
 
   gint         dst_width, dst_height;   /* Destination width height          */
   gint         dst_rowstride;           /* Destination rowstride             */
   guchar      *dst_buf=NULL;            /* Pointers to image data            */
 
   gdouble      du ,dv;                  /* Pos in source image (double)      */
-  gdouble      fu ,fv;                  /* Pos in source image (fract.  part)*/
   gint         u, v;                    /* Pos in source image (integer part)*/
   gint         x, y;                    /* Position in destination image     */
-
-  gint	       i,j,pos,byte;            /* loop vars to fill source window   */
+  gint	       i, j, byte;              /* loop vars to fill source window   */
 
   gdouble      sx,  sy;                 /* Scalefactor                       */
   gdouble      trans[6],itrans[6];      /* Scale transformations             */
@@ -946,134 +966,144 @@ scale_region_lanczos (PixelRegion *srcPR
   /* Calculate kernel */
   kernel = kernel_lanczos ();
 
-  /* allocate buffer for 2 * LANCZOS_WIDTH2 + 1 temp source rows
-     LANCZOS_WIDTH2   : lines are sliding window buffer
+  /* 
+     allocate buffer for width + 2 * LANCZOS_WIDTH
+     We need 2* LANCZOS_WIDTH lines for sliding window 
+     buffer with edge mirror     
   */
-  src_rowstride = src_width * bytes;
+  src_rowstride = (src_width+LANCZOS_WIDTH2) * bytes;
   src_buf = g_new0 (guchar, LANCZOS_WIDTH2 * src_rowstride);
 
+  /* 
+     fill src pointers with correct offset 
+     offset is needed for pixel_region_get_row
+  */
   for (i = 0; i < LANCZOS_WIDTH2; i++)
-    src[i]=src_buf + i * src_rowstride;
+    src[i]=src_buf + i * src_rowstride + LANCZOS_WIDTH * bytes;
 
   /* allocate buffer for 1 destination row */
   dst_rowstride = dst_width * bytes;
   dst_buf = g_new0 (guchar, dst_rowstride);
-
-  for ( srcrow = -1, y = 0 ; y < dst_height ; y ++ )
+  
+  /* fill buffer with first lines */
+  for ( i = 0 ; i < LANCZOS_WIDTH2 ; i++ )
+    {
+    	pixel_region_get_row (srcPR, 0, ABS(LANCZOS_WIDTH-i-1),
+                                        src_width, src[i], 1);
+        mirror_edge (src[i], src_width,  bytes);
+    }
+  
+  for ( srcrow = 0, y = 0 ; y < dst_height ; y ++ )
     {
       pixel_region_get_row (dstPR, 0, y, dst_width, dst_buf, 1);
-
       for ( x = 0 ; x < dst_width ; x ++ )
         {
            du = itrans[0] * (gdouble) x + itrans[1] * (gdouble) y + itrans[2];
            dv = itrans[3] * (gdouble) x + itrans[4] * (gdouble) y + itrans[5];
            u = (gint) du;
            v = (gint) dv;
-
+  
            /* make sure we have enough data available */
-           if (srcrow < v + LANCZOS_WIDTH && srcrow < src_height-1 )
+           if (srcrow != v )           
              {
-               for (i = srcrow + 1; i <= v + LANCZOS_WIDTH; i++)
+               if ( v > srcrow )
                  {
-                   /* 2nd row in src buffer becomes first */
-                   rotate_pointers (src, LANCZOS_WIDTH2);
-                   /* Make sure we do not read past the end of image */
-                   srcrow = ( i < src_height ) ? i : src_height - 1;
-                   /* append row at the end src buffer*/
-                   pos = LANCZOS_WIDTH2 - 1;
-                   pixel_region_get_row (srcPR,
-                                         0, srcrow, src_width, src[pos], 1);
+                   for ( ; srcrow < v ; )
+                     {
+                       srcrow++;
+                       row =  srcrow+LANCZOS_WIDTH;
+                       row = ( row < src_height ) ? row : src_height - (row-src_height+1);
+                       rotate_pointers (src, LANCZOS_WIDTH2);               
+                       pixel_region_get_row (srcPR,
+                                             0, row,
+                                             src_width, src[LANCZOS_WIDTH2-1], 1);
+                       mirror_edge (src[LANCZOS_WIDTH2-1], src_width,  bytes);                       
+                     }
                  }
-
-                 /* current src(v) line in sliding window */
-                 cur_buf = src[LANCZOS_WIDTH-1];
+               else
+                 {
+                   for ( ; srcrow > v ; )
+                     {
+                       rotate_pointers (src, LANCZOS_WIDTH2);               
+                       pixel_region_get_row (srcPR,
+                                             0, --srcrow,
+                                             src_width, src[LANCZOS_WIDTH2-1], 1);
+                       mirror_edge (src[LANCZOS_WIDTH2-1], src_width,  bytes);
+                     }
+                 }  
              }
-           /* check edge condition */
-           if ((u < LANCZOS_WIDTH - 1         ) ||
-               (u > src_width - LANCZOS_WIDTH ) ||
-               (v < LANCZOS_WIDTH - 1         ) ||
-               (v > src_height - LANCZOS_WIDTH))
-            {
-              u = CLAMP (u, 0, src_width - 1);
-              v = CLAMP (v, 0, src_height - 1);
-
-	      for ( byte = 0 ; byte < bytes ; byte++ )
-                dst_buf[x * bytes + byte] = cur_buf[u * bytes + byte];
-            }
-          else
-            {
-              /* get weight for fractional error */
-              fu = du - u;
-              su = (gint) (fu * LANCZOS_SPP);
-              fv = dv - v;
-              sv = (gint) (fv * LANCZOS_SPP);
-
-              for (lusum = lvsum = i = 0, j = LANCZOS_WIDTH - 1;
-                   j >= -LANCZOS_WIDTH;
-                   j--, i++)
-                {
-                  lusum += lu[i] = kernel[ABS (j * LANCZOS_SPP + su)];
-                  lvsum += lv[i] = kernel[ABS (j * LANCZOS_SPP + sv)];
-                }
-
-              weight = (lusum * lvsum);
-
-              if (pixel_region_has_alpha (srcPR))
-                {
-                  alpha = bytes - 1;
-
-                  for (aval = 0, row = 0; row < LANCZOS_WIDTH2; row++)
-                    aval += lv[row] * lanczos_sum (src, lu,
-                                                   row, u, bytes, alpha);
-
-                  /* calculate alpha of result */
-                  aval /= weight;
-
-                  if (aval <= 0.0)
-                    {
-                      arecip = 0.0;
-                      dst_buf[x * bytes + alpha] = 0;
-                    }
-                  else if (aval > 255.0)
-                    {
-                      arecip = 1.0 / aval;
-                      dst_buf[x * bytes + alpha] = 255;
-                    }
-                  else
-                    {
-                      arecip = 1.0 / aval;
-                      dst_buf[x * bytes + alpha] = RINT (aval);
-                    }
-
-                  for (byte = 0; byte < alpha; byte++)
-                    {
-                      for (newval = 0, row = 0; row < LANCZOS_WIDTH2; row ++)
-                        newval += lv[row] * lanczos_sum_mul (src, lu,
-                                                             row, u, bytes,
-                                                             byte, alpha);
-
-                      newval *= arecip;
-                      dst_buf[x * bytes + byte] = CLAMP (newval, 0, 255);
-                    }
-                }
-              else
-                {
-                  for (byte = 0; byte < bytes; byte++)
-                    {
-                      for (newval = 0, row = 0 ; row < LANCZOS_WIDTH2 ; row++ )
-                        newval += lv[row] * lanczos_sum (src, lu,
-                                                         row, u, bytes, byte);
-                      newval /= weight;
-                      dst_buf[x * bytes + byte] = CLAMP ((gint)newval, 0, 255);
-                    }
-                }
-            }
-        }
+
+	   /* get weight for fractional error */
+	   su = (gint) ((du-u) * LANCZOS_SPP);
+	   sv = (gint) ((dv-v) * LANCZOS_SPP);
+
+	   for (lusum = lvsum = i = 0, j = LANCZOS_WIDTH - 1;
+		j >= -LANCZOS_WIDTH;
+		j--, i++)
+	     {
+	       lusum += lu[i] = kernel[ABS (j * LANCZOS_SPP + su)];
+	       lvsum += lv[i] = kernel[ABS (j * LANCZOS_SPP + sv)];
+	     }
+
+	   weight = (lusum * lvsum);
+
+	   if (pixel_region_has_alpha (srcPR))
+	     {
+	       alpha = bytes - 1;
+
+	       for (aval = 0, row = 0; row < LANCZOS_WIDTH2; row++)
+		 aval += lv[row] * lanczos_sum (src, lu,
+						row, u, bytes, alpha);
+
+	       /* calculate alpha of result */
+	       aval /= weight;
+
+	       if (aval <= 0.0)
+		 {
+		   arecip = 0.0;
+		   dst_buf[x * bytes + alpha] = 0;
+		 }
+	       else if (aval > 255.0)
+		 {
+		   arecip = 1.0 / aval;
+		   dst_buf[x * bytes + alpha] = 255;
+		 }
+	       else
+		 {
+		   arecip = 1.0 / aval;
+		   dst_buf[x * bytes + alpha] = RINT (aval);
+		 }
+
+	       for (byte = 0; byte < alpha; byte++)
+		 {
+		   for (newval = 0, row = 0; row < LANCZOS_WIDTH2; row ++)
+		     newval += lv[row] * lanczos_sum_mul (src, lu,
+							  row, u, bytes,
+							  byte, alpha);
+
+		   newval *= arecip;
+		   dst_buf[x * bytes + byte] = CLAMP (newval, 0, 255);
+		 }
+	     }
+	   else
+	     {
+	       for (byte = 0; byte < bytes; byte++)
+		 {
+		   for (newval = 0, row = 0 ; row < LANCZOS_WIDTH2 ; row++ )
+		     newval += lv[row] * lanczos_sum (src, lu,
+						      row, u, bytes, byte);
+		   newval /= weight;
+		   dst_buf[x * bytes + byte] = CLAMP ((gint)newval, 0, 255);
+		 }
+	     }
+	}
 
       pixel_region_set_row (dstPR, 0, y , dst_width, dst_buf);
+      
     }
 
   g_free (src_buf);
   g_free (dst_buf);
   g_free (kernel);
 }
+
Index: scale-funcs.h
===================================================================
RCS file: /cvs/gnome/gimp/app/paint-funcs/scale-funcs.h,v
retrieving revision 1.1
diff -u -p -r1.1 scale-funcs.h
--- scale-funcs.h	11 Jan 2005 18:31:07 -0000	1.1
+++ scale-funcs.h	19 Jan 2005 11:49:33 -0000
@@ -22,7 +22,7 @@
 
 #define EPSILON          (0.0001)
 #define LANCZOS_SPP      (1000)
-#define LANCZOS_WIDTH    (2)
+#define LANCZOS_WIDTH    (4)
 #define LANCZOS_SAMPLES  (1 + (LANCZOS_SPP * LANCZOS_WIDTH))
 #define LANCZOS_WIDTH2   (LANCZOS_WIDTH * 2)
 
@@ -35,3 +35,4 @@ void  scale_region (PixelRegion         
 
 
 #endif  /*  __SCALE_FUNCS_H__  */
+
