diff --git a/app/actions/image-commands.c b/app/actions/image-commands.c index 8191b09b02..e792198d32 100644 --- a/app/actions/image-commands.c +++ b/app/actions/image-commands.c @@ -52,6 +52,7 @@ #include "display/gimpdisplay.h" #include "display/gimpdisplayshell.h" +#include "dialogs/convert-precision-dialog.h" #include "dialogs/convert-type-dialog.h" #include "dialogs/grid-dialog.h" #include "dialogs/image-merge-layers-dialog.h" @@ -67,7 +68,8 @@ #include "gimp-intl.h" -#define IMAGE_CONVERT_TYPE_DIALOG_KEY "image-convert-type-dialog" +#define IMAGE_CONVERT_PRECISION_DIALOG_KEY "image-convert-precision-dialog" +#define IMAGE_CONVERT_TYPE_DIALOG_KEY "image-convert-type-dialog" typedef struct @@ -150,7 +152,7 @@ image_new_cmd_callback (GtkAction *action, } static void -image_convert_dialog_unset (GtkWidget *widget) +image_convert_type_dialog_unset (GtkWidget *widget) { g_object_set_data (G_OBJECT (widget), IMAGE_CONVERT_TYPE_DIALOG_KEY, NULL); } @@ -208,7 +210,7 @@ image_convert_base_type_cmd_callback (GtkAction *action, IMAGE_CONVERT_TYPE_DIALOG_KEY, dialog); g_signal_connect_object (dialog, "destroy", - G_CALLBACK (image_convert_dialog_unset), + G_CALLBACK (image_convert_type_dialog_unset), widget, G_CONNECT_SWAPPED); } @@ -220,15 +222,23 @@ image_convert_base_type_cmd_callback (GtkAction *action, gimp_image_flush (image); } +static void +image_convert_precision_dialog_unset (GtkWidget *widget) +{ + g_object_set_data (G_OBJECT (widget), IMAGE_CONVERT_PRECISION_DIALOG_KEY, NULL); +} + void image_convert_precision_cmd_callback (GtkAction *action, GtkAction *current, gpointer data) { GimpImage *image; + GtkWidget *widget; GimpDisplay *display; GimpPrecision value; return_if_no_image (image, data); + return_if_no_widget (widget, data); return_if_no_display (display, data); value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); @@ -236,7 +246,37 @@ image_convert_precision_cmd_callback (GtkAction *action, if (value == gimp_image_get_precision (image)) return; - gimp_image_convert_precision (image, value, GIMP_PROGRESS (display)); + if (value < gimp_image_get_precision (image)) + { + GtkWidget *dialog; + + dialog = g_object_get_data (G_OBJECT (widget), + IMAGE_CONVERT_PRECISION_DIALOG_KEY); + + if (! dialog) + { + dialog = convert_precision_dialog_new (image, + action_data_get_context (data), + widget, + value, + GIMP_PROGRESS (display)); + + g_object_set_data (G_OBJECT (widget), + IMAGE_CONVERT_PRECISION_DIALOG_KEY, dialog); + + g_signal_connect_object (dialog, "destroy", + G_CALLBACK (image_convert_precision_dialog_unset), + widget, G_CONNECT_SWAPPED); + } + + gtk_window_present (GTK_WINDOW (dialog)); + } + else + { + gimp_image_convert_precision (image, value, 0, 0, + GIMP_PROGRESS (display)); + } + gimp_image_flush (image); } diff --git a/app/core/gimpimage-convert-precision.c b/app/core/gimpimage-convert-precision.c index 7243ffda5c..b009c9250c 100644 --- a/app/core/gimpimage-convert-precision.c +++ b/app/core/gimpimage-convert-precision.c @@ -39,6 +39,8 @@ void gimp_image_convert_precision (GimpImage *image, GimpPrecision precision, + gint layer_dither_type, + gint mask_dither_type, GimpProgress *progress) { GList *all_drawables; diff --git a/app/core/gimpimage-convert-precision.h b/app/core/gimpimage-convert-precision.h index 84ed2126fa..617eea8130 100644 --- a/app/core/gimpimage-convert-precision.h +++ b/app/core/gimpimage-convert-precision.h @@ -24,6 +24,8 @@ void gimp_image_convert_precision (GimpImage *image, GimpPrecision precision, + gint layer_dither_type, + gint mask_dither_type, GimpProgress *progress); diff --git a/app/dialogs/Makefile.am b/app/dialogs/Makefile.am index c6ae168fec..45e7d4a61c 100644 --- a/app/dialogs/Makefile.am +++ b/app/dialogs/Makefile.am @@ -25,6 +25,8 @@ libappdialogs_a_sources = \ about-dialog.h \ channel-options-dialog.c \ channel-options-dialog.h \ + convert-precision-dialog.c \ + convert-precision-dialog.h \ convert-type-dialog.c \ convert-type-dialog.h \ data-delete-dialog.c \ diff --git a/app/dialogs/convert-precision-dialog.c b/app/dialogs/convert-precision-dialog.c new file mode 100644 index 0000000000..bf06eaf733 --- /dev/null +++ b/app/dialogs/convert-precision-dialog.c @@ -0,0 +1,260 @@ +/* GIMP - The GNU 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 3 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, see . + */ + +#include "config.h" + +#include +#include + +#include "libgimpbase/gimpbase.h" +#include "libgimpwidgets/gimpwidgets.h" + +#include "dialogs-types.h" + +#include "core/gimp.h" +#include "core/gimpcontext.h" +#include "core/gimpimage.h" +#include "core/gimpimage-convert-precision.h" +#include "core/gimplist.h" +#include "core/gimpprogress.h" + +#include "widgets/gimphelp-ids.h" +#include "widgets/gimpviewablebox.h" +#include "widgets/gimpviewabledialog.h" +#include "widgets/gimpwidgets-utils.h" + +#include "convert-precision-dialog.h" + +#include "gimp-intl.h" + + +typedef struct +{ + GtkWidget *dialog; + + GimpImage *image; + GimpProgress *progress; + GimpContext *context; + + GimpPrecision precision; + gint layer_dither_type; + gint mask_dither_type; +} ConvertDialog; + + +static void convert_precision_dialog_response (GtkWidget *widget, + gint response_id, + ConvertDialog *dialog); +static void convert_precision_dialog_free (ConvertDialog *dialog); + + +/* defaults */ + +static gint saved_layer_dither_type = 0; +static gint saved_mask_dither_type = 0; + + +/* public functions */ + +GtkWidget * +convert_precision_dialog_new (GimpImage *image, + GimpContext *context, + GtkWidget *parent, + GimpPrecision precision, + GimpProgress *progress) +{ + ConvertDialog *dialog; + GtkWidget *button; + GtkWidget *main_vbox; + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *label; + GtkWidget *frame; + GtkWidget *combo; + GtkSizeGroup *size_group; + const gchar *enum_desc; + gchar *blurb; + GType operation_type; + GParamSpec *dither_pspec; + GType dither_type; + + g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); + g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); + g_return_val_if_fail (GTK_IS_WIDGET (parent), NULL); + g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL); + + dialog = g_slice_new0 (ConvertDialog); + + dialog->image = image; + dialog->precision = precision; + dialog->progress = progress; + dialog->layer_dither_type = saved_layer_dither_type; + dialog->mask_dither_type = saved_mask_dither_type; + + gimp_enum_get_value (GIMP_TYPE_PRECISION, precision, + NULL, NULL, &enum_desc, NULL); + + blurb = g_strdup_printf (_("Convert Image to %s"), enum_desc); + + dialog->dialog = + gimp_viewable_dialog_new (GIMP_VIEWABLE (image), context, + _("Precision Conversion"), + "gimp-image-convert-precision", + GIMP_STOCK_CONVERT_PRECISION, + blurb, + parent, + gimp_standard_help_func, + GIMP_HELP_IMAGE_CONVERT_PRECISION, + + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + + NULL); + + g_free (blurb); + + button = gtk_dialog_add_button (GTK_DIALOG (dialog->dialog), + _("C_onvert"), GTK_RESPONSE_OK); + gtk_button_set_image (GTK_BUTTON (button), + gtk_image_new_from_stock (GIMP_STOCK_CONVERT_PRECISION, + GTK_ICON_SIZE_BUTTON)); + + gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog->dialog), + GTK_RESPONSE_OK, + GTK_RESPONSE_CANCEL, + -1); + + gtk_window_set_resizable (GTK_WINDOW (dialog->dialog), FALSE); + + g_object_weak_ref (G_OBJECT (dialog->dialog), + (GWeakNotify) convert_precision_dialog_free, dialog); + + g_signal_connect (dialog->dialog, "response", + G_CALLBACK (convert_precision_dialog_response), + dialog); + + main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); + gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog->dialog))), + main_vbox, TRUE, TRUE, 0); + gtk_widget_show (main_vbox); + + + /* dithering */ + + operation_type = gegl_operation_gtype_from_name ("gegl:color-reduction"); + dither_pspec = g_object_class_find_property (g_type_class_peek (operation_type), + "dither-strategy"); + dither_type = G_TYPE_FROM_CLASS (G_PARAM_SPEC_ENUM (dither_pspec)->enum_class); + + frame = gimp_frame_new (_("Dithering")); + gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_container_add (GTK_CONTAINER (frame), vbox); + gtk_widget_show (vbox); + + size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + /* layers */ + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + label = gtk_label_new_with_mnemonic (_("_Layers:")); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_size_group_add_widget (size_group, label); + gtk_widget_show (label); + + combo = gimp_enum_combo_box_new (dither_type); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo); + gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0); + gtk_widget_show (combo); + + gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), + dialog->layer_dither_type, + G_CALLBACK (gimp_int_combo_box_get_active), + &dialog->layer_dither_type); + + /* layers */ + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + label = gtk_label_new_with_mnemonic (_("_Channels and Masks:")); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_size_group_add_widget (size_group, label); + gtk_widget_show (label); + + combo = gimp_enum_combo_box_new (dither_type); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo); + gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0); + gtk_widget_show (combo); + + gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), + dialog->mask_dither_type, + G_CALLBACK (gimp_int_combo_box_get_active), + &dialog->mask_dither_type); + + g_object_unref (size_group); + + return dialog->dialog; +} + + +/* private functions */ + +static void +convert_precision_dialog_response (GtkWidget *widget, + gint response_id, + ConvertDialog *dialog) +{ + if (response_id == GTK_RESPONSE_OK) + { + GimpProgress *progress; + + progress = gimp_progress_start (dialog->progress, + _("Converting to lower bit depth"), FALSE); + + gimp_image_convert_precision (dialog->image, + dialog->precision, + dialog->layer_dither_type, + dialog->mask_dither_type, + progress); + + if (progress) + gimp_progress_end (progress); + + gimp_image_flush (dialog->image); + + /* Save defaults for next time */ + saved_layer_dither_type = dialog->layer_dither_type; + saved_mask_dither_type = dialog->mask_dither_type; + } + + gtk_widget_destroy (dialog->dialog); +} + +static void +convert_precision_dialog_free (ConvertDialog *dialog) +{ + g_slice_free (ConvertDialog, dialog); +} diff --git a/app/dialogs/convert-precision-dialog.h b/app/dialogs/convert-precision-dialog.h new file mode 100644 index 0000000000..0a25a43a81 --- /dev/null +++ b/app/dialogs/convert-precision-dialog.h @@ -0,0 +1,29 @@ +/* GIMP - The GNU 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 3 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, see . + */ + +#ifndef __CONVERT_PRECISION_DIALOG_H__ +#define __CONVERT_PRECISION_DIALOG_H__ + + +GtkWidget * convert_precision_dialog_new (GimpImage *image, + GimpContext *context, + GtkWidget *parent, + GimpPrecision precision, + GimpProgress *progress); + + +#endif /* __CONVERT_PRECISION_DIALOG_H__ */ diff --git a/app/pdb/convert-cmds.c b/app/pdb/convert-cmds.c index 35ddb4b717..93da3cdecb 100644 --- a/app/pdb/convert-cmds.c +++ b/app/pdb/convert-cmds.c @@ -247,7 +247,7 @@ image_convert_precision_invoker (GimpProcedure *procedure, if (gimp_pdb_image_is_not_base_type (image, GIMP_INDEXED, error) && gimp_pdb_image_is_not_precision (image, precision, error)) { - gimp_image_convert_precision (image, precision, NULL); + gimp_image_convert_precision (image, precision, 0, 0, NULL); } else { diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h index 332ec3597f..77d43b4618 100644 --- a/app/widgets/gimphelp-ids.h +++ b/app/widgets/gimphelp-ids.h @@ -121,6 +121,7 @@ #define GIMP_HELP_IMAGE_CONVERT_U32 "gimp-image-convert-u32" #define GIMP_HELP_IMAGE_CONVERT_HALF "gimp-image-convert-half" #define GIMP_HELP_IMAGE_CONVERT_FLOAT "gimp-image-convert-float" +#define GIMP_HELP_IMAGE_CONVERT_PRECISION "gimp-image-convert-precision" #define GIMP_HELP_IMAGE_FLIP_HORIZONTAL "gimp-image-flip-horizontal" #define GIMP_HELP_IMAGE_FLIP_VERTICAL "gimp-image-flip-vertical" #define GIMP_HELP_IMAGE_ROTATE_90 "gimp-image-rotate-90" diff --git a/libgimpwidgets/gimpstock.h b/libgimpwidgets/gimpstock.h index ed26f149bb..bd854fcc81 100644 --- a/libgimpwidgets/gimpstock.h +++ b/libgimpwidgets/gimpstock.h @@ -285,6 +285,7 @@ G_BEGIN_DECLS #define GIMP_STOCK_PALETTE GTK_STOCK_SELECT_COLOR #define GIMP_STOCK_PATTERN GIMP_STOCK_TOOL_BUCKET_FILL #define GIMP_STOCK_CONTROLLER_MOUSE GIMP_STOCK_CURSOR +#define GIMP_STOCK_CONVERT_PRECISION GIMP_STOCK_CONVERT_RGB void gimp_stock_init (void); diff --git a/po/POTFILES.in b/po/POTFILES.in index 29cfa64cab..c0943ab249 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -168,6 +168,7 @@ app/core/gimp-user-install.c app/dialogs/about-dialog.c app/dialogs/channel-options-dialog.c +app/dialogs/convert-precision-dialog.c app/dialogs/convert-type-dialog.c app/dialogs/data-delete-dialog.c app/dialogs/dialogs.c diff --git a/tools/pdbgen/pdb/convert.pdb b/tools/pdbgen/pdb/convert.pdb index 690cfeadb3..116a82e172 100644 --- a/tools/pdbgen/pdb/convert.pdb +++ b/tools/pdbgen/pdb/convert.pdb @@ -246,7 +246,7 @@ HELP if (gimp_pdb_image_is_not_base_type (image, GIMP_INDEXED, error) && gimp_pdb_image_is_not_precision (image, precision, error)) { - gimp_image_convert_precision (image, precision, NULL); + gimp_image_convert_precision (image, precision, 0, 0, NULL); } else {