/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* file-webp - WebP file format plug-in for the GIMP
* Copyright (C) 2015 Nathan Osman
* Copyright (C) 2016 Ben Touchette
*
* 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
#include "file-webp.h"
#include "file-webp-dialog.h"
#include "libgimp/stdplugins-intl.h"
static void save_dialog_toggle_scale (GtkWidget *widget,
gpointer data);
static void save_dialog_toggle_minsize (GtkWidget *widget,
gpointer data);
static void show_maxkeyframe_hints (GtkAdjustment *adj,
GtkLabel *label);
static void
save_dialog_toggle_scale (GtkWidget *widget,
gpointer data)
{
gimp_scale_entry_set_sensitive (GTK_OBJECT (data),
! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
}
static void
save_dialog_toggle_minsize (GtkWidget *widget,
gpointer data)
{
gtk_widget_set_sensitive (GTK_WIDGET (data),
! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
}
static void
show_maxkeyframe_hints (GtkAdjustment *adj,
GtkLabel *label)
{
gint kmax;
kmax = (gint) gtk_adjustment_get_value (adj);
if (kmax == 0)
{
gtk_label_set_text (label, _("(no keyframes)"));
}
else if (kmax == 1)
{
gtk_label_set_text (label, _("(all frames are keyframes)"));
}
else
{
gtk_label_set_text (label, "");
}
}
gboolean
save_dialog (WebPSaveParams *params,
gint32 image_ID)
{
GtkWidget *dialog;
GtkWidget *vbox;
GtkWidget *table;
GtkWidget *expander;
GtkWidget *frame;
GtkWidget *vbox2;
GtkWidget *label;
GtkWidget *toggle;
GtkWidget *toggle_minsize;
GtkWidget *toggle_iptc;
GtkWidget *combo;
GtkObject *quality_scale;
GtkObject *alpha_quality_scale;
gint32 nlayers;
gboolean animation_supported = FALSE;
gboolean run;
gchar *text;
gint row = 0;
g_free (gimp_image_get_layers (image_ID, &nlayers));
animation_supported = nlayers > 1;
/* Create the dialog */
dialog = gimp_export_dialog_new (_("WebP"), PLUG_IN_BINARY, SAVE_PROC);
/* Create the vbox */
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
gtk_box_pack_start (GTK_BOX (gimp_export_dialog_get_content_area (dialog)),
vbox, FALSE, FALSE, 0);
gtk_widget_show (vbox);
/* Create the table */
table = gtk_table_new (4, 3, FALSE);
gtk_table_set_row_spacings (GTK_TABLE (table), 6);
gtk_table_set_col_spacings (GTK_TABLE (table), 6);
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
gtk_widget_show (table);
/* Create the lossless checkbox */
toggle = gtk_check_button_new_with_mnemonic (_("_Lossless"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
params->lossless);
gtk_table_attach (GTK_TABLE (table), toggle,
0, 3, row, row + 1,
GTK_FILL, GTK_FILL, 0, 0);
gtk_widget_show (toggle);
row++;
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update),
¶ms->lossless);
/* Create the slider for image quality */
quality_scale = gimp_scale_entry_new (GTK_TABLE (table),
0, row++,
_("Image _quality:"),
125,
0,
params->quality,
0.0, 100.0,
1.0, 10.0,
0, TRUE,
0.0, 0.0,
_("Image quality"),
NULL);
gimp_scale_entry_set_sensitive (quality_scale, ! params->lossless);
g_signal_connect (quality_scale, "value-changed",
G_CALLBACK (gimp_float_adjustment_update),
¶ms->quality);
/* Create the slider for alpha channel quality */
alpha_quality_scale = gimp_scale_entry_new (GTK_TABLE (table),
0, row++,
_("Alpha q_uality:"),
125,
0,
params->alpha_quality,
0.0, 100.0,
1.0, 10.0,
0, TRUE,
0.0, 0.0,
_("Alpha channel quality"),
NULL);
gimp_scale_entry_set_sensitive (alpha_quality_scale, ! params->lossless);
g_signal_connect (alpha_quality_scale, "value-changed",
G_CALLBACK (gimp_float_adjustment_update),
¶ms->alpha_quality);
/* Enable and disable the sliders when the lossless option is selected */
g_signal_connect (toggle, "toggled",
G_CALLBACK (save_dialog_toggle_scale),
quality_scale);
g_signal_connect (toggle, "toggled",
G_CALLBACK (save_dialog_toggle_scale),
alpha_quality_scale);
/* Create the combobox containing the presets */
combo = gimp_int_combo_box_new ("Default", WEBP_PRESET_DEFAULT,
"Picture", WEBP_PRESET_PICTURE,
"Photo", WEBP_PRESET_PHOTO,
"Drawing", WEBP_PRESET_DRAWING,
"Icon", WEBP_PRESET_ICON,
"Text", WEBP_PRESET_TEXT,
NULL);
label = gimp_table_attach_aligned (GTK_TABLE (table), 0, row++,
_("Source _type:"), 0.0, 0.5,
combo, 2, FALSE);
gimp_help_set_help_data (label,
_("WebP encoder \"preset\""),
NULL);
gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
params->preset,
G_CALLBACK (gimp_int_combo_box_get_active),
¶ms->preset);
if (animation_supported)
{
GtkWidget *animation_box;
GtkAdjustment *adj;
GtkWidget *delay;
GtkWidget *hbox;
GtkWidget *label_kf;
GtkAdjustment *adj_kf;
GtkWidget *kf_distance;
GtkWidget *hbox_kf;
PangoAttrList *attrs;
PangoAttribute *attr;
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
gtk_box_pack_start (GTK_BOX (vbox), vbox2, FALSE, FALSE, 0);
gtk_widget_show (vbox2);
text = g_strdup_printf ("%s", _("_Advanced Options"));
expander = gtk_expander_new_with_mnemonic (text);
gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE);
g_free (text);
/* Create the top-level animation checkbox expander */
text = g_strdup_printf ("%s", _("As A_nimation"));
toggle = gtk_check_button_new_with_mnemonic (text);
g_free (text);
gtk_label_set_use_markup (GTK_LABEL (gtk_bin_get_child (GTK_BIN (toggle))),
TRUE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
params->animation);
gtk_box_pack_start (GTK_BOX (vbox2), toggle, TRUE, TRUE, 0);
gtk_widget_show (toggle);
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update),
¶ms->animation);
frame = gimp_frame_new ("");
gtk_box_pack_start (GTK_BOX (vbox2), frame, TRUE, TRUE, 0);
gtk_widget_show (frame);
g_object_bind_property (toggle, "active",
frame, "visible",
G_BINDING_SYNC_CREATE);
/* animation options box */
animation_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
gtk_container_add (GTK_CONTAINER (frame), animation_box);
gtk_widget_show (animation_box);
/* loop animation checkbox */
toggle = gtk_check_button_new_with_mnemonic (_("Loop _forever"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), params->loop);
gtk_box_pack_start (GTK_BOX (animation_box), toggle,
FALSE, FALSE, 0);
gtk_widget_show (toggle);
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update),
¶ms->loop);
/* create a hbox for 'max key-frame distance */
hbox_kf = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
gtk_box_pack_start (GTK_BOX (animation_box), hbox_kf, FALSE, FALSE, 0);
gtk_widget_set_sensitive (hbox_kf, TRUE);
gtk_widget_show (hbox_kf);
/* label for 'max key-frame distance' adjustment */
label_kf = gtk_label_new (_("Max distance between key-frames:"));
gtk_label_set_xalign (GTK_LABEL (label_kf), 0.2);
gtk_box_pack_start (GTK_BOX (hbox_kf), label_kf, FALSE, FALSE, 0);
gtk_widget_show (label_kf);
/* key-frame distance entry */
adj_kf = (GtkAdjustment *) gtk_adjustment_new (params->kf_distance,
0.0, 10000.0,
1.0, 10.0, 0.0);
kf_distance = gimp_spin_button_new (adj_kf, 1, 0);
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (kf_distance), TRUE);
gtk_box_pack_start (GTK_BOX (hbox_kf), kf_distance, FALSE, FALSE, 0);
gtk_widget_show (kf_distance);
g_signal_connect (adj_kf, "value-changed",
G_CALLBACK (gimp_int_adjustment_update),
¶ms->kf_distance);
/* Add some hinting text for special values of key-frame distance. */
label_kf = gtk_label_new (NULL);
gtk_box_pack_start (GTK_BOX (hbox_kf), label_kf, FALSE, FALSE, 0);
gtk_widget_show (label_kf);
attrs = pango_attr_list_new ();
attr = pango_attr_style_new (PANGO_STYLE_ITALIC);
pango_attr_list_insert (attrs, attr);
gtk_label_set_attributes (GTK_LABEL (label_kf), attrs);
pango_attr_list_unref (attrs);
g_signal_connect (adj_kf, "value-changed",
G_CALLBACK (show_maxkeyframe_hints),
label_kf);
show_maxkeyframe_hints (adj_kf, GTK_LABEL (label_kf));
/* minimize-size checkbox */
toggle_minsize = gtk_check_button_new_with_mnemonic (_("_Minimize output size (slower)"));
gtk_box_pack_start (GTK_BOX (animation_box), toggle_minsize,
FALSE, FALSE, 0);
gtk_widget_show (toggle_minsize);
g_signal_connect (toggle_minsize, "toggled",
G_CALLBACK (gimp_toggle_button_update),
¶ms->minimize_size);
/* Enable and disable the kf-distance box when the 'minimize size' option is selected */
g_signal_connect (toggle_minsize, "toggled",
G_CALLBACK (save_dialog_toggle_minsize),
hbox_kf);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle_minsize), params->minimize_size);
/* create a hbox for delay */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
gtk_box_pack_start (GTK_BOX (animation_box), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
/* label for 'delay' adjustment */
label = gtk_label_new (_("Delay between frames where unspecified:"));
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
/* default delay */
adj = (GtkAdjustment *) gtk_adjustment_new (params->delay,
1, 10000, 1, 10, 0);
delay = gimp_spin_button_new (adj, 1, 0);
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (delay), TRUE);
gtk_box_pack_start (GTK_BOX (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 */
label = gtk_label_new (_("milliseconds"));
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
/* Create the force-delay checkbox */
toggle = gtk_check_button_new_with_mnemonic (_("Use _delay entered above for all frames"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
params->force_delay);
gtk_box_pack_start (GTK_BOX (animation_box), toggle, FALSE, FALSE, 0);
gtk_widget_show (toggle);
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update),
¶ms->force_delay);
}
/* Save EXIF data */
toggle = gtk_check_button_new_with_mnemonic (_("_Save Exif data"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), params->exif);
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
gtk_widget_show (toggle);
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update),
¶ms->exif);
/* IPTC metadata */
toggle_iptc = gtk_check_button_new_with_mnemonic (_("Save _IPTC"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle_iptc), params->iptc);
gtk_box_pack_start (GTK_BOX (vbox), toggle_iptc, FALSE, FALSE, 0);
gtk_widget_show (toggle_iptc);
g_signal_connect (toggle_iptc, "toggled",
G_CALLBACK (gimp_toggle_button_update),
¶ms->iptc);
gtk_widget_set_sensitive (toggle_iptc, params->xmp);
/* XMP metadata */
toggle = gtk_check_button_new_with_mnemonic (_("Save _XMP data"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), params->xmp);
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
gtk_widget_show (toggle);
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update),
¶ms->xmp);
g_object_bind_property (toggle, "active",
toggle_iptc, "sensitive",
G_BINDING_SYNC_CREATE);
/* Color profile */
toggle = gtk_check_button_new_with_mnemonic (_("Save color _profile"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), params->profile);
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
gtk_widget_show (toggle);
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update),
¶ms->profile);
/* Save Thumbnail */
toggle = gtk_check_button_new_with_mnemonic (_("Save _thumbnail"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), params->thumbnail);
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
gtk_widget_show (toggle);
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update),
¶ms->thumbnail);
gtk_widget_show (dialog);
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
gtk_widget_destroy (dialog);
return run;
}