1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimpcolorbalanceconfig.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 <cairo.h>
24 #include <gegl.h>
25 #include <gdk-pixbuf/gdk-pixbuf.h>
26 
27 #include "libgimpcolor/gimpcolor.h"
28 #include "libgimpmath/gimpmath.h"
29 #include "libgimpconfig/gimpconfig.h"
30 
31 #include "operations-types.h"
32 
33 #include "gimpcolorbalanceconfig.h"
34 
35 #include "gimp-intl.h"
36 
37 
38 enum
39 {
40   PROP_0,
41   PROP_RANGE,
42   PROP_CYAN_RED,
43   PROP_MAGENTA_GREEN,
44   PROP_YELLOW_BLUE,
45   PROP_PRESERVE_LUMINOSITY
46 };
47 
48 
49 static void     gimp_color_balance_config_iface_init   (GimpConfigInterface *iface);
50 
51 static void     gimp_color_balance_config_get_property (GObject          *object,
52                                                         guint             property_id,
53                                                         GValue           *value,
54                                                         GParamSpec       *pspec);
55 static void     gimp_color_balance_config_set_property (GObject          *object,
56                                                         guint             property_id,
57                                                         const GValue     *value,
58                                                         GParamSpec       *pspec);
59 
60 static gboolean gimp_color_balance_config_serialize    (GimpConfig       *config,
61                                                         GimpConfigWriter *writer,
62                                                         gpointer          data);
63 static gboolean gimp_color_balance_config_deserialize  (GimpConfig       *config,
64                                                         GScanner         *scanner,
65                                                         gint              nest_level,
66                                                         gpointer          data);
67 static gboolean gimp_color_balance_config_equal        (GimpConfig       *a,
68                                                         GimpConfig       *b);
69 static void     gimp_color_balance_config_reset        (GimpConfig       *config);
70 static gboolean gimp_color_balance_config_copy         (GimpConfig       *src,
71                                                         GimpConfig       *dest,
72                                                         GParamFlags       flags);
73 
74 
G_DEFINE_TYPE_WITH_CODE(GimpColorBalanceConfig,gimp_color_balance_config,GIMP_TYPE_OPERATION_SETTINGS,G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG,gimp_color_balance_config_iface_init))75 G_DEFINE_TYPE_WITH_CODE (GimpColorBalanceConfig, gimp_color_balance_config,
76                          GIMP_TYPE_OPERATION_SETTINGS,
77                          G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG,
78                                                 gimp_color_balance_config_iface_init))
79 
80 #define parent_class gimp_color_balance_config_parent_class
81 
82 
83 static void
84 gimp_color_balance_config_class_init (GimpColorBalanceConfigClass *klass)
85 {
86   GObjectClass      *object_class   = G_OBJECT_CLASS (klass);
87   GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
88 
89   object_class->set_property        = gimp_color_balance_config_set_property;
90   object_class->get_property        = gimp_color_balance_config_get_property;
91 
92   viewable_class->default_icon_name = "gimp-tool-color-balance";
93 
94   GIMP_CONFIG_PROP_ENUM (object_class, PROP_RANGE,
95                          "range",
96                          _("Range"),
97                          _("The affected range"),
98                          GIMP_TYPE_TRANSFER_MODE,
99                          GIMP_TRANSFER_MIDTONES, 0);
100 
101   GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_CYAN_RED,
102                            "cyan-red",
103                            _("Cyan-Red"),
104                            _("Cyan-Red"),
105                            -1.0, 1.0, 0.0, 0);
106 
107   GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_MAGENTA_GREEN,
108                            "magenta-green",
109                            _("Magenta-Green"),
110                            _("Magenta-Green"),
111                            -1.0, 1.0, 0.0, 0);
112 
113   GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_YELLOW_BLUE,
114                            "yellow-blue",
115                            _("Yellow-Blue"),
116                            _("Yellow-Blue"),
117                            -1.0, 1.0, 0.0, 0);
118 
119   GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_PRESERVE_LUMINOSITY,
120                             "preserve-luminosity",
121                             _("Preserve Luminosity"),
122                             _("Preserve Luminosity"),
123                             TRUE, 0);
124 }
125 
126 static void
gimp_color_balance_config_iface_init(GimpConfigInterface * iface)127 gimp_color_balance_config_iface_init (GimpConfigInterface *iface)
128 {
129   iface->serialize   = gimp_color_balance_config_serialize;
130   iface->deserialize = gimp_color_balance_config_deserialize;
131   iface->equal       = gimp_color_balance_config_equal;
132   iface->reset       = gimp_color_balance_config_reset;
133   iface->copy        = gimp_color_balance_config_copy;
134 }
135 
136 static void
gimp_color_balance_config_init(GimpColorBalanceConfig * self)137 gimp_color_balance_config_init (GimpColorBalanceConfig *self)
138 {
139   gimp_config_reset (GIMP_CONFIG (self));
140 }
141 
142 static void
gimp_color_balance_config_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)143 gimp_color_balance_config_get_property (GObject    *object,
144                                         guint       property_id,
145                                         GValue     *value,
146                                         GParamSpec *pspec)
147 {
148   GimpColorBalanceConfig *self = GIMP_COLOR_BALANCE_CONFIG (object);
149 
150   switch (property_id)
151     {
152     case PROP_RANGE:
153       g_value_set_enum (value, self->range);
154       break;
155 
156     case PROP_CYAN_RED:
157       g_value_set_double (value, self->cyan_red[self->range]);
158       break;
159 
160     case PROP_MAGENTA_GREEN:
161       g_value_set_double (value, self->magenta_green[self->range]);
162       break;
163 
164     case PROP_YELLOW_BLUE:
165       g_value_set_double (value, self->yellow_blue[self->range]);
166       break;
167 
168     case PROP_PRESERVE_LUMINOSITY:
169       g_value_set_boolean (value, self->preserve_luminosity);
170       break;
171 
172     default:
173       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
174       break;
175     }
176 }
177 
178 static void
gimp_color_balance_config_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)179 gimp_color_balance_config_set_property (GObject      *object,
180                                         guint         property_id,
181                                         const GValue *value,
182                                         GParamSpec   *pspec)
183 {
184   GimpColorBalanceConfig *self = GIMP_COLOR_BALANCE_CONFIG (object);
185 
186   switch (property_id)
187     {
188     case PROP_RANGE:
189       self->range = g_value_get_enum (value);
190       g_object_notify (object, "cyan-red");
191       g_object_notify (object, "magenta-green");
192       g_object_notify (object, "yellow-blue");
193       break;
194 
195     case PROP_CYAN_RED:
196       self->cyan_red[self->range] = g_value_get_double (value);
197       break;
198 
199     case PROP_MAGENTA_GREEN:
200       self->magenta_green[self->range] = g_value_get_double (value);
201       break;
202 
203     case PROP_YELLOW_BLUE:
204       self->yellow_blue[self->range] = g_value_get_double (value);
205       break;
206 
207     case PROP_PRESERVE_LUMINOSITY:
208       self->preserve_luminosity = g_value_get_boolean (value);
209       break;
210 
211    default:
212       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
213       break;
214     }
215 }
216 
217 static gboolean
gimp_color_balance_config_serialize(GimpConfig * config,GimpConfigWriter * writer,gpointer data)218 gimp_color_balance_config_serialize (GimpConfig       *config,
219                                      GimpConfigWriter *writer,
220                                      gpointer          data)
221 {
222   GimpColorBalanceConfig *bc_config = GIMP_COLOR_BALANCE_CONFIG (config);
223   GimpTransferMode        range;
224   GimpTransferMode        old_range;
225   gboolean                success = TRUE;
226 
227   if (! gimp_operation_settings_config_serialize_base (config, writer, data))
228     return FALSE;
229 
230   old_range = bc_config->range;
231 
232   for (range = GIMP_TRANSFER_SHADOWS;
233        range <= GIMP_TRANSFER_HIGHLIGHTS;
234        range++)
235     {
236       bc_config->range = range;
237 
238       success = (gimp_config_serialize_property_by_name (config,
239                                                          "range",
240                                                          writer) &&
241                  gimp_config_serialize_property_by_name (config,
242                                                          "cyan-red",
243                                                          writer) &&
244                  gimp_config_serialize_property_by_name (config,
245                                                          "magenta-green",
246                                                          writer) &&
247                  gimp_config_serialize_property_by_name (config,
248                                                          "yellow-blue",
249                                                          writer));
250 
251       if (! success)
252         break;
253     }
254 
255   if (success)
256     success = gimp_config_serialize_property_by_name (config,
257                                                       "preserve-luminosity",
258                                                       writer);
259 
260   bc_config->range = old_range;
261 
262   return success;
263 }
264 
265 static gboolean
gimp_color_balance_config_deserialize(GimpConfig * config,GScanner * scanner,gint nest_level,gpointer data)266 gimp_color_balance_config_deserialize (GimpConfig *config,
267                                        GScanner   *scanner,
268                                        gint        nest_level,
269                                        gpointer    data)
270 {
271   GimpColorBalanceConfig *cb_config = GIMP_COLOR_BALANCE_CONFIG (config);
272   GimpTransferMode        old_range;
273   gboolean                success = TRUE;
274 
275   old_range = cb_config->range;
276 
277   success = gimp_config_deserialize_properties (config, scanner, nest_level);
278 
279   g_object_set (config, "range", old_range, NULL);
280 
281   return success;
282 }
283 
284 static gboolean
gimp_color_balance_config_equal(GimpConfig * a,GimpConfig * b)285 gimp_color_balance_config_equal (GimpConfig *a,
286                                  GimpConfig *b)
287 {
288   GimpColorBalanceConfig *config_a = GIMP_COLOR_BALANCE_CONFIG (a);
289   GimpColorBalanceConfig *config_b = GIMP_COLOR_BALANCE_CONFIG (b);
290   GimpTransferMode        range;
291 
292   if (! gimp_operation_settings_config_equal_base (a, b))
293     return FALSE;
294 
295   for (range = GIMP_TRANSFER_SHADOWS;
296        range <= GIMP_TRANSFER_HIGHLIGHTS;
297        range++)
298     {
299       if (config_a->cyan_red[range]      != config_b->cyan_red[range]      ||
300           config_a->magenta_green[range] != config_b->magenta_green[range] ||
301           config_a->yellow_blue[range]   != config_b->yellow_blue[range])
302         return FALSE;
303     }
304 
305   /* don't compare "range" */
306 
307   if (config_a->preserve_luminosity != config_b->preserve_luminosity)
308     return FALSE;
309 
310   return TRUE;
311 }
312 
313 static void
gimp_color_balance_config_reset(GimpConfig * config)314 gimp_color_balance_config_reset (GimpConfig *config)
315 {
316   GimpColorBalanceConfig *cb_config = GIMP_COLOR_BALANCE_CONFIG (config);
317   GimpTransferMode        range;
318 
319   gimp_operation_settings_config_reset_base (config);
320 
321   for (range = GIMP_TRANSFER_SHADOWS;
322        range <= GIMP_TRANSFER_HIGHLIGHTS;
323        range++)
324     {
325       cb_config->range = range;
326       gimp_color_balance_config_reset_range (cb_config);
327     }
328 
329   gimp_config_reset_property (G_OBJECT (config), "range");
330   gimp_config_reset_property (G_OBJECT (config), "preserve-luminosity");
331 }
332 
333 static gboolean
gimp_color_balance_config_copy(GimpConfig * src,GimpConfig * dest,GParamFlags flags)334 gimp_color_balance_config_copy (GimpConfig  *src,
335                                 GimpConfig  *dest,
336                                 GParamFlags  flags)
337 {
338   GimpColorBalanceConfig *src_config  = GIMP_COLOR_BALANCE_CONFIG (src);
339   GimpColorBalanceConfig *dest_config = GIMP_COLOR_BALANCE_CONFIG (dest);
340   GimpTransferMode        range;
341 
342   if (! gimp_operation_settings_config_copy_base (src, dest, flags))
343     return FALSE;
344 
345   for (range = GIMP_TRANSFER_SHADOWS;
346        range <= GIMP_TRANSFER_HIGHLIGHTS;
347        range++)
348     {
349       dest_config->cyan_red[range]      = src_config->cyan_red[range];
350       dest_config->magenta_green[range] = src_config->magenta_green[range];
351       dest_config->yellow_blue[range]   = src_config->yellow_blue[range];
352     }
353 
354   g_object_notify (G_OBJECT (dest), "cyan-red");
355   g_object_notify (G_OBJECT (dest), "magenta-green");
356   g_object_notify (G_OBJECT (dest), "yellow-blue");
357 
358   dest_config->range               = src_config->range;
359   dest_config->preserve_luminosity = src_config->preserve_luminosity;
360 
361   g_object_notify (G_OBJECT (dest), "range");
362   g_object_notify (G_OBJECT (dest), "preserve-luminosity");
363 
364   return TRUE;
365 }
366 
367 
368 /*  public functions  */
369 
370 void
gimp_color_balance_config_reset_range(GimpColorBalanceConfig * config)371 gimp_color_balance_config_reset_range (GimpColorBalanceConfig *config)
372 {
373   g_return_if_fail (GIMP_IS_COLOR_BALANCE_CONFIG (config));
374 
375   g_object_freeze_notify (G_OBJECT (config));
376 
377   gimp_config_reset_property (G_OBJECT (config), "cyan-red");
378   gimp_config_reset_property (G_OBJECT (config), "magenta-green");
379   gimp_config_reset_property (G_OBJECT (config), "yellow-blue");
380 
381   g_object_thaw_notify (G_OBJECT (config));
382 }
383