/* GIMP - The GNU Image Manipulation Program * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis * * gimppropgui-convolution-matrix.c * Copyright (C) 2002-2014 Michael Natterer * Sven Neumann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include #include #include "libgimpwidgets/gimpwidgets.h" #include "propgui-types.h" #include "core/gimpcontext.h" #include "gimppropgui.h" #include "gimppropgui-convolution-matrix.h" #include "gimppropgui-generic.h" #include "gimp-intl.h" static const gchar * convolution_matrix_prop_name (gint x, gint y) { static const gchar * const prop_names[5][5] = { {"a1", "a2", "a3", "a4", "a5"}, {"b1", "b2", "b3", "b4", "b5"}, {"c1", "c2", "c3", "c4", "c5"}, {"d1", "d2", "d3", "d4", "d5"}, {"e1", "e2", "e3", "e4", "e5"}}; return prop_names[x][y]; } static void convolution_matrix_rotate_flip (GtkWidget *button, GObject *config) { gint rotate = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "convolution-matrix-rotate")); gint flip = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "convolution-matrix-flip")); gint x, y; while (rotate--) { for (y = 0; y < 2; y++) { for (x = y; x < 4 - y; x++) { gint i; gdouble temp; g_object_get (config, convolution_matrix_prop_name (x, y), &temp, NULL); for (i = 0; i < 4; i++) { gint next_x, next_y; gdouble val; next_x = 4 - y; next_y = x; if (i < 3) { g_object_get (config, convolution_matrix_prop_name (next_x, next_y), &val, NULL); } else { val = temp; } g_object_set (config, convolution_matrix_prop_name (x, y), val, NULL); x = next_x; y = next_y; } } } } while (flip--) { for (y = 0; y < 5; y++) { for (x = 0; x < 2; x++) { gdouble val1, val2; g_object_get (config, convolution_matrix_prop_name (x, y), &val1, NULL); g_object_get (config, convolution_matrix_prop_name (4 - x, y), &val2, NULL); g_object_set (config, convolution_matrix_prop_name (x, y), val2, NULL); g_object_set (config, convolution_matrix_prop_name (4 - x, y), val1, NULL); } } } } GtkWidget * _gimp_prop_gui_new_convolution_matrix (GObject *config, GParamSpec **param_specs, guint n_param_specs, GeglRectangle *area, GimpContext *context, GimpCreatePickerFunc create_picker_func, GimpCreateControllerFunc create_controller_func, gpointer creator) { GtkWidget *main_vbox; GtkWidget *vbox; GtkWidget *table; GtkWidget *hbox; GtkWidget *scale; GtkWidget *vbox2; const gchar *label; gint x, y; g_return_val_if_fail (G_IS_OBJECT (config), NULL); g_return_val_if_fail (param_specs != NULL, NULL); g_return_val_if_fail (n_param_specs > 0, NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0); gtk_widget_show (vbox); /* matrix */ table = gtk_table_new (5, 5, TRUE); gtk_table_set_row_spacings (GTK_TABLE (table), 2); gtk_table_set_col_spacings (GTK_TABLE (table), 4); gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); gtk_widget_show (table); for (y = 0; y < 5; y++) { for (x = 0; x < 5; x++) { GtkWidget *spin; spin = gimp_prop_spin_button_new (config, convolution_matrix_prop_name (x, y), 1.0, 10.0, 2); gtk_entry_set_width_chars (GTK_ENTRY (spin), 8); gtk_table_attach (GTK_TABLE (table), spin, x, x + 1, y, y + 1, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); gtk_widget_show (spin); } } /* rotate / flip buttons */ { typedef struct { const gchar *tooltip; const gchar *icon_name; gint rotate; gint flip; } ButtonInfo; gint i; const ButtonInfo buttons[] = { { .tooltip = _("Rotate matrix 90° counter-clockwise"), .icon_name = GIMP_ICON_OBJECT_ROTATE_270, .rotate = 1, .flip = 0 }, { .tooltip = _("Rotate matrix 90° clockwise"), .icon_name = GIMP_ICON_OBJECT_ROTATE_90, .rotate = 3, .flip = 0 }, { .tooltip = _("Flip matrix horizontally"), .icon_name = GIMP_ICON_OBJECT_FLIP_HORIZONTAL, .rotate = 0, .flip = 1 }, { .tooltip = _("Flip matrix vertically"), .icon_name = GIMP_ICON_OBJECT_FLIP_VERTICAL, .rotate = 2, .flip = 1 }}; hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); for (i = 0; i < G_N_ELEMENTS (buttons); i++) { const ButtonInfo *info = &buttons[i]; GtkWidget *button; GtkWidget *image; button = gtk_button_new (); gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); gtk_widget_set_tooltip_text (button, info->tooltip); gtk_widget_set_can_focus (button, FALSE); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); gtk_widget_show (button); image = gtk_image_new_from_icon_name (info->icon_name, GTK_ICON_SIZE_BUTTON); gtk_container_add (GTK_CONTAINER (button), image); gtk_widget_show (image); g_object_set_data (G_OBJECT (button), "convolution-matrix-rotate", GINT_TO_POINTER (info->rotate)); g_object_set_data (G_OBJECT (button), "convolution-matrix-flip", GINT_TO_POINTER (info->flip)); g_signal_connect (button, "clicked", G_CALLBACK (convolution_matrix_rotate_flip), config); } } vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0); gtk_widget_show (vbox); /* divisor / offset spin scales */ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); scale = gimp_prop_widget_new (config, "divisor", area, context, NULL, NULL, NULL, &label); gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0); gtk_widget_show (scale); scale = gimp_prop_widget_new (config, "offset", area, context, NULL, NULL, NULL, &label); gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0); gtk_widget_show (scale); /* rest of the properties */ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); vbox2 = _gimp_prop_gui_new_generic (config, param_specs + 27, 4, area, context, create_picker_func, create_controller_func, creator); gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0); gtk_widget_show (vbox2); vbox2 = _gimp_prop_gui_new_generic (config, param_specs + 31, n_param_specs - 31, area, context, create_picker_func, create_controller_func, creator); gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0); gtk_widget_show (vbox2); return main_vbox; }