Index: gimp/app/core/gimpdrawable-transform.c
===================================================================
RCS file: /cvs/gnome/gimp/app/core/gimpdrawable-transform.c,v
retrieving revision 1.117
diff -u -r1.117 gimpdrawable-transform.c
--- gimp/app/core/gimpdrawable-transform.c	24 Sep 2006 16:45:12 -0000	1.117
+++ gimp/app/core/gimpdrawable-transform.c	12 Oct 2006 23:09:21 -0000
@@ -98,7 +98,6 @@
                                    guchar        *color,
                                    gint           bytes,
                                    gint           alpha);
-static gdouble *create_lanczos_lookup_transform (void);
 
 
 static inline gdouble
@@ -106,18 +105,18 @@
 {
   gdouble y = x * G_PI;
 
-  if (ABS (x) < EPSILON)
+  if (ABS (x) < LANCZOS_MIN)
     return 1.0;
 
   return sin (y) / y;
 }
 
-gdouble *
+gfloat *
 create_lanczos_lookup_transform (void)
 {
-  const gdouble dx = (gdouble) LANCZOS_WIDTH / (gdouble) (LANCZOS_SAMPLES - 1);
+  const gdouble dx = (gdouble) LANCZOS_WIDTH / (gdouble) (LANCZOS_SAMPLES);
 
-  gdouble *lanczos = g_new (gdouble, LANCZOS_SAMPLES);
+  gfloat *lanczos = g_new (gdouble, LANCZOS_SAMPLES);
   gdouble  x      = 0.0;
   gint     i;
 
@@ -320,6 +319,9 @@
       break;
     case GIMP_INTERPOLATION_LANCZOS:
       break;
+    default:
+      g_assert_not_reached ();
+      break;
     }
 
   dest = g_new (guchar, tile_manager_width (new_tiles) * bytes);
@@ -333,19 +335,19 @@
   /* 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 ) 
+  if ( interpolation_type == GIMP_INTERPOLATION_LANCZOS )
     {
-       gdouble *lanczos  = NULL;             /* Lanczos lookup table                */
+       gdouble *lanczos = NULL;              /* Lanczos lookup table                 */
        gdouble  x_kernel[LANCZOS_WIDTH2],    /* 1-D kernels of Lanczos window coeffs */
                 y_kernel[LANCZOS_WIDTH2];
-       gdouble  x_sum, y_sum;                /* sum of Lanczos weights              */
+       gdouble  x_sum, y_sum;                /* sum of Lanczos weights               */
 
        gdouble uw;
        gdouble ww;
        gdouble vw;
        gdouble du;
        gdouble dv;
-     
+
        gint    pos;
        gdouble newval;
        gdouble arecip;
@@ -375,6 +377,7 @@
                dv = vw = m.coeff[1][0] * x + m.coeff[1][1] * y + m.coeff[1][2];
                ww = m.coeff[2][0] * x + m.coeff[2][1] * y + m.coeff[2][2];
 
+
                if (ww == 1.0)
                  {
                    du = uw;
@@ -390,11 +393,14 @@
                    g_warning ("homogeneous coordinate = 0...\n");
                  }
 
+               du += 0.5;
+               dv += 0.5;
+
                u = (gint) du;
                v = (gint) dv;
                /* get weight for fractional error */
-               su = (gint) ((du - u) * LANCZOS_SPP);
-               sv = (gint) ((dv - v) * LANCZOS_SPP);
+               su = (gint) ((du - u) * LANCZOS_SPP + 0.5);
+               sv = (gint) ((dv - v) * LANCZOS_SPP + 0.5);
 
 
                if (u <  u1 || v <  v1 || u >= u2 || v >= v2 )
@@ -531,6 +537,8 @@
                 {
                   g_warning ("homogeneous coordinate = 0...\n");
                 }
+              u[i] += 0.5;  /* correct image offset due to mean int() truncation of 0.5*/
+              v[i] += 0.5;
             }
 
           /*  Set the destination pixels  */
@@ -645,6 +653,8 @@
       break;
     case GIMP_INTERPOLATION_LANCZOS:
       break;
+    default:
+      break;
     }
 
   g_free (dest);
@@ -1714,6 +1724,7 @@
 
 /*  Note: cubic function no longer clips result. */
 /*  Inlining this function makes sample_cubic() run about 10% faster. (Sven) */
+#if 0
 static inline gdouble
 gimp_drawable_transform_cubic (gdouble dx,
                                gint    jm1,
@@ -1723,7 +1734,6 @@
 {
   gdouble result;
 
-#if 0
   /* Equivalent to Gimp 1.1.1 and earlier - some ringing */
   result = ((( ( - jm1 + j - jp1 + jp2 ) * dx +
                ( jm1 + jm1 - j - j + jp1 - jp2 ) ) * dx +
@@ -1732,7 +1742,6 @@
   result = ((( ( - 7 * jm1 + 21 * j - 21 * jp1 + 7 * jp2 ) * dx +
                ( 15 * jm1 - 36 * j + 27 * jp1 - 6 * jp2 ) ) * dx +
                ( - 9 * jm1 + 9 * jp1 ) ) * dx + (jm1 + 16 * j + jp1) ) / 18.0;
-#endif
 
   /* Catmull-Rom - not bad */
   result = ((( ( - jm1 + 3 * j - 3 * jp1 + jp2 ) * dx +
@@ -1741,12 +1750,34 @@
 
   return result;
 }
+#endif
+
+static inline gdouble
+gimp_drawable_transform_cubic (gdouble dx,
+                      gint    pt0,
+                      gint    pt1,
+                      gint    pt2,
+                      gint    pt3)
+{
+  /* Catmull-Rom spline
+   * basic intro http://www.mvps.org/directx/articles/catmull/
+   * This formula will calculate an interpolated point between pt1 and pt2
+   * dx=0 returns pt1; dx=1 returns pt2
+   */
+
+
+  return (gdouble) ((( ( - pt0 + 3 * pt1 - 3 * pt2 + pt3 ) * dx +
+      ( 2 * pt0 - 5 * pt1 + 4 * pt2 - pt3 ) ) * dx +
+      ( - pt0 + pt2 ) ) * dx + (pt1 + pt1) ) / 2.0;
+}
+
+
 
 
   /*  u & v are the subpixel coordinates of the point in
    *  the original selection's floating buffer.
    *  We need the four integer pixel coords around them:
-   *  iu to iu + 3, iv to iv + 3
+   *  iu - 1 to iu + 2, iv - 1 to iv + 2: catmull-rom interps between 2nd and 3rd pt
    */
 static void
 sample_cubic (PixelSurround *surround,
