diff --git a/app/actions/image-actions.c b/app/actions/image-actions.c index 94e1298f4c..7f0218138f 100644 --- a/app/actions/image-actions.c +++ b/app/actions/image-actions.c @@ -54,6 +54,7 @@ static const GimpActionEntry image_actions[] = { "image-menu", NULL, NC_("image-action", "_Image") }, { "image-mode-menu", NULL, NC_("image-action", "_Mode") }, + { "image-precision-menu", NULL, NC_("image-action", "_Precision") }, { "image-transform-menu", NULL, NC_("image-action", "_Transform") }, { "image-guides-menu", NULL, NC_("image-action", "_Guides") }, @@ -136,7 +137,7 @@ static const GimpActionEntry image_actions[] = GIMP_HELP_IMAGE_PROPERTIES } }; -static const GimpRadioActionEntry image_convert_actions[] = +static const GimpRadioActionEntry image_convert_base_type_actions[] = { { "image-convert-rgb", GIMP_STOCK_CONVERT_RGB, NC_("image-convert-action", "_RGB"), NULL, @@ -154,6 +155,24 @@ static const GimpRadioActionEntry image_convert_actions[] = GIMP_INDEXED, GIMP_HELP_IMAGE_CONVERT_INDEXED } }; +static const GimpRadioActionEntry image_convert_precision_actions[] = +{ + { "image-convert-u8", NULL, + NC_("image-convert-action", "8 bit unsigned integer"), NULL, + NC_("image-convert-action", "Convert the image to 8 bit unsigned integer"), + GIMP_PRECISION_U8, GIMP_HELP_IMAGE_CONVERT_U8 }, + + { "image-convert-u16", NULL, + NC_("image-convert-action", "16 bit unsigned integer"), NULL, + NC_("image-convert-action", "Convert the image to 16 bit unsigned integer"), + GIMP_PRECISION_U16, GIMP_HELP_IMAGE_CONVERT_U16 }, + + { "image-convert-float", NULL, + NC_("image-convert-action", "16 bit floating point"), NULL, + NC_("image-convert-action", "Convert the image to 16 bit floating point"), + GIMP_PRECISION_FLOAT, GIMP_HELP_IMAGE_CONVERT_FLOAT } +}; + static const GimpEnumActionEntry image_flip_actions[] = { { "image-flip-horizontal", GIMP_STOCK_FLIP_HORIZONTAL, @@ -199,10 +218,16 @@ image_actions_setup (GimpActionGroup *group) G_N_ELEMENTS (image_actions)); gimp_action_group_add_radio_actions (group, "image-convert-action", - image_convert_actions, - G_N_ELEMENTS (image_convert_actions), + image_convert_base_type_actions, + G_N_ELEMENTS (image_convert_base_type_actions), NULL, 0, - G_CALLBACK (image_convert_cmd_callback)); + G_CALLBACK (image_convert_base_type_cmd_callback)); + + gimp_action_group_add_radio_actions (group, "image-convert-action", + image_convert_precision_actions, + G_N_ELEMENTS (image_convert_precision_actions), + NULL, 0, + G_CALLBACK (image_convert_precision_cmd_callback)); gimp_action_group_add_enum_actions (group, "image-action", image_flip_actions, @@ -228,12 +253,13 @@ void image_actions_update (GimpActionGroup *group, gpointer data) { - GimpImage *image = action_data_get_image (data); - gboolean is_u8 = FALSE; - gboolean aux = FALSE; - gboolean lp = FALSE; - gboolean sel = FALSE; - gboolean groups = FALSE; + GimpImage *image = action_data_get_image (data); + gboolean is_indexed = FALSE; + gboolean is_u8 = FALSE; + gboolean aux = FALSE; + gboolean lp = FALSE; + gboolean sel = FALSE; + gboolean groups = FALSE; if (image) { @@ -242,25 +268,29 @@ image_actions_update (GimpActionGroup *group, switch (gimp_image_base_type (image)) { - case GIMP_RGB: - action = "image-convert-rgb"; - break; - - case GIMP_GRAY: - action = "image-convert-grayscale"; - break; - - case GIMP_INDEXED: - action = "image-convert-indexed"; + case GIMP_RGB: action = "image-convert-rgb"; break; + case GIMP_GRAY: action = "image-convert-grayscale"; break; + case GIMP_INDEXED: action = "image-convert-indexed"; break; break; } gimp_action_group_set_action_active (group, action, TRUE); - is_u8 = (gimp_image_get_precision (image) == GIMP_PRECISION_U8); - aux = (gimp_image_get_active_channel (image) != NULL); - lp = ! gimp_image_is_empty (image); - sel = ! gimp_channel_is_empty (gimp_image_get_mask (image)); + switch (gimp_image_get_precision (image)) + { + case GIMP_PRECISION_U8: action = "image-convert-u8"; break; + case GIMP_PRECISION_U16: action = "image-convert-u16"; break; + case GIMP_PRECISION_FLOAT: action = "image-convert-float"; break; + break; + } + + gimp_action_group_set_action_active (group, action, TRUE); + + is_indexed = (gimp_image_base_type (image) == GIMP_INDEXED); + is_u8 = (gimp_image_get_precision (image) == GIMP_PRECISION_U8); + aux = (gimp_image_get_active_channel (image) != NULL); + lp = ! gimp_image_is_empty (image); + sel = ! gimp_channel_is_empty (gimp_image_get_mask (image)); layers = gimp_image_get_layers (image); @@ -274,6 +304,10 @@ image_actions_update (GimpActionGroup *group, SET_SENSITIVE ("image-convert-grayscale", image); SET_SENSITIVE ("image-convert-indexed", image && !groups && is_u8); + SET_SENSITIVE ("image-convert-u8", image); + SET_SENSITIVE ("image-convert-u16", image && !is_indexed); + SET_SENSITIVE ("image-convert-float", image && !is_indexed); + SET_SENSITIVE ("image-flip-horizontal", image); SET_SENSITIVE ("image-flip-vertical", image); SET_SENSITIVE ("image-rotate-90", image); diff --git a/app/actions/image-commands.c b/app/actions/image-commands.c index 2526b1e790..e17509aad9 100644 --- a/app/actions/image-commands.c +++ b/app/actions/image-commands.c @@ -149,9 +149,9 @@ image_convert_dialog_unset (GtkWidget *widget) } void -image_convert_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +image_convert_base_type_cmd_callback (GtkAction *action, + GtkAction *current, + gpointer data) { GimpImage *image; GtkWidget *widget; @@ -211,6 +211,26 @@ image_convert_cmd_callback (GtkAction *action, gimp_image_flush (image); } +void +image_convert_precision_cmd_callback (GtkAction *action, + GtkAction *current, + gpointer data) +{ + GimpImage *image; + GimpDisplay *display; + GimpPrecision value; + return_if_no_image (image, data); + return_if_no_display (display, data); + + value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + + if (value == gimp_image_get_precision (image)) + return; + + gimp_image_convert_precision (image, value, GIMP_PROGRESS (display)); + gimp_image_flush (image); +} + void image_resize_cmd_callback (GtkAction *action, gpointer data) diff --git a/app/actions/image-commands.h b/app/actions/image-commands.h index 0897c83528..07fdaecc08 100644 --- a/app/actions/image-commands.h +++ b/app/actions/image-commands.h @@ -22,7 +22,10 @@ void image_new_cmd_callback (GtkAction *action, gpointer data); -void image_convert_cmd_callback (GtkAction *action, +void image_convert_base_type_cmd_callback (GtkAction *action, + GtkAction *current, + gpointer data); +void image_convert_precision_cmd_callback (GtkAction *action, GtkAction *current, gpointer data); diff --git a/app/core/core-enums.c b/app/core/core-enums.c index 8310c3e457..e4391d509d 100644 --- a/app/core/core-enums.c +++ b/app/core/core-enums.c @@ -1027,6 +1027,7 @@ gimp_undo_type_get_type (void) { GIMP_UNDO_GROUP_VECTORS_IMPORT, "GIMP_UNDO_GROUP_VECTORS_IMPORT", "group-vectors-import" }, { GIMP_UNDO_GROUP_MISC, "GIMP_UNDO_GROUP_MISC", "group-misc" }, { GIMP_UNDO_IMAGE_TYPE, "GIMP_UNDO_IMAGE_TYPE", "image-type" }, + { GIMP_UNDO_IMAGE_PRECISION, "GIMP_UNDO_IMAGE_PRECISION", "image-precision" }, { GIMP_UNDO_IMAGE_SIZE, "GIMP_UNDO_IMAGE_SIZE", "image-size" }, { GIMP_UNDO_IMAGE_RESOLUTION, "GIMP_UNDO_IMAGE_RESOLUTION", "image-resolution" }, { GIMP_UNDO_IMAGE_GRID, "GIMP_UNDO_IMAGE_GRID", "image-grid" }, @@ -1113,6 +1114,7 @@ gimp_undo_type_get_type (void) { GIMP_UNDO_GROUP_VECTORS_IMPORT, NC_("undo-type", "Import paths"), NULL }, { GIMP_UNDO_GROUP_MISC, NC_("undo-type", "Plug-In"), NULL }, { GIMP_UNDO_IMAGE_TYPE, NC_("undo-type", "Image type"), NULL }, + { GIMP_UNDO_IMAGE_PRECISION, NC_("undo-type", "Image precision"), NULL }, { GIMP_UNDO_IMAGE_SIZE, NC_("undo-type", "Image size"), NULL }, { GIMP_UNDO_IMAGE_RESOLUTION, NC_("undo-type", "Image resolution change"), NULL }, { GIMP_UNDO_IMAGE_GRID, NC_("undo-type", "Grid"), NULL }, diff --git a/app/core/core-enums.h b/app/core/core-enums.h index f1f7d6e7a7..a49c8cc83c 100644 --- a/app/core/core-enums.h +++ b/app/core/core-enums.h @@ -487,6 +487,7 @@ typedef enum /*< pdb-skip >*/ /* Undo types which actually do something */ GIMP_UNDO_IMAGE_TYPE, /*< desc="Image type" >*/ + GIMP_UNDO_IMAGE_PRECISION, /*< desc="Image precision" >*/ GIMP_UNDO_IMAGE_SIZE, /*< desc="Image size" >*/ GIMP_UNDO_IMAGE_RESOLUTION, /*< desc="Image resolution change" >*/ GIMP_UNDO_IMAGE_GRID, /*< desc="Grid" >*/ diff --git a/app/core/gimpimage-convert.c b/app/core/gimpimage-convert.c index fe4130a787..dfd6477233 100644 --- a/app/core/gimpimage-convert.c +++ b/app/core/gimpimage-convert.c @@ -1085,6 +1085,79 @@ gimp_image_convert (GimpImage *image, return TRUE; } +void +gimp_image_convert_precision (GimpImage *image, + GimpPrecision precision, + GimpProgress *progress) +{ + GList *all_drawables; + GList *list; + const gchar *undo_desc = NULL; + gint nth_drawable, n_drawables; + + g_return_if_fail (GIMP_IS_IMAGE (image)); + g_return_if_fail (precision != gimp_image_get_precision (image)); + g_return_if_fail (precision == GIMP_PRECISION_U8 || + gimp_image_base_type (image) != GIMP_INDEXED); + g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress)); + + all_drawables = g_list_concat (gimp_image_get_layer_list (image), + gimp_image_get_channel_list (image)); + + n_drawables = g_list_length (all_drawables); + + switch (precision) + { + case GIMP_PRECISION_U8: + undo_desc = C_("undo-type", "Convert Image to 8 bit unsigned integer"); + break; + + case GIMP_PRECISION_U16: + undo_desc = C_("undo-type", "Convert Image to 16 bit unsigned integer"); + break; + + case GIMP_PRECISION_FLOAT: + undo_desc = C_("undo-type", "Convert Image to 32 bit float"); + break; + } + + if (progress) + gimp_progress_start (progress, undo_desc, FALSE); + + g_object_freeze_notify (G_OBJECT (image)); + + gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_CONVERT, + undo_desc); + + /* Push the image type to the stack */ + gimp_image_undo_push_image_precision (image, NULL); + + /* Set the new precision */ + g_object_set (image, "precision", precision, NULL); + + for (list = all_drawables, nth_drawable = 0; + list; + list = g_list_next (list), nth_drawable++) + { + GimpDrawable *drawable = list->data; + + gimp_drawable_convert_type (drawable, image, + gimp_drawable_get_base_type (drawable), + precision, TRUE); + + if (progress) + gimp_progress_set_value (progress, + (gdouble) nth_drawable / (gdouble) n_drawables); + } + + gimp_image_undo_group_end (image); + + gimp_image_precision_changed (image); + g_object_thaw_notify (G_OBJECT (image)); + + if (progress) + gimp_progress_end (progress); +} /* * Indexed color conversion machinery diff --git a/app/core/gimpimage-convert.h b/app/core/gimpimage-convert.h index 8437f0e8e1..e689b39210 100644 --- a/app/core/gimpimage-convert.h +++ b/app/core/gimpimage-convert.h @@ -22,19 +22,23 @@ #define MAXNUMCOLORS 256 -gboolean gimp_image_convert (GimpImage *image, - GimpImageBaseType new_type, - /* The following params used only for - * new_type == GIMP_INDEXED - */ - gint num_cols, - GimpConvertDitherType dither, - gboolean alpha_dither, - gboolean remove_dups, - GimpConvertPaletteType palette_type, - GimpPalette *custom_palette, - GimpProgress *progress, - GError **error); +gboolean gimp_image_convert (GimpImage *image, + GimpImageBaseType new_type, + /* The following params used only for + * new_type == GIMP_INDEXED + */ + gint num_cols, + GimpConvertDitherType dither, + gboolean alpha_dither, + gboolean remove_dups, + GimpConvertPaletteType palette_type, + GimpPalette *custom_palette, + GimpProgress *progress, + GError **error); + +void gimp_image_convert_precision (GimpImage *image, + GimpPrecision precision, + GimpProgress *progress); void gimp_image_convert_set_dither_matrix (const guchar *matrix, gint width, diff --git a/app/core/gimpimage-undo-push.c b/app/core/gimpimage-undo-push.c index aed00ee601..7db3f4dab0 100644 --- a/app/core/gimpimage-undo-push.c +++ b/app/core/gimpimage-undo-push.c @@ -76,6 +76,18 @@ gimp_image_undo_push_image_type (GimpImage *image, NULL); } +GimpUndo * +gimp_image_undo_push_image_precision (GimpImage *image, + const gchar *undo_desc) +{ + g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); + + return gimp_image_undo_push (image, GIMP_TYPE_IMAGE_UNDO, + GIMP_UNDO_IMAGE_PRECISION, undo_desc, + GIMP_DIRTY_IMAGE, + NULL); +} + GimpUndo * gimp_image_undo_push_image_size (GimpImage *image, const gchar *undo_desc, diff --git a/app/core/gimpimage-undo-push.h b/app/core/gimpimage-undo-push.h index 7aab4bb70f..41e93c8f34 100644 --- a/app/core/gimpimage-undo-push.h +++ b/app/core/gimpimage-undo-push.h @@ -23,6 +23,8 @@ GimpUndo * gimp_image_undo_push_image_type (GimpImage *image, const gchar *undo_desc); +GimpUndo * gimp_image_undo_push_image_precision (GimpImage *image, + const gchar *undo_desc); GimpUndo * gimp_image_undo_push_image_size (GimpImage *image, const gchar *undo_desc, gint previous_origin_x, diff --git a/app/core/gimpimage-undo.c b/app/core/gimpimage-undo.c index dcf365f208..1b24561af4 100644 --- a/app/core/gimpimage-undo.c +++ b/app/core/gimpimage-undo.c @@ -507,6 +507,9 @@ gimp_image_undo_pop_stack (GimpImage *image, if (accum.mode_changed) gimp_image_mode_changed (image); + if (accum.precision_changed) + gimp_image_precision_changed (image); + if (accum.size_changed) gimp_image_size_changed_detailed (image, accum.previous_origin_x, diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c index 20efde0ef2..64032d88d2 100644 --- a/app/core/gimpimage.c +++ b/app/core/gimpimage.c @@ -89,6 +89,7 @@ enum { MODE_CHANGED, + PRECISION_CHANGED, ALPHA_CHANGED, FLOATING_SELECTION_CHANGED, ACTIVE_LAYER_CHANGED, @@ -161,6 +162,7 @@ static gchar * gimp_image_get_description (GimpViewable *viewable, gchar **tooltip); static void gimp_image_real_mode_changed (GimpImage *image); +static void gimp_image_real_precision_changed(GimpImage *image); static void gimp_image_real_size_changed_detailed (GimpImage *image, gint previous_origin_x, @@ -252,6 +254,15 @@ gimp_image_class_init (GimpImageClass *klass) gimp_marshal_VOID__VOID, G_TYPE_NONE, 0); + gimp_image_signals[PRECISION_CHANGED] = + g_signal_new ("precision-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpImageClass, precision_changed), + NULL, NULL, + gimp_marshal_VOID__VOID, + G_TYPE_NONE, 0); + gimp_image_signals[ALPHA_CHANGED] = g_signal_new ("alpha-changed", G_TYPE_FROM_CLASS (klass), @@ -536,6 +547,7 @@ gimp_image_class_init (GimpImageClass *klass) viewable_class->get_description = gimp_image_get_description; klass->mode_changed = gimp_image_real_mode_changed; + klass->precision_changed = gimp_image_real_precision_changed; klass->alpha_changed = NULL; klass->floating_selection_changed = NULL; klass->active_layer_changed = NULL; @@ -1172,6 +1184,12 @@ gimp_image_real_mode_changed (GimpImage *image) gimp_projectable_structure_changed (GIMP_PROJECTABLE (image)); } +static void +gimp_image_real_precision_changed (GimpImage *image) +{ + gimp_projectable_structure_changed (GIMP_PROJECTABLE (image)); +} + static void gimp_image_real_size_changed_detailed (GimpImage *image, gint previous_origin_x, @@ -2278,6 +2296,14 @@ gimp_image_mode_changed (GimpImage *image) g_signal_emit (image, gimp_image_signals[MODE_CHANGED], 0); } +void +gimp_image_precision_changed (GimpImage *image) +{ + g_return_if_fail (GIMP_IS_IMAGE (image)); + + g_signal_emit (image, gimp_image_signals[PRECISION_CHANGED], 0); +} + void gimp_image_alpha_changed (GimpImage *image) { diff --git a/app/core/gimpimage.h b/app/core/gimpimage.h index 3d34d4ad80..edccd8b1ac 100644 --- a/app/core/gimpimage.h +++ b/app/core/gimpimage.h @@ -48,6 +48,7 @@ struct _GimpImageClass /* signals */ void (* mode_changed) (GimpImage *image); + void (* precision_changed) (GimpImage *image); void (* alpha_changed) (GimpImage *image); void (* floating_selection_changed) (GimpImage *image); void (* active_layer_changed) (GimpImage *image); @@ -214,6 +215,7 @@ void gimp_image_get_visible_array (const GimpImage *image, /* emitting image signals */ void gimp_image_mode_changed (GimpImage *image); +void gimp_image_precision_changed (GimpImage *image); void gimp_image_alpha_changed (GimpImage *image); void gimp_image_invalidate (GimpImage *image, gint x, diff --git a/app/core/gimpimageundo.c b/app/core/gimpimageundo.c index f67a59f5b0..e10b5b17d1 100644 --- a/app/core/gimpimageundo.c +++ b/app/core/gimpimageundo.c @@ -160,6 +160,10 @@ gimp_image_undo_constructed (GObject *object) image_undo->base_type = gimp_image_base_type (image); break; + case GIMP_UNDO_IMAGE_PRECISION: + image_undo->precision = gimp_image_get_precision (image); + break; + case GIMP_UNDO_IMAGE_SIZE: image_undo->width = gimp_image_get_width (image); image_undo->height = gimp_image_get_height (image); @@ -317,6 +321,19 @@ gimp_image_undo_pop (GimpUndo *undo, } break; + case GIMP_UNDO_IMAGE_PRECISION: + { + GimpPrecision precision; + + precision = image_undo->precision; + image_undo->precision = gimp_image_get_precision (image); + g_object_set (image, "precision", precision, NULL); + + if (image_undo->precision != gimp_image_get_precision (image)) + accum->precision_changed = TRUE; + } + break; + case GIMP_UNDO_IMAGE_SIZE: { gint width; diff --git a/app/core/gimpimageundo.h b/app/core/gimpimageundo.h index ecbf04d3cb..33b2c5e79c 100644 --- a/app/core/gimpimageundo.h +++ b/app/core/gimpimageundo.h @@ -37,6 +37,7 @@ struct _GimpImageUndo GimpUndo parent_instance; GimpImageBaseType base_type; + GimpPrecision precision; gint width; gint height; gint previous_origin_x; diff --git a/app/core/gimpundo.h b/app/core/gimpundo.h index d3d1584365..419ac23460 100644 --- a/app/core/gimpundo.h +++ b/app/core/gimpundo.h @@ -25,6 +25,7 @@ struct _GimpUndoAccumulator { gboolean mode_changed; + gboolean precision_changed; gboolean size_changed; gint previous_origin_x; diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h index e6f5132c59..d5019c8220 100644 --- a/app/widgets/gimphelp-ids.h +++ b/app/widgets/gimphelp-ids.h @@ -116,6 +116,9 @@ #define GIMP_HELP_IMAGE_CONVERT_RGB "gimp-image-convert-rgb" #define GIMP_HELP_IMAGE_CONVERT_GRAYSCALE "gimp-image-convert-grayscale" #define GIMP_HELP_IMAGE_CONVERT_INDEXED "gimp-image-convert-indexed" +#define GIMP_HELP_IMAGE_CONVERT_U8 "gimp-image-convert-u8" +#define GIMP_HELP_IMAGE_CONVERT_U16 "gimp-image-convert-u16" +#define GIMP_HELP_IMAGE_CONVERT_FLOAT "gimp-image-convert-float" #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/menus/image-menu.xml.in b/menus/image-menu.xml.in index 80dcd6748d..131a08a813 100644 --- a/menus/image-menu.xml.in +++ b/menus/image-menu.xml.in @@ -320,6 +320,12 @@ + + + + + +