[gimp-gap] added GUI for the exact align transformation plugin
- From: Wolfgang Hofer <wolfgangh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp-gap] added GUI for the exact align transformation plugin
- Date: Sat, 9 Jun 2012 18:12:17 +0000 (UTC)
commit b088ae86c2b27a11558c9c619d16a6691bcb54a5
Author: Wolfgang Hofer <wolfgangh svn gnome org>
Date: Sat Jun 9 20:08:54 2012 +0200
added GUI for the exact align transformation plugin
ChangeLog | 20 ++
gap/gap_detail_align_exec.c | 531 ++++++++++++++++++++++++++++++++++++++--
gap/gap_detail_align_exec.h | 9 +-
gap/gap_detail_tracking_main.c | 36 ++-
4 files changed, 566 insertions(+), 30 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index c522b57..5d0bb28 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2012-06-07 Wolfgang Hofer <hof gimp org>
+
+- Implementation of dialog window for the exact align transform filter.
+ Now supports 2 modes for path point interpretation.
+ The mode is persisted as gimprc setting
+
+ (gap-exact-aligner-path-point-order "0")
+ (gap-exact-aligner-path-point-order "1")
+
+ where value 0 (default) is compatible behavior to previous
+ implementation (and to the exact aligner script
+ that is available in the plug-in regstry)
+
+ use mode TRANSFORM-RESIZE-ADJUST (0) for the transformation
+ because this feature is intended to do no clipping.
+
+ * gap/gap_detail_align_exec.c [.h]
+ * gap/gap_detail_tracking_main.c
+
+
2012-05-26 Wolfgang Hofer <hof gimp org>
- added AC_CHECK_LIB(gthread-2.0, g_thread_init)
diff --git a/gap/gap_detail_align_exec.c b/gap/gap_detail_align_exec.c
index 49fd2d2..b59d7e7 100644
--- a/gap/gap_detail_align_exec.c
+++ b/gap/gap_detail_align_exec.c
@@ -1,11 +1,8 @@
/* gap_detail_align_exec.c
- * This filter locates the position of a small
- * outside the selction into the selected area.
- * It was implemented for fixing small pixel defects of my video camera sensor
- * and is intended to be used as filter when processing video frames
- * that are shot by such faulty cameras and typically runs
- * as filtermacro. Therefore the selection can be provided via an external image
- * or as path vectors via an extrernal SVG file.
+ * This transforms and/or moves the active layer with 4 or 2 controlpoints.
+ * controlpoints input from current path (or from an xml input file recorded by GAP detail tracking feature)
+ * 4 points: rotate scale and move the layer in a way that 2 reference points match 2 target points.
+ * 2 points: simple move the layer from reference point to target point.
*
* 2011/12/01
*/
@@ -50,6 +47,28 @@ extern int gap_debug;
#include "gap-intl.h"
+#define GIMPRC_EXACT_ALIGN_PATH_POINT_ORDER "gap-exact-aligner-path-point-order"
+#define GAP_RESPONSE_REFRESH_PATH 1
+
+
+
+typedef struct AlignDialogVals
+{
+ gint32 pointOrder;
+
+ gboolean runExactAlign;
+ gint countVaildPoints;
+ gint32 image_id;
+ gint32 activeDrawableId;
+
+ GtkWidget *radio_order_mode_31_42;
+ GtkWidget *radio_order_mode_21_43;
+ GtkWidget *infoLabel;
+ GtkWidget *okButton;
+ GtkWidget *shell;
+
+} AlignDialogVals;
+
typedef struct PixelCoords
{
@@ -414,7 +433,7 @@ p_exact_align_drawable(gint32 activeDrawableId, AlingCoords *alingCoords)
dx2 = px4 - px3;
dy2 = py4 - py3;
- /* the angle between the two lines. i.e., the angle layer2 must be clockwise rotatet
+ /* the angle between the two lines. i.e., the angle layer2 must be clockwise rotated
* in order to overlap with initial start layer1
*/
angle1Rad = 0;
@@ -456,7 +475,7 @@ p_exact_align_drawable(gint32 activeDrawableId, AlingCoords *alingCoords)
, 2 /* INTERPOLATION-CUBIC (2) */
, TRUE /* supersample */
, 1 /* Maximum recursion level used for supersampling */
- , 1 /* TRANSFORM-RESIZE-CLIP (1) */
+ , 0 /* TRANSFORM-RESIZE-ADJUST (0) TRANSFORM-RESIZE-CLIP (1) */
);
if(gap_debug)
@@ -672,20 +691,32 @@ gap_detail_xml_align_dialog(XmlAlignValues *xaVals)
* p_capture_4_vector_points
* ------------------------------------------
* capture the first 4 points of the 1st stroke in the active path vectors
+ * pointOrder POINT_ORDER_MODE_31_42 : order 0,1,2,3 compatible with the exactAligner script
+ * POINT_ORDER_MODE_21_43 : order 0,2,1,3
*/
static gint
-p_capture_4_vector_points(gint32 imageId, AlingCoords *alingCoords)
+p_capture_4_vector_points(gint32 imageId, AlingCoords *alingCoords, gint32 pointOrder)
{
gint32 activeVectorsId;
PixelCoords *coordPtr[4];
gint ii;
gint countVaildPoints;
-
- coordPtr[0] = &alingCoords->startCoords;
- coordPtr[1] = &alingCoords->startCoords2;
- coordPtr[2] = &alingCoords->currCoords;
- coordPtr[3] = &alingCoords->currCoords2;
+ if (pointOrder == POINT_ORDER_MODE_31_42)
+ {
+ coordPtr[0] = &alingCoords->startCoords;
+ coordPtr[1] = &alingCoords->startCoords2;
+ coordPtr[2] = &alingCoords->currCoords;
+ coordPtr[3] = &alingCoords->currCoords2;
+ }
+ else
+ {
+ coordPtr[0] = &alingCoords->startCoords;
+ coordPtr[2] = &alingCoords->startCoords2;
+ coordPtr[1] = &alingCoords->currCoords;
+ coordPtr[3] = &alingCoords->currCoords2;
+ }
+
countVaildPoints = 0;
for(ii=0; ii < 4; ii++)
@@ -772,6 +803,401 @@ p_capture_4_vector_points(gint32 imageId, AlingCoords *alingCoords)
} /* end p_capture_4_vector_points */
+/* ---------------------------------
+ * p_save_gimprc_gint32_value
+ * ---------------------------------
+ */
+static void
+p_save_gimprc_gint32_value(const char *gimprc_option_name, gint32 value)
+{
+ gchar *value_string;
+
+ value_string = g_strdup_printf("%d", value);
+ gimp_gimprc_set(gimprc_option_name, value_string);
+ g_free(value_string);
+
+} /* p_save_gimprc_gint32_value */
+
+
+
+
+
+
+
+
+
+
+/* ================= DIALOG stuff Start ================= */
+
+/* -------------------------------------
+ * p_exact_align_calculate_4point_values
+ * -------------------------------------
+ * calculate 4-point alignment transformation setting.
+ * (this procedure is intended for GUI feedback, therfore
+ * deliver angle in degree and scale in percent)
+ */
+static void
+p_exact_align_calculate_4point_values(AlingCoords *alingCoords
+ , gdouble *angleDeg, gdouble *scalePercent, gdouble *moveDx, gdouble *moveDy)
+{
+ gdouble px1, py1, px2, py2;
+ gdouble px3, py3, px4, py4;
+ gdouble dx1, dy1, dx2, dy2;
+ gdouble angle1Rad, angle2Rad, angleRad;
+ gdouble len1, len2;
+ gdouble scaleXY;
+
+ px1 = alingCoords->startCoords.px;
+ py1 = alingCoords->startCoords.py;
+ px2 = alingCoords->startCoords2.px;
+ py2 = alingCoords->startCoords2.py;
+
+ px3 = alingCoords->currCoords.px;
+ py3 = alingCoords->currCoords.py;
+ px4 = alingCoords->currCoords2.px;
+ py4 = alingCoords->currCoords2.py;
+
+ dx1 = px2 - px1;
+ dy1 = py2 - py1;
+ dx2 = px4 - px3;
+ dy2 = py4 - py3;
+
+ /* the angle between the two lines. i.e., the angle layer2 must be clockwise rotated
+ * in order to overlap with initial start layer1
+ */
+ angle1Rad = 0;
+ angle2Rad = 0;
+ if (dx1 != 0.0)
+ {
+ angle1Rad = atan(dy1 / dx1);
+ }
+ if (dx2 != 0.0)
+ {
+ angle2Rad = atan(dy2 / dx2);
+ }
+ angleRad = angle1Rad - angle2Rad;
+
+ /* the scale factors current layer must be mulitplied by,
+ * in order to fit onto reference start layer.
+ * this is simply the ratio of the two line lenths from the path we created with the 4 points
+ */
+
+ len1 = sqrt((dx1 * dx1) + (dy1 * dy1));
+ len2 = sqrt((dx2 * dx2) + (dy2 * dy2));
+
+ scaleXY = 1.0;
+ if ((len1 != len2)
+ && (len2 != 0.0))
+ {
+ scaleXY = len1 / len2;
+ }
+
+
+ *angleDeg = (angleRad * 180.0) / G_PI;
+ *scalePercent = scaleXY * 100.0;
+ *moveDx = px3 - px1;
+ *moveDy = py3 - py1;
+
+
+} /* end p_exact_align_calculate_4point_values */
+
+
+
+/* ------------------------------
+ * p_refresh_and_update_infoLabel
+ * ------------------------------
+ */
+static void
+p_refresh_and_update_infoLabel(GtkWidget *widgetDummy, AlignDialogVals *advPtr)
+{
+ AlingCoords tmpAlingCoords;
+ gboolean okSensitiveFlag;
+ gdouble angleDeg;
+ gdouble scalePercent;
+ gdouble moveDx;
+ gdouble moveDy;
+ gchar *infoText;
+
+
+ if(gap_debug)
+ {
+ printf("p_refresh_and_update_infoLabel widgetDummy:%d advPtr:%d\n"
+ , (int) widgetDummy
+ , (int) advPtr
+ );
+ }
+
+ if ((advPtr->okButton == NULL) || (advPtr->infoLabel == NULL))
+ {
+ return;
+ }
+
+ angleDeg = 0.0;
+ scalePercent = 100.0;
+ moveDx = 0.0;
+ moveDy = 0.0;
+
+ advPtr->countVaildPoints = p_capture_4_vector_points(advPtr->image_id, &tmpAlingCoords, advPtr->pointOrder);
+
+ if (advPtr->countVaildPoints == 4)
+ {
+ p_exact_align_calculate_4point_values(&tmpAlingCoords
+ , &angleDeg, &scalePercent, &moveDx, &moveDy);
+
+
+ infoText = g_strdup_printf(_("Current path with 4 point triggers transformations:\n"
+ " Rotation: %.4f (degree)\n"
+ " Scale: %.1f (%%)\n"
+ " Movement X: %.0f (pixels)\n"
+ " Movement Y: %.0f (pixels)\n"
+ "Press OK button to transform the layer\n"
+ "in a way that point3 moves to point1 and point4 moves to point2")
+ , (float) angleDeg
+ , (float) scalePercent
+ , (float) moveDx
+ , (float) moveDy
+ );
+ gtk_label_set_text(GTK_LABEL(advPtr->infoLabel), infoText);
+ g_free(infoText);
+ okSensitiveFlag = TRUE;
+ }
+ else if (advPtr->countVaildPoints == 2)
+ {
+ moveDx = tmpAlingCoords.currCoords.px - tmpAlingCoords.startCoords.px;
+ moveDy = tmpAlingCoords.currCoords.py - tmpAlingCoords.startCoords.py;
+
+ infoText = g_strdup_printf(_("Current path with 2 points triggers simple move:\n"
+ " Movement X: %.0f (pixels)\n"
+ " Movement Y: %.0f (pixels)\n"
+ "Press OK button to move the layer\n"
+ "in a way that point2 moves to point1")
+ , (float) moveDx
+ , (float) moveDy
+ );
+
+ gtk_label_set_text(GTK_LABEL(advPtr->infoLabel), infoText);
+ g_free(infoText);
+ okSensitiveFlag = TRUE;
+ }
+ else
+ {
+ gtk_label_set_text(GTK_LABEL(advPtr->infoLabel)
+ , _("This filter requires a current path with 4 or 2 points\n"
+ "It can transform and/or move the current layer according to such path coordinate points.\n"
+ "Please create a path and press the Refresh button."));
+ okSensitiveFlag = FALSE;
+ }
+
+ gtk_widget_set_sensitive(advPtr->okButton, okSensitiveFlag);
+
+} /* end p_refresh_and_update_infoLabel */
+
+
+
+/* ---------------------------------
+ * on_exact_align_response
+ * ---------------------------------
+ */
+static void
+on_exact_align_response (GtkWidget *widget,
+ gint response_id,
+ AlignDialogVals *advPtr)
+{
+ GtkWidget *dialog;
+
+ switch (response_id)
+ {
+ case GAP_RESPONSE_REFRESH_PATH:
+ if(advPtr != NULL)
+ {
+ p_refresh_and_update_infoLabel(NULL, advPtr);
+ }
+ break;
+ case GTK_RESPONSE_OK:
+ if(advPtr)
+ {
+ if (GTK_WIDGET_VISIBLE (advPtr->shell))
+ {
+ gtk_widget_hide (advPtr->shell);
+ }
+
+ advPtr->runExactAlign = TRUE;
+ }
+
+ default:
+ dialog = NULL;
+ if(advPtr)
+ {
+ dialog = advPtr->shell;
+ if(advPtr)
+ {
+ advPtr->shell = NULL;
+ gtk_widget_destroy (dialog);
+ }
+ }
+ gtk_main_quit ();
+ break;
+ }
+} /* end on_exact_align_response */
+
+
+/* --------------------------------------
+ * on_order_mode_radio_callback
+ * --------------------------------------
+ */
+static void
+on_order_mode_radio_callback(GtkWidget *wgt, gpointer user_data)
+{
+ AlignDialogVals *advPtr;
+
+ if(gap_debug)
+ {
+ printf("on_order_mode_radio_callback: START\n");
+ }
+ advPtr = (AlignDialogVals*)user_data;
+ if(advPtr != NULL)
+ {
+ if(wgt == advPtr->radio_order_mode_31_42) { advPtr->pointOrder = POINT_ORDER_MODE_31_42; }
+ if(wgt == advPtr->radio_order_mode_21_43) { advPtr->pointOrder = POINT_ORDER_MODE_21_43; }
+
+ p_refresh_and_update_infoLabel(NULL, advPtr);
+
+ }
+}
+
+
+/* --------------------------
+ * p_align_dialog
+ * --------------------------
+ */
+static void
+p_align_dialog(AlignDialogVals *advPtr)
+
+{
+ GtkWidget *dialog;
+ GtkWidget *main_vbox;
+ GtkWidget *label;
+ GtkWidget *button;
+ GtkWidget *table;
+ GtkWidget *vbox1;
+ GSList *vbox1_group = NULL;
+ GtkWidget *radiobutton;
+ gint row;
+
+
+ advPtr->runExactAlign = FALSE;
+
+ gimp_ui_init (GAP_EXACT_ALIGNER_PLUG_IN_NAME_BINARY, TRUE);
+
+ dialog = gimp_dialog_new (_("Transform Layer via 4 (or 2) point Alignment"), GAP_EXACT_ALIGNER_PLUG_IN_NAME_BINARY,
+ NULL, 0,
+ gimp_standard_help_func, GAP_EXACT_ALIGNER_PLUG_IN_NAME,
+
+ GTK_STOCK_REFRESH, GAP_RESPONSE_REFRESH_PATH,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+
+ NULL);
+ advPtr->shell = dialog;
+ button = gimp_dialog_add_button (GIMP_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK);
+ advPtr->okButton = button;
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ gimp_window_set_transient (GTK_WINDOW (dialog));
+
+ main_vbox = gtk_vbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), main_vbox);
+ gtk_widget_show (main_vbox);
+
+ g_signal_connect (G_OBJECT (dialog), "response",
+ G_CALLBACK (on_exact_align_response),
+ advPtr);
+
+
+ /* Controls */
+ table = gtk_table_new (3, 3, FALSE);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+ gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0);
+ gtk_widget_show (table);
+
+ row = 0;
+
+ /* info label */
+ label = gtk_label_new ("--");
+ advPtr->infoLabel = label;
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table), label, 0, 3, row, row+1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
+
+ row++;
+
+
+ /* pointOrder radiobutton
+ * POINT_ORDER_MODE_31_42: compatible to the exact aligner script (from the plugin registry)
+ */
+ label = gtk_label_new (_("Path Point Order:"));
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+
+ /* vbox for radio group */
+ vbox1 = gtk_vbox_new (FALSE, 0);
+
+ gtk_widget_show (vbox1);
+ gtk_table_attach (GTK_TABLE (table), vbox1, 1, 3, row, row+1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+
+ /* Order Mode the radio buttons */
+ radiobutton = gtk_radio_button_new_with_label (vbox1_group, _("( 3 --> 1 ) ( 4 --> 2 )\nTarget is marked by points 1&2 "));
+ advPtr->radio_order_mode_31_42 = radiobutton;
+ vbox1_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton));
+ gtk_widget_show (radiobutton);
+ gtk_box_pack_start (GTK_BOX (vbox1), radiobutton, FALSE, FALSE, 0);
+ g_signal_connect (G_OBJECT (radiobutton), "clicked", G_CALLBACK (on_order_mode_radio_callback), advPtr);
+ if(advPtr->pointOrder == POINT_ORDER_MODE_31_42)
+ {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (radiobutton), TRUE);
+ }
+
+ radiobutton = gtk_radio_button_new_with_label (vbox1_group, "( 2 --> 1 ) ( 4 --> 3 )\nTarget is marked by points 1&3");
+ advPtr->radio_order_mode_21_43 = radiobutton;
+ vbox1_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton));
+ gtk_widget_show (radiobutton);
+ gtk_box_pack_start (GTK_BOX (vbox1), radiobutton, FALSE, FALSE, 0);
+ g_signal_connect (G_OBJECT (radiobutton), "clicked", G_CALLBACK (on_order_mode_radio_callback), advPtr);
+ if(advPtr->pointOrder == POINT_ORDER_MODE_21_43)
+ {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (radiobutton), TRUE);
+ }
+
+ p_refresh_and_update_infoLabel(NULL, advPtr);
+
+ /* Done */
+
+ gtk_widget_show (dialog);
+
+ gtk_main ();
+ gdk_flush ();
+
+
+} /* end p_align_dialog */
+
+
+/* ================= DIALOG stuff End =================== */
+
+
/* ------------------------------------------
* gap_detail_exact_align_via_4point_path
@@ -779,17 +1205,62 @@ p_capture_4_vector_points(gint32 imageId, AlingCoords *alingCoords)
*
*/
gint32
-gap_detail_exact_align_via_4point_path(gint32 image_id, gint32 activeDrawableId)
+gap_detail_exact_align_via_4point_path(gint32 image_id, gint32 activeDrawableId
+ , gint32 pointOrder, GimpRunMode runMode)
{
AlingCoords alingCoordinates;
AlingCoords *alingCoords;
gint countVaildPoints;
gint32 ret;
+ AlignDialogVals advals;
alingCoords = &alingCoordinates;
ret = -1;
- countVaildPoints = p_capture_4_vector_points(image_id, alingCoords);
+
+ advals.runExactAlign = TRUE;
+ advals.image_id = image_id;
+ advals.activeDrawableId = activeDrawableId;
+
+ if (runMode == GIMP_RUN_NONINTERACTIVE)
+ {
+ advals.pointOrder = pointOrder;
+ }
+ else
+ {
+ /* get last used value (or default)
+ * from gimprc settings
+ */
+ advals.pointOrder = gap_base_get_gimprc_int_value(GIMPRC_EXACT_ALIGN_PATH_POINT_ORDER
+ , POINT_ORDER_MODE_31_42 /* DEFAULT */
+ , POINT_ORDER_MODE_31_42 /* min */
+ , POINT_ORDER_MODE_21_43 /* max */
+ );
+ }
+
+
+ if (runMode == GIMP_RUN_INTERACTIVE)
+ {
+ p_align_dialog(&advals);
+ }
+
+ if (advals.runExactAlign != TRUE)
+ {
+ return (ret);
+ }
+
+ if (runMode == GIMP_RUN_INTERACTIVE)
+ {
+ /* store order flag when entered via userdialog
+ * in gimprc (for next use in same or later gimp session)
+ */
+ p_save_gimprc_gint32_value(GIMPRC_EXACT_ALIGN_PATH_POINT_ORDER, advals.pointOrder);
+ }
+
+
+ gimp_image_undo_group_start (image_id);
+
+ countVaildPoints = p_capture_4_vector_points(image_id, alingCoords, advals.pointOrder);
if(countVaildPoints == 4)
{
ret = p_exact_align_drawable(activeDrawableId, alingCoords);
@@ -797,14 +1268,17 @@ gap_detail_exact_align_via_4point_path(gint32 image_id, gint32 activeDrawableId)
}
else if(countVaildPoints == 2)
{
- alingCoords->currCoords.px = alingCoords->startCoords2.px;
- alingCoords->currCoords.py = alingCoords->startCoords2.py;
- alingCoords->currCoords.valid = alingCoords->startCoords2.valid;
+ /* force order 0213
+ * (captures the 2 valid points into startCoords and currCoords)
+ */
+ countVaildPoints = p_capture_4_vector_points(image_id, alingCoords, POINT_ORDER_MODE_21_43);
ret = p_set_drawable_offsets(activeDrawableId, alingCoords);
}
else
{
- g_message(_("This filter requires a current path with 4 points,"
+ if (advals.pointOrder == POINT_ORDER_MODE_31_42)
+ {
+ g_message(_("This filter requires a current path with 4 points,"
"where point 1 and 2 mark reference positions "
"and point 3 and 4 mark postions in the target layer."
"It transforms the target layer in a way that "
@@ -812,10 +1286,25 @@ gap_detail_exact_align_via_4point_path(gint32 image_id, gint32 activeDrawableId)
"(this may include rotate an scale transforamtion).\n"
"A path with 2 points can be used to move point2 to point1."
"(via simple move operation without rotate and scale)"));
+ }
+ else
+ {
+ g_message(_("This filter requires a current path with 4 points,"
+ "where point 1 and 3 mark reference positions "
+ "and point 2 and 4 mark postions in the target layer."
+ "It transforms the target layer in a way that "
+ "point2 is moved to point1 and point4 moves to point3."
+ "(this may include rotate an scale transforamtion).\n"
+ "A path with 2 points can be used to move point2 to point1."
+ "(via simple move operation without rotate and scale)"));
+ }
}
+
+ gimp_image_undo_group_end (image_id);
return(ret);
} /* end gap_detail_exact_align_via_4point_path */
+
diff --git a/gap/gap_detail_align_exec.h b/gap/gap_detail_align_exec.h
index 702bd9a..afb56c5 100644
--- a/gap/gap_detail_align_exec.h
+++ b/gap/gap_detail_align_exec.h
@@ -55,6 +55,12 @@
#define GAP_DETAIL_TRACKING_XML_ALIGNER_PLUG_IN_NAME "gap-detail-tracking-xml-aligner"
#define GAP_EXACT_ALIGNER_PLUG_IN_NAME "gap-exact-aligner"
+#define GAP_EXACT_ALIGNER_PLUG_IN_NAME_BINARY "gap_exact_aligner"
+
+
+#define POINT_ORDER_MODE_31_42 0
+#define POINT_ORDER_MODE_21_43 1
+
typedef struct XmlAlignValues {
gint32 framePhase;
@@ -67,7 +73,8 @@ gint32 gap_detail_xml_align(gint32 drawableId, XmlAlignValues *xaVals);
void gap_detail_xml_align_get_values(XmlAlignValues *xaVals);
gboolean gap_detail_xml_align_dialog(XmlAlignValues *xaVals);
-gint32 gap_detail_exact_align_via_4point_path(gint32 image_id, gint32 activeDrawableId);
+gint32 gap_detail_exact_align_via_4point_path(gint32 image_id, gint32 activeDrawableId
+ ,gint32 pointOrder, GimpRunMode runMode);
diff --git a/gap/gap_detail_tracking_main.c b/gap/gap_detail_tracking_main.c
index 551ae64..93528b7 100644
--- a/gap/gap_detail_tracking_main.c
+++ b/gap/gap_detail_tracking_main.c
@@ -1,4 +1,8 @@
/* gap_detail_tracking_main.c
+ * This main module provides multiple filters:
+ *
+ * A) Detail Tracking
+ *
* This filter locates the position of a small area of one layer
* in another layer.
* It was implemented for recording postions as XML input
@@ -16,6 +20,15 @@
* (or on top and BG layer)
* in the snapshot image that is created and updated by the player.
*
+ * B) Transformation of a Layer by 4 or 2 controlpoints.
+ * 4 points: rotate scale and move the layer in a way that 2 reference points match 2 target points.
+ * (Note that the 4 point mode works similar to the Exact Aligner script in the plug-in registry)
+ * 2 points: simple move the layer from reference point to target point.
+ *
+ * This filter transformation is available in 2 variants:
+ * B1) controlpoints input from current path
+ * B2) controlpoints from an xml input file recorded by GAP detail tracking feature.
+ *
* 2011/12/01
*/
/* The GIMP -- an image manipulation program
@@ -134,7 +147,9 @@ static const GimpParamDef in_exalign_args[] =
{
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
{ GIMP_PDB_IMAGE, "image", "Input image" },
- { GIMP_PDB_DRAWABLE, "drawable", "layer to be aligned" }
+ { GIMP_PDB_DRAWABLE, "drawable", "layer to be aligned" },
+ { GIMP_PDB_INT32, "pointOrder", "0: use path coordinate points in order: 3 --> 1, 4 --> 2 "
+ "1: use path coordinate points in order: 2 --> 1, 4 --> 3 " }
};
@@ -346,16 +361,21 @@ runExactAlign (const gchar *name, /* name of plugin */
if (status == GIMP_PDB_SUCCESS)
{
-
- gimp_image_undo_group_start (image_id);
-
-
+ gint32 pointOrder;
+
+ pointOrder = POINT_ORDER_MODE_31_42;
+ if(nparams >= global_number_in_exalign_args)
+ {
+ pointOrder = param[3].data.d_int32;
+ }
+
+
/* Run the main function */
values[1].data.d_drawable =
- gap_detail_exact_align_via_4point_path(image_id, activeDrawableId);
-
- gimp_image_undo_group_end (image_id);
+ gap_detail_exact_align_via_4point_path(image_id, activeDrawableId
+ , pointOrder, run_mode);
+
if (values[1].data.d_drawable < 0)
{
status = GIMP_PDB_CALLING_ERROR;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]