gimp r24608 - in trunk: . app/gegl app/tools



Author: mitch
Date: Mon Jan 14 20:44:01 2008
New Revision: 24608
URL: http://svn.gnome.org/viewvc/gimp?rev=24608&view=rev

Log:
2008-01-14  Michael Natterer  <mitch gimp org>

	* app/gegl/Makefile.am
	* app/gegl/gegl-types.h
	* app/gegl/gimpoperationhuesaturation.[ch]: new operation.

	* app/gegl/gimp-gegl.c: register it.

	* app/tools/gimphuesaturationtool.c: use it.



Added:
   trunk/app/gegl/gimpoperationhuesaturation.c
   trunk/app/gegl/gimpoperationhuesaturation.h
Modified:
   trunk/ChangeLog
   trunk/app/gegl/Makefile.am
   trunk/app/gegl/gegl-types.h
   trunk/app/gegl/gimp-gegl.c
   trunk/app/tools/gimphuesaturationtool.c

Modified: trunk/app/gegl/Makefile.am
==============================================================================
--- trunk/app/gegl/Makefile.am	(original)
+++ trunk/app/gegl/Makefile.am	Mon Jan 14 20:44:01 2008
@@ -13,6 +13,8 @@
 	gimpoperationcolorize.h		\
 	gimpoperationdesaturate.c	\
 	gimpoperationdesaturate.h	\
+	gimpoperationhuesaturation.c	\
+	gimpoperationhuesaturation.h	\
 	gimpoperationlevels.c		\
 	gimpoperationlevels.h		\
 	gimpoperationposterize.c	\

Modified: trunk/app/gegl/gegl-types.h
==============================================================================
--- trunk/app/gegl/gegl-types.h	(original)
+++ trunk/app/gegl/gegl-types.h	Mon Jan 14 20:44:01 2008
@@ -25,14 +25,15 @@
 #include "base/base-types.h"
 
 
-typedef struct _GimpOperationColorBalance GimpOperationColorBalance;
-typedef struct _GimpOperationColorize     GimpOperationColorize;
-typedef struct _GimpOperationDesaturate   GimpOperationDesaturate;
-typedef struct _GimpOperationLevels       GimpOperationLevels;
-typedef struct _GimpOperationPosterize    GimpOperationPosterize;
-typedef struct _GimpOperationThreshold    GimpOperationThreshold;
-typedef struct _GimpOperationTileSink     GimpOperationTileSink;
-typedef struct _GimpOperationTileSource   GimpOperationTileSource;
+typedef struct _GimpOperationColorBalance  GimpOperationColorBalance;
+typedef struct _GimpOperationColorize      GimpOperationColorize;
+typedef struct _GimpOperationDesaturate    GimpOperationDesaturate;
+typedef struct _GimpOperationHueSaturation GimpOperationHueSaturation;
+typedef struct _GimpOperationLevels        GimpOperationLevels;
+typedef struct _GimpOperationPosterize     GimpOperationPosterize;
+typedef struct _GimpOperationThreshold     GimpOperationThreshold;
+typedef struct _GimpOperationTileSink      GimpOperationTileSink;
+typedef struct _GimpOperationTileSource    GimpOperationTileSource;
 
 
 #endif /* __OUR_GEGL_TYPES_H__ */

Modified: trunk/app/gegl/gimp-gegl.c
==============================================================================
--- trunk/app/gegl/gimp-gegl.c	(original)
+++ trunk/app/gegl/gimp-gegl.c	Mon Jan 14 20:44:01 2008
@@ -30,6 +30,7 @@
 #include "gimpoperationcolorbalance.h"
 #include "gimpoperationcolorize.h"
 #include "gimpoperationdesaturate.h"
+#include "gimpoperationhuesaturation.h"
 #include "gimpoperationlevels.h"
 #include "gimpoperationposterize.h"
 #include "gimpoperationthreshold.h"
@@ -43,6 +44,7 @@
   g_type_class_ref (GIMP_TYPE_OPERATION_COLOR_BALANCE);
   g_type_class_ref (GIMP_TYPE_OPERATION_COLORIZE);
   g_type_class_ref (GIMP_TYPE_OPERATION_DESATURATE);
+  g_type_class_ref (GIMP_TYPE_OPERATION_HUE_SATURATION);
   g_type_class_ref (GIMP_TYPE_OPERATION_LEVELS);
   g_type_class_ref (GIMP_TYPE_OPERATION_POSTERIZE);
   g_type_class_ref (GIMP_TYPE_OPERATION_THRESHOLD);

Added: trunk/app/gegl/gimpoperationhuesaturation.c
==============================================================================
--- (empty file)
+++ trunk/app/gegl/gimpoperationhuesaturation.c	Mon Jan 14 20:44:01 2008
@@ -0,0 +1,364 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpoperationhuesaturation.c
+ * Copyright (C) 2007 Michael Natterer <mitch gimp org>
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpmath/gimpmath.h"
+
+#include "gegl-types.h"
+
+#include "gimpoperationhuesaturation.h"
+
+
+enum
+{
+  PROP_0,
+  PROP_RANGE,
+  PROP_HUE,
+  PROP_SATURATION,
+  PROP_LIGHTNESS,
+  PROP_OVERLAP
+};
+
+
+static void     gimp_operation_hue_saturation_get_property (GObject       *object,
+                                                            guint          property_id,
+                                                            GValue        *value,
+                                                            GParamSpec    *pspec);
+static void     gimp_operation_hue_saturation_set_property (GObject       *object,
+                                                            guint          property_id,
+                                                            const GValue  *value,
+                                                            GParamSpec    *pspec);
+
+static gboolean gimp_operation_hue_saturation_process      (GeglOperation *operation,
+                                                            void          *in_buf,
+                                                            void          *out_buf,
+                                                            glong          samples);
+
+
+G_DEFINE_TYPE (GimpOperationHueSaturation, gimp_operation_hue_saturation,
+               GEGL_TYPE_OPERATION_POINT_FILTER)
+
+#define parent_class gimp_operation_hue_saturation_parent_class
+
+
+static void
+gimp_operation_hue_saturation_class_init (GimpOperationHueSaturationClass * klass)
+{
+  GObjectClass                  *object_class    = G_OBJECT_CLASS (klass);
+  GeglOperationClass            *operation_class = GEGL_OPERATION_CLASS (klass);
+  GeglOperationPointFilterClass *point_class     = GEGL_OPERATION_POINT_FILTER_CLASS (klass);
+
+  object_class->set_property = gimp_operation_hue_saturation_set_property;
+  object_class->get_property = gimp_operation_hue_saturation_get_property;
+
+  point_class->process       = gimp_operation_hue_saturation_process;
+
+  gegl_operation_class_set_name (operation_class, "gimp-hue-saturation");
+
+  g_object_class_install_property (object_class, PROP_RANGE,
+                                   g_param_spec_enum ("range",
+                                                      "range",
+                                                      "The affected range",
+                                                      GIMP_TYPE_HUE_RANGE,
+                                                      GIMP_ALL_HUES,
+                                                      G_PARAM_READWRITE |
+                                                      G_PARAM_CONSTRUCT));
+
+  g_object_class_install_property (object_class, PROP_HUE,
+                                   g_param_spec_double ("hue",
+                                                        "Hue",
+                                                        "Hue",
+                                                        -1.0, 1.0, 0.0,
+                                                        G_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT));
+
+  g_object_class_install_property (object_class, PROP_SATURATION,
+                                   g_param_spec_double ("saturation",
+                                                        "Saturation",
+                                                        "Saturation",
+                                                        -1.0, 1.0, 0.0,
+                                                        G_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT));
+
+  g_object_class_install_property (object_class, PROP_LIGHTNESS,
+                                   g_param_spec_double ("lightness",
+                                                        "Lightness",
+                                                        "Lightness",
+                                                        -1.0, 1.0, 0.0,
+                                                        G_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT));
+
+  g_object_class_install_property (object_class, PROP_OVERLAP,
+                                   g_param_spec_double ("overlap",
+                                                        "Overlap",
+                                                        "Overlap",
+                                                        0.0, 1.0, 0.0,
+                                                        G_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT));
+}
+
+static void
+gimp_operation_hue_saturation_init (GimpOperationHueSaturation *self)
+{
+  GimpHueRange range;
+
+  self->range = GIMP_ALL_HUES;
+
+  for (range = GIMP_ALL_HUES; range <= GIMP_MAGENTA_HUES; range++)
+    {
+      self->hue[range]        = 0.0;
+      self->saturation[range] = 0.0;
+      self->lightness[range]  = 0.0;
+    }
+
+  self->overlap = 0.0;
+}
+
+static void
+gimp_operation_hue_saturation_get_property (GObject    *object,
+                                            guint       property_id,
+                                            GValue     *value,
+                                            GParamSpec *pspec)
+{
+  GimpOperationHueSaturation *self = GIMP_OPERATION_HUE_SATURATION (object);
+
+  switch (property_id)
+    {
+    case PROP_RANGE:
+      g_value_set_enum (value, self->range);
+      break;
+
+    case PROP_HUE:
+      g_value_set_double (value, self->hue[self->range]);
+      break;
+
+    case PROP_SATURATION:
+      g_value_set_double (value, self->saturation[self->range]);
+      break;
+
+    case PROP_LIGHTNESS:
+      g_value_set_double (value, self->lightness[self->range]);
+      break;
+
+    case PROP_OVERLAP:
+      g_value_set_double (value, self->overlap);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_operation_hue_saturation_set_property (GObject      *object,
+                                            guint         property_id,
+                                            const GValue *value,
+                                            GParamSpec   *pspec)
+{
+  GimpOperationHueSaturation *self = GIMP_OPERATION_HUE_SATURATION (object);
+
+  switch (property_id)
+    {
+    case PROP_RANGE:
+      self->range = g_value_get_enum (value);
+      break;
+
+    case PROP_HUE:
+      self->hue[self->range] = g_value_get_double (value);
+      break;
+
+    case PROP_SATURATION:
+      self->saturation[self->range] = g_value_get_double (value);
+      break;
+
+    case PROP_LIGHTNESS:
+      self->lightness[self->range] = g_value_get_double (value);
+      break;
+
+    case PROP_OVERLAP:
+      self->overlap = g_value_get_double (value);
+      break;
+
+   default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static inline gdouble
+map_hue (GimpOperationHueSaturation *self,
+         gint                        hue,
+         gdouble                     value)
+{
+  value += (self->hue[0] + self->hue[hue + 1]) / 2.0;
+
+  if (value < 0)
+    return value + 1.0;
+  else if (value > 1.0)
+    return value - 1.0;
+  else
+    return value;
+}
+
+static inline gdouble
+map_saturation (GimpOperationHueSaturation *self,
+                gint                        hue,
+                gdouble                     value)
+{
+  gdouble v = self->saturation[0] + self->saturation[hue + 1];
+
+  // v = CLAMP (v, -1.0, 1.0);
+
+  /* This change affects the way saturation is computed. With the old
+   * code (different code for value < 0), increasing the saturation
+   * affected muted colors very much, and bright colors less. With the
+   * new code, it affects muted colors and bright colors more or less
+   * evenly. For enhancing the color in photos, the new behavior is
+   * exactly what you want. It's hard for me to imagine a case in
+   * which the old behavior is better.
+  */
+  value *= (v + 1.0);
+
+  return CLAMP (value, 0.0, 1.0);
+}
+
+static inline gdouble
+map_lightness (GimpOperationHueSaturation *self,
+               gint                        hue,
+               gdouble                     value)
+{
+  gdouble v = (self->lightness[0] + self->lightness[hue + 1]) / 2.0;
+
+  // v = CLAMP (v, -1.0, 1.0);
+
+  if (v < 0)
+    return value * (v + 1.0);
+  else
+    return value + (v * (1.0 - value));
+}
+
+static gboolean
+gimp_operation_hue_saturation_process (GeglOperation *operation,
+                                       void          *in_buf,
+                                       void          *out_buf,
+                                       glong          samples)
+{
+  GimpOperationHueSaturation *self = GIMP_OPERATION_HUE_SATURATION (operation);
+  gfloat                     *src  = in_buf;
+  gfloat                     *dest = out_buf;
+  glong                       sample;
+
+  for (sample = 0; sample < samples; sample++)
+    {
+      GimpRGB  rgb;
+      GimpHSL  hsl;
+      gdouble  h;
+      gint     hue_counter;
+      gint     hue                 = 0;
+      gint     secondary_hue       = 0;
+      gboolean use_secondary_hue   = FALSE;
+      gfloat   primary_intensity   = 0.0;
+      gfloat   secondary_intensity = 0.0;
+      gfloat   overlap             = self->overlap / 2.0;
+
+      rgb.r = src[RED_PIX];
+      rgb.g = src[GREEN_PIX];
+      rgb.b = src[BLUE_PIX];
+
+      gimp_rgb_to_hsl (&rgb, &hsl);
+
+      h = hsl.h * 6.0;
+
+      for (hue_counter = 0; hue_counter < 7; hue_counter++)
+        {
+          gdouble hue_threshold = (gdouble) hue_counter + 0.5;
+
+          if (h < ((gdouble) hue_threshold + overlap))
+            {
+              hue = hue_counter;
+
+              if (overlap > 0.0 && h > ((gdouble) hue_threshold - overlap))
+                {
+                  use_secondary_hue = TRUE;
+
+                  secondary_hue = hue_counter + 1;
+
+                  secondary_intensity =
+                    (h - (gdouble) hue_threshold + overlap) / (2.0 * overlap);
+
+                  primary_intensity = 1.0 - secondary_intensity;
+                }
+              else
+                {
+                  use_secondary_hue = FALSE;
+                }
+
+              break;
+            }
+        }
+
+      if (hue >= 6)
+        {
+          hue = 0;
+          use_secondary_hue = FALSE;
+        }
+
+      if (secondary_hue >= 6)
+        {
+          secondary_hue = 0;
+        }
+
+      if (use_secondary_hue)
+        {
+          hsl.h = (map_hue        (self, hue,           hsl.h) * primary_intensity +
+                   map_hue        (self, secondary_hue, hsl.h) * secondary_intensity);
+
+          hsl.s = (map_saturation (self, hue,           hsl.s) * primary_intensity +
+                   map_saturation (self, secondary_hue, hsl.s) * secondary_intensity);
+
+          hsl.l = (map_lightness  (self, hue,           hsl.l) * primary_intensity +
+                   map_lightness  (self, secondary_hue, hsl.l) * secondary_intensity);
+        }
+      else
+        {
+          hsl.h = map_hue        (self, hue, hsl.h);
+          hsl.s = map_saturation (self, hue, hsl.s);
+          hsl.l = map_lightness  (self, hue, hsl.l);
+        }
+
+      gimp_hsl_to_rgb (&hsl, &rgb);
+
+      dest[RED_PIX]   = rgb.r;
+      dest[GREEN_PIX] = rgb.g;
+      dest[BLUE_PIX]  = rgb.b;
+      dest[ALPHA_PIX] = src[ALPHA_PIX];
+
+      src  += 4;
+      dest += 4;
+    }
+
+  return TRUE;
+}

Added: trunk/app/gegl/gimpoperationhuesaturation.h
==============================================================================
--- (empty file)
+++ trunk/app/gegl/gimpoperationhuesaturation.h	Mon Jan 14 20:44:01 2008
@@ -0,0 +1,61 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpoperationhuesaturation.h
+ * Copyright (C) 2007 Michael Natterer <mitch gimp org>
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_OPERATION_HUE_SATURATION_H__
+#define __GIMP_OPERATION_HUE_SATURATION_H__
+
+
+#include "gegl/gegl-operation-point-filter.h"
+
+
+#define GIMP_TYPE_OPERATION_HUE_SATURATION            (gimp_operation_hue_saturation_get_type ())
+#define GIMP_OPERATION_HUE_SATURATION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_OPERATION_HUE_SATURATION, GimpOperationHueSaturation))
+#define GIMP_OPERATION_HUE_SATURATION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  GIMP_TYPE_OPERATION_HUE_SATURATION, GimpOperationHueSaturationClass))
+#define GIMP_IS_OPERATION_HUE_SATURATION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_OPERATION_HUE_SATURATION))
+#define GIMP_IS_OPERATION_HUE_SATURATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GIMP_TYPE_OPERATION_HUE_SATURATION))
+#define GIMP_OPERATION_HUE_SATURATION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  GIMP_TYPE_OPERATION_HUE_SATURATION, GimpOperationHueSaturationClass))
+
+
+typedef struct _GimpOperationHueSaturationClass GimpOperationHueSaturationClass;
+
+struct _GimpOperationHueSaturation
+{
+  GeglOperationPointFilter  parent_instance;
+
+  GimpHueRange              range;
+
+  gdouble                   hue[7];
+  gdouble                   saturation[7];
+  gdouble                   lightness[7];
+
+  gdouble                   overlap;
+};
+
+struct _GimpOperationHueSaturationClass
+{
+  GeglOperationPointFilterClass  parent_class;
+};
+
+
+GType   gimp_operation_hue_saturation_get_type (void) G_GNUC_CONST;
+
+
+#endif /* __GIMP_OPERATION_HUE_SATURATION_H__ */

Modified: trunk/app/tools/gimphuesaturationtool.c
==============================================================================
--- trunk/app/tools/gimphuesaturationtool.c	(original)
+++ trunk/app/tools/gimphuesaturationtool.c	Mon Jan 14 20:44:01 2008
@@ -49,15 +49,16 @@
 
 /*  local function prototypes  */
 
-static void     gimp_hue_saturation_tool_finalize   (GObject          *object);
+static void       gimp_hue_saturation_tool_finalize      (GObject          *object);
 
-static gboolean gimp_hue_saturation_tool_initialize (GimpTool         *tool,
-                                                     GimpDisplay      *display,
-                                                     GError          **error);
-
-static void     gimp_hue_saturation_tool_map        (GimpImageMapTool *im_tool);
-static void     gimp_hue_saturation_tool_dialog     (GimpImageMapTool *im_tool);
-static void     gimp_hue_saturation_tool_reset      (GimpImageMapTool *im_tool);
+static gboolean   gimp_hue_saturation_tool_initialize    (GimpTool         *tool,
+                                                          GimpDisplay      *display,
+                                                          GError          **error);
+
+static GeglNode * gimp_hue_saturation_tool_get_operation (GimpImageMapTool *im_tool);
+static void       gimp_hue_saturation_tool_map           (GimpImageMapTool *im_tool);
+static void       gimp_hue_saturation_tool_dialog        (GimpImageMapTool *im_tool);
+static void       gimp_hue_saturation_tool_reset         (GimpImageMapTool *im_tool);
 
 static void     hue_saturation_update_sliders       (GimpHueSaturationTool *hs_tool);
 static void     hue_saturation_update_color_areas   (GimpHueSaturationTool *hs_tool);
@@ -115,15 +116,16 @@
   GimpToolClass         *tool_class    = GIMP_TOOL_CLASS (klass);
   GimpImageMapToolClass *im_tool_class = GIMP_IMAGE_MAP_TOOL_CLASS (klass);
 
-  object_class->finalize    = gimp_hue_saturation_tool_finalize;
+  object_class->finalize       = gimp_hue_saturation_tool_finalize;
 
-  tool_class->initialize    = gimp_hue_saturation_tool_initialize;
+  tool_class->initialize       = gimp_hue_saturation_tool_initialize;
 
-  im_tool_class->shell_desc = _("Adjust Hue / Lightness / Saturation");
+  im_tool_class->shell_desc    = _("Adjust Hue / Lightness / Saturation");
 
-  im_tool_class->map        = gimp_hue_saturation_tool_map;
-  im_tool_class->dialog     = gimp_hue_saturation_tool_dialog;
-  im_tool_class->reset      = gimp_hue_saturation_tool_reset;
+  im_tool_class->get_operation = gimp_hue_saturation_tool_get_operation;
+  im_tool_class->map           = gimp_hue_saturation_tool_map;
+  im_tool_class->dialog        = gimp_hue_saturation_tool_dialog;
+  im_tool_class->reset         = gimp_hue_saturation_tool_reset;
 }
 
 static void
@@ -181,9 +183,37 @@
   return TRUE;
 }
 
+static GeglNode *
+gimp_hue_saturation_tool_get_operation (GimpImageMapTool *im_tool)
+{
+  return g_object_new (GEGL_TYPE_NODE,
+                       "operation", "gimp-hue-saturation",
+                       NULL);
+}
+
 static void
 gimp_hue_saturation_tool_map (GimpImageMapTool *image_map_tool)
 {
+  GimpHueSaturationTool *hs_tool = GIMP_HUE_SATURATION_TOOL (image_map_tool);
+  HueSaturation         *hs      = hs_tool->hue_saturation;
+  GimpHueRange           range;
+
+  for (range = GIMP_ALL_HUES; range <= GIMP_MAGENTA_HUES; range++)
+    {
+      gegl_node_set (image_map_tool->operation,
+                     "range", range,
+                     NULL);
+
+      gegl_node_set (image_map_tool->operation,
+                     "hue",        hs->hue[range]        / 180.0,
+                     "saturation", hs->saturation[range] / 100.0,
+                     "lightness",  hs->lightness[range]  / 100.0,
+                     NULL);
+    }
+
+  gegl_node_set (image_map_tool->operation,
+                 "overlap", hs->overlap / 100.0,
+                 NULL);
 }
 
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]