1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include <string.h>
21 
22 #include <gegl.h>
23 #include <gtk/gtk.h>
24 
25 #include "libgimpconfig/gimpconfig.h"
26 #include "libgimpwidgets/gimpwidgets.h"
27 
28 #include "tools-types.h"
29 
30 #include "operations/gimpbrightnesscontrastconfig.h"
31 
32 #include "core/gimpdrawable.h"
33 #include "core/gimperror.h"
34 #include "core/gimpimage.h"
35 
36 #include "widgets/gimphelp-ids.h"
37 #include "widgets/gimppropwidgets.h"
38 #include "widgets/gimpspinscale.h"
39 #include "widgets/gimpwidgets-constructors.h"
40 
41 #include "display/gimpdisplay.h"
42 
43 #include "gimpbrightnesscontrasttool.h"
44 #include "gimpfilteroptions.h"
45 #include "gimptoolcontrol.h"
46 
47 #include "gimp-intl.h"
48 
49 
50 #define SLIDER_WIDTH 200
51 
52 
53 static gboolean   gimp_brightness_contrast_tool_initialize (GimpTool              *tool,
54                                                             GimpDisplay           *display,
55                                                             GError               **error);
56 static void   gimp_brightness_contrast_tool_button_press   (GimpTool              *tool,
57                                                             const GimpCoords      *coords,
58                                                             guint32                time,
59                                                             GdkModifierType        state,
60                                                             GimpButtonPressType    press_type,
61                                                             GimpDisplay           *display);
62 static void   gimp_brightness_contrast_tool_button_release (GimpTool              *tool,
63                                                             const GimpCoords      *coords,
64                                                             guint32                time,
65                                                             GdkModifierType        state,
66                                                             GimpButtonReleaseType  release_type,
67                                                             GimpDisplay           *display);
68 static void   gimp_brightness_contrast_tool_motion         (GimpTool              *tool,
69                                                             const GimpCoords      *coords,
70                                                             guint32                time,
71                                                             GdkModifierType        state,
72                                                             GimpDisplay           *display);
73 
74 static gchar *
75               gimp_brightness_contrast_tool_get_operation  (GimpFilterTool        *filter_tool,
76                                                             gchar                **description);
77 static void   gimp_brightness_contrast_tool_dialog         (GimpFilterTool        *filter_tool);
78 
79 static void   brightness_contrast_to_levels_callback       (GtkWidget             *widget,
80                                                             GimpFilterTool        *filter_tool);
81 
82 
G_DEFINE_TYPE(GimpBrightnessContrastTool,gimp_brightness_contrast_tool,GIMP_TYPE_FILTER_TOOL)83 G_DEFINE_TYPE (GimpBrightnessContrastTool, gimp_brightness_contrast_tool,
84                GIMP_TYPE_FILTER_TOOL)
85 
86 #define parent_class gimp_brightness_contrast_tool_parent_class
87 
88 
89 void
90 gimp_brightness_contrast_tool_register (GimpToolRegisterCallback  callback,
91                                         gpointer                  data)
92 {
93   (* callback) (GIMP_TYPE_BRIGHTNESS_CONTRAST_TOOL,
94                 GIMP_TYPE_FILTER_OPTIONS, NULL,
95                 0,
96                 "gimp-brightness-contrast-tool",
97                 _("Brightness-Contrast"),
98                 _("Adjust brightness and contrast"),
99                 N_("B_rightness-Contrast..."), NULL,
100                 NULL, GIMP_HELP_TOOL_BRIGHTNESS_CONTRAST,
101                 GIMP_ICON_TOOL_BRIGHTNESS_CONTRAST,
102                 data);
103 }
104 
105 static void
gimp_brightness_contrast_tool_class_init(GimpBrightnessContrastToolClass * klass)106 gimp_brightness_contrast_tool_class_init (GimpBrightnessContrastToolClass *klass)
107 {
108   GimpToolClass       *tool_class        = GIMP_TOOL_CLASS (klass);
109   GimpFilterToolClass *filter_tool_class = GIMP_FILTER_TOOL_CLASS (klass);
110 
111   tool_class->initialize           = gimp_brightness_contrast_tool_initialize;
112   tool_class->button_press         = gimp_brightness_contrast_tool_button_press;
113   tool_class->button_release       = gimp_brightness_contrast_tool_button_release;
114   tool_class->motion               = gimp_brightness_contrast_tool_motion;
115 
116   filter_tool_class->get_operation = gimp_brightness_contrast_tool_get_operation;
117   filter_tool_class->dialog        = gimp_brightness_contrast_tool_dialog;
118 }
119 
120 static void
gimp_brightness_contrast_tool_init(GimpBrightnessContrastTool * bc_tool)121 gimp_brightness_contrast_tool_init (GimpBrightnessContrastTool *bc_tool)
122 {
123 }
124 
125 static gboolean
gimp_brightness_contrast_tool_initialize(GimpTool * tool,GimpDisplay * display,GError ** error)126 gimp_brightness_contrast_tool_initialize (GimpTool     *tool,
127                                           GimpDisplay  *display,
128                                           GError      **error)
129 {
130   GimpBrightnessContrastTool *bc_tool  = GIMP_BRIGHTNESS_CONTRAST_TOOL (tool);
131   GimpImage                  *image    = gimp_display_get_image (display);
132   GimpDrawable               *drawable = gimp_image_get_active_drawable (image);
133 
134   if (! GIMP_TOOL_CLASS (parent_class)->initialize (tool, display, error))
135     {
136       return FALSE;
137     }
138 
139   if (gimp_drawable_get_component_type (drawable) == GIMP_COMPONENT_TYPE_U8)
140     {
141       gimp_prop_widget_set_factor (bc_tool->brightness_scale,
142                                    127.0, 1.0, 8.0, 0);
143       gimp_prop_widget_set_factor (bc_tool->contrast_scale,
144                                    127.0, 1.0, 8.0, 0);
145     }
146   else
147     {
148       gimp_prop_widget_set_factor (bc_tool->brightness_scale,
149                                    0.5, 0.01, 0.1, 3);
150       gimp_prop_widget_set_factor (bc_tool->contrast_scale,
151                                    0.5, 0.01, 0.1, 3);
152     }
153 
154   return TRUE;
155 }
156 
157 static gchar *
gimp_brightness_contrast_tool_get_operation(GimpFilterTool * filter_tool,gchar ** description)158 gimp_brightness_contrast_tool_get_operation (GimpFilterTool  *filter_tool,
159                                              gchar          **description)
160 {
161   *description = g_strdup (_("Adjust Brightness and Contrast"));
162 
163   return g_strdup ("gimp:brightness-contrast");
164 }
165 
166 static void
gimp_brightness_contrast_tool_button_press(GimpTool * tool,const GimpCoords * coords,guint32 time,GdkModifierType state,GimpButtonPressType press_type,GimpDisplay * display)167 gimp_brightness_contrast_tool_button_press (GimpTool            *tool,
168                                             const GimpCoords    *coords,
169                                             guint32              time,
170                                             GdkModifierType      state,
171                                             GimpButtonPressType  press_type,
172                                             GimpDisplay         *display)
173 {
174   GimpBrightnessContrastTool *bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (tool);
175 
176   bc_tool->dragging = ! gimp_filter_tool_on_guide (GIMP_FILTER_TOOL (tool),
177                                                    coords, display);
178 
179   if (! bc_tool->dragging)
180     {
181       GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state,
182                                                     press_type, display);
183     }
184   else
185     {
186       gdouble brightness;
187       gdouble contrast;
188 
189       g_object_get (GIMP_FILTER_TOOL (tool)->config,
190                     "brightness", &brightness,
191                     "contrast",   &contrast,
192                     NULL);
193 
194       bc_tool->x  = coords->x - contrast   * 127.0;
195       bc_tool->y  = coords->y + brightness * 127.0;
196       bc_tool->dx =   contrast   * 127.0;
197       bc_tool->dy = - brightness * 127.0;
198 
199       tool->display = display;
200 
201       gimp_tool_control_activate (tool->control);
202     }
203 }
204 
205 static void
gimp_brightness_contrast_tool_button_release(GimpTool * tool,const GimpCoords * coords,guint32 time,GdkModifierType state,GimpButtonReleaseType release_type,GimpDisplay * display)206 gimp_brightness_contrast_tool_button_release (GimpTool              *tool,
207                                               const GimpCoords      *coords,
208                                               guint32                time,
209                                               GdkModifierType        state,
210                                               GimpButtonReleaseType  release_type,
211                                               GimpDisplay           *display)
212 {
213   GimpBrightnessContrastTool *bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (tool);
214 
215   if (! bc_tool->dragging)
216     {
217       GIMP_TOOL_CLASS (parent_class)->button_release (tool, coords, time, state,
218                                                       release_type, display);
219     }
220   else
221     {
222       gimp_tool_control_halt (tool->control);
223 
224       bc_tool->dragging = FALSE;
225 
226       if (bc_tool->dx == 0 && bc_tool->dy == 0)
227         return;
228 
229       if (release_type == GIMP_BUTTON_RELEASE_CANCEL)
230         gimp_config_reset (GIMP_CONFIG (GIMP_FILTER_TOOL (tool)->config));
231     }
232 }
233 
234 static void
gimp_brightness_contrast_tool_motion(GimpTool * tool,const GimpCoords * coords,guint32 time,GdkModifierType state,GimpDisplay * display)235 gimp_brightness_contrast_tool_motion (GimpTool         *tool,
236                                       const GimpCoords *coords,
237                                       guint32           time,
238                                       GdkModifierType   state,
239                                       GimpDisplay      *display)
240 {
241   GimpBrightnessContrastTool *bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (tool);
242 
243   if (! bc_tool->dragging)
244     {
245       GIMP_TOOL_CLASS (parent_class)->motion (tool, coords, time, state,
246                                               display);
247     }
248   else
249     {
250       bc_tool->dx =   (coords->x - bc_tool->x);
251       bc_tool->dy = - (coords->y - bc_tool->y);
252 
253       g_object_set (GIMP_FILTER_TOOL (tool)->config,
254                     "brightness", CLAMP (bc_tool->dy, -127.0, 127.0) / 127.0,
255                     "contrast",   CLAMP (bc_tool->dx, -127.0, 127.0) / 127.0,
256                     NULL);
257     }
258 }
259 
260 
261 /********************************/
262 /*  Brightness Contrast dialog  */
263 /********************************/
264 
265 static void
gimp_brightness_contrast_tool_dialog(GimpFilterTool * filter_tool)266 gimp_brightness_contrast_tool_dialog (GimpFilterTool *filter_tool)
267 {
268   GimpBrightnessContrastTool *bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (filter_tool);
269   GtkWidget                  *main_vbox;
270   GtkWidget                  *scale;
271   GtkWidget                  *button;
272 
273   main_vbox = gimp_filter_tool_dialog_get_vbox (filter_tool);
274 
275   /*  Create the brightness scale widget  */
276   scale = gimp_prop_spin_scale_new (filter_tool->config, "brightness",
277                                     _("_Brightness"), 0.01, 0.1, 3);
278   gtk_box_pack_start (GTK_BOX (main_vbox), scale, FALSE, FALSE, 0);
279   gtk_widget_show (scale);
280 
281   bc_tool->brightness_scale = scale;
282 
283   /*  Create the contrast scale widget  */
284   scale = gimp_prop_spin_scale_new (filter_tool->config, "contrast",
285                                     _("_Contrast"), 0.01, 0.1, 3);
286   gtk_box_pack_start (GTK_BOX (main_vbox), scale, FALSE, FALSE, 0);
287   gtk_widget_show (scale);
288 
289   bc_tool->contrast_scale = scale;
290 
291   button = gimp_icon_button_new (GIMP_ICON_TOOL_LEVELS,
292                                  _("Edit these Settings as Levels"));
293   gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0);
294   gtk_widget_show (button);
295 
296   g_signal_connect (button, "clicked",
297                     G_CALLBACK (brightness_contrast_to_levels_callback),
298                     filter_tool);
299 }
300 
301 static void
brightness_contrast_to_levels_callback(GtkWidget * widget,GimpFilterTool * filter_tool)302 brightness_contrast_to_levels_callback (GtkWidget      *widget,
303                                         GimpFilterTool *filter_tool)
304 {
305   GimpLevelsConfig *levels;
306 
307   levels = gimp_brightness_contrast_config_to_levels_config (GIMP_BRIGHTNESS_CONTRAST_CONFIG (filter_tool->config));
308 
309   gimp_filter_tool_edit_as (filter_tool,
310                             "gimp-levels-tool",
311                             GIMP_CONFIG (levels));
312 
313   g_object_unref (levels);
314 }
315