diff --git a/ChangeLog b/ChangeLog index 927bf9413c..16e6a5f11e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2008-01-10 Michael Natterer + + * app/gegl/Makefile.am + * app/gegl/gegl-types.h + * app/gegl/gimpoperationcolorbalance.[ch]: new operator. + + * app/gegl/gimp-gegl.c: register it. + + * app/tools/gimpcolorbalancetool.c: use it. + 2008-01-09 Joao S. O. Bueno * plug-ins/pygimp/pygimp-vectors.c: Allow Vectors.remove_stroke diff --git a/app/gegl/Makefile.am b/app/gegl/Makefile.am index 8b2f62a043..3ce9bf5031 100644 --- a/app/gegl/Makefile.am +++ b/app/gegl/Makefile.am @@ -7,6 +7,8 @@ libappgegl_a_SOURCES = \ gimp-gegl.h \ gimp-gegl-utils.c \ gimp-gegl-utils.h \ + gimpoperationcolorbalance.c \ + gimpoperationcolorbalance.h \ gimpoperationcolorize.c \ gimpoperationcolorize.h \ gimpoperationdesaturate.c \ diff --git a/app/gegl/gegl-types.h b/app/gegl/gegl-types.h index 044e110a7d..837a2252cf 100644 --- a/app/gegl/gegl-types.h +++ b/app/gegl/gegl-types.h @@ -25,13 +25,14 @@ #include "base/base-types.h" -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 _GimpOperationLevels GimpOperationLevels; +typedef struct _GimpOperationPosterize GimpOperationPosterize; +typedef struct _GimpOperationThreshold GimpOperationThreshold; +typedef struct _GimpOperationTileSink GimpOperationTileSink; +typedef struct _GimpOperationTileSource GimpOperationTileSource; #endif /* __OUR_GEGL_TYPES_H__ */ diff --git a/app/gegl/gimp-gegl.c b/app/gegl/gimp-gegl.c index cbb615c841..6fc3bbe2df 100644 --- a/app/gegl/gimp-gegl.c +++ b/app/gegl/gimp-gegl.c @@ -27,6 +27,7 @@ #include "gegl-types.h" #include "gimp-gegl.h" +#include "gimpoperationcolorbalance.h" #include "gimpoperationcolorize.h" #include "gimpoperationdesaturate.h" #include "gimpoperationlevels.h" @@ -39,6 +40,7 @@ void gimp_gegl_init (void) { + 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_LEVELS); diff --git a/app/gegl/gimpoperationcolorbalance.c b/app/gegl/gimpoperationcolorbalance.c new file mode 100644 index 0000000000..4c7139dbb2 --- /dev/null +++ b/app/gegl/gimpoperationcolorbalance.c @@ -0,0 +1,317 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpoperationcolorbalance.c + * Copyright (C) 2007 Michael Natterer + * + * 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 + +#include "libgimpcolor/gimpcolor.h" +#include "libgimpmath/gimpmath.h" + +#include "gegl-types.h" + +#include "gimpoperationcolorbalance.h" + + +enum +{ + PROP_0, + PROP_RANGE, + PROP_CYAN_RED, + PROP_MAGENTA_GREEN, + PROP_YELLOW_BLUE, + PROP_PRESERVE_LUMINOSITY +}; + + +static void gimp_operation_color_balance_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); +static void gimp_operation_color_balance_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); + +static gboolean gimp_operation_color_balance_process (GeglOperation *operation, + void *in_buf, + void *out_buf, + glong samples); + + +G_DEFINE_TYPE (GimpOperationColorBalance, gimp_operation_color_balance, + GEGL_TYPE_OPERATION_POINT_FILTER) + +#define parent_class gimp_operation_color_balance_parent_class + + +static void +gimp_operation_color_balance_class_init (GimpOperationColorBalanceClass * 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_color_balance_set_property; + object_class->get_property = gimp_operation_color_balance_get_property; + + point_class->process = gimp_operation_color_balance_process; + + gegl_operation_class_set_name (operation_class, "gimp-color-balance"); + + g_object_class_install_property (object_class, PROP_RANGE, + g_param_spec_enum ("range", + "range", + "The affected range", + GIMP_TYPE_TRANSFER_MODE, + GIMP_MIDTONES, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_CYAN_RED, + g_param_spec_double ("cyan-red", + "Cyan-Red", + "Cyan-Red", + -1.0, 1.0, 0.0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_MAGENTA_GREEN, + g_param_spec_double ("magenta-green", + "Magenta-Green", + "Magenta-Green", + -1.0, 1.0, 0.0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_YELLOW_BLUE, + g_param_spec_double ("yellow-blue", + "Yellow-Blue", + "Yellow-Blue", + -1.0, 1.0, 1.0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_PRESERVE_LUMINOSITY, + g_param_spec_boolean ("preserve-luminosity", + "Preserve Luminosity", + "Preserve Luminosity", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); +} + +static void +gimp_operation_color_balance_init (GimpOperationColorBalance *self) +{ + GimpTransferMode range; + + self->range = GIMP_MIDTONES; + + for (range = GIMP_SHADOWS; range <= GIMP_HIGHLIGHTS; range++) + { + self->cyan_red[range] = 0.0; + self->magenta_green[range] = 0.0; + self->yellow_blue[range] = 0.0; + } + + self->preserve_luminosity = TRUE; +} + +static void +gimp_operation_color_balance_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpOperationColorBalance *self = GIMP_OPERATION_COLOR_BALANCE (object); + + switch (property_id) + { + case PROP_RANGE: + g_value_set_enum (value, self->range); + break; + + case PROP_CYAN_RED: + g_value_set_double (value, self->cyan_red[self->range]); + break; + + case PROP_MAGENTA_GREEN: + g_value_set_double (value, self->magenta_green[self->range]); + break; + + case PROP_YELLOW_BLUE: + g_value_set_double (value, self->yellow_blue[self->range]); + break; + + case PROP_PRESERVE_LUMINOSITY: + g_value_set_boolean (value, self->preserve_luminosity); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_operation_color_balance_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpOperationColorBalance *self = GIMP_OPERATION_COLOR_BALANCE (object); + + switch (property_id) + { + case PROP_RANGE: + self->range = g_value_get_enum (value); + break; + + case PROP_CYAN_RED: + self->cyan_red[self->range] = g_value_get_double (value); + break; + + case PROP_MAGENTA_GREEN: + self->magenta_green[self->range] = g_value_get_double (value); + break; + + case PROP_YELLOW_BLUE: + self->yellow_blue[self->range] = g_value_get_double (value); + break; + + case PROP_PRESERVE_LUMINOSITY: + self->preserve_luminosity = g_value_get_boolean (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static inline gfloat +gimp_operation_color_balance_map (gfloat value, + gdouble shadows, + gdouble midtones, + gdouble highlights) +{ + gdouble low = 1.075 - 1.0 / (value / 16.0 + 1.0); + gdouble mid = 0.667 * (1.0 - SQR (value - 0.5)); + gdouble shadows_add; + gdouble shadows_sub; + gdouble midtones_add; + gdouble midtones_sub; + gdouble highlights_add; + gdouble highlights_sub; + + shadows_add = low + 1.0; + shadows_sub = 1.0 - low; + + midtones_add = mid; + midtones_sub = mid; + + highlights_add = 1.0 - low; + highlights_sub = low + 1.0; + + value += shadows * (shadows > 0 ? shadows_add : shadows_sub); + value = CLAMP (value, 0.0, 1.0); + + value += midtones * (midtones > 0 ? midtones_add : midtones_sub); + value = CLAMP (value, 0.0, 1.0); + + value += highlights * (highlights > 0 ? highlights_add : highlights_sub); + value = CLAMP (value, 0.0, 1.0); + + return value; +} + +static gboolean +gimp_operation_color_balance_process (GeglOperation *operation, + void *in_buf, + void *out_buf, + glong samples) +{ + GimpOperationColorBalance *self = GIMP_OPERATION_COLOR_BALANCE (operation); + gfloat *src = in_buf; + gfloat *dest = out_buf; + glong sample; + + for (sample = 0; sample < samples; sample++) + { + gfloat r = src[RED_PIX]; + gfloat g = src[GREEN_PIX]; + gfloat b = src[BLUE_PIX]; + gfloat r_n; + gfloat g_n; + gfloat b_n; + + r_n = gimp_operation_color_balance_map (r, + self->cyan_red[GIMP_SHADOWS], + self->cyan_red[GIMP_MIDTONES], + self->cyan_red[GIMP_HIGHLIGHTS]); + + g_n = gimp_operation_color_balance_map (g, + self->magenta_green[GIMP_SHADOWS], + self->magenta_green[GIMP_MIDTONES], + self->magenta_green[GIMP_HIGHLIGHTS]); + + b_n = gimp_operation_color_balance_map (b, + self->yellow_blue[GIMP_SHADOWS], + self->yellow_blue[GIMP_MIDTONES], + self->yellow_blue[GIMP_HIGHLIGHTS]); + + if (self->preserve_luminosity) + { + GimpRGB rgb; + GimpHSL hsl; + GimpHSL hsl2; + + rgb.r = r_n; + rgb.g = g_n; + rgb.b = b_n; + gimp_rgb_to_hsl (&rgb, &hsl); + + rgb.r = r; + rgb.g = g; + rgb.b = b; + gimp_rgb_to_hsl (&rgb, &hsl2); + + hsl.l = hsl2.l; + + gimp_hsl_to_rgb (&hsl, &rgb); + + r_n = rgb.r; + g_n = rgb.g; + b_n = rgb.b; + } + + dest[RED_PIX] = r_n; + dest[GREEN_PIX] = g_n; + dest[BLUE_PIX] = b_n; + dest[ALPHA_PIX] = src[ALPHA_PIX]; + + src += 4; + dest += 4; + } + + return TRUE; +} diff --git a/app/gegl/gimpoperationcolorbalance.h b/app/gegl/gimpoperationcolorbalance.h new file mode 100644 index 0000000000..ee2545ac6b --- /dev/null +++ b/app/gegl/gimpoperationcolorbalance.h @@ -0,0 +1,61 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpoperationcolorbalance.h + * Copyright (C) 2007 Michael Natterer + * + * 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_COLOR_BALANCE_H__ +#define __GIMP_OPERATION_COLOR_BALANCE_H__ + + +#include "gegl/gegl-operation-point-filter.h" + + +#define GIMP_TYPE_OPERATION_COLOR_BALANCE (gimp_operation_color_balance_get_type ()) +#define GIMP_OPERATION_COLOR_BALANCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_OPERATION_COLOR_BALANCE, GimpOperationColorBalance)) +#define GIMP_OPERATION_COLOR_BALANCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_OPERATION_COLOR_BALANCE, GimpOperationColorBalanceClass)) +#define GIMP_IS_OPERATION_COLOR_BALANCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_OPERATION_COLOR_BALANCE)) +#define GIMP_IS_OPERATION_COLOR_BALANCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_OPERATION_COLOR_BALANCE)) +#define GIMP_OPERATION_COLOR_BALANCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_OPERATION_COLOR_BALANCE, GimpOperationColorBalanceClass)) + + +typedef struct _GimpOperationColorBalanceClass GimpOperationColorBalanceClass; + +struct _GimpOperationColorBalance +{ + GeglOperationPointFilter parent_instance; + + GimpTransferMode range; + + gdouble cyan_red[3]; + gdouble magenta_green[3]; + gdouble yellow_blue[3]; + + gboolean preserve_luminosity; +}; + +struct _GimpOperationColorBalanceClass +{ + GeglOperationPointFilterClass parent_class; +}; + + +GType gimp_operation_color_balance_get_type (void) G_GNUC_CONST; + + +#endif /* __GIMP_OPERATION_COLOR_BALANCE_H__ */ diff --git a/app/tools/gimpcolorbalancetool.c b/app/tools/gimpcolorbalancetool.c index 12334c88ed..a9bfbce19a 100644 --- a/app/tools/gimpcolorbalancetool.c +++ b/app/tools/gimpcolorbalancetool.c @@ -43,15 +43,16 @@ /* local function prototypes */ -static void gimp_color_balance_tool_finalize (GObject *object); +static void gimp_color_balance_tool_finalize (GObject *object); -static gboolean gimp_color_balance_tool_initialize (GimpTool *tool, - GimpDisplay *display, - GError **error); +static gboolean gimp_color_balance_tool_initialize (GimpTool *tool, + GimpDisplay *display, + GError **error); -static void gimp_color_balance_tool_map (GimpImageMapTool *im_tool); -static void gimp_color_balance_tool_dialog (GimpImageMapTool *im_tool); -static void gimp_color_balance_tool_reset (GimpImageMapTool *im_tool); +static GeglNode * gimp_color_balance_tool_get_operation (GimpImageMapTool *im_tool); +static void gimp_color_balance_tool_map (GimpImageMapTool *im_tool); +static void gimp_color_balance_tool_dialog (GimpImageMapTool *im_tool); +static void gimp_color_balance_tool_reset (GimpImageMapTool *im_tool); static void color_balance_update (GimpColorBalanceTool *cb_tool); static void color_balance_range_callback (GtkWidget *widget, @@ -97,15 +98,16 @@ gimp_color_balance_tool_class_init (GimpColorBalanceToolClass *klass) GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass); GimpImageMapToolClass *im_tool_class = GIMP_IMAGE_MAP_TOOL_CLASS (klass); - object_class->finalize = gimp_color_balance_tool_finalize; + object_class->finalize = gimp_color_balance_tool_finalize; - tool_class->initialize = gimp_color_balance_tool_initialize; + tool_class->initialize = gimp_color_balance_tool_initialize; - im_tool_class->shell_desc = _("Adjust Color Balance"); + im_tool_class->shell_desc = _("Adjust Color Balance"); - im_tool_class->map = gimp_color_balance_tool_map; - im_tool_class->dialog = gimp_color_balance_tool_dialog; - im_tool_class->reset = gimp_color_balance_tool_reset; + im_tool_class->get_operation = gimp_color_balance_tool_get_operation; + im_tool_class->map = gimp_color_balance_tool_map; + im_tool_class->dialog = gimp_color_balance_tool_dialog; + im_tool_class->reset = gimp_color_balance_tool_reset; } static void @@ -163,10 +165,41 @@ gimp_color_balance_tool_initialize (GimpTool *tool, return TRUE; } -static void -gimp_color_balance_tool_map (GimpImageMapTool *im_tool) +static GeglNode * +gimp_color_balance_tool_get_operation (GimpImageMapTool *im_tool) { - GimpColorBalanceTool *cb_tool = GIMP_COLOR_BALANCE_TOOL (im_tool); + return g_object_new (GEGL_TYPE_NODE, + "operation", "gimp-color-balance", + NULL); +} + +static void +gimp_color_balance_tool_map (GimpImageMapTool *image_map_tool) +{ + GimpColorBalanceTool *cb_tool = GIMP_COLOR_BALANCE_TOOL (image_map_tool); + + if (image_map_tool->operation) + { + ColorBalance *cb = cb_tool->color_balance; + GimpTransferMode range; + + for (range = GIMP_SHADOWS; range <= GIMP_HIGHLIGHTS; range++) + { + gegl_node_set (image_map_tool->operation, + "range", range, + NULL); + + gegl_node_set (image_map_tool->operation, + "cyan-red", cb->cyan_red[range] / 256.0, + "magenta-green", cb->magenta_green[range] / 256.0, + "yellow-blue", cb->yellow_blue[range] / 256.0, + NULL); + } + + gegl_node_set (image_map_tool->operation, + "preserve-luminosity", cb->preserve_luminosity, + NULL); + } color_balance_create_lookup_tables (cb_tool->color_balance); }