101
98
static gboolean check_filmvals (void);
103
static void convert_to_rgb (GimpDrawable *srcdrawable,
108
100
static void set_pixels (gint numpix,
112
static gboolean scale_layer (gint32 src_layer,
123
104
static guchar * create_hole_rgb (gint width,
126
107
static void draw_hole_rgb (GimpDrawable *drw,
133
114
static void draw_number (gint32 layer_ID,
140
121
static void add_list_item_callback (GtkWidget *widget,
141
GtkTreeSelection *sel);
122
GtkTreeSelection *sel);
142
123
static void del_list_item_callback (GtkWidget *widget,
143
GtkTreeSelection *sel);
124
GtkTreeSelection *sel);
145
126
static GtkTreeModel * add_image_list (gboolean add_box_flag,
150
static gboolean film_dialog (gint32 image_ID);
151
static void film_reset_callback (GtkWidget *widget,
153
static void film_font_select_callback (const gchar *name,
158
GimpPlugInInfo PLUG_IN_INFO =
131
static gboolean film_dialog (gint32 image_ID);
132
static void film_reset_callback (GtkWidget *widget,
134
static void film_font_select_callback (GimpFontSelectButton *button,
140
const GimpPlugInInfo PLUG_IN_INFO =
160
142
NULL, /* init_proc */
161
143
NULL, /* quit_proc */
213
static GimpParamDef args[] =
215
{ GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
216
{ GIMP_PDB_IMAGE, "image", "Input image (only used as default image in interactive mode)" },
217
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable (not used)" },
218
{ GIMP_PDB_INT32, "film_height", "Height of film (0: fit to images)" },
219
{ GIMP_PDB_COLOR, "film_color", "Color of the film" },
220
{ GIMP_PDB_INT32, "number_start", "Start index for numbering" },
221
{ GIMP_PDB_STRING, "number_font", "Font for drawing numbers" },
222
{ GIMP_PDB_COLOR, "number_color", "Color for numbers" },
223
{ GIMP_PDB_INT32, "at_top", "Flag for drawing numbers at top of film" },
224
{ GIMP_PDB_INT32, "at_bottom", "Flag for drawing numbers at bottom of film" },
225
{ GIMP_PDB_INT32, "num_images", "Number of images to be used for film" },
226
{ GIMP_PDB_INT32ARRAY, "image_ids", "num_images image IDs to be used for film"}
229
static GimpParamDef return_vals[] =
231
{ GIMP_PDB_IMAGE, "new_image", "Output image" }
234
gimp_install_procedure ("plug_in_film",
235
"Compose several images to a roll film",
236
"Compose several images to a roll film",
237
"Peter Kirchgessner",
238
"Peter Kirchgessner (peter@kirchgessner.net)",
241
"INDEXED*, GRAY*, RGB*",
195
static const GimpParamDef args[] =
197
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
198
{ GIMP_PDB_IMAGE, "image", "Input image (only used as default image in interactive mode)" },
199
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable (not used)" },
200
{ GIMP_PDB_INT32, "film-height", "Height of film (0: fit to images)" },
201
{ GIMP_PDB_COLOR, "film-color", "Color of the film" },
202
{ GIMP_PDB_INT32, "number-start", "Start index for numbering" },
203
{ GIMP_PDB_STRING, "number-font", "Font for drawing numbers" },
204
{ GIMP_PDB_COLOR, "number-color", "Color for numbers" },
205
{ GIMP_PDB_INT32, "at-top", "Flag for drawing numbers at top of film" },
206
{ GIMP_PDB_INT32, "at-bottom", "Flag for drawing numbers at bottom of film" },
207
{ GIMP_PDB_INT32, "num-images", "Number of images to be used for film" },
208
{ GIMP_PDB_INT32ARRAY, "image-ids", "num_images image IDs to be used for film"}
211
static const GimpParamDef return_vals[] =
213
{ GIMP_PDB_IMAGE, "new-image", "Output image" }
216
gimp_install_procedure (PLUG_IN_PROC,
217
N_("Combine several images on a film strip"),
218
"Compose several images to a roll film",
219
"Peter Kirchgessner",
220
"Peter Kirchgessner (peter@kirchgessner.net)",
223
"INDEXED*, GRAY*, RGB*",
244
226
G_N_ELEMENTS (return_vals),
247
gimp_plugin_menu_register ("plug_in_film", "<Image>/Filters/Combine");
229
gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Filters/Combine");
276
258
case GIMP_RUN_INTERACTIVE:
277
259
/* Possibly retrieve data */
278
gimp_get_data ("plug_in_film", &filmvals);
260
gimp_get_data (PLUG_IN_PROC, &filmvals);
280
262
/* First acquire information with a dialog */
281
263
if (! film_dialog (param[1].data.d_int32))
285
267
case GIMP_RUN_NONINTERACTIVE:
286
268
/* Make sure all the arguments are there! */
287
269
/* Also we want to have some images to compose */
288
270
if ((nparams != 12) || (param[10].data.d_int32 < 1))
290
status = GIMP_PDB_CALLING_ERROR;
272
status = GIMP_PDB_CALLING_ERROR;
294
276
filmvals.keep_height = (param[3].data.d_int32 <= 0);
295
277
filmvals.film_height = (filmvals.keep_height ?
296
128 : param[3].data.d_int32);
297
filmvals.film_color = param[4].data.d_color;
278
128 : param[3].data.d_int32);
279
filmvals.film_color = param[4].data.d_color;
298
280
filmvals.number_start = param[5].data.d_int32;
299
281
g_strlcpy (filmvals.number_font, param[6].data.d_string, FONT_LEN);
300
filmvals.number_color = param[7].data.d_color;
282
filmvals.number_color = param[7].data.d_color;
301
283
filmvals.number_pos[0] = param[8].data.d_int32;
302
284
filmvals.number_pos[1] = param[9].data.d_int32;
303
285
filmvals.num_images = param[10].data.d_int32;
354
gint width, height, tile_height, scan_lines;
356
gint film_height, film_width;
357
gint picture_width, picture_height, picture_space, picture_x0, picture_y0;
358
gint hole_offset, hole_width, hole_height, hole_space, hole_x;
359
gint number_height, num_images, num_pictures;
360
gint i, j, k, picture_count;
363
gint32 *image_ID_src, image_ID_dst, layer_ID_src, layer_ID_dst;
336
gint width, height, tile_height;
338
gint film_height, film_width;
339
gint picture_width, picture_height;
340
gint picture_space, picture_x0, picture_y0;
341
gint hole_offset, hole_width, hole_height, hole_space, hole_x;
342
gint number_height, num_images, num_pictures;
343
gint j, k, picture_count;
346
gint32 *image_ID_src, image_ID_dst, layer_ID_src, layer_ID_dst;
365
349
GimpDrawable *drawable_dst;
366
GimpPixelRgn pixel_rgn_dst;
350
GimpPixelRgn pixel_rgn_dst;
475
448
while (hole_x < film_width)
477
draw_hole_rgb (drawable_dst, hole_x,
479
hole_width, hole_height, hole);
480
draw_hole_rgb (drawable_dst, hole_x,
481
film_height-hole_offset-hole_height,
482
hole_width, hole_height, hole);
450
draw_hole_rgb (drawable_dst, hole_x,
452
hole_width, hole_height, hole);
453
draw_hole_rgb (drawable_dst, hole_x,
454
film_height-hole_offset-hole_height,
455
hole_width, hole_height, hole);
484
hole_x += hole_width + hole_space;
457
hole_x += hole_width + hole_space;
488
461
gimp_drawable_detach (drawable_dst);
490
464
/* Compose all images and layers */
492
466
picture_count = 0;
493
467
for (j = 0; j < num_images; j++)
495
width = gimp_image_width (image_ID_src[j]);
496
height = gimp_image_height (image_ID_src[j]);
469
image_ID_tmp = gimp_image_duplicate (image_ID_src[j]);
470
width = gimp_image_width (image_ID_tmp);
471
height = gimp_image_height (image_ID_tmp);
497
472
f = ((gdouble) picture_height) / (gdouble) height;
498
473
picture_width = width * f;
500
layers = gimp_image_get_layers (image_ID_src[j], &num_layers);
474
if (gimp_image_base_type (image_ID_tmp) != GIMP_RGB_IMAGE)
475
gimp_image_convert_rgb (image_ID_tmp);
476
gimp_image_scale (image_ID_tmp, picture_width, picture_height);
478
layers = gimp_image_get_layers (image_ID_tmp, &num_layers);
502
479
for (k = 0; k < num_layers; k++)
504
if (gimp_layer_is_floating_sel (layers[k]))
507
picture_x0 += picture_space / 2;
509
layer_ID_src = layers[k];
510
/* Scale the layer and insert int new image */
511
if (! scale_layer (layer_ID_src, 0, 0, width, height,
512
layer_ID_dst, picture_x0, picture_y0,
513
picture_width, picture_height))
515
g_warning ("film: error during scale_layer\n");
519
/* Draw picture numbers */
520
if ((number_height > 0) &&
521
(filmvals.number_pos[0] || filmvals.number_pos[1]))
523
if (filmvals.number_pos[0])
524
draw_number (layer_ID_dst, filmvals.number_start + picture_count,
525
picture_x0 + picture_width/2,
526
(hole_offset-number_height)/2, number_height);
527
if (filmvals.number_pos[1])
528
draw_number (layer_ID_dst, filmvals.number_start + picture_count,
529
picture_x0 + picture_width/2,
530
film_height - (hole_offset + number_height)/2,
534
picture_x0 += picture_width + (picture_space/2);
481
if (gimp_layer_is_floating_sel (layers[k]))
484
picture_x0 += picture_space / 2;
486
layer_ID_src = layers[k];
487
gimp_layer_resize_to_image_size (layer_ID_src);
488
new_layer = gimp_layer_new_from_drawable (layer_ID_src,
490
gimp_image_add_layer (image_ID_dst, new_layer, -1);
491
gimp_layer_set_offsets (new_layer, picture_x0, picture_y0);
493
/* Draw picture numbers */
494
if ((number_height > 0) &&
495
(filmvals.number_pos[0] || filmvals.number_pos[1]))
497
if (filmvals.number_pos[0])
498
draw_number (layer_ID_dst,
499
filmvals.number_start + picture_count,
500
picture_x0 + picture_width/2,
501
(hole_offset-number_height)/2, number_height);
502
if (filmvals.number_pos[1])
503
draw_number (layer_ID_dst,
504
filmvals.number_start + picture_count,
505
picture_x0 + picture_width/2,
506
film_height - (hole_offset + number_height)/2,
510
picture_x0 += picture_width + (picture_space/2);
536
512
gimp_progress_update (((gdouble) (picture_count + 1)) /
537
513
(gdouble) num_pictures);
519
gimp_image_delete (image_ID_tmp);
522
gimp_image_flatten (image_ID_dst);
545
524
/* Drawing text/numbers leaves us with a floating selection. Stop it */
546
gimp_floating_sel_anchor (gimp_image_get_floating_sel (image_ID_dst));
525
floating_sel = gimp_image_get_floating_sel (image_ID_dst);
526
if (floating_sel != -1)
527
gimp_floating_sel_anchor (floating_sel);
548
529
gimp_context_pop ();
674
/* Scales a portion of a layer and places it in another layer. */
675
/* On success, TRUE is returned. Otherwise FALSE is returned */
677
scale_layer (gint32 src_layer,
688
gint tile_height, i, scan_lines, numpix;
689
guchar *src, *tmp = (guchar *) ident; /* Just to satisfy gcc */
690
gint32 tmp_image, tmp_layer;
691
GimpDrawable *tmp_drawable, *src_drawable, *dst_drawable;
692
GimpPixelRgn tmp_pixel_rgn, src_pixel_rgn, dst_pixel_rgn;
694
tile_height = gimp_tile_height ();
696
src_drawable = gimp_drawable_get (src_layer);
698
/*** Get a RGB copy of the source region ***/
700
tmp_image = create_new_image (_("Temporary"), src_width, src_height,
702
&tmp_layer, &tmp_drawable, &tmp_pixel_rgn);
704
src = g_new (guchar, src_width * tile_height * src_drawable->bpp);
705
tmp = g_new (guchar, src_width * tile_height * tmp_drawable->bpp);
707
gimp_pixel_rgn_init (&src_pixel_rgn, src_drawable, src_x0, src_y0,
708
src_width, src_height, FALSE, FALSE);
711
while (i < src_height)
713
scan_lines = (i+tile_height-1 < src_height) ? tile_height : (src_height-i);
714
numpix = scan_lines*src_width;
716
/* Get part of source image */
717
gimp_pixel_rgn_get_rect (&src_pixel_rgn, src, src_x0, src_y0+i,
718
src_width, scan_lines);
720
convert_to_rgb (src_drawable, numpix, src, tmp);
722
/* Set part of temporary image */
723
gimp_pixel_rgn_set_rect (&tmp_pixel_rgn, tmp, 0, i, src_width, scan_lines);
728
/* Now we have an image that is a copy of the */
729
/* source region and has been converted to RGB. */
730
/* We dont need any more access to the source image. */
731
gimp_drawable_detach (src_drawable);
734
/*** Resize the temporary image if necessary ***/
735
if ((src_width != dst_width) || (src_height != dst_height))
737
gimp_drawable_detach (tmp_drawable);
739
gimp_layer_scale (tmp_layer, dst_width, dst_height, 0);
741
tmp_drawable = gimp_drawable_get (tmp_layer);
744
/*** Copy temporary image to destination image */
745
gimp_pixel_rgn_init (&tmp_pixel_rgn, tmp_drawable, 0, 0,
746
dst_width, dst_height, FALSE, FALSE);
749
tmp = g_new (guchar, dst_width * tile_height * tmp_drawable->bpp);
751
dst_drawable = gimp_drawable_get (dst_layer);
752
gimp_pixel_rgn_init (&dst_pixel_rgn, dst_drawable, dst_x0, dst_y0,
753
dst_width, dst_height, TRUE, FALSE);
755
while (i < dst_height)
757
scan_lines = (i+tile_height-1 < dst_height) ? tile_height : (dst_height-i);
759
/* Get strip of temporary image */
760
gimp_pixel_rgn_get_rect (&tmp_pixel_rgn, tmp, 0, i,
761
dst_width, scan_lines);
763
/* Set strip of destination image */
764
gimp_pixel_rgn_set_rect (&dst_pixel_rgn, tmp, dst_x0, dst_y0+i,
765
dst_width, scan_lines);
769
/* No more access to the temporary image */
770
gimp_drawable_detach (tmp_drawable);
772
gimp_image_delete (tmp_image);
774
gimp_drawable_detach (dst_drawable);
779
577
/* Create the RGB-pixels that make up the hole */
781
579
create_hole_rgb (gint width,
784
582
guchar *hole, *top, *bottom;
785
gint radius, length, k;
583
gint radius, length, k;
787
585
hole = g_new (guchar, width * height * 3);
1249
1049
/* Startindex */
1250
1050
spinbutton = gimp_spin_button_new (&adj, filmvals.number_start, 0,
1251
GIMP_MAX_IMAGE_SIZE, 1, 10, 0, 1, 0);
1051
GIMP_MAX_IMAGE_SIZE, 1, 10, 0, 1, 0);
1252
1052
label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
1253
1053
_("Start _index:"), 0.0, 0.5,
1254
1054
spinbutton, 1, TRUE);
1255
1055
gtk_size_group_add_widget (group, label);
1257
g_signal_connect (adj, "value_changed",
1057
g_signal_connect (adj, "value-changed",
1258
1058
G_CALLBACK (gimp_int_adjustment_update),
1259
1059
&filmvals.number_start);
1261
1061
/* Fontfamily for numbering */
1262
font_sel = gimp_font_select_widget_new (NULL,
1263
filmvals.number_font,
1264
film_font_select_callback,
1062
font_button = gimp_font_select_button_new (NULL, filmvals.number_font);
1063
g_signal_connect (font_button, "font-set",
1064
G_CALLBACK (film_font_select_callback), &filmvals);
1266
1065
label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
1267
1066
_("_Font:"), 0.0, 0.5,
1268
font_sel, 1, FALSE);
1067
font_button, 1, FALSE);
1269
1068
gtk_size_group_add_widget (group, label);
1271
1070
/* Numbering color */
1272
1071
button = gimp_color_button_new (_("Select Number Color"),
1273
COLOR_BUTTON_WIDTH, COLOR_BUTTON_HEIGHT,
1274
&filmvals.number_color,
1275
GIMP_COLOR_AREA_FLAT);
1072
COLOR_BUTTON_WIDTH, COLOR_BUTTON_HEIGHT,
1073
&filmvals.number_color,
1074
GIMP_COLOR_AREA_FLAT);
1276
1075
label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
1277
1076
_("Co_lor:"), 0.0, 0.5,
1278
1077
button, 1, FALSE);
1279
1078
gtk_size_group_add_widget (group, label);
1281
g_signal_connect (button, "color_changed",
1080
g_signal_connect (button, "color-changed",
1282
1081
G_CALLBACK (gimp_color_button_get_color),
1283
1082
&filmvals.number_color);
1349
1148
filmint.advanced_adj[0] = adj =
1350
1149
gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
1351
_("Image _height:"), 0, 0,
1352
filmvals.picture_height,
1353
0.0, 1.0, 0.001, 0.01, 3,
1356
g_signal_connect (adj, "value_changed",
1150
_("Image _height:"), 0, 0,
1151
filmvals.picture_height,
1152
0.0, 1.0, 0.001, 0.01, 3,
1155
g_signal_connect (adj, "value-changed",
1357
1156
G_CALLBACK (gimp_double_adjustment_update),
1358
1157
&filmvals.picture_height);
1360
1159
filmint.advanced_adj[1] = adj =
1361
1160
gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
1362
_("Image spac_ing:"), 0, 0,
1363
filmvals.picture_space,
1364
0.0, 1.0, 0.001, 0.01, 3,
1367
g_signal_connect (adj, "value_changed",
1161
_("Image spac_ing:"), 0, 0,
1162
filmvals.picture_space,
1163
0.0, 1.0, 0.001, 0.01, 3,
1166
g_signal_connect (adj, "value-changed",
1368
1167
G_CALLBACK (gimp_double_adjustment_update),
1369
1168
&filmvals.picture_space);
1371
1170
filmint.advanced_adj[2] = adj =
1372
1171
gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
1373
_("_Hole offset:"), 0, 0,
1374
filmvals.hole_offset,
1375
0.0, 1.0, 0.001, 0.01, 3,
1378
g_signal_connect (adj, "value_changed",
1172
_("_Hole offset:"), 0, 0,
1173
filmvals.hole_offset,
1174
0.0, 1.0, 0.001, 0.01, 3,
1177
g_signal_connect (adj, "value-changed",
1379
1178
G_CALLBACK (gimp_double_adjustment_update),
1380
1179
&filmvals.hole_offset);
1382
1181
filmint.advanced_adj[3] = adj =
1383
1182
gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
1384
_("Ho_le width:"), 0, 0,
1385
filmvals.hole_width,
1386
0.0, 1.0, 0.001, 0.01, 3,
1389
g_signal_connect (adj, "value_changed",
1183
_("Ho_le width:"), 0, 0,
1184
filmvals.hole_width,
1185
0.0, 1.0, 0.001, 0.01, 3,
1188
g_signal_connect (adj, "value-changed",
1390
1189
G_CALLBACK (gimp_double_adjustment_update),
1391
1190
&filmvals.hole_width);
1393
1192
filmint.advanced_adj[4] = adj =
1394
1193
gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
1395
_("Hol_e height:"), 0, 0,
1396
filmvals.hole_height,
1397
0.0, 1.0, 0.001, 0.01, 3,
1400
g_signal_connect (adj, "value_changed",
1194
_("Hol_e height:"), 0, 0,
1195
filmvals.hole_height,
1196
0.0, 1.0, 0.001, 0.01, 3,
1199
g_signal_connect (adj, "value-changed",
1401
1200
G_CALLBACK (gimp_double_adjustment_update),
1402
1201
&filmvals.hole_height);
1404
1203
filmint.advanced_adj[5] = adj =
1405
1204
gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
1406
_("Hole sp_acing:"), 0, 0,
1407
filmvals.hole_space,
1408
0.0, 1.0, 0.001, 0.01, 3,
1411
g_signal_connect (adj, "value_changed",
1205
_("Hole sp_acing:"), 0, 0,
1206
filmvals.hole_space,
1207
0.0, 1.0, 0.001, 0.01, 3,
1210
g_signal_connect (adj, "value-changed",
1412
1211
G_CALLBACK (gimp_double_adjustment_update),
1413
1212
&filmvals.hole_space);
1415
1214
filmint.advanced_adj[6] = adj =
1416
1215
gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
1417
_("_Number height:"), 0, 0,
1418
filmvals.number_height,
1419
0.0, 1.0, 0.001, 0.01, 3,
1422
g_signal_connect (adj, "value_changed",
1216
_("_Number height:"), 0, 0,
1217
filmvals.number_height,
1218
0.0, 1.0, 0.001, 0.01, 3,
1221
g_signal_connect (adj, "value-changed",
1423
1222
G_CALLBACK (gimp_double_adjustment_update),
1424
1223
&filmvals.number_height);
1444
1243
GtkWidget *notebook;
1447
gimp_ui_init ("film", TRUE);
1246
gimp_ui_init (PLUG_IN_BINARY, TRUE);
1449
dlg = gimp_dialog_new (_("Film"), "film",
1248
dlg = gimp_dialog_new (_("Filmstrip"), PLUG_IN_BINARY,
1451
gimp_standard_help_func, "plug-in-film",
1453
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1454
GTK_STOCK_OK, GTK_RESPONSE_OK,
1250
gimp_standard_help_func, PLUG_IN_PROC,
1252
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1253
GTK_STOCK_OK, GTK_RESPONSE_OK,
1257
gtk_dialog_set_alternative_button_order (GTK_DIALOG (dlg),
1259
GTK_RESPONSE_CANCEL,
1262
gimp_window_set_transient (GTK_WINDOW (dlg));
1458
1264
main_vbox = gtk_vbox_new (FALSE, 12);
1459
1265
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);