app: implement converting images between precisions, including menu items

This commit is contained in:
Michael Natterer 2012-04-25 16:46:58 +02:00
parent 17e36e9b3f
commit b4580e74e6
17 changed files with 251 additions and 41 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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 },

View File

@ -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" >*/

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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)
{

View File

@ -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,

View File

@ -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;

View File

@ -37,6 +37,7 @@ struct _GimpImageUndo
GimpUndo parent_instance;
GimpImageBaseType base_type;
GimpPrecision precision;
gint width;
gint height;
gint previous_origin_x;

View File

@ -25,6 +25,7 @@
struct _GimpUndoAccumulator
{
gboolean mode_changed;
gboolean precision_changed;
gboolean size_changed;
gint previous_origin_x;

View File

@ -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"

View File

@ -320,6 +320,12 @@
<placeholder name="Color Profile" />
<separator />
</menu>
<menu action="image-precision-menu" name="Precision">
<menuitem action="image-convert-u8" />
<menuitem action="image-convert-u16" />
<menuitem action="image-convert-float" />
<separator />
</menu>
<menu action="image-transform-menu" name="Transform">
<placeholder name="Flip">
<menuitem action="image-flip-horizontal" />