mirror of https://github.com/GNOME/gimp.git
Bug 773450 - Animated WEBP images should be able to set frame delay.
animated webp saving: parse time-stamp from layer_name (instead of using default value of '100') also: - add a default delay field to UI, in case time-stamps are not present. - add a 'force delay' checkbox - revamp the whole UI to look like the GIF saving UI.
This commit is contained in:
parent
87d38194d7
commit
d516f9bef8
|
@ -92,27 +92,25 @@ save_dialog (WebPSaveParams *params,
|
||||||
gint32 image_ID,
|
gint32 image_ID,
|
||||||
gint32 n_layers)
|
gint32 n_layers)
|
||||||
{
|
{
|
||||||
GtkWidget *dialog;
|
GtkWidget *dialog;
|
||||||
GtkWidget *vbox;
|
GtkWidget *vbox;
|
||||||
GtkWidget *label;
|
GtkWidget *label;
|
||||||
GtkWidget *table;
|
GtkWidget *table;
|
||||||
GtkWidget *expander;
|
GtkWidget *expander;
|
||||||
GtkWidget *frame;
|
GtkWidget *frame;
|
||||||
GtkWidget *vbox2;
|
GtkWidget *vbox2;
|
||||||
GtkWidget *save_exif;
|
GtkWidget *save_exif;
|
||||||
GtkWidget *save_xmp;
|
GtkWidget *save_xmp;
|
||||||
GtkWidget *preset_label;
|
GtkWidget *preset_label;
|
||||||
GtkListStore *preset_list;
|
GtkListStore *preset_list;
|
||||||
GtkWidget *preset_combo;
|
GtkWidget *preset_combo;
|
||||||
GtkWidget *lossless_checkbox;
|
GtkWidget *lossless_checkbox;
|
||||||
GtkWidget *animation_checkbox;
|
GtkWidget *animation_checkbox;
|
||||||
GtkWidget *loop_anim_checkbox;
|
GtkObject *quality_scale;
|
||||||
GtkObject *quality_scale;
|
GtkObject *alpha_quality_scale;
|
||||||
GtkObject *alpha_quality_scale;
|
gboolean animation_supported = FALSE;
|
||||||
gboolean animation_supported = FALSE;
|
gboolean run;
|
||||||
gint slider1 , slider2;
|
gchar *text;
|
||||||
gboolean run;
|
|
||||||
gchar *text;
|
|
||||||
|
|
||||||
animation_supported = n_layers > 1;
|
animation_supported = n_layers > 1;
|
||||||
|
|
||||||
|
@ -127,7 +125,11 @@ save_dialog (WebPSaveParams *params,
|
||||||
gtk_widget_show (vbox);
|
gtk_widget_show (vbox);
|
||||||
|
|
||||||
/* Create the descriptive label at the top */
|
/* Create the descriptive label at the top */
|
||||||
label = gtk_label_new (_("Use the options below to customize the image."));
|
text = g_strdup_printf ("<b>%s</b>", _("WebP Options"));
|
||||||
|
label = gtk_label_new (NULL);
|
||||||
|
gtk_label_set_markup(GTK_LABEL(label), text);
|
||||||
|
g_free (text);
|
||||||
|
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||||
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
|
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
|
||||||
gtk_widget_show (label);
|
gtk_widget_show (label);
|
||||||
|
|
||||||
|
@ -138,80 +140,9 @@ save_dialog (WebPSaveParams *params,
|
||||||
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
|
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
|
||||||
gtk_widget_show (table);
|
gtk_widget_show (table);
|
||||||
|
|
||||||
/* Create the label for the selecting a preset */
|
|
||||||
preset_label = gtk_label_new (_("Preset:"));
|
|
||||||
gtk_label_set_xalign (GTK_LABEL (preset_label), 0.0);
|
|
||||||
gtk_table_attach (GTK_TABLE (table), preset_label,
|
|
||||||
0, 1, 0, 1,
|
|
||||||
GTK_FILL, GTK_FILL, 0, 0);
|
|
||||||
gtk_widget_show (preset_label);
|
|
||||||
|
|
||||||
/* Create the combobox containing the presets */
|
|
||||||
preset_list = save_dialog_presets ();
|
|
||||||
preset_combo = gimp_string_combo_box_new (GTK_TREE_MODEL (preset_list), 0, 1);
|
|
||||||
g_object_unref (preset_list);
|
|
||||||
|
|
||||||
gimp_string_combo_box_set_active (GIMP_STRING_COMBO_BOX (preset_combo),
|
|
||||||
params->preset);
|
|
||||||
gtk_table_attach (GTK_TABLE (table), preset_combo,
|
|
||||||
1, 3, 0, 1,
|
|
||||||
GTK_FILL, GTK_FILL, 0, 0);
|
|
||||||
gtk_widget_show (preset_combo);
|
|
||||||
|
|
||||||
g_signal_connect (preset_combo, "changed",
|
|
||||||
G_CALLBACK (save_dialog_preset_changed),
|
|
||||||
¶ms->preset);
|
|
||||||
|
|
||||||
/* Create the lossless checkbox */
|
|
||||||
lossless_checkbox = gtk_check_button_new_with_label (_("Lossless"));
|
|
||||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lossless_checkbox),
|
|
||||||
params->lossless);
|
|
||||||
gtk_table_attach (GTK_TABLE (table), lossless_checkbox,
|
|
||||||
1, 3, 1, 2,
|
|
||||||
GTK_FILL, GTK_FILL, 0, 0);
|
|
||||||
gtk_widget_show (lossless_checkbox);
|
|
||||||
|
|
||||||
g_signal_connect (lossless_checkbox, "toggled",
|
|
||||||
G_CALLBACK (gimp_toggle_button_update),
|
|
||||||
¶ms->lossless);
|
|
||||||
|
|
||||||
slider1 = 2;
|
|
||||||
slider2 = 3;
|
|
||||||
if (animation_supported)
|
|
||||||
{
|
|
||||||
slider1 = 4;
|
|
||||||
slider2 = 5;
|
|
||||||
|
|
||||||
/* Create the animation checkbox */
|
|
||||||
animation_checkbox = gtk_check_button_new_with_label (_("Use animation"));
|
|
||||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (animation_checkbox),
|
|
||||||
params->animation);
|
|
||||||
gtk_table_attach (GTK_TABLE (table), animation_checkbox,
|
|
||||||
1, 3, 2, 3,
|
|
||||||
GTK_FILL, GTK_FILL, 0, 0);
|
|
||||||
gtk_widget_show (animation_checkbox);
|
|
||||||
|
|
||||||
g_signal_connect (animation_checkbox, "toggled",
|
|
||||||
G_CALLBACK (gimp_toggle_button_update),
|
|
||||||
¶ms->animation);
|
|
||||||
|
|
||||||
/* Create the loop animation checkbox */
|
|
||||||
loop_anim_checkbox = gtk_check_button_new_with_label (_("Loop infinitely"));
|
|
||||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (loop_anim_checkbox),
|
|
||||||
params->loop);
|
|
||||||
gtk_table_attach (GTK_TABLE (table), loop_anim_checkbox,
|
|
||||||
1, 3, 3, 4,
|
|
||||||
GTK_FILL, GTK_FILL, 0, 0);
|
|
||||||
gtk_widget_show (loop_anim_checkbox);
|
|
||||||
|
|
||||||
g_signal_connect (loop_anim_checkbox, "toggled",
|
|
||||||
G_CALLBACK (gimp_toggle_button_update),
|
|
||||||
¶ms->loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the slider for image quality */
|
/* Create the slider for image quality */
|
||||||
quality_scale = gimp_scale_entry_new (GTK_TABLE (table),
|
quality_scale = gimp_scale_entry_new (GTK_TABLE (table),
|
||||||
0, slider1,
|
0, 0,
|
||||||
_("Image quality:"),
|
_("Image quality:"),
|
||||||
125,
|
125,
|
||||||
0,
|
0,
|
||||||
|
@ -230,7 +161,7 @@ save_dialog (WebPSaveParams *params,
|
||||||
|
|
||||||
/* Create the slider for alpha channel quality */
|
/* Create the slider for alpha channel quality */
|
||||||
alpha_quality_scale = gimp_scale_entry_new (GTK_TABLE (table),
|
alpha_quality_scale = gimp_scale_entry_new (GTK_TABLE (table),
|
||||||
0, slider2,
|
0, 1,
|
||||||
_("Alpha quality:"),
|
_("Alpha quality:"),
|
||||||
125,
|
125,
|
||||||
0,
|
0,
|
||||||
|
@ -247,6 +178,43 @@ save_dialog (WebPSaveParams *params,
|
||||||
G_CALLBACK (gimp_float_adjustment_update),
|
G_CALLBACK (gimp_float_adjustment_update),
|
||||||
¶ms->alpha_quality);
|
¶ms->alpha_quality);
|
||||||
|
|
||||||
|
/* Create the label for the selecting a preset */
|
||||||
|
preset_label = gtk_label_new (_("Preset:"));
|
||||||
|
gtk_label_set_xalign (GTK_LABEL (preset_label), 0.0);
|
||||||
|
gtk_table_attach (GTK_TABLE (table), preset_label,
|
||||||
|
0, 1, 2, 3,
|
||||||
|
GTK_FILL, GTK_FILL, 0, 0);
|
||||||
|
gtk_widget_show (preset_label);
|
||||||
|
|
||||||
|
/* Create the combobox containing the presets */
|
||||||
|
preset_list = save_dialog_presets ();
|
||||||
|
preset_combo = gimp_string_combo_box_new (GTK_TREE_MODEL (preset_list), 0, 1);
|
||||||
|
g_object_unref (preset_list);
|
||||||
|
|
||||||
|
gimp_string_combo_box_set_active (GIMP_STRING_COMBO_BOX (preset_combo),
|
||||||
|
params->preset);
|
||||||
|
gtk_table_attach (GTK_TABLE (table), preset_combo,
|
||||||
|
1, 3, 2, 3,
|
||||||
|
GTK_FILL, GTK_FILL, 0, 0);
|
||||||
|
gtk_widget_show (preset_combo);
|
||||||
|
|
||||||
|
g_signal_connect (preset_combo, "changed",
|
||||||
|
G_CALLBACK (save_dialog_preset_changed),
|
||||||
|
¶ms->preset);
|
||||||
|
|
||||||
|
/* Create the lossless checkbox */
|
||||||
|
lossless_checkbox = gtk_check_button_new_with_label (_("Lossless"));
|
||||||
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lossless_checkbox),
|
||||||
|
params->lossless);
|
||||||
|
gtk_table_attach (GTK_TABLE (table), lossless_checkbox,
|
||||||
|
0, 4, 3, 4,
|
||||||
|
GTK_FILL, GTK_FILL, 0, 0);
|
||||||
|
gtk_widget_show (lossless_checkbox);
|
||||||
|
|
||||||
|
g_signal_connect (lossless_checkbox, "toggled",
|
||||||
|
G_CALLBACK (gimp_toggle_button_update),
|
||||||
|
¶ms->lossless);
|
||||||
|
|
||||||
/* Enable and disable the sliders when the lossless option is selected */
|
/* Enable and disable the sliders when the lossless option is selected */
|
||||||
g_signal_connect (lossless_checkbox, "toggled",
|
g_signal_connect (lossless_checkbox, "toggled",
|
||||||
G_CALLBACK (save_dialog_toggle_scale),
|
G_CALLBACK (save_dialog_toggle_scale),
|
||||||
|
@ -255,6 +223,113 @@ save_dialog (WebPSaveParams *params,
|
||||||
G_CALLBACK (save_dialog_toggle_scale),
|
G_CALLBACK (save_dialog_toggle_scale),
|
||||||
alpha_quality_scale);
|
alpha_quality_scale);
|
||||||
|
|
||||||
|
if (animation_supported)
|
||||||
|
{
|
||||||
|
GtkWidget *animation_box;
|
||||||
|
GtkWidget *animation_box2;
|
||||||
|
GtkWidget *animation_label;
|
||||||
|
GtkWidget *loop_anim_checkbox;
|
||||||
|
GtkWidget *animation_expander;
|
||||||
|
GtkWidget *animation_frame;
|
||||||
|
GtkAdjustment *adj;
|
||||||
|
GtkWidget *delay;
|
||||||
|
GtkWidget *delay_label;
|
||||||
|
GtkWidget *delay_label2;
|
||||||
|
GtkWidget *delay_hbox;
|
||||||
|
GtkWidget *delay_checkbox;
|
||||||
|
|
||||||
|
/* Create the top-level animation checkbox */
|
||||||
|
animation_checkbox = gtk_check_button_new_with_label (_("As animation"));
|
||||||
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (animation_checkbox),
|
||||||
|
params->animation);
|
||||||
|
gtk_table_attach (GTK_TABLE (table), animation_checkbox,
|
||||||
|
0, 4, 4, 5,
|
||||||
|
GTK_FILL, GTK_FILL, 0, 0);
|
||||||
|
gtk_widget_set_sensitive (animation_checkbox, TRUE);
|
||||||
|
g_signal_connect (animation_checkbox, "toggled",
|
||||||
|
G_CALLBACK (gimp_toggle_button_update),
|
||||||
|
¶ms->animation);
|
||||||
|
gtk_widget_show (animation_checkbox);
|
||||||
|
|
||||||
|
text = g_strdup_printf ("<b>%s</b>", _("Animated WebP Options"));
|
||||||
|
animation_expander = gtk_expander_new_with_mnemonic (text);
|
||||||
|
gtk_expander_set_use_markup (GTK_EXPANDER (animation_expander), TRUE);
|
||||||
|
g_free (text);
|
||||||
|
gtk_box_pack_start (GTK_BOX (vbox), animation_expander, TRUE, TRUE, 0);
|
||||||
|
gtk_widget_show (animation_expander);
|
||||||
|
|
||||||
|
/* animation options box */
|
||||||
|
animation_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (animation_box), 6);
|
||||||
|
gtk_container_add (GTK_CONTAINER (animation_expander), animation_box);
|
||||||
|
gtk_widget_show (animation_box);
|
||||||
|
|
||||||
|
animation_frame = gimp_frame_new ("<expander>");
|
||||||
|
gtk_box_pack_start (GTK_BOX (animation_box), animation_frame, FALSE, FALSE, 0);
|
||||||
|
gtk_widget_show (animation_frame);
|
||||||
|
|
||||||
|
animation_box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||||
|
gtk_container_add (GTK_CONTAINER (animation_frame), animation_box2);
|
||||||
|
gtk_widget_show (animation_box2);
|
||||||
|
|
||||||
|
/* loop animation checkbox */
|
||||||
|
loop_anim_checkbox = gtk_check_button_new_with_label (_("Loop forever"));
|
||||||
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (loop_anim_checkbox),
|
||||||
|
params->loop);
|
||||||
|
gtk_box_pack_start (GTK_BOX (animation_box2), loop_anim_checkbox, FALSE, FALSE, 0);
|
||||||
|
gtk_widget_show (loop_anim_checkbox);
|
||||||
|
|
||||||
|
g_signal_connect (loop_anim_checkbox, "toggled",
|
||||||
|
G_CALLBACK (gimp_toggle_button_update),
|
||||||
|
¶ms->loop);
|
||||||
|
|
||||||
|
/* create a hbox for delay */
|
||||||
|
delay_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
||||||
|
gtk_box_pack_start (GTK_BOX (animation_box2), delay_hbox, FALSE, FALSE, 0);
|
||||||
|
gtk_widget_show (delay_hbox);
|
||||||
|
|
||||||
|
/* label for 'delay' adjustment */
|
||||||
|
delay_label = gtk_label_new (_("Delay between frames where unspecified:"));
|
||||||
|
gtk_label_set_xalign (GTK_LABEL (delay_label), 0.0);
|
||||||
|
gtk_box_pack_start (GTK_BOX (delay_hbox), delay_label, FALSE, FALSE, 0);
|
||||||
|
gtk_widget_show (delay_label);
|
||||||
|
|
||||||
|
/* default delay */
|
||||||
|
adj = (GtkAdjustment *) gtk_adjustment_new (params->delay, 1, 10000, 1, 10, 0);
|
||||||
|
delay = gtk_spin_button_new (adj, 1, 0);
|
||||||
|
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (delay), TRUE);
|
||||||
|
gtk_box_pack_start (GTK_BOX (delay_hbox), delay, FALSE, FALSE, 0);
|
||||||
|
gtk_widget_show (delay);
|
||||||
|
|
||||||
|
g_signal_connect (adj, "value-changed",
|
||||||
|
G_CALLBACK (gimp_int_adjustment_update),
|
||||||
|
¶ms->delay);
|
||||||
|
|
||||||
|
/* label for 'ms' adjustment */
|
||||||
|
delay_label2 = gtk_label_new (_("milliseconds"));
|
||||||
|
gtk_box_pack_start (GTK_BOX (delay_hbox), delay_label2, FALSE, FALSE, 0);
|
||||||
|
gtk_widget_show (delay_label2);
|
||||||
|
|
||||||
|
/* Create the force-delay checkbox */
|
||||||
|
delay_checkbox = gtk_check_button_new_with_label (_("Use delay entered above for all frames"));
|
||||||
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (delay_checkbox),
|
||||||
|
params->force_delay);
|
||||||
|
gtk_box_pack_start (GTK_BOX (animation_box2), delay_checkbox, FALSE, FALSE, 0);
|
||||||
|
gtk_widget_show (delay_checkbox);
|
||||||
|
|
||||||
|
g_signal_connect (delay_checkbox, "toggled",
|
||||||
|
G_CALLBACK (gimp_toggle_button_update),
|
||||||
|
¶ms->force_delay);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* bind the animation checkbox to the parameters */
|
||||||
|
g_object_bind_property (animation_checkbox, "active",
|
||||||
|
animation_expander, "sensitive",
|
||||||
|
G_BINDING_SYNC_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Advanced options */
|
||||||
text = g_strdup_printf ("<b>%s</b>", _("_Advanced Options"));
|
text = g_strdup_printf ("<b>%s</b>", _("_Advanced Options"));
|
||||||
expander = gtk_expander_new_with_mnemonic (text);
|
expander = gtk_expander_new_with_mnemonic (text);
|
||||||
gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE);
|
gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE);
|
||||||
|
@ -295,6 +370,7 @@ save_dialog (WebPSaveParams *params,
|
||||||
G_CALLBACK (gimp_toggle_button_update),
|
G_CALLBACK (gimp_toggle_button_update),
|
||||||
¶ms->xmp);
|
¶ms->xmp);
|
||||||
|
|
||||||
|
|
||||||
gtk_widget_show (dialog);
|
gtk_widget_show (dialog);
|
||||||
|
|
||||||
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
|
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
|
||||||
|
|
|
@ -368,6 +368,53 @@ save_layer (const gchar *filename,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
parse_ms_tag (const gchar *str)
|
||||||
|
{
|
||||||
|
gint sum = 0;
|
||||||
|
gint offset = 0;
|
||||||
|
gint length;
|
||||||
|
|
||||||
|
length = strlen (str);
|
||||||
|
|
||||||
|
find_another_bra:
|
||||||
|
|
||||||
|
while ((offset < length) && (str[offset] != '('))
|
||||||
|
offset++;
|
||||||
|
|
||||||
|
if (offset >= length)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (! g_ascii_isdigit (str[++offset]))
|
||||||
|
goto find_another_bra;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
sum *= 10;
|
||||||
|
sum += str[offset] - '0';
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
while ((offset < length) && (g_ascii_isdigit (str[offset])));
|
||||||
|
|
||||||
|
if (length - offset <= 2)
|
||||||
|
return(-3);
|
||||||
|
|
||||||
|
if ((g_ascii_toupper (str[offset]) != 'M') ||
|
||||||
|
(g_ascii_toupper (str[offset + 1]) != 'S'))
|
||||||
|
return -4;
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
get_layer_delay(gint32 layer)
|
||||||
|
{
|
||||||
|
gchar *layer_name = gimp_item_get_name (layer);
|
||||||
|
gint delay_ms = parse_ms_tag (layer_name);
|
||||||
|
g_free (layer_name);
|
||||||
|
return delay_ms;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
save_animation (const gchar *filename,
|
save_animation (const gchar *filename,
|
||||||
gint32 nLayers,
|
gint32 nLayers,
|
||||||
|
@ -399,7 +446,9 @@ save_animation (const gchar *filename,
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
gint loop;
|
gint loop;
|
||||||
|
gint default_delay = params->delay;
|
||||||
|
gboolean force_delay = params->force_delay;
|
||||||
|
|
||||||
/* Begin displaying export progress */
|
/* Begin displaying export progress */
|
||||||
gimp_progress_init_printf (_("Saving '%s'"),
|
gimp_progress_init_printf (_("Saving '%s'"),
|
||||||
|
@ -438,6 +487,7 @@ save_animation (const gchar *filename,
|
||||||
WebPPicture picture;
|
WebPPicture picture;
|
||||||
WebPMemoryWriter mw = { 0 };
|
WebPMemoryWriter mw = { 0 };
|
||||||
gint32 drawable = allLayers[nLayers - 1 - loop];
|
gint32 drawable = allLayers[nLayers - 1 - loop];
|
||||||
|
gint delay = get_layer_delay (drawable);
|
||||||
|
|
||||||
/* Obtain the drawable type */
|
/* Obtain the drawable type */
|
||||||
has_alpha = gimp_drawable_has_alpha (drawable);
|
has_alpha = gimp_drawable_has_alpha (drawable);
|
||||||
|
@ -537,7 +587,7 @@ save_animation (const gchar *filename,
|
||||||
g_object_unref (geglbuffer);
|
g_object_unref (geglbuffer);
|
||||||
|
|
||||||
gimp_progress_update ((loop + 1.0) / nLayers);
|
gimp_progress_update ((loop + 1.0) / nLayers);
|
||||||
frame_timestamp += 100; /* TODO: should extract the real time stamp from layer */
|
frame_timestamp += (delay <= 0 || force_delay) ? default_delay : delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == FALSE)
|
if (status == FALSE)
|
||||||
|
|
|
@ -34,6 +34,8 @@ typedef struct
|
||||||
gboolean exif;
|
gboolean exif;
|
||||||
gboolean iptc;
|
gboolean iptc;
|
||||||
gboolean xmp;
|
gboolean xmp;
|
||||||
|
gint delay;
|
||||||
|
gboolean force_delay;
|
||||||
} WebPSaveParams;
|
} WebPSaveParams;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ static void run (const gchar *name,
|
||||||
GimpParam **return_vals);
|
GimpParam **return_vals);
|
||||||
|
|
||||||
|
|
||||||
GimpPlugInInfo PLUG_IN_INFO =
|
const GimpPlugInInfo PLUG_IN_INFO =
|
||||||
{
|
{
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -85,7 +85,9 @@ query (void)
|
||||||
{ GIMP_PDB_INT32, "anim-loop", "Loop animation infinitely (0/1)" },
|
{ GIMP_PDB_INT32, "anim-loop", "Loop animation infinitely (0/1)" },
|
||||||
{ GIMP_PDB_INT32, "exif", "Toggle saving exif data (0/1)" },
|
{ GIMP_PDB_INT32, "exif", "Toggle saving exif data (0/1)" },
|
||||||
{ GIMP_PDB_INT32, "iptc", "Toggle saving iptc data (0/1)" },
|
{ GIMP_PDB_INT32, "iptc", "Toggle saving iptc data (0/1)" },
|
||||||
{ GIMP_PDB_INT32, "xmp", "Toggle saving xmp data (0/1)" }
|
{ GIMP_PDB_INT32, "xmp", "Toggle saving xmp data (0/1)" },
|
||||||
|
{ GIMP_PDB_INT32, "delay", "Delay to use when timestamp are not available or forced" },
|
||||||
|
{ GIMP_PDB_INT32, "force-delay", "Toggle to for delay" }
|
||||||
};
|
};
|
||||||
|
|
||||||
gimp_install_procedure (LOAD_PROC,
|
gimp_install_procedure (LOAD_PROC,
|
||||||
|
@ -172,28 +174,23 @@ run (const gchar *name,
|
||||||
{
|
{
|
||||||
WebPSaveParams params;
|
WebPSaveParams params;
|
||||||
GimpExportReturn export = GIMP_EXPORT_CANCEL;
|
GimpExportReturn export = GIMP_EXPORT_CANCEL;
|
||||||
gint32 *layers;
|
gint32 *layers = NULL;
|
||||||
gint32 n_layers;
|
gint32 n_layers;
|
||||||
|
|
||||||
/* Initialize the parameters to their defaults */
|
if (run_mode == GIMP_RUN_INTERACTIVE ||
|
||||||
params.preset = g_strdup ("default");
|
run_mode == GIMP_RUN_WITH_LAST_VALS)
|
||||||
params.lossless = FALSE;
|
gimp_ui_init (PLUG_IN_BINARY, FALSE);
|
||||||
params.animation = FALSE;
|
|
||||||
params.loop = TRUE;
|
|
||||||
params.quality = 90.0f;
|
|
||||||
params.alpha_quality = 100.0f;
|
|
||||||
params.exif = TRUE;
|
|
||||||
params.iptc = TRUE;
|
|
||||||
params.xmp = TRUE;
|
|
||||||
|
|
||||||
image_ID = param[1].data.d_int32;
|
image_ID = param[1].data.d_int32;
|
||||||
drawable_ID = param[2].data.d_int32;
|
drawable_ID = param[2].data.d_int32;
|
||||||
|
|
||||||
switch (run_mode)
|
switch (run_mode)
|
||||||
{
|
{
|
||||||
case GIMP_RUN_INTERACTIVE:
|
|
||||||
case GIMP_RUN_WITH_LAST_VALS:
|
case GIMP_RUN_WITH_LAST_VALS:
|
||||||
gimp_ui_init (PLUG_IN_BINARY, FALSE);
|
case GIMP_RUN_INTERACTIVE:
|
||||||
|
/* Possibly retrieve data */
|
||||||
|
gimp_get_data (SAVE_PROC, ¶ms);
|
||||||
|
params.preset = g_strdup ("default"); /* can't serialize strings, so restore default */
|
||||||
|
|
||||||
export = gimp_export_image (&image_ID, &drawable_ID, "WebP",
|
export = gimp_export_image (&image_ID, &drawable_ID, "WebP",
|
||||||
GIMP_EXPORT_CAN_HANDLE_RGB |
|
GIMP_EXPORT_CAN_HANDLE_RGB |
|
||||||
|
@ -205,31 +202,19 @@ run (const gchar *name,
|
||||||
if (export == GIMP_EXPORT_CANCEL)
|
if (export == GIMP_EXPORT_CANCEL)
|
||||||
{
|
{
|
||||||
values[0].data.d_status = GIMP_PDB_CANCEL;
|
values[0].data.d_status = GIMP_PDB_CANCEL;
|
||||||
return;
|
status = GIMP_PDB_CANCEL;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
layers = gimp_image_get_layers (image_ID, &n_layers);
|
|
||||||
|
|
||||||
switch (run_mode)
|
|
||||||
{
|
|
||||||
case GIMP_RUN_INTERACTIVE:
|
|
||||||
if (! save_dialog (¶ms, image_ID, n_layers))
|
|
||||||
status = GIMP_PDB_CANCEL;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GIMP_RUN_NONINTERACTIVE:
|
case GIMP_RUN_NONINTERACTIVE:
|
||||||
if (nparams != 10)
|
if (nparams != 16)
|
||||||
{
|
{
|
||||||
status = GIMP_PDB_CALLING_ERROR;
|
status = GIMP_PDB_CALLING_ERROR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_free (params.preset);
|
|
||||||
params.preset = g_strdup (param[5].data.d_string);
|
params.preset = g_strdup (param[5].data.d_string);
|
||||||
params.lossless = param[6].data.d_int32;
|
params.lossless = param[6].data.d_int32;
|
||||||
params.quality = param[7].data.d_float;
|
params.quality = param[7].data.d_float;
|
||||||
|
@ -239,6 +224,8 @@ run (const gchar *name,
|
||||||
params.exif = param[11].data.d_int32;
|
params.exif = param[11].data.d_int32;
|
||||||
params.iptc = param[12].data.d_int32;
|
params.iptc = param[12].data.d_int32;
|
||||||
params.xmp = param[13].data.d_int32;
|
params.xmp = param[13].data.d_int32;
|
||||||
|
params.delay = param[14].data.d_int32;
|
||||||
|
params.force_delay = param[15].data.d_int32;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -246,24 +233,50 @@ run (const gchar *name,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (status == GIMP_PDB_SUCCESS)
|
if (status == GIMP_PDB_SUCCESS)
|
||||||
{
|
{
|
||||||
if (! save_image (param[3].data.d_string,
|
layers = gimp_image_get_layers (image_ID, &n_layers);
|
||||||
n_layers, layers,
|
if (run_mode == GIMP_RUN_INTERACTIVE)
|
||||||
image_ID,
|
|
||||||
drawable_ID,
|
|
||||||
¶ms,
|
|
||||||
&error))
|
|
||||||
{
|
{
|
||||||
status = GIMP_PDB_EXECUTION_ERROR;
|
if (! save_dialog (¶ms, image_ID, n_layers))
|
||||||
|
{
|
||||||
|
status = GIMP_PDB_CANCEL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (status != GIMP_PDB_SUCCESS)
|
||||||
|
{
|
||||||
|
g_free(params.preset);
|
||||||
|
g_free (layers);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! save_image (param[3].data.d_string,
|
||||||
|
n_layers, layers,
|
||||||
|
image_ID,
|
||||||
|
drawable_ID,
|
||||||
|
¶ms,
|
||||||
|
&error))
|
||||||
|
{
|
||||||
|
status = GIMP_PDB_EXECUTION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
g_free (params.preset);
|
g_free (params.preset);
|
||||||
|
params.preset = NULL;
|
||||||
|
|
||||||
g_free (layers);
|
g_free (layers);
|
||||||
|
|
||||||
if (export == GIMP_EXPORT_EXPORT)
|
if (export == GIMP_EXPORT_EXPORT)
|
||||||
gimp_image_delete (image_ID);
|
gimp_image_delete (image_ID);
|
||||||
|
|
||||||
|
if (status == GIMP_PDB_SUCCESS)
|
||||||
|
{
|
||||||
|
/* save parameters for later */
|
||||||
|
/* we can't serialize strings this way. params.preset isn't saved. */
|
||||||
|
gimp_set_data (SAVE_PROC, ¶ms, sizeof (params));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If an error was supplied, include it in the return values */
|
/* If an error was supplied, include it in the return values */
|
||||||
|
|
Loading…
Reference in New Issue