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
This commit is contained in:
Massimo Valentini
2013-06-01 17:07:24 +02:00
parent dd8aeeec92
commit ba98aedcb1
2 changed files with 27 additions and 16 deletions

View File

@ -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 &&

View File

@ -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;
const gdouble (*c)[3] = matrix->coeff;
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;
}
}
#define approximately(a, b) (fabs ((a) - (b)) < EPSILON)
#define integer(a) (approximately (a, RINT (a)))
return TRUE;
/* 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]))));
}
/**