diff --git a/ChangeLog b/ChangeLog index 2e43c84903..d55c44e9fc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2005-04-16 Sven Neumann + + Applied a patch (with minor modifications) from Karine Delvare + that makes it possible to choose between various ways to remove + color from a drawable (bug #155507): + + * libgimpbase/gimpbaseenums.h: added new enum GimpDesaturateMode. + + * libgimpbase/gimpbaseenums.c + * libgimp/gimpenums.c.tail + * plug-ins/pygimp/gimpenums.py + * tools/pdbgen/enums.pl: regenerated. + + * app/core/gimpdrawable-desaturate.[ch]: implement other formulas + to remove colors from a drawable. + + * tools/pdbgen/pdb/color.pdb: let gimp_desaturate() call + gimp_drawable_desaturate() with GIMP_DESATURATE_LIGHTNESS so that + it behaves like it always did. + + * app/pdb/color_cmds.c: regenerated. + + * app/dialogs/Makefile.am + * app/dialogs/desaturate-dialog.[ch]: new files that define a simple + dialog to choose a mode for desaturation. + + * app/actions/drawable-actions.[ch]: use the new dialog. + 2005-04-16 Sven Neumann * tools/pdbgen/pdb/vectors.pdb: let pdbgen create the code to diff --git a/app/actions/drawable-actions.c b/app/actions/drawable-actions.c index 10788fad61..94fd256048 100644 --- a/app/actions/drawable-actions.c +++ b/app/actions/drawable-actions.c @@ -42,7 +42,7 @@ static GimpActionEntry drawable_actions[] = { { "drawable-desaturate", GIMP_STOCK_CONVERT_GRAYSCALE, - N_("_Desaturate"), NULL, NULL, + N_("_Desaturate..."), NULL, NULL, G_CALLBACK (drawable_desaturate_cmd_callback), GIMP_HELP_LAYER_DESATURATE }, diff --git a/app/actions/drawable-commands.c b/app/actions/drawable-commands.c index d199e090f4..3a10c9c223 100644 --- a/app/actions/drawable-commands.c +++ b/app/actions/drawable-commands.c @@ -35,6 +35,7 @@ #include "core/gimpitemundo.h" #include "core/gimplayermask.h" +#include "dialogs/desaturate-dialog.h" #include "dialogs/offset-dialog.h" #include "actions.h" @@ -43,15 +44,30 @@ #include "gimp-intl.h" +/* local function prototypes */ + +static void desaturate_response (GtkWidget *widget, + gint response_id, + DesaturateDialog *dialog); + + +/* private variables */ + +static GimpDesaturateMode desaturate_mode = GIMP_DESATURATE_LIGHTNESS; + + /* public functions */ void drawable_desaturate_cmd_callback (GtkAction *action, gpointer data) { - GimpImage *gimage; - GimpDrawable *drawable; + DesaturateDialog *dialog; + GimpImage *gimage; + GimpDrawable *drawable; + GtkWidget *widget; return_if_no_drawable (gimage, drawable, data); + return_if_no_widget (widget, data); if (! gimp_drawable_is_rgb (drawable)) { @@ -59,8 +75,13 @@ drawable_desaturate_cmd_callback (GtkAction *action, return; } - gimp_drawable_desaturate (drawable); - gimp_image_flush (gimage); + dialog = desaturate_dialog_new (drawable, widget, desaturate_mode); + + g_signal_connect (dialog->dialog, "response", + G_CALLBACK (desaturate_response), + dialog); + + gtk_widget_show (dialog->dialog); } void @@ -287,3 +308,26 @@ drawable_rotate_cmd_callback (GtkAction *action, gimp_image_flush (gimage); } + +/* private functions */ + +static void +desaturate_response (GtkWidget *widget, + gint response_id, + DesaturateDialog *dialog) +{ + if (response_id == GTK_RESPONSE_OK) + { + GimpDrawable *drawable = dialog->drawable; + GimpImage *gimage = gimp_item_get_image (GIMP_ITEM (drawable)); + + /* remember for next invocation of the dialog */ + desaturate_mode = dialog->mode; + + gimp_drawable_desaturate (drawable, desaturate_mode); + + gimp_image_flush (gimage); + } + + gtk_widget_destroy (dialog->dialog); +} diff --git a/app/core/gimpdrawable-desaturate.c b/app/core/gimpdrawable-desaturate.c index 5288e63845..3c14b0d6de 100644 --- a/app/core/gimpdrawable-desaturate.c +++ b/app/core/gimpdrawable-desaturate.c @@ -20,6 +20,8 @@ #include +#include "libgimpcolor/gimpcolor.h" + #include "core-types.h" #include "base/pixel-processor.h" @@ -32,34 +34,64 @@ #include "gimp-intl.h" -static void desaturate_region (gpointer data, - PixelRegion *srcPR, - PixelRegion *destPR); +static void desaturate_region_lightness (gpointer data, + PixelRegion *srcPR, + PixelRegion *destPR); + +static void desaturate_region_luminosity (gpointer data, + PixelRegion *srcPR, + PixelRegion *destPR); + +static void desaturate_region_average (gpointer data, + PixelRegion *srcPR, + PixelRegion *destPR); void -gimp_drawable_desaturate (GimpDrawable *drawable) +gimp_drawable_desaturate (GimpDrawable *drawable, + GimpDesaturateMode mode) { - PixelRegion srcPR, destPR; - gint x, y, width, height; - gboolean has_alpha; + PixelRegion srcPR, destPR; + PixelProcessorFunc function; + gint x, y; + gint width, height; + gboolean has_alpha; g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); g_return_if_fail (gimp_drawable_is_rgb (drawable)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); - has_alpha = gimp_drawable_has_alpha (drawable); - if (! gimp_drawable_mask_intersect (drawable, &x, &y, &width, &height)) return; + switch (mode) + { + case GIMP_DESATURATE_LIGHTNESS: + function = (PixelProcessorFunc) desaturate_region_lightness; + break; + + break; + case GIMP_DESATURATE_LUMINOSITY: + function = (PixelProcessorFunc) desaturate_region_luminosity; + break; + + case GIMP_DESATURATE_AVERAGE: + function = (PixelProcessorFunc) desaturate_region_average; + break; + + default: + g_return_if_reached (); + return; + } + + has_alpha = gimp_drawable_has_alpha (drawable); + pixel_region_init (&srcPR, gimp_drawable_data (drawable), x, y, width, height, FALSE); pixel_region_init (&destPR, gimp_drawable_shadow (drawable), x, y, width, height, TRUE); - pixel_regions_process_parallel ((PixelProcessorFunc) desaturate_region, - GINT_TO_POINTER (has_alpha), + pixel_regions_process_parallel (function, GINT_TO_POINTER (has_alpha), 2, &srcPR, &destPR); gimp_drawable_merge_shadow (drawable, TRUE, _("Desaturate")); @@ -68,9 +100,9 @@ gimp_drawable_desaturate (GimpDrawable *drawable) } static void -desaturate_region (gpointer data, - PixelRegion *srcPR, - PixelRegion *destPR) +desaturate_region_lightness (gpointer data, + PixelRegion *srcPR, + PixelRegion *destPR) { const guchar *src = srcPR->data; guchar *dest = destPR->data; @@ -110,3 +142,77 @@ desaturate_region (gpointer data, dest += destPR->rowstride; } } + +static void +desaturate_region_luminosity (gpointer data, + PixelRegion *srcPR, + PixelRegion *destPR) +{ + const guchar *src = srcPR->data; + guchar *dest = destPR->data; + gint h = srcPR->h; + gboolean has_alpha = GPOINTER_TO_INT (data); + + while (h--) + { + const guchar *s = src; + guchar *d = dest; + gint j; + + for (j = 0; j < srcPR->w; j++) + { + gint luminosity = GIMP_RGB_INTENSITY (s[RED_PIX], + s[GREEN_PIX], + s[BLUE_PIX]) + 0.5; + + d[RED_PIX] = luminosity; + d[GREEN_PIX] = luminosity; + d[BLUE_PIX] = luminosity; + + if (has_alpha) + d[ALPHA_PIX] = s[ALPHA_PIX]; + + d += destPR->bytes; + s += srcPR->bytes; + } + + src += srcPR->rowstride; + dest += destPR->rowstride; + } +} + +static void +desaturate_region_average (gpointer data, + PixelRegion *srcPR, + PixelRegion *destPR) +{ + const guchar *src = srcPR->data; + guchar *dest = destPR->data; + gint h = srcPR->h; + gboolean has_alpha = GPOINTER_TO_INT (data); + + while (h--) + { + const guchar *s = src; + guchar *d = dest; + gint j; + + for (j = 0; j < srcPR->w; j++) + { + gint average = (s[RED_PIX] + s[GREEN_PIX] + s[BLUE_PIX] + 1) / 3; + + d[RED_PIX] = average; + d[GREEN_PIX] = average; + d[BLUE_PIX] = average; + + if (has_alpha) + d[ALPHA_PIX] = s[ALPHA_PIX]; + + d += destPR->bytes; + s += srcPR->bytes; + } + + src += srcPR->rowstride; + dest += destPR->rowstride; + } +} diff --git a/app/core/gimpdrawable-desaturate.h b/app/core/gimpdrawable-desaturate.h index c230dd7af2..6a5872629e 100644 --- a/app/core/gimpdrawable-desaturate.h +++ b/app/core/gimpdrawable-desaturate.h @@ -20,7 +20,8 @@ #define __GIMP_DRAWABLE_DESATURATE_H__ -void gimp_drawable_desaturate (GimpDrawable *drawable); +void gimp_drawable_desaturate (GimpDrawable *drawable, + GimpDesaturateMode mode); #endif /* __GIMP_DRAWABLE_DESATURATE_H__ */ diff --git a/app/dialogs/Makefile.am b/app/dialogs/Makefile.am index 53f413e71b..be986c6ddc 100644 --- a/app/dialogs/Makefile.am +++ b/app/dialogs/Makefile.am @@ -28,6 +28,8 @@ libappdialogs_a_sources = \ channel-options-dialog.h \ convert-dialog.c \ convert-dialog.h \ + desaturate-dialog.c \ + desaturate-dialog.h \ file-open-dialog.c \ file-open-dialog.h \ file-open-location-dialog.c \ diff --git a/app/dialogs/desaturate-dialog.c b/app/dialogs/desaturate-dialog.c new file mode 100644 index 0000000000..fb6e667377 --- /dev/null +++ b/app/dialogs/desaturate-dialog.c @@ -0,0 +1,99 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * 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 "libgimpwidgets/gimpwidgets.h" + +#include "dialogs-types.h" + +#include "core/gimplayer.h" + +#include "widgets/gimphelp-ids.h" +#include "widgets/gimpviewabledialog.h" + +#include "desaturate-dialog.h" + +#include "gimp-intl.h" + + +/* public functions */ + +DesaturateDialog * +desaturate_dialog_new (GimpDrawable *drawable, + GtkWidget *parent, + GimpDesaturateMode mode) +{ + DesaturateDialog *dialog; + GtkWidget *vbox; + GtkWidget *frame; + GtkWidget *button; + + g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); + g_return_val_if_fail (GTK_IS_WIDGET (parent), NULL); + + dialog = g_new0 (DesaturateDialog, 1); + + dialog->drawable = drawable; + dialog->mode = mode; + + dialog->dialog = + gimp_viewable_dialog_new (GIMP_VIEWABLE (drawable), + _("Desaturate"), "gimp-drawable-desaturate", + GIMP_STOCK_CONVERT_GRAYSCALE, + _("Remove colors"), + parent, + gimp_standard_help_func, + GIMP_HELP_LAYER_DESATURATE, + + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + _("Desaturate"), GTK_RESPONSE_OK, + + NULL); + + gtk_window_set_resizable (GTK_WINDOW (dialog->dialog), FALSE); + + g_object_weak_ref (G_OBJECT (dialog->dialog), + (GWeakNotify) g_free, dialog); + + gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog->dialog), + GTK_RESPONSE_OK, + GTK_RESPONSE_CANCEL, + -1); + + vbox = gtk_vbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog->dialog)->vbox), vbox); + gtk_widget_show (vbox); + + frame = + gimp_enum_radio_frame_new (GIMP_TYPE_DESATURATE_MODE, + gtk_label_new (_("Choose shade of gray based on:")), + G_CALLBACK (gimp_radio_button_update), + &dialog->mode, + &button); + + gimp_int_radio_group_set_active (GTK_RADIO_BUTTON (button), dialog->mode); + + gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + return dialog; +} diff --git a/app/dialogs/desaturate-dialog.h b/app/dialogs/desaturate-dialog.h new file mode 100644 index 0000000000..59fe242a19 --- /dev/null +++ b/app/dialogs/desaturate-dialog.h @@ -0,0 +1,39 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * 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 __DESATURATE_DIALOG_H__ +#define __DESATURATE_DIALOG_H__ + + +typedef struct _DesaturateDialog DesaturateDialog; + +struct _DesaturateDialog +{ + GtkWidget *dialog; + + GimpDrawable *drawable; + GimpDesaturateMode mode; +}; + + +DesaturateDialog * desaturate_dialog_new (GimpDrawable *drawable, + GtkWidget *parent, + GimpDesaturateMode mode); + + +#endif /* __DESATURATE_DIALOG_H__ */ diff --git a/app/pdb/color_cmds.c b/app/pdb/color_cmds.c index 2bc3289399..1b19e90eb6 100644 --- a/app/pdb/color_cmds.c +++ b/app/pdb/color_cmds.c @@ -515,7 +515,7 @@ desaturate_invoker (Gimp *gimp, success = FALSE; if (success) - gimp_drawable_desaturate (drawable); + gimp_drawable_desaturate (drawable, GIMP_DESATURATE_LIGHTNESS); } return procedural_db_return_args (&desaturate_proc, success); diff --git a/libgimp/gimpenums.c.tail b/libgimp/gimpenums.c.tail index 541b8fee06..a9d30e0706 100644 --- a/libgimp/gimpenums.c.tail +++ b/libgimp/gimpenums.c.tail @@ -14,6 +14,7 @@ static GimpGetTypeFunc get_type_funcs[] = gimp_convert_palette_type_get_type, gimp_convolution_type_get_type, gimp_convolve_type_get_type, + gimp_desaturate_mode_get_type, gimp_dodge_burn_type_get_type, gimp_fill_type_get_type, gimp_gradient_segment_color_get_type, @@ -58,6 +59,7 @@ static const gchar *type_names[] = "GimpConvertPaletteType", "GimpConvolutionType", "GimpConvolveType", + "GimpDesaturateMode", "GimpDodgeBurnType", "GimpFillType", "GimpGradientSegmentColor", diff --git a/libgimpbase/gimpbaseenums.c b/libgimpbase/gimpbaseenums.c index e9b907129d..38bc17557c 100644 --- a/libgimpbase/gimpbaseenums.c +++ b/libgimpbase/gimpbaseenums.c @@ -275,6 +275,37 @@ gimp_clone_type_get_type (void) return type; } +GType +gimp_desaturate_mode_get_type (void) +{ + static const GEnumValue values[] = + { + { GIMP_DESATURATE_LIGHTNESS, "GIMP_DESATURATE_LIGHTNESS", "lightness" }, + { GIMP_DESATURATE_LUMINOSITY, "GIMP_DESATURATE_LUMINOSITY", "luminosity" }, + { GIMP_DESATURATE_AVERAGE, "GIMP_DESATURATE_AVERAGE", "average" }, + { 0, NULL, NULL } + }; + + static const GimpEnumDesc descs[] = + { + { GIMP_DESATURATE_LIGHTNESS, N_("Lightness"), NULL }, + { GIMP_DESATURATE_LUMINOSITY, N_("Luminosity"), NULL }, + { GIMP_DESATURATE_AVERAGE, N_("Average"), NULL }, + { 0, NULL, NULL } + }; + + static GType type = 0; + + if (! type) + { + type = g_enum_register_static ("GimpDesaturateMode", values); + gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp"); + gimp_enum_set_value_descriptions (type, descs); + } + + return type; +} + GType gimp_dodge_burn_type_get_type (void) { diff --git a/libgimpbase/gimpbaseenums.h b/libgimpbase/gimpbaseenums.h index e0fc996472..4a4e31df4f 100644 --- a/libgimpbase/gimpbaseenums.h +++ b/libgimpbase/gimpbaseenums.h @@ -132,6 +132,18 @@ typedef enum } GimpCloneType; +#define GIMP_TYPE_DESATURATE_MODE (gimp_desaturate_mode_get_type ()) + +GType gimp_desaturate_mode_get_type (void) G_GNUC_CONST; + +typedef enum +{ + GIMP_DESATURATE_LIGHTNESS, /*< desc="Lightness" >*/ + GIMP_DESATURATE_LUMINOSITY, /*< desc="Luminosity" >*/ + GIMP_DESATURATE_AVERAGE /*< desc="Average" >*/ +} GimpDesaturateMode; + + #define GIMP_TYPE_DODGE_BURN_TYPE (gimp_dodge_burn_type_get_type ()) GType gimp_dodge_burn_type_get_type (void) G_GNUC_CONST; diff --git a/plug-ins/pygimp/gimpenums.py b/plug-ins/pygimp/gimpenums.py index 3ea1d57da9..e3e9682ce1 100644 --- a/plug-ins/pygimp/gimpenums.py +++ b/plug-ins/pygimp/gimpenums.py @@ -106,6 +106,11 @@ NEGATIVE_CONVOL = 2 BLUR_CONVOLVE = 0 SHARPEN_CONVOLVE = 1 +# GimpDesaturateMode +DESATURATE_LIGHTNESS = 0 +DESATURATE_LUMINOSITY = 1 +DESATURATE_AVERAGE = 2 + # GimpDodgeBurnType DODGE = 0 BURN = 1 diff --git a/po/POTFILES.in b/po/POTFILES.in index 765cf205b9..079851f339 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -133,6 +133,7 @@ app/core/gimpunit.c app/dialogs/about-dialog.c app/dialogs/channel-options-dialog.c app/dialogs/convert-dialog.c +app/dialogs/desaturate-dialog.c app/dialogs/dialogs-constructors.c app/dialogs/dialogs.c app/dialogs/file-open-dialog.c diff --git a/tools/pdbgen/enums.pl b/tools/pdbgen/enums.pl index b833f2d022..0973a593ed 100644 --- a/tools/pdbgen/enums.pl +++ b/tools/pdbgen/enums.pl @@ -82,6 +82,15 @@ package Gimp::CodeGen::enums; mapping => { GIMP_IMAGE_CLONE => '0', GIMP_PATTERN_CLONE => '1' } }, + GimpDesaturateMode => + { contig => 1, + header => 'libgimpbase/gimpbaseenums.h', + symbols => [ qw(GIMP_DESATURATE_LIGHTNESS + GIMP_DESATURATE_LUMINOSITY GIMP_DESATURATE_AVERAGE) ], + mapping => { GIMP_DESATURATE_LIGHTNESS => '0', + GIMP_DESATURATE_LUMINOSITY => '1', + GIMP_DESATURATE_AVERAGE => '2' } + }, GimpDodgeBurnType => { contig => 1, header => 'libgimpbase/gimpbaseenums.h', diff --git a/tools/pdbgen/pdb/color.pdb b/tools/pdbgen/pdb/color.pdb index 6b3148b4af..757a6a7527 100644 --- a/tools/pdbgen/pdb/color.pdb +++ b/tools/pdbgen/pdb/color.pdb @@ -284,7 +284,7 @@ HELP success = FALSE; if (success) - gimp_drawable_desaturate (drawable); + gimp_drawable_desaturate (drawable, GIMP_DESATURATE_LIGHTNESS); } CODE );