1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimpbrightnesscontrastconfig.c
5 * Copyright (C) 2007 Michael Natterer <mitch@gimp.org>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <gdk-pixbuf/gdk-pixbuf.h>
24 #include <gegl.h>
25
26 #include "libgimpmath/gimpmath.h"
27 #include "libgimpconfig/gimpconfig.h"
28
29 #include "operations-types.h"
30
31 #include "gimpbrightnesscontrastconfig.h"
32 #include "gimplevelsconfig.h"
33
34 #include "gimp-intl.h"
35
36
37 enum
38 {
39 PROP_0,
40 PROP_BRIGHTNESS,
41 PROP_CONTRAST
42 };
43
44
45 static void gimp_brightness_contrast_config_iface_init (GimpConfigInterface *iface);
46
47 static void gimp_brightness_contrast_config_get_property (GObject *object,
48 guint property_id,
49 GValue *value,
50 GParamSpec *pspec);
51 static void gimp_brightness_contrast_config_set_property (GObject *object,
52 guint property_id,
53 const GValue *value,
54 GParamSpec *pspec);
55
56 static gboolean gimp_brightness_contrast_config_equal (GimpConfig *a,
57 GimpConfig *b);
58
59
G_DEFINE_TYPE_WITH_CODE(GimpBrightnessContrastConfig,gimp_brightness_contrast_config,GIMP_TYPE_OPERATION_SETTINGS,G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG,gimp_brightness_contrast_config_iface_init))60 G_DEFINE_TYPE_WITH_CODE (GimpBrightnessContrastConfig,
61 gimp_brightness_contrast_config,
62 GIMP_TYPE_OPERATION_SETTINGS,
63 G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG,
64 gimp_brightness_contrast_config_iface_init))
65
66 #define parent_class gimp_brightness_contrast_config_parent_class
67
68
69 static void
70 gimp_brightness_contrast_config_class_init (GimpBrightnessContrastConfigClass *klass)
71 {
72 GObjectClass *object_class = G_OBJECT_CLASS (klass);
73 GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
74
75 object_class->set_property = gimp_brightness_contrast_config_set_property;
76 object_class->get_property = gimp_brightness_contrast_config_get_property;
77
78 viewable_class->default_icon_name = "gimp-tool-brightness-contrast";
79
80 GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_BRIGHTNESS,
81 "brightness",
82 _("Brightness"),
83 _("Brightness"),
84 -1.0, 1.0, 0.0, 0);
85
86 GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_CONTRAST,
87 "contrast",
88 _("Contrast"),
89 _("Contrast"),
90 -1.0, 1.0, 0.0, 0);
91 }
92
93 static void
gimp_brightness_contrast_config_iface_init(GimpConfigInterface * iface)94 gimp_brightness_contrast_config_iface_init (GimpConfigInterface *iface)
95 {
96 iface->equal = gimp_brightness_contrast_config_equal;
97 }
98
99 static void
gimp_brightness_contrast_config_init(GimpBrightnessContrastConfig * self)100 gimp_brightness_contrast_config_init (GimpBrightnessContrastConfig *self)
101 {
102 }
103
104 static void
gimp_brightness_contrast_config_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)105 gimp_brightness_contrast_config_get_property (GObject *object,
106 guint property_id,
107 GValue *value,
108 GParamSpec *pspec)
109 {
110 GimpBrightnessContrastConfig *self = GIMP_BRIGHTNESS_CONTRAST_CONFIG (object);
111
112 switch (property_id)
113 {
114 case PROP_BRIGHTNESS:
115 g_value_set_double (value, self->brightness);
116 break;
117
118 case PROP_CONTRAST:
119 g_value_set_double (value, self->contrast);
120 break;
121
122 default:
123 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
124 break;
125 }
126 }
127
128 static void
gimp_brightness_contrast_config_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)129 gimp_brightness_contrast_config_set_property (GObject *object,
130 guint property_id,
131 const GValue *value,
132 GParamSpec *pspec)
133 {
134 GimpBrightnessContrastConfig *self = GIMP_BRIGHTNESS_CONTRAST_CONFIG (object);
135
136 switch (property_id)
137 {
138 case PROP_BRIGHTNESS:
139 self->brightness = g_value_get_double (value);
140 break;
141
142 case PROP_CONTRAST:
143 self->contrast = g_value_get_double (value);
144 break;
145
146 default:
147 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
148 break;
149 }
150 }
151
152 static gboolean
gimp_brightness_contrast_config_equal(GimpConfig * a,GimpConfig * b)153 gimp_brightness_contrast_config_equal (GimpConfig *a,
154 GimpConfig *b)
155 {
156 GimpBrightnessContrastConfig *config_a = GIMP_BRIGHTNESS_CONTRAST_CONFIG (a);
157 GimpBrightnessContrastConfig *config_b = GIMP_BRIGHTNESS_CONTRAST_CONFIG (b);
158
159 if (! gimp_operation_settings_config_equal_base (a, b) ||
160 config_a->brightness != config_b->brightness ||
161 config_a->contrast != config_b->contrast)
162 {
163 return FALSE;
164 }
165
166 return TRUE;
167 }
168
169
170 /* public functions */
171
172 GimpLevelsConfig *
gimp_brightness_contrast_config_to_levels_config(GimpBrightnessContrastConfig * config)173 gimp_brightness_contrast_config_to_levels_config (GimpBrightnessContrastConfig *config)
174 {
175 GimpLevelsConfig *levels;
176 gdouble brightness;
177 gdouble slant;
178 gdouble value;
179
180 g_return_val_if_fail (GIMP_IS_BRIGHTNESS_CONTRAST_CONFIG (config), NULL);
181
182 levels = g_object_new (GIMP_TYPE_LEVELS_CONFIG, NULL);
183
184 gimp_operation_settings_config_copy_base (GIMP_CONFIG (config),
185 GIMP_CONFIG (levels),
186 0);
187
188 brightness = config->brightness / 2.0;
189 slant = tan ((config->contrast + 1) * G_PI_4);
190
191 if (config->brightness >= 0)
192 {
193 value = -0.5 * slant + brightness * slant + 0.5;
194
195 if (value < 0.0)
196 {
197 value = 0.0;
198
199 /* this slightly convoluted math follows by inverting the
200 * calculation of the brightness/contrast LUT in base/lut-funcs.h */
201
202 levels->low_input[GIMP_HISTOGRAM_VALUE] =
203 (- brightness * slant + 0.5 * slant - 0.5) / (slant - brightness * slant);
204 }
205
206 levels->low_output[GIMP_HISTOGRAM_VALUE] = value;
207
208 value = 0.5 * slant + 0.5;
209
210 if (value > 1.0)
211 {
212 value = 1.0;
213
214 levels->high_input[GIMP_HISTOGRAM_VALUE] =
215 (- brightness * slant + 0.5 * slant + 0.5) / (slant - brightness * slant);
216 }
217
218 levels->high_output[GIMP_HISTOGRAM_VALUE] = value;
219 }
220 else
221 {
222 value = 0.5 - 0.5 * slant;
223
224 if (value < 0.0)
225 {
226 value = 0.0;
227
228 levels->low_input[GIMP_HISTOGRAM_VALUE] =
229 (0.5 * slant - 0.5) / (slant + brightness * slant);
230 }
231
232 levels->low_output[GIMP_HISTOGRAM_VALUE] = value;
233
234 value = slant * brightness + slant * 0.5 + 0.5;
235
236 if (value > 1.0)
237 {
238 value = 1.0;
239
240 levels->high_input[GIMP_HISTOGRAM_VALUE] =
241 (0.5 * slant + 0.5) / (slant + brightness * slant);
242 }
243
244 levels->high_output[GIMP_HISTOGRAM_VALUE] = value;
245 }
246
247 return levels;
248 }
249