97
96
gint *nreturn_vals,
98
97
GimpParam **return_vals);
100
static void iwarp (void);
101
static void iwarp_frame (void);
103
static gboolean iwarp_dialog (void);
104
static void iwarp_animate_dialog (GtkWidget *dlg,
105
GtkWidget *notebook);
107
static void iwarp_settings_dialog (GtkWidget *dlg,
108
GtkWidget *notebook);
110
static void iwarp_response (GtkWidget *widget,
114
static void iwarp_realize_callback (GtkWidget *widget);
116
static gint iwarp_motion_callback (GtkWidget *widget,
119
static void iwarp_update_preview (gint x0,
124
static void iwarp_get_pixel (gint x,
128
static void iwarp_get_deform_vector (gdouble x,
133
static void iwarp_get_point (gdouble x,
137
static gint iwarp_supersample_test (GimpVector2 *v0,
142
static void iwarp_getsample (GimpVector2 v0,
153
static void iwarp_supersample (gint sxl,
162
static void iwarp_cpy_images (void);
164
static void iwarp_preview_get_pixel (gint x,
168
static void iwarp_preview_get_point (gdouble x,
172
static void iwarp_deform (gint x,
177
static void iwarp_move (gint x,
183
GimpPlugInInfo PLUG_IN_INFO =
99
static void iwarp (void);
100
static void iwarp_frame (void);
102
static gboolean iwarp_dialog (void);
103
static void iwarp_animate_dialog (GtkWidget *dlg,
104
GtkWidget *notebook);
106
static void iwarp_settings_dialog (GtkWidget *dlg,
107
GtkWidget *notebook);
109
static void iwarp_response (GtkWidget *widget,
113
static void iwarp_realize_callback (GtkWidget *widget);
114
static gboolean iwarp_motion_callback (GtkWidget *widget,
116
static void iwarp_resize_callback (GtkWidget *widget);
118
static void iwarp_update_preview (gint x0,
123
static void iwarp_get_pixel (gint x,
127
static void iwarp_get_deform_vector (gdouble x,
132
static void iwarp_get_point (gdouble x,
136
static gint iwarp_supersample_test (GimpVector2 *v0,
141
static void iwarp_getsample (GimpVector2 v0,
152
static void iwarp_supersample (gint sxl,
161
static void iwarp_cpy_images (void);
163
static void iwarp_preview_get_pixel (gint x,
167
static void iwarp_preview_get_point (gdouble x,
171
static void iwarp_deform (gint x,
176
static void iwarp_move (gint x,
181
static void iwarp_scale_preview (gint new_width,
185
static void iwarp_preview_build (GtkWidget *vbox);
187
static void iwarp_init (void);
188
static void iwarp_preview_init (void);
192
const GimpPlugInInfo PLUG_IN_INFO =
185
194
NULL, /* init_proc */
186
195
NULL, /* quit_proc */
207
static GimpDrawable *drawable = NULL;
208
static GimpDrawable *destdrawable = NULL;
209
static GtkWidget *preview = NULL;
210
static guchar *srcimage = NULL;
211
static guchar *dstimage = NULL;
212
static gint preview_width, preview_height;
213
static gint sel_width, sel_height;
214
static gint image_bpp;
215
static gint preserve_trans;
216
static GimpVector2 *deform_vectors = NULL;
217
static GimpVector2 *deform_area_vectors = NULL;
218
static gint lastx, lasty;
219
static gdouble filter[MAX_DEFORM_AREA_RADIUS];
220
static gboolean do_animate = FALSE;
221
static gboolean do_animate_reverse = FALSE;
222
static gboolean do_animate_ping_pong = FALSE;
223
static gdouble supersample_threshold_2;
224
static gint xl, yl, xh, yh;
225
static gint tile_width, tile_height;
226
static GimpTile *tile = NULL;
227
static gdouble pre2img, img2pre;
228
static gint preview_bpp;
229
static gdouble animate_deform_value = 1.0;
230
static gint32 imageID;
231
static gint animate_num_frames = 2;
232
static gint frame_number;
233
static gboolean layer_alpha;
217
static GimpDrawable *drawable = NULL;
218
static GimpDrawable *destdrawable = NULL;
219
static GtkWidget *preview = NULL;
220
static guchar *srcimage = NULL;
221
static guchar *dstimage = NULL;
222
static gint preview_width, preview_height;
223
static gint sel_width, sel_height;
224
static gint image_bpp;
225
static gint lock_alpha;
226
static GimpVector2 *deform_vectors = NULL;
227
static GimpVector2 *deform_area_vectors = NULL;
228
static gint lastx, lasty;
229
static gdouble filter[MAX_DEFORM_AREA_RADIUS];
230
static gboolean do_animate = FALSE;
231
static gboolean do_animate_reverse = FALSE;
232
static gboolean do_animate_ping_pong = FALSE;
233
static gdouble supersample_threshold_2;
234
static gint xl, yl, xh, yh;
235
static gint tile_width, tile_height;
236
static GimpTile *tile = NULL;
237
static gdouble pre2img, img2pre;
238
static gint preview_bpp;
239
static gdouble animate_deform_value = 1.0;
240
static gint32 imageID;
241
static gint animate_num_frames = 2;
242
static gint frame_number;
243
static gboolean layer_alpha;
244
static gint max_current_preview_width = 320;
245
static gint max_current_preview_height = 320;
246
static gint resize_idle = 0;
241
static GimpParamDef args[] =
254
static const GimpParamDef args[] =
243
{ GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
256
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
244
257
{ GIMP_PDB_IMAGE, "image", "Input image (unused)" },
245
258
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }
248
gimp_install_procedure ("plug_in_iwarp",
249
"Interactive warping of the specified drawable",
261
gimp_install_procedure (PLUG_IN_PROC,
262
N_("Use mouse control to warp image areas"),
250
263
"Interactive warping of the specified drawable",
251
264
"Norbert Schmitz",
252
265
"Norbert Schmitz",
860
iwarp_scale_preview (gint new_width,
866
gdouble ox, oy, dx, dy;
867
gint src1, src2, ix, iy;
868
gdouble in0, in1, in2;
871
new_data = g_new (guchar, new_width * new_height * preview_bpp);
873
for (y = 0; y < new_height; y++)
874
for (x = 0; x < new_width; x++)
876
ox = ((gdouble) x / new_width) * old_width;
877
oy = ((gdouble) y / new_height) * old_height;
885
if (ix == old_width - 1)
888
for (z = 0; z < preview_bpp; z++)
890
src1 = (iy * old_width + ix) * preview_bpp + z;
892
if (iy != old_height - 1)
893
src2 = src1 + old_width * preview_bpp;
897
in0 = dstimage [src1] + (dstimage [src1 + preview_bpp] -
898
dstimage [src1]) * dx;
899
in1 = dstimage [src2] + (dstimage [src2 + preview_bpp] -
900
dstimage [src2]) * dx;
901
in2 = in0 + (in1 - in0) * dy;
903
new_data[(y * new_width + x) * preview_bpp + z] = (guchar) in2;
912
iwarp_preview_init (void)
848
914
gint y, x, xi, i;
849
915
GimpPixelRgn srcrgn;
851
917
guchar *linebuffer = NULL;
854
gimp_drawable_mask_bounds (drawable->drawable_id, &xl, &yl, &xh, &yh);
856
sel_height = yh - yl;
858
image_bpp = gimp_drawable_bpp (drawable->drawable_id);
860
if (gimp_drawable_is_layer (drawable->drawable_id))
861
preserve_trans = gimp_layer_get_preserve_trans (drawable->drawable_id);
863
preserve_trans = FALSE;
865
preview_bpp = image_bpp;
867
dx = (gdouble) sel_width / MAX_PREVIEW_WIDTH;
868
dy = (gdouble) sel_height / MAX_PREVIEW_HEIGHT;
921
dx = (gdouble) sel_width / max_current_preview_width;
922
dy = (gdouble) sel_height / max_current_preview_height;
880
934
preview_width = (gint) (sel_width / pre2img);
881
935
preview_height = (gint) (sel_height / pre2img);
883
tile_width = gimp_tile_width ();
884
tile_height = gimp_tile_height ();
886
srcimage = g_new (guchar, preview_width * preview_height * image_bpp);
887
dstimage = g_new (guchar, preview_width * preview_height * preview_bpp);
888
deform_vectors = g_new0 (GimpVector2, preview_width * preview_height);
889
deform_area_vectors = g_new (GimpVector2,
890
(MAX_DEFORM_AREA_RADIUS * 2 + 1) *
891
(MAX_DEFORM_AREA_RADIUS * 2 + 1));
940
srcimage = g_renew (guchar,
941
srcimage, preview_width * preview_height * image_bpp);
945
srcimage = g_new (guchar, preview_width * preview_height * image_bpp);
946
dstimage = g_new (guchar, preview_width * preview_height * preview_bpp);
892
949
linebuffer = g_new (guchar, sel_width * image_bpp);
894
951
gimp_pixel_rgn_init (&srcrgn, drawable,
903
960
pts = srcimage + (y * preview_width + x) * image_bpp;
904
961
xi = (gint) (pre2img * x);
905
963
for (i = 0; i < image_bpp; i++)
907
*pts++ = linebuffer[xi*image_bpp+i];
964
*pts++ = linebuffer[xi * image_bpp + i];
976
gimp_drawable_mask_bounds (drawable->drawable_id, &xl, &yl, &xh, &yh);
978
sel_height = yh - yl;
980
image_bpp = gimp_drawable_bpp (drawable->drawable_id);
982
if (gimp_drawable_is_layer (drawable->drawable_id))
983
lock_alpha = gimp_layer_get_lock_alpha (drawable->drawable_id);
987
preview_bpp = image_bpp;
989
tile_width = gimp_tile_width ();
990
tile_height = gimp_tile_height ();
992
iwarp_preview_init ();
912
993
iwarp_cpy_images ();
995
deform_vectors = g_new0 (GimpVector2, preview_width * preview_height);
996
deform_area_vectors = g_new (GimpVector2,
997
(MAX_DEFORM_AREA_RADIUS * 2 + 1) *
998
(MAX_DEFORM_AREA_RADIUS * 2 + 1));
914
1000
for (i = 0; i < MAX_DEFORM_AREA_RADIUS; i++)
917
1003
pow ((cos (sqrt((gdouble) i / MAX_DEFORM_AREA_RADIUS) * G_PI) + 1) *
918
1004
0.5, 0.7); /*0.7*/
925
1009
iwarp_animate_dialog (GtkWidget *dlg,
926
1010
GtkWidget *notebook)
928
1013
GtkWidget *vbox;
930
1014
GtkWidget *table;
931
1015
GtkWidget *button;
932
1016
GtkObject *scale_data;
957
1041
gtk_widget_set_sensitive (table, do_animate);
959
1043
scale_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
960
_("Number of _Frames:"), SCALE_WIDTH, 0,
1044
_("Number of _frames:"), SCALE_WIDTH, 0,
961
1045
animate_num_frames,
962
1046
2, MAX_NUM_FRAMES, 1, 10, 0,
965
g_signal_connect (scale_data, "value_changed",
1049
g_signal_connect (scale_data, "value-changed",
966
1050
G_CALLBACK (gimp_int_adjustment_update),
967
1051
&animate_num_frames);
975
1059
G_CALLBACK (gimp_toggle_button_update),
976
1060
&do_animate_reverse);
978
button = gtk_check_button_new_with_mnemonic (_("_Ping Pong"));
1062
button = gtk_check_button_new_with_mnemonic (_("_Ping pong"));
979
1063
gtk_table_attach (GTK_TABLE (table), button, 0, 3, 2, 3,
980
1064
GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
981
1065
gtk_widget_show (button);
1061
1145
5.0, MAX_DEFORM_AREA_RADIUS, 1.0, 10.0, 0,
1064
g_signal_connect (scale_data, "value_changed",
1148
g_signal_connect (scale_data, "value-changed",
1065
1149
G_CALLBACK (gimp_int_adjustment_update),
1066
1150
&iwarp_vals.deform_area_radius);
1135
1219
gtk_label_new_with_mnemonic (_("_Settings")));
1223
iwarp_preview_build (GtkWidget *vbox)
1227
frame = gtk_aspect_frame_new (NULL, 0.0, 0.0, 1.0, TRUE);
1228
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1229
gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
1230
gtk_widget_show (frame);
1232
preview = gimp_preview_area_new ();
1233
gtk_widget_set_size_request (preview, preview_width, preview_height);
1234
gtk_container_add (GTK_CONTAINER (frame), preview);
1235
gtk_widget_show (preview);
1237
gtk_widget_add_events (preview,
1238
GDK_BUTTON_PRESS_MASK |
1239
GDK_BUTTON_RELEASE_MASK |
1240
GDK_BUTTON1_MOTION_MASK |
1241
GDK_POINTER_MOTION_HINT_MASK);
1243
g_signal_connect (preview, "realize",
1244
G_CALLBACK (iwarp_realize_callback),
1246
g_signal_connect (preview, "event",
1247
G_CALLBACK (iwarp_motion_callback),
1249
g_signal_connect (preview, "size-allocate",
1250
G_CALLBACK (iwarp_resize_callback),
1138
1255
static gboolean
1139
1256
iwarp_dialog (void)
1141
1258
GtkWidget *dlg;
1142
1259
GtkWidget *main_hbox;
1145
1262
GtkWidget *notebook;
1147
gimp_ui_init ("iwarp", TRUE);
1264
gimp_ui_init (PLUG_IN_BINARY, TRUE);
1151
dlg = gimp_dialog_new (_("IWarp"), "iwarp",
1268
dlg = gimp_dialog_new (_("IWarp"), PLUG_IN_BINARY,
1153
gimp_standard_help_func, "plug-in-iwarp",
1270
gimp_standard_help_func, PLUG_IN_PROC,
1155
1272
GIMP_STOCK_RESET, RESPONSE_RESET,
1156
1273
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1168
1293
main_hbox = gtk_hbox_new (FALSE, 12);
1169
1294
gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
1170
1295
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), main_hbox,
1172
1297
gtk_widget_show (main_hbox);
1174
abox = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
1175
gtk_box_pack_start (GTK_BOX (main_hbox), abox, FALSE, FALSE, 0);
1176
gtk_widget_show (abox);
1178
frame = gtk_frame_new (NULL);
1179
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1180
gtk_container_add (GTK_CONTAINER (abox), frame);
1181
gtk_widget_show (frame);
1183
preview = gimp_preview_area_new ();
1184
gtk_widget_set_size_request (preview, preview_width, preview_height);
1185
gtk_container_add (GTK_CONTAINER (frame), preview);
1186
gtk_widget_show (preview);
1188
gtk_widget_set_events (preview,
1189
GDK_BUTTON_PRESS_MASK |
1190
GDK_BUTTON_RELEASE_MASK |
1191
GDK_BUTTON1_MOTION_MASK |
1192
GDK_POINTER_MOTION_HINT_MASK);
1194
g_signal_connect (preview, "realize",
1195
G_CALLBACK (iwarp_realize_callback),
1197
g_signal_connect (preview, "event",
1198
G_CALLBACK (iwarp_motion_callback),
1299
vbox = gtk_vbox_new (FALSE, 12);
1300
gtk_box_pack_start (GTK_BOX (main_hbox), vbox, TRUE, TRUE, 0);
1301
gtk_widget_show (vbox);
1303
iwarp_preview_build (vbox);
1304
hint = gimp_hint_box_new (_("Click and drag in the preview to define "
1305
"the distortions to apply to the image."));
1306
gtk_box_pack_end (GTK_BOX (vbox), hint, FALSE, FALSE, 0);
1307
gtk_widget_show (hint);
1201
1309
notebook = gtk_notebook_new ();
1202
1310
gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
1203
gtk_box_pack_start (GTK_BOX (main_hbox), notebook, TRUE, TRUE, 0);
1311
gtk_box_pack_start (GTK_BOX (main_hbox), notebook, FALSE, FALSE, 0);
1204
1312
gtk_widget_show (notebook);
1206
1314
iwarp_settings_dialog (dlg, notebook);
1227
x1 = MIN (x1, preview_width);
1228
y1 = MIN (y1, preview_height);
1332
x0 = CLAMP (x0, 0, preview_width);
1333
y0 = CLAMP (y0, 0, preview_height);
1334
x1 = CLAMP (x1, x0, preview_width);
1335
y1 = CLAMP (y1, y0, preview_height);
1230
gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview),
1233
gimp_drawable_type(drawable->drawable_id),
1234
dstimage + (y0 * preview_width + x0) * preview_bpp,
1235
preview_width * preview_bpp);
1337
if (x1 > x0 && y1 > y0)
1338
gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview),
1341
gimp_drawable_type(drawable->drawable_id),
1342
dstimage + (y0 * preview_width + x0) * preview_bpp,
1343
preview_width * preview_bpp);
1565
1675
case GDK_MOTION_NOTIFY:
1566
1676
if (mb->state & GDK_BUTTON1_MASK)
1678
gtk_widget_get_pointer (widget, &x, &y);
1570
1680
if (iwarp_vals.deform_mode == MOVE)
1571
1681
iwarp_move (x, y, lastx, lasty);
1573
1683
iwarp_deform (x, y, 0.0, 0.0);
1576
gtk_widget_get_pointer (widget, NULL, NULL);
1698
iwarp_resize_idle (GtkWidget *widget)
1700
GimpVector2 *new_deform_vectors;
1701
gint old_preview_width, old_preview_height;
1702
gint new_preview_width, new_preview_height;
1708
old_preview_width = preview_width;
1709
old_preview_height = preview_height;
1711
max_current_preview_width = widget->allocation.width;
1712
max_current_preview_height = widget->allocation.height;
1714
/* preview width and height get updated here: */
1715
iwarp_preview_init ();
1716
new_preview_width = preview_width;
1717
new_preview_height = preview_height;
1719
new_deform_vectors = g_new0 (GimpVector2, preview_width * preview_height);
1720
new2old = (gdouble) old_preview_width / preview_width;
1722
/* preview_width and height are used as global variables inside
1723
* iwarp_get_deform_factor(). In the following call to the function,
1724
* I need it to run with the old values. Adding a width and height
1725
* to these function parameters would be an option for cleaner code,
1726
* but that would also mean pushing 16 extra parameter bytes several
1727
* times over for each pixel processed.
1730
preview_width = old_preview_width;
1731
preview_height = old_preview_height;
1733
for (y = 0; y < new_preview_height; y++)
1734
for (x = 0; x < new_preview_width; x++)
1735
iwarp_get_deform_vector (new2old * x,
1737
&new_deform_vectors[x + new_preview_width * y].x,
1738
&new_deform_vectors[x + new_preview_width * y].y);
1740
preview_width = new_preview_width;
1741
preview_height = new_preview_height;
1743
g_free (deform_vectors);
1744
deform_vectors = new_deform_vectors;
1746
iwarp_scale_preview (new_preview_width, new_preview_height,
1747
old_preview_width, old_preview_height);
1749
iwarp_update_preview (0, 0, preview_width, preview_height);
1755
iwarp_resize_callback (GtkWidget *widget)
1758
g_source_remove (resize_idle);
1760
resize_idle = g_idle_add_full (G_PRIORITY_LOW,
1761
(GSourceFunc) iwarp_resize_idle, widget,