[gimp/gimp-2-8] Bug 680290: -90 degree rotation distortion of layer



commit ba98aedcb1f03b7307e22b20487d5cc9e7665f54
Author: Massimo Valentini <mvalentini src gnome org>
Date:   Sat Jun 1 17:07:24 2013 +0200

    Bug 680290: -90 degree rotation distortion of layer
    
    The previous code did not consider that a transformation
    described by a matrix with non integer values in the 3rd
    column or by a non affine matrix requires interpolation
    
    and make floating point arithmetic rounding errors
    consistent with INTERPOLATION_NONE

 app/core/gimp-transform-region.c |    9 +++++++--
 libgimpmath/gimpmatrix.c         |   38 ++++++++++++++++++++++----------------
 2 files changed, 29 insertions(+), 18 deletions(-)
---
diff --git a/app/core/gimp-transform-region.c b/app/core/gimp-transform-region.c
index 87714c8..c289174 100644
--- a/app/core/gimp-transform-region.c
+++ b/app/core/gimp-transform-region.c
@@ -331,8 +331,13 @@ gimp_transform_region_nearest (TileManager        *orig_tiles,
               /*  normalize homogeneous coords  */
               normalize_coords (1, &tu, &tv, &tw, &u, &v);
 
-              iu = RINT (u);
-              iv = RINT (v);
+              /* EPSILON here is useful to make floating point arithmetic
+               * rounding errors consistent when the exact computation
+               * results in a 'integer and a half'
+               */
+#define EPSILON 1.e-5
+              iu = floor (u + 0.5 + EPSILON);
+              iv = floor (v + 0.5 + EPSILON);
 
               /*  Set the destination pixels  */
               if (iu >= u1 && iu < u2 &&
diff --git a/libgimpmath/gimpmatrix.c b/libgimpmath/gimpmatrix.c
index 594cdd3..599c8bc 100644
--- a/libgimpmath/gimpmatrix.c
+++ b/libgimpmath/gimpmatrix.c
@@ -843,26 +843,32 @@ gimp_matrix3_is_affine (const GimpMatrix3 *matrix)
  * Checks if we'll need to interpolate when applying this matrix as
  * a transformation.
  *
- * Returns: %TRUE if all entries of the upper left 2x2 matrix are
- *          either 0 or 1, %FALSE otherwise
+ * Returns: %TRUE if the matrix is simple, %FALSE otherwise
  */
 gboolean
 gimp_matrix3_is_simple (const GimpMatrix3 *matrix)
 {
-  gdouble absm;
-  gint    i, j;
-
-  for (i = 0; i < 2; i++)
-    {
-      for (j = 0; j < 2; j++)
-        {
-          absm = fabs (matrix->coeff[i][j]);
-          if (absm > EPSILON && fabs (absm - 1.0) > EPSILON)
-            return FALSE;
-        }
-    }
-
-  return TRUE;
+  const gdouble (*c)[3] = matrix->coeff;
+
+#define approximately(a, b) (fabs ((a) - (b)) < EPSILON)
+#define integer(a) (approximately (a, RINT (a)))
+
+  /* 3rd row like identity matrix (perspective requires interpolation) */
+  return approximately (0.0,       c[2][0] ) &&
+         approximately (0.0,       c[2][1] ) &&
+         approximately (1.0, fabs (c[2][2])) &&
+         /* 3rd column integer (subpixel translation requires interpolation)*/
+         integer (c[0][2]) &&
+         integer (c[1][2]) &&
+         /* upper left 2x2 matrix [ 0, +-1; +-1, 0] or [+-1, 0; 0, +-1] */
+         ((approximately (0.0,       c[0][0] ) &&
+           approximately (1.0, fabs (c[0][1])) &&
+           approximately (1.0, fabs (c[1][0])) &&
+           approximately (0.0,       c[1][1] )) ||
+          (approximately (1.0, fabs (c[0][0])) &&
+           approximately (0.0,       c[0][1] ) &&
+           approximately (0.0,       c[1][0] ) &&
+           approximately (1.0, fabs (c[1][1]))));
 }
 
 /**


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]