diff --git a/ChangeLog b/ChangeLog index a8b146734a..4c5951548e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2002-02-19 Michael Natterer + + Fixed #10466 (disappearing pixels when rotating by 90 deg): + + * app/core/gimpdrawable-transform.c: when transforming backwards + to find the destination line's sub-pixel source coordinates, we + need to transform the pixels _center_, not it's upper left corner. + + * app/core/gimpdrawable-transform-utils.[ch]: added + gimp_drawable_transform_matrix_rotate_center() which takes double + center coordinates instead of an integer pixel bounding box. + + * app/tools/gimptransformtool.[ch]: use double instead of int for + all coordinates except the original bounding box. + + * app/tools/gimprotatetool.c: use double whenever touching the + "center" value, so it can be sub-pixel positioned. + 2002-02-19 Sven Neumann * plug-ins/pagecurl/pagecurl.c: code cleanup based on a patch from diff --git a/app/core/gimp-transform-region.c b/app/core/gimp-transform-region.c index 1348b47f0f..a20d48536d 100644 --- a/app/core/gimp-transform-region.c +++ b/app/core/gimp-transform-region.c @@ -207,19 +207,17 @@ gimp_drawable_transform_tiles_affine (GimpDrawable *drawable, gimp_matrix3_transform_point (matrix, x1, y2, &dx3, &dy3); gimp_matrix3_transform_point (matrix, x2, y2, &dx4, &dy4); - tx1 = MIN (dx1, dx2); - tx1 = MIN (tx1, dx3); - tx1 = MIN (tx1, dx4); - ty1 = MIN (dy1, dy2); - ty1 = MIN (ty1, dy3); - ty1 = MIN (ty1, dy4); +#define MIN4(a,b,c,d) MIN(MIN(MIN(a,b),c),d) +#define MAX4(a,b,c,d) MAX(MAX(MAX(a,b),c),d) - tx2 = MAX (dx1, dx2); - tx2 = MAX (tx2, dx3); - tx2 = MAX (tx2, dx4); - ty2 = MAX (dy1, dy2); - ty2 = MAX (ty2, dy3); - ty2 = MAX (ty2, dy4); + tx1 = ROUND (MIN4 (dx1, dx2, dx3, dx4)); + ty1 = ROUND (MIN4 (dy1, dy2, dy3, dy4)); + + tx2 = ROUND (MAX4 (dx1, dx2, dx3, dx4)); + ty2 = ROUND (MAX4 (dy1, dy2, dy3, dy4)); + +#undef MIN2 +#undef MAX4 } /* Get the new temporary buffer for the transformed result */ @@ -265,11 +263,12 @@ gimp_drawable_transform_tiles_affine (GimpDrawable *drawable, (* progress_callback) (ty1, ty2, y, progress_data); /* set up inverse transform steps */ - tx = xinc * tx1 + m[0][1] * y + m[0][2]; - ty = yinc * tx1 + m[1][1] * y + m[1][2]; - tw = winc * tx1 + m[2][1] * y + m[2][2]; + tx = xinc * (tx1 + 0.5) + m[0][1] * (y + 0.5) + m[0][2]; + ty = yinc * (tx1 + 0.5) + m[1][1] * (y + 0.5) + m[1][2]; + tw = winc * (tx1 + 0.5) + m[2][1] * (y + 0.5) + m[2][2]; d = dest; + for (x = tx1; x < tx2; x++) { /* normalize homogeneous coords */ @@ -480,7 +479,7 @@ gimp_drawable_transform_tiles_affine (GimpDrawable *drawable, ity = floor (tty); if (itx >= x1 && itx < x2 && - ity >= y1 && ity < y2 ) + ity >= y1 && ity < y2) { /* x, y coordinates into source tiles */ sx = itx - x1; diff --git a/app/core/gimp-transform-utils.c b/app/core/gimp-transform-utils.c index 99d3cab543..a38098c1a8 100644 --- a/app/core/gimp-transform-utils.c +++ b/app/core/gimp-transform-utils.c @@ -47,6 +47,18 @@ gimp_drawable_transform_matrix_rotate (gint x1, gimp_matrix3_translate (result, +cx, +cy); } +void +gimp_drawable_transform_matrix_rotate_center (gdouble cx, + gdouble cy, + gdouble angle, + GimpMatrix3 result) +{ + gimp_matrix3_identity (result); + gimp_matrix3_translate (result, -cx, -cy); + gimp_matrix3_rotate (result, angle); + gimp_matrix3_translate (result, +cx, +cy); +} + void gimp_drawable_transform_matrix_scale (gint x1, gint y1, diff --git a/app/core/gimp-transform-utils.h b/app/core/gimp-transform-utils.h index c7163fdb8b..d82c43477d 100644 --- a/app/core/gimp-transform-utils.h +++ b/app/core/gimp-transform-utils.h @@ -20,41 +20,45 @@ #define __GIMP_DRAWABLE_TRANSFORM_UTILS_H__ -void gimp_drawable_transform_matrix_rotate (gint x1, - gint y1, - gint x2, - gint y2, - gdouble angle, - GimpMatrix3 result); -void gimp_drawable_transform_matrix_scale (gint x1, - gint y1, - gint x2, - gint y2, - gdouble tx1, - gdouble ty1, - gdouble tx2, - gdouble ty2, - GimpMatrix3 result); -void gimp_drawable_transform_matrix_shear (gint x1, - gint y1, - gint x2, - gint y2, - InternalOrientationType orientation, - gdouble amount, - GimpMatrix3 result); -void gimp_drawable_transform_matrix_perspective (gint x1, - gint y1, - gint x2, - gint y2, - gdouble tx1, - gdouble ty1, - gdouble tx2, - gdouble ty2, - gdouble tx3, - gdouble ty3, - gdouble tx4, - gdouble ty5, - GimpMatrix3 result); +void gimp_drawable_transform_matrix_rotate (gint x1, + gint y1, + gint x2, + gint y2, + gdouble angle, + GimpMatrix3 result); +void gimp_drawable_transform_matrix_rotate_center (gdouble cx, + gdouble cy, + gdouble angle, + GimpMatrix3 result); +void gimp_drawable_transform_matrix_scale (gint x1, + gint y1, + gint x2, + gint y2, + gdouble tx1, + gdouble ty1, + gdouble tx2, + gdouble ty2, + GimpMatrix3 result); +void gimp_drawable_transform_matrix_shear (gint x1, + gint y1, + gint x2, + gint y2, + InternalOrientationType orientation, + gdouble amount, + GimpMatrix3 result); +void gimp_drawable_transform_matrix_perspective (gint x1, + gint y1, + gint x2, + gint y2, + gdouble tx1, + gdouble ty1, + gdouble tx2, + gdouble ty2, + gdouble tx3, + gdouble ty3, + gdouble tx4, + gdouble ty5, + GimpMatrix3 result); #endif /* __GIMP_DRAWABLE_TRANSFORM_SHEAR_H__ */ diff --git a/app/core/gimpdrawable-transform-utils.c b/app/core/gimpdrawable-transform-utils.c index 99d3cab543..a38098c1a8 100644 --- a/app/core/gimpdrawable-transform-utils.c +++ b/app/core/gimpdrawable-transform-utils.c @@ -47,6 +47,18 @@ gimp_drawable_transform_matrix_rotate (gint x1, gimp_matrix3_translate (result, +cx, +cy); } +void +gimp_drawable_transform_matrix_rotate_center (gdouble cx, + gdouble cy, + gdouble angle, + GimpMatrix3 result) +{ + gimp_matrix3_identity (result); + gimp_matrix3_translate (result, -cx, -cy); + gimp_matrix3_rotate (result, angle); + gimp_matrix3_translate (result, +cx, +cy); +} + void gimp_drawable_transform_matrix_scale (gint x1, gint y1, diff --git a/app/core/gimpdrawable-transform-utils.h b/app/core/gimpdrawable-transform-utils.h index c7163fdb8b..d82c43477d 100644 --- a/app/core/gimpdrawable-transform-utils.h +++ b/app/core/gimpdrawable-transform-utils.h @@ -20,41 +20,45 @@ #define __GIMP_DRAWABLE_TRANSFORM_UTILS_H__ -void gimp_drawable_transform_matrix_rotate (gint x1, - gint y1, - gint x2, - gint y2, - gdouble angle, - GimpMatrix3 result); -void gimp_drawable_transform_matrix_scale (gint x1, - gint y1, - gint x2, - gint y2, - gdouble tx1, - gdouble ty1, - gdouble tx2, - gdouble ty2, - GimpMatrix3 result); -void gimp_drawable_transform_matrix_shear (gint x1, - gint y1, - gint x2, - gint y2, - InternalOrientationType orientation, - gdouble amount, - GimpMatrix3 result); -void gimp_drawable_transform_matrix_perspective (gint x1, - gint y1, - gint x2, - gint y2, - gdouble tx1, - gdouble ty1, - gdouble tx2, - gdouble ty2, - gdouble tx3, - gdouble ty3, - gdouble tx4, - gdouble ty5, - GimpMatrix3 result); +void gimp_drawable_transform_matrix_rotate (gint x1, + gint y1, + gint x2, + gint y2, + gdouble angle, + GimpMatrix3 result); +void gimp_drawable_transform_matrix_rotate_center (gdouble cx, + gdouble cy, + gdouble angle, + GimpMatrix3 result); +void gimp_drawable_transform_matrix_scale (gint x1, + gint y1, + gint x2, + gint y2, + gdouble tx1, + gdouble ty1, + gdouble tx2, + gdouble ty2, + GimpMatrix3 result); +void gimp_drawable_transform_matrix_shear (gint x1, + gint y1, + gint x2, + gint y2, + InternalOrientationType orientation, + gdouble amount, + GimpMatrix3 result); +void gimp_drawable_transform_matrix_perspective (gint x1, + gint y1, + gint x2, + gint y2, + gdouble tx1, + gdouble ty1, + gdouble tx2, + gdouble ty2, + gdouble tx3, + gdouble ty3, + gdouble tx4, + gdouble ty5, + GimpMatrix3 result); #endif /* __GIMP_DRAWABLE_TRANSFORM_SHEAR_H__ */ diff --git a/app/core/gimpdrawable-transform.c b/app/core/gimpdrawable-transform.c index 1348b47f0f..a20d48536d 100644 --- a/app/core/gimpdrawable-transform.c +++ b/app/core/gimpdrawable-transform.c @@ -207,19 +207,17 @@ gimp_drawable_transform_tiles_affine (GimpDrawable *drawable, gimp_matrix3_transform_point (matrix, x1, y2, &dx3, &dy3); gimp_matrix3_transform_point (matrix, x2, y2, &dx4, &dy4); - tx1 = MIN (dx1, dx2); - tx1 = MIN (tx1, dx3); - tx1 = MIN (tx1, dx4); - ty1 = MIN (dy1, dy2); - ty1 = MIN (ty1, dy3); - ty1 = MIN (ty1, dy4); +#define MIN4(a,b,c,d) MIN(MIN(MIN(a,b),c),d) +#define MAX4(a,b,c,d) MAX(MAX(MAX(a,b),c),d) - tx2 = MAX (dx1, dx2); - tx2 = MAX (tx2, dx3); - tx2 = MAX (tx2, dx4); - ty2 = MAX (dy1, dy2); - ty2 = MAX (ty2, dy3); - ty2 = MAX (ty2, dy4); + tx1 = ROUND (MIN4 (dx1, dx2, dx3, dx4)); + ty1 = ROUND (MIN4 (dy1, dy2, dy3, dy4)); + + tx2 = ROUND (MAX4 (dx1, dx2, dx3, dx4)); + ty2 = ROUND (MAX4 (dy1, dy2, dy3, dy4)); + +#undef MIN2 +#undef MAX4 } /* Get the new temporary buffer for the transformed result */ @@ -265,11 +263,12 @@ gimp_drawable_transform_tiles_affine (GimpDrawable *drawable, (* progress_callback) (ty1, ty2, y, progress_data); /* set up inverse transform steps */ - tx = xinc * tx1 + m[0][1] * y + m[0][2]; - ty = yinc * tx1 + m[1][1] * y + m[1][2]; - tw = winc * tx1 + m[2][1] * y + m[2][2]; + tx = xinc * (tx1 + 0.5) + m[0][1] * (y + 0.5) + m[0][2]; + ty = yinc * (tx1 + 0.5) + m[1][1] * (y + 0.5) + m[1][2]; + tw = winc * (tx1 + 0.5) + m[2][1] * (y + 0.5) + m[2][2]; d = dest; + for (x = tx1; x < tx2; x++) { /* normalize homogeneous coords */ @@ -480,7 +479,7 @@ gimp_drawable_transform_tiles_affine (GimpDrawable *drawable, ity = floor (tty); if (itx >= x1 && itx < x2 && - ity >= y1 && ity < y2 ) + ity >= y1 && ity < y2) { /* x, y coordinates into source tiles */ sx = itx - x1; diff --git a/app/tools/gimprotatetool.c b/app/tools/gimprotatetool.c index 4f4252864c..15a8caba64 100644 --- a/app/tools/gimprotatetool.c +++ b/app/tools/gimprotatetool.c @@ -320,14 +320,14 @@ rotate_center_changed (GtkWidget *widget, { GimpTool *tool; GimpTransformTool *transform_tool; - gint cx; - gint cy; + gdouble cx; + gdouble cy; tool = GIMP_TOOL (data); transform_tool = GIMP_TRANSFORM_TOOL (data); - cx = RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 0)); - cy = RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 1)); + cx = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 0); + cy = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 1); if ((cx != transform_tool->trans_info[CENTER_X]) || (cy != transform_tool->trans_info[CENTER_Y])) @@ -369,7 +369,7 @@ rotate_tool_motion (GimpTransformTool *transform_tool, cx = transform_tool->trans_info[CENTER_X]; cy = transform_tool->trans_info[CENTER_Y]; - x1 = transform_tool->curx - cx; + x1 = transform_tool->curx - cx; x2 = transform_tool->lastx - cx; y1 = cy - transform_tool->cury; y2 = cy - transform_tool->lasty; @@ -422,12 +422,10 @@ rotate_tool_recalc (GimpTransformTool *transform_tool, transform_tool->cx = cx; transform_tool->cy = cy; - gimp_drawable_transform_matrix_rotate (transform_tool->cx, - transform_tool->cy, - transform_tool->cx, - transform_tool->cy, - transform_tool->trans_info[ANGLE], - transform_tool->transform); + gimp_drawable_transform_matrix_rotate_center (transform_tool->cx, + transform_tool->cy, + transform_tool->trans_info[ANGLE], + transform_tool->transform); /* transform the bounding box */ gimp_transform_tool_transform_bounding_box (transform_tool); diff --git a/app/tools/gimptransformtool.c b/app/tools/gimptransformtool.c index 3f09167d50..8b312206e4 100644 --- a/app/tools/gimptransformtool.c +++ b/app/tools/gimptransformtool.c @@ -912,7 +912,6 @@ gimp_transform_tool_bounds (GimpTransformTool *tr_tool, { TileManager *tiles; GimpDrawable *drawable; - gint offset_x, offset_y; tiles = tr_tool->original; drawable = gimp_image_active_drawable (gdisp->gimage); @@ -928,7 +927,10 @@ gimp_transform_tool_bounds (GimpTransformTool *tr_tool, } else { + gint offset_x, offset_y; + gimp_drawable_offsets (drawable, &offset_x, &offset_y); + gimp_drawable_mask_bounds (drawable, &tr_tool->x1, &tr_tool->y1, &tr_tool->x2, &tr_tool->y2); @@ -938,8 +940,8 @@ gimp_transform_tool_bounds (GimpTransformTool *tr_tool, tr_tool->y2 += offset_y; } - tr_tool->cx = (tr_tool->x1 + tr_tool->x2) / 2; - tr_tool->cy = (tr_tool->y1 + tr_tool->y2) / 2; + tr_tool->cx = (gdouble) (tr_tool->x1 + tr_tool->x2) / 2.0; + tr_tool->cy = (gdouble) (tr_tool->y1 + tr_tool->y2) / 2.0; if (tr_tool->use_grid) { @@ -1053,23 +1055,23 @@ gimp_transform_tool_setup_grid (GimpTransformTool *tr_tool, for (i = 1; i <= tr_tool->ngx; i++) { - coords[gci] = tr_tool->x1 + - ((gdouble) i) / (tr_tool->ngx + 1) * - (tr_tool->x2 - tr_tool->x1); - coords[gci+1] = tr_tool->y1; - coords[gci+2] = coords[gci]; - coords[gci+3] = tr_tool->y2; + coords[gci] = tr_tool->x1 + (((gdouble) i) / (tr_tool->ngx + 1) * + (tr_tool->x2 - tr_tool->x1)); + coords[gci + 1] = tr_tool->y1; + coords[gci + 2] = coords[gci]; + coords[gci + 3] = tr_tool->y2; + gci += 4; } for (i = 1; i <= tr_tool->ngy; i++) { - coords[gci] = tr_tool->x1; - coords[gci+1] = tr_tool->y1 + - ((gdouble) i) / (tr_tool->ngy + 1) * - (tr_tool->y2 - tr_tool->y1); - coords[gci+2] = tr_tool->x2; - coords[gci+3] = coords[gci+1]; + coords[gci] = tr_tool->x1; + coords[gci + 1] = tr_tool->y1 + (((gdouble) i) / (tr_tool->ngy + 1) * + (tr_tool->y2 - tr_tool->y1)); + coords[gci + 2] = tr_tool->x2; + coords[gci + 3] = coords[gci + 1]; + gci += 4; } } diff --git a/app/tools/gimptransformtool.h b/app/tools/gimptransformtool.h index 51c166ae63..807918e40d 100644 --- a/app/tools/gimptransformtool.h +++ b/app/tools/gimptransformtool.h @@ -49,20 +49,20 @@ struct _GimpTransformTool { GimpDrawTool parent_instance; - gint startx; /* starting x coord */ - gint starty; /* starting y coord */ + gdouble startx; /* starting x coord */ + gdouble starty; /* starting y coord */ - gint curx; /* current x coord */ - gint cury; /* current y coord */ + gdouble curx; /* current x coord */ + gdouble cury; /* current y coord */ - gint lastx; /* last x coord */ - gint lasty; /* last y coord */ + gdouble lastx; /* last x coord */ + gdouble lasty; /* last y coord */ - gint state; /* state of buttons and keys */ + GdkModifierType state; /* state of buttons and keys */ gint x1, y1; /* upper left hand coordinate */ gint x2, y2; /* lower right hand coords */ - gint cx, cy; /* center point (for rotation) */ + gdouble cx, cy; /* center point (for rotation) */ gdouble tx1, ty1; /* transformed coords */ gdouble tx2, ty2;