Fixed #10466 (disappearing pixels when rotating by 90 deg):

2002-02-19  Michael Natterer  <mitch@gimp.org>

	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.
This commit is contained in:
Michael Natterer 2002-02-19 16:35:13 +00:00 committed by Michael Natterer
parent f17c891b3b
commit 8d0af04c3a
10 changed files with 184 additions and 136 deletions

View File

@ -1,3 +1,21 @@
2002-02-19 Michael Natterer <mitch@gimp.org>
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 <sven@gimp.org>
* plug-ins/pagecurl/pagecurl.c: code cleanup based on a patch from

View File

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

View File

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

View File

@ -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__ */

View File

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

View File

@ -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__ */

View File

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

View File

@ -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);

View File

@ -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;
}
}

View File

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