148
168
1, /* Alpha-handling algorithm */
149
169
CLEAR, /* border-mode */
150
{ 1, 1, 1, 1, 1 }, /* Channels mask */
154
static config my_config;
170
{ TRUE, TRUE, TRUE, TRUE, TRUE }, /* Channels mask */
176
static const config_struct default_config =
179
{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
180
{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
181
{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
182
{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
183
{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
184
{ 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
185
{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
186
{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
187
{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
188
{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
189
{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }
193
1, /* Alpha-handling algorithm */
194
CLEAR, /* border-mode */
195
{ TRUE, TRUE, TRUE, TRUE, TRUE }, /* Channels mask */
202
static config_struct config;
158
GtkWidget *matrix[5][5];
206
GtkWidget *matrix[MATRIX_SIZE][MATRIX_SIZE];
159
207
GtkWidget *divisor;
160
208
GtkWidget *offset;
161
GtkWidget *alpha_alg;
163
GtkWidget *channels[5];
209
GtkWidget *alpha_weighting;
210
GtkWidget *bmode[BORDER_MODES];
211
GtkWidget *channels[CHANNELS];
164
212
GtkWidget *autoset;
173
static GimpParamDef args[] =
221
static const GimpParamDef args[] =
175
{ GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
176
{ GIMP_PDB_IMAGE, "image", "Input image (unused)" },
177
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
178
{ GIMP_PDB_INT32, "argc_matrix", "The number of elements in the following array. Should be always 25." },
179
{ GIMP_PDB_FLOATARRAY, "matrix", "The 5x5 convolution matrix" },
180
{ GIMP_PDB_INT32, "alpha_alg", "Enable weighting by alpha channel" },
181
{ GIMP_PDB_FLOAT, "divisor", "Divisor" },
182
{ GIMP_PDB_FLOAT, "offset", "Offset" },
223
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
224
{ GIMP_PDB_IMAGE, "image", "Input image (unused)" },
225
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
226
{ GIMP_PDB_INT32, "argc-matrix", "The number of elements in the following array. Should be always 25." },
227
{ GIMP_PDB_FLOATARRAY, "matrix", "The 5x5 convolution matrix" },
228
{ GIMP_PDB_INT32, "alpha-alg", "Enable weighting by alpha channel" },
229
{ GIMP_PDB_FLOAT, "divisor", "Divisor" },
230
{ GIMP_PDB_FLOAT, "offset", "Offset" },
184
{ GIMP_PDB_INT32, "argc_channels", "The number of elements in following array. Should be always 5." },
185
{ GIMP_PDB_INT32ARRAY, "channels", "Mask of the channels to be filtered" },
186
{ GIMP_PDB_INT32, "bmode", "Mode for treating image borders" }
232
{ GIMP_PDB_INT32, "argc-channels", "The number of elements in following array. Should be always 5." },
233
{ GIMP_PDB_INT32ARRAY, "channels", "Mask of the channels to be filtered" },
234
{ GIMP_PDB_INT32, "bmode", "Mode for treating image borders" },
189
gimp_install_procedure ("plug_in_convmatrix",
190
"A generic 5x5 convolution matrix",
195
N_("_Convolution Matrix..."),
198
G_N_ELEMENTS (args), 0,
237
gimp_install_procedure (PLUG_IN_PROC,
238
N_("Apply a generic 5x5 convolution matrix"),
243
N_("_Convolution Matrix..."),
246
G_N_ELEMENTS (args), 0,
201
gimp_plugin_menu_register ("plug_in_convmatrix", "<Image>/Filters/Generic");
249
gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Filters/Generic");
223
272
/* Get the specified drawable */
224
273
drawable = gimp_drawable_get (param[2].data.d_drawable);
226
/* The plug-in is not able to handle images smaller than 3 pixels */
275
/* The plug-in is not able to handle images smaller than 3x3 pixels */
227
276
if (drawable->width < 3 || drawable->height < 3)
229
g_message (_("Convolution Matrix does not work on layers "
230
"smaller than 3 pixels."));
278
g_message (_("Convolution does not work on layers "
279
"smaller than 3x3 pixels."));
231
280
status = GIMP_PDB_EXECUTION_ERROR;
232
281
values[0].type = GIMP_PDB_STATUS;
233
282
values[0].data.d_status = status;
237
my_config = default_config;
286
config = default_config;
238
287
if (run_mode == GIMP_RUN_NONINTERACTIVE)
289
if ((nparams != 11) && (nparams != 12))
242
291
status = GIMP_PDB_CALLING_ERROR;
246
if (param[3].data.d_int32 != 25)
248
status = GIMP_PDB_CALLING_ERROR;
252
for (y = 0; y < 5; y++)
253
for (x = 0; x < 5; x++)
254
my_config.matrix[x][y]=param[4].data.d_floatarray[y*5+x];
257
my_config.alpha_alg = param[5].data.d_int32;
258
my_config.divisor = param[6].data.d_float;
259
my_config.offset = param[7].data.d_float;
262
if (param[8].data.d_int32 != 5)
264
status = GIMP_PDB_CALLING_ERROR;
268
for (y = 0; y < 5; y++)
269
my_config.channels[y] = param[9].data.d_int32array[y];
272
my_config.bmode = param[10].data.d_int32;
295
if (param[3].data.d_int32 != MATRIX_CELLS)
297
status = GIMP_PDB_CALLING_ERROR;
301
for (y = 0; y < MATRIX_SIZE; y++)
302
for (x = 0; x < MATRIX_SIZE; x++)
304
= param[4].data.d_floatarray[x * MATRIX_SIZE + y];
307
config.alpha_weighting = param[5].data.d_int32;
308
config.divisor = param[6].data.d_float;
309
config.offset = param[7].data.d_float;
311
if (param[8].data.d_int32 != CHANNELS)
313
status = GIMP_PDB_CALLING_ERROR;
317
for (y = 0; y < CHANNELS; y++)
318
config.channels[y] = param[9].data.d_int32array[y];
321
config.bmode = param[10].data.d_int32;
323
check_config (drawable);
279
gimp_get_data ("plug_in_convmatrix", &my_config);
328
gimp_get_data (PLUG_IN_PROC, &config);
281
330
if (run_mode == GIMP_RUN_INTERACTIVE)
283
/* Oh boy. We get to do a dialog box, because we can't really
284
* expect the user to set us up with the right values using gdb.
332
/* Oh boy. We get to do a dialog box, because we can't really
333
* expect the user to set us up with the right values using gdb.
335
check_config (drawable);
290
/* The dialog was closed, or something similarly evil happened. */
291
status = GIMP_PDB_EXECUTION_ERROR;
337
if (! convolve_image_dialog (drawable))
339
/* The dialog was closed, or something similarly evil happened. */
340
status = GIMP_PDB_EXECUTION_ERROR;
296
345
if (status == GIMP_PDB_SUCCESS)
298
347
/* Make sure that the drawable is gray or RGB color */
299
348
if (gimp_drawable_is_rgb (drawable->drawable_id) ||
300
gimp_drawable_is_gray (drawable->drawable_id))
302
gimp_progress_init (_("Applying convolution"));
303
gimp_tile_cache_ntiles (2 * (drawable->width /
304
gimp_tile_width () + 1));
308
if (run_mode != GIMP_RUN_NONINTERACTIVE)
309
gimp_displays_flush ();
311
if (run_mode == GIMP_RUN_INTERACTIVE)
312
gimp_set_data ("plug_in_convmatrix",
313
&my_config, sizeof (my_config));
349
gimp_drawable_is_gray (drawable->drawable_id))
351
gimp_progress_init (_("Applying convolution"));
352
gimp_tile_cache_ntiles (2 * (drawable->width /
353
gimp_tile_width () + 1));
354
convolve_image (drawable, NULL);
356
if (run_mode != GIMP_RUN_NONINTERACTIVE)
357
gimp_displays_flush ();
359
if (run_mode == GIMP_RUN_INTERACTIVE)
360
gimp_set_data (PLUG_IN_PROC, &config, sizeof (config));
317
status = GIMP_PDB_EXECUTION_ERROR;
364
status = GIMP_PDB_EXECUTION_ERROR;
320
367
gimp_drawable_detach (drawable);
328
375
/* A generic wrapper to gimp_pixel_rgn_get_row which handles unlimited
329
* wrapping or gives you transparent regions outside the image
376
* wrapping or gives the transparent regions outside the image
377
* fills additional bytes before and after image row to provide border modes.
333
381
my_get_row (GimpPixelRgn *PR,
339
gint width, height, bytes;
387
gint width, height, bpp;
342
390
width = PR->drawable->width;
343
391
height = PR->drawable->height;
344
bytes = PR->drawable->bpp;
392
bpp = PR->drawable->bpp;
346
394
/* Y-wrappings */
348
switch (my_config.bmode)
395
switch (config.bmode)
351
398
/* Wrapped, so we get the proper row from the other side */
352
399
while (y < 0) /* This is the _sure_ way to wrap. :) */
354
401
while (y >= height)
359
406
/* Beyond borders, so set full transparent. */
360
407
if (y < 0 || y >= height)
362
memset (dest, 0, w * bytes);
363
return; /* Done, so back. */
366
/* The border lines are _not_ duplicated in the mirror image */
368
while (y < 0 || y >= height)
373
y = 2 * height - y - 2; /* y=2*height-y-1 */
409
memset (dest, 0, w * bpp);
410
return; /* Done, so back. */
378
414
y = CLAMP (y , 0 , height - 1);
382
switch (my_config.bmode)
420
switch (config.bmode)
388
memset (dest, 0, i * bytes);
396
gimp_pixel_rgn_get_row (PR, dest, x, y, i);
402
memset (dest, 0, w * bytes);
426
memset (dest, 0, i * bpp);
434
gimp_pixel_rgn_get_row (PR, dest, x, y, i);
440
memset (dest, 0, w * bpp);
408
446
i = MIN (w, width - x);
409
447
gimp_pixel_rgn_get_row (PR, dest, x, y, i);
416
gimp_pixel_rgn_get_row (PR, dest, x, y, i);
454
gimp_pixel_rgn_get_row (PR, dest, x, y, i);
425
gimp_pixel_rgn_get_pixel (PR, dest, 0, y);
463
gimp_pixel_rgn_get_pixel (PR, dest, 0, y);
432
for (i = 0; i < bytes; i++)
434
*dest = *(dest - bytes);
470
for (i = 0; i < bpp; i++)
472
*dest = *(dest - bpp);
441
479
if (w && width - x > 0)
443
i = MIN (w, width - x);
444
gimp_pixel_rgn_get_row (PR, dest, x, y, i);
481
i = MIN (w, width - x);
482
gimp_pixel_rgn_get_row (PR, dest, x, y, i);
450
for (i = 0; i < bytes; i++)
452
*dest= *(dest - bytes);
488
for (i = 0; i < bpp; i++)
490
*dest= *(dest - bpp);
460
case MIRROR: /* Not yet handled */
466
calcmatrix (guchar **srcrow,
502
convolve_pixel (guchar **src_row,
505
GimpDrawable *drawable)
470
static gfloat matrixsum = 0;
471
static gint bytes = 0;
507
static gfloat matrixsum = 0; /* FIXME: this certainly breaks the preview */
480
bytes = drawable->bpp;
481
for (y = 0; y < 5; y++)
482
for (x = 0; x < 5; x++)
484
temp = my_config.matrix[x][y];
485
matrixsum += ABS (temp);
520
for (y = 0; y < MATRIX_SIZE; y++)
521
for (x = 0; x < MATRIX_SIZE; x++)
523
temp = config.matrix[x][y];
524
matrixsum += ABS (config.matrix[x][y]);
488
for (y = 0; y < 5; y++)
489
for (x = 0; x < 5; x++)
528
alpha_channel = bpp - 1;
530
for (y = 0; y < MATRIX_SIZE; y++)
531
for (x = 0; x < MATRIX_SIZE; x++)
491
temp = my_config.matrix[x][y];
492
if (i != (bytes - 1) && my_config.alpha_alg == 1)
494
temp *= srcrow[y][xoff + x * bytes +bytes - 1 - i];
495
alphasum += ABS (temp);
497
temp *= srcrow[y][xoff + x * bytes];
533
temp = config.matrix[x][y];
535
if (channel != alpha_channel && config.alpha_weighting == 1)
537
temp *= src_row[y][x_offset + x * bpp + alpha_channel - channel];
538
alphasum += ABS (temp);
541
temp *= src_row[y][x_offset + x * bpp];
500
sum /= my_config.divisor;
501
if (i != (bytes - 1) && my_config.alpha_alg == 1)
545
sum /= config.divisor;
547
if (channel != alpha_channel && config.alpha_weighting == 1)
503
549
if (alphasum != 0)
504
sum = sum * matrixsum / alphasum;
550
sum = sum * matrixsum / alphasum;
507
/* sum = srcrow[2][xoff + 2 * bytes] * my_config.matrix[2][2];*/
509
sum += my_config.offset;
555
sum += config.offset;
561
convolve_image (GimpDrawable *drawable,
562
GimpPreview *preview)
517
564
GimpPixelRgn srcPR, destPR;
518
565
gint width, height, row, col;
520
gint sx1, sy1, sx2, sy2;
566
gint src_w, src_row_w, src_h, i;
567
gint src_x1, src_y1, src_x2, src_y2;
521
568
gint x1, x2, y1, y2;
569
guchar *dest_row[DEST_ROWS];
570
guchar *src_row[MATRIX_SIZE];
574
gboolean chanmask[CHANNELS-1];
575
gint bpp,channel,alpha_channel;
529
577
/* Get the input area. This is the bounding box of the selection in
530
578
* the image (or the entire image if there is no selection). Only
532
580
* need to be done for correct operation. (It simply makes it go
533
581
* faster, since fewer pixels need to be operated on).
535
gimp_drawable_mask_bounds (drawable->drawable_id, &sx1, &sy1, &sx2, &sy2);
585
gimp_preview_get_position (preview, &src_x1, &src_y1);
586
gimp_preview_get_size (preview, &src_w, &src_h);
587
src_x2 = src_x1 + src_w;
588
src_y2 = src_y1 + src_h;
592
gimp_drawable_mask_bounds (drawable->drawable_id,
593
&src_x1, &src_y1, &src_x2, &src_y2);
594
src_w = src_x2 - src_x1;
595
src_h = src_y2 - src_y1;
539
598
/* Get the size of the input image. (This will/must be the same
540
599
* as the size of the output image.
542
601
width = drawable->width;
543
602
height = drawable->height;
544
bytes = drawable->bpp;
604
alpha_channel = bpp - 1;
546
606
if (gimp_drawable_is_rgb (drawable->drawable_id))
547
for (i = 0; i <3; i++)
548
chanmask[i] = my_config.channels[i + 1];
608
for (i = 0; i <CHANNELS; i++)
609
chanmask[i] = config.channels[i + 1];
549
611
else /* Grayscale */
550
chanmask[0] = my_config.channels[0];
612
chanmask[0] = config.channels[0];
552
614
if (gimp_drawable_has_alpha (drawable->drawable_id))
553
chanmask[bytes - 1] = my_config.channels[4];
555
for (i = 0; i < 5; i++)
556
srcrow[i] = g_new (guchar, (w + 4) * bytes);
557
for (i = 0; i < 3; i++)
558
destrow[i]= g_new (guchar, w * bytes);
615
chanmask[alpha_channel] = config.channels[alpha_channel];
617
src_row_w = src_w + HALF_WINDOW + HALF_WINDOW;
619
for (i = 0; i < MATRIX_SIZE; i++)
620
src_row[i] = g_new (guchar, src_row_w * bpp);
622
for (i = 0; i < DEST_ROWS; i++)
623
dest_row[i]= g_new (guchar, src_w * bpp);
560
625
/* initialize the pixel regions */
561
x1 = MAX (sx1 - 2, 0);
562
y1 = MAX (sy1 - 2, 0);
563
x2 = MIN (sx2 + 2, width);
564
y2 = MIN (sy2 + 2, height);
626
x1 = MAX (src_x1 - HALF_WINDOW, 0);
627
y1 = MAX (src_y1 - HALF_WINDOW, 0);
628
x2 = MIN (src_x2 + HALF_WINDOW, width);
629
y2 = MIN (src_y2 + HALF_WINDOW, height);
565
630
gimp_pixel_rgn_init (&srcPR, drawable,
566
631
x1, y1, x2 - x1, y2 - y1, FALSE, FALSE);
567
gimp_pixel_rgn_init (&destPR, drawable, sx1, sy1, w, h, TRUE, TRUE);
632
gimp_pixel_rgn_init (&destPR, drawable,
633
src_x1, src_y1, src_w, src_h,
634
preview == NULL, TRUE);
569
636
/* initialize source arrays */
570
for (i = 0; i < 5; i++)
571
my_get_row (&srcPR, srcrow[i], sx1 - 2, sy1 + i - 2, w + 4);
573
for (row = sy1; row < sy2; row++)
577
for (col = sx1; col < sx2; col++)
578
for (i = 0; i < bytes; i++)
580
if (chanmask[i] <= 0)
581
sum = srcrow[2][xoff + 2 * bytes];
583
sum = calcmatrix(srcrow, xoff, i);
585
destrow[2][xoff]= (guchar) CLAMP (sum, 0, 255);
590
gimp_pixel_rgn_set_row (&destPR, destrow[0], sx1, row - 2, w);
592
temprow = destrow[0];
593
destrow[0] = destrow[1];
594
destrow[1] = destrow[2];
595
destrow[2] = temprow;
598
for (i = 0; i < 4; i++)
599
srcrow[i] = srcrow[i + 1];
602
my_get_row (&srcPR, srcrow[4], sx1 - 2, row + 3, w + 4);
605
gimp_progress_update ((double) (row - sy1) / h);
608
/* put the final rows in the buffer in place */
610
gimp_pixel_rgn_set_row (&destPR, destrow[2], sx1, row - 3, w);
612
gimp_pixel_rgn_set_row (&destPR, destrow[0], sx1, row - 2, w);
614
gimp_pixel_rgn_set_row (&destPR, destrow[1], sx1, row - 1, w);
616
/* update the timred region */
617
gimp_drawable_flush (drawable);
618
gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
619
gimp_drawable_update (drawable->drawable_id, sx1, sy1, sx2 - sx1, sy2 - sy1);
637
for (i = 0; i < MATRIX_SIZE; i++)
638
my_get_row (&srcPR, src_row[i], src_x1 - HALF_WINDOW,
639
src_y1 - HALF_WINDOW + i , src_row_w);
641
for (row = src_y1; row < src_y2; row++)
645
for (col = src_x1; col < src_x2; col++)
646
for (channel = 0; channel < bpp; channel++)
648
if (chanmask[channel])
649
sum = convolve_pixel(src_row, x_offset, channel, drawable);
651
sum = src_row[HALF_WINDOW][x_offset + HALF_WINDOW * bpp]; /* copy unmodified px */
653
dest_row[HALF_WINDOW][x_offset] = (guchar) CLAMP (sum, 0, 255);
657
if (row >= src_y1 + HALF_WINDOW)
658
gimp_pixel_rgn_set_row (&destPR, dest_row[0], src_x1, row - HALF_WINDOW, src_w);
660
if (row < src_y2 - 1)
662
tmp_row = dest_row[0];
663
for (i = 0; i < DEST_ROWS - 1; i++)
664
dest_row[i] = dest_row[i + 1];
666
dest_row[DEST_ROWS - 1] = tmp_row;
668
tmp_row = src_row[0];
669
for (i = 0; i < MATRIX_SIZE - 1; i++)
670
src_row[i] = src_row[i + 1];
671
src_row[MATRIX_SIZE-1] = tmp_row;
673
my_get_row (&srcPR, src_row[MATRIX_SIZE - 1],
674
src_x1 - HALF_WINDOW, row + HALF_WINDOW + 1, src_row_w);
677
if ((row % 10 == 0) && !preview)
678
gimp_progress_update ((double) (row - src_y1) / src_h);
681
/* put the remaining rows in the buffer in place */
682
for (i = 1; i < DEST_ROWS; i++)
683
gimp_pixel_rgn_set_row (&destPR, dest_row[i],
684
src_x1, src_y2 + i - 1 - HALF_WINDOW, src_w);
687
/* update the region */
690
gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview),
695
gimp_drawable_flush (drawable);
696
gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
697
gimp_drawable_update (drawable->drawable_id, src_x1, src_y1, src_x2 - src_x1, src_y2 - src_y1);
699
for (i = 0; i < MATRIX_SIZE; i++)
701
for (i = 0; i < DEST_ROWS; i++)
702
g_free (dest_row[i]);
622
705
/***************************************************
781
865
/* Checks that the configuration is valid for the image type */
867
check_config (GimpDrawable *drawable)
787
for (i = 0; i < 5; i++)
788
if (my_config.channels[i] < 0)
789
my_config.channels[i] = 0;
791
if (gimp_drawable_is_rgb (drawable->drawable_id))
792
my_config.channels[0] = -1;
793
else if (gimp_drawable_is_gray (drawable->drawable_id))
794
for (i = 1; i < 4; i++)
795
my_config.channels[i] = -1;
871
for (i = 0; i < CHANNELS; i++)
872
config.channels[i] = FALSE;
873
config.alpha_weighting = 0;
797
875
if (!gimp_drawable_has_alpha (drawable->drawable_id))
799
my_config.channels[4] = -1;
800
my_config.alpha_alg = -1;
801
my_config.bmode = EXTEND;
877
config.alpha_weighting = -1;
878
config.bmode = EXTEND;
806
883
entry_callback (GtkWidget *widget,
809
886
gfloat *value = (gfloat *) data;
811
888
*value = atof (gtk_entry_get_text (GTK_ENTRY (widget)));
816
if (widget == my_widgets.divisor)
890
if (widget == widget_set.divisor)
817
891
gtk_dialog_set_response_sensitive (GTK_DIALOG (gtk_widget_get_toplevel (widget)),
818
GTK_RESPONSE_OK, (*value != 0.0));
819
else if (widget != my_widgets.offset)
894
else if (widget != widget_set.offset)
825
900
my_toggle_callback (GtkWidget *widget,
828
903
gint val = GTK_TOGGLE_BUTTON (widget)->active;
831
*(gint *) data = TRUE;
833
*(gint *) data = FALSE;
835
if (widget == my_widgets.alpha_alg)
907
if (widget == widget_set.alpha_weighting)
837
gtk_widget_set_sensitive (my_widgets.bmode[CLEAR], val);
838
if (val == 0 && my_config.bmode == CLEAR)
840
my_config.bmode = EXTEND;
909
gtk_widget_set_sensitive (widget_set.bmode[CLEAR], val);
910
if (val == 0 && config.bmode == CLEAR)
912
config.bmode = EXTEND;
844
else if (widget == my_widgets.autoset)
916
else if (widget == widget_set.autoset)
846
gtk_widget_set_sensitive (my_widgets.divisor, !val);
847
gtk_widget_set_sensitive (my_widgets.offset, !val);
918
gtk_widget_set_sensitive (widget_set.divisor, !val);
919
gtk_widget_set_sensitive (widget_set.offset, !val);
853
925
my_bmode_callback (GtkWidget *widget,
856
my_config.bmode = GPOINTER_TO_INT (data) - 1;
928
config.bmode = GPOINTER_TO_INT (data) - 1;
932
convolve_image_dialog (GimpDrawable *drawable)
935
GtkWidget *main_vbox;
863
937
GtkWidget *main_hbox;
864
938
GtkWidget *table;
865
939
GtkWidget *label;
875
gimp_ui_init ("convmatrix", FALSE);
877
dlg = gimp_dialog_new (_("Convolution Matrix"), "convmatrix",
879
gimp_standard_help_func, "plug-in-convmatrix",
881
GIMP_STOCK_RESET, RESPONSE_RESET,
882
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
883
GTK_STOCK_OK, GTK_RESPONSE_OK,
887
g_signal_connect (dlg, "response",
888
G_CALLBACK (response_callback),
890
g_signal_connect (dlg, "destroy",
891
G_CALLBACK (gtk_main_quit),
949
gimp_ui_init (PLUG_IN_BINARY, FALSE);
951
dialog = gimp_dialog_new (_("Convolution Matrix"), PLUG_IN_BINARY,
953
gimp_standard_help_func, PLUG_IN_PROC,
955
GIMP_STOCK_RESET, RESPONSE_RESET,
956
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
957
GTK_STOCK_OK, GTK_RESPONSE_OK,
961
gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
967
gimp_window_set_transient (GTK_WINDOW (dialog));
969
main_vbox = gtk_vbox_new (FALSE, 12);
970
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
971
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), main_vbox);
972
gtk_widget_show (main_vbox);
974
preview = gimp_drawable_preview_new (drawable, NULL);
975
gtk_box_pack_start_defaults (GTK_BOX (main_vbox), preview);
976
gtk_widget_show (preview);
977
g_signal_connect_swapped (preview, "invalidated",
978
G_CALLBACK (convolve_image),
894
981
main_hbox = gtk_hbox_new (FALSE, 12);
895
gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
896
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), main_hbox,
982
gtk_box_pack_start (GTK_BOX (main_vbox), main_hbox, FALSE, FALSE, 0);
983
gtk_widget_show (main_hbox),
899
985
vbox = gtk_vbox_new (FALSE, 12);
900
986
gtk_box_pack_start (GTK_BOX (main_hbox), vbox, TRUE, TRUE, 0);
905
991
inbox = gtk_vbox_new (FALSE, 12);
906
992
gtk_container_add (GTK_CONTAINER (frame), inbox);
908
table = gtk_table_new (5, 5, FALSE);
994
table = gtk_table_new (MATRIX_SIZE, MATRIX_SIZE, FALSE);
909
995
gtk_table_set_row_spacings (GTK_TABLE (table), 4);
910
996
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
911
997
gtk_box_pack_start (GTK_BOX (inbox), table, TRUE, TRUE, 0);
913
for (y = 0; y < 5; y++)
914
for (x = 0; x < 5; x++)
999
for (y = 0; y < MATRIX_SIZE; y++)
1000
for (x = 0; x < MATRIX_SIZE; x++)
916
my_widgets.matrix[x][y] = entry = gtk_entry_new ();
917
gtk_widget_set_size_request (entry, 40, -1);
918
gtk_table_attach (GTK_TABLE (table), entry, x, x+1, y, y+1,
919
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
920
gtk_widget_show (entry);
1002
widget_set.matrix[x][y] = entry = gtk_entry_new ();
1003
gtk_widget_set_size_request (entry, 40, -1);
1004
gtk_table_attach (GTK_TABLE (table), entry, x, x+1, y, y+1,
1005
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
1006
gtk_widget_show (entry);
922
g_signal_connect (entry, "changed",
1008
g_signal_connect (entry, "changed",
923
1009
G_CALLBACK (entry_callback),
924
&my_config.matrix[x][y]);
1010
&config.matrix[x][y]);
1011
g_signal_connect_swapped (entry, "changed",
1012
G_CALLBACK (gimp_preview_invalidate),
927
1016
gtk_widget_show (table);
979
1077
box = gtk_vbox_new (FALSE, 6);
980
1078
gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, FALSE, 0);
982
my_widgets.autoset = button =
983
gtk_check_button_new_with_mnemonic (_("A_utomatic"));
1080
widget_set.autoset = button =
1081
gtk_check_button_new_with_mnemonic (_("N_ormalise"));
984
1082
gtk_box_pack_start (GTK_BOX (box), button, TRUE, FALSE, 0);
985
1083
gtk_widget_show (button);
987
1085
g_signal_connect (button, "toggled",
988
1086
G_CALLBACK (my_toggle_callback),
1088
g_signal_connect_swapped (button, "toggled",
1089
G_CALLBACK (gimp_preview_invalidate),
991
my_widgets.alpha_alg = button =
1092
widget_set.alpha_weighting = button =
992
1093
gtk_check_button_new_with_mnemonic (_("A_lpha-weighting"));
993
if (my_config.alpha_alg == -1)
1094
if (config.alpha_weighting == -1)
994
1095
gtk_widget_set_sensitive (button, FALSE);
995
1096
gtk_box_pack_start (GTK_BOX (box), button, TRUE, FALSE, 0);
996
1097
gtk_widget_show (button);
998
1099
g_signal_connect (button, "toggled",
999
1100
G_CALLBACK (my_toggle_callback),
1000
&my_config.alpha_alg);
1101
&config.alpha_weighting);
1102
g_signal_connect_swapped (button, "toggled",
1103
G_CALLBACK (gimp_preview_invalidate),
1002
1106
gtk_widget_show (box);
1003
1107
gtk_widget_show (vbox);
1035
1142
box = gtk_vbox_new (FALSE, 2);
1036
1143
gtk_container_add (GTK_CONTAINER (frame), box);
1038
for (i = 0; i < 5; i++)
1145
for (i = 0; i < CHANNELS; i++)
1040
my_widgets.channels[i] = button =
1041
gtk_check_button_new_with_mnemonic (gettext (channel_labels[i]));
1043
if (my_config.channels[i] < 0)
1044
gtk_widget_set_sensitive (button, FALSE);
1046
gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1047
gtk_widget_show (button);
1049
g_signal_connect (button, "toggled",
1050
G_CALLBACK (my_toggle_callback),
1051
&my_config.channels[i]);
1147
if ((gimp_drawable_is_gray (drawable->drawable_id) && i==0) ||
1148
(gimp_drawable_is_rgb (drawable->drawable_id) && i>=1 && i<=3) ||
1149
(gimp_drawable_has_alpha (drawable->drawable_id) && i==4))
1151
widget_set.channels[i] = button =
1152
gtk_check_button_new_with_mnemonic (gettext (channel_labels[i]));
1154
gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1155
gtk_widget_show (button);
1157
g_signal_connect (button, "toggled",
1158
G_CALLBACK (my_toggle_callback),
1159
&config.channels[i]);
1160
g_signal_connect_swapped (button, "toggled",
1161
G_CALLBACK (gimp_preview_invalidate),
1166
widget_set.channels[i] = NULL;
1054
1170
gtk_widget_show (box);