1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * file-webp - WebP file format plug-in for the GIMP
5  * Copyright (C) 2015  Nathan Osman
6  * Copyright (C) 2016  Ben Touchette
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include "config.h"
23 
24 #include <string.h>
25 
26 #include <libgimp/gimp.h>
27 #include <libgimp/gimpui.h>
28 
29 #include <webp/encode.h>
30 
31 #include "file-webp-dialog.h"
32 #include "file-webp-load.h"
33 #include "file-webp-save.h"
34 #include "file-webp.h"
35 
36 #include "libgimp/stdplugins-intl.h"
37 
38 
39 static void   query (void);
40 static void   run   (const gchar      *name,
41                      gint              nparams,
42                      const GimpParam  *param,
43                      gint             *nreturn_vals,
44                      GimpParam       **return_vals);
45 
46 
47 const GimpPlugInInfo PLUG_IN_INFO =
48 {
49   NULL,
50   NULL,
51   query,
52   run
53 };
54 
55 
MAIN()56 MAIN()
57 
58 static void
59 query (void)
60 {
61   static const GimpParamDef load_arguments[] =
62   {
63     { GIMP_PDB_INT32,  "run-mode",     "Interactive, non-interactive" },
64     { GIMP_PDB_STRING, "filename",     "The name of the file to load" },
65     { GIMP_PDB_STRING, "raw-filename", "The name entered" }
66   };
67 
68   static const GimpParamDef load_return_values[] =
69   {
70     { GIMP_PDB_IMAGE, "image", "Output image" }
71   };
72 
73   static const GimpParamDef save_arguments[] =
74   {
75     { GIMP_PDB_INT32,    "run-mode",      "Interactive, non-interactive" },
76     { GIMP_PDB_IMAGE,    "image",         "Input image" },
77     { GIMP_PDB_DRAWABLE, "drawable",      "Drawable to save" },
78     { GIMP_PDB_STRING,   "filename",      "The name of the file to save the image to" },
79     { GIMP_PDB_STRING,   "raw-filename",  "The name entered" },
80     { GIMP_PDB_INT32,    "preset",        "preset (Default=0, Picture=1, Photo=2, Drawing=3, Icon=4, Text=5)" },
81     { GIMP_PDB_INT32,    "lossless",      "Use lossless encoding (0/1)" },
82     { GIMP_PDB_FLOAT,    "quality",       "Quality of the image (0 <= quality <= 100)" },
83     { GIMP_PDB_FLOAT,    "alpha-quality", "Quality of the image's alpha channel (0 <= alpha-quality <= 100)" },
84     { GIMP_PDB_INT32,    "animation",     "Use layers for animation (0/1)" },
85     { GIMP_PDB_INT32,    "anim-loop",     "Loop animation infinitely (0/1)" },
86     { GIMP_PDB_INT32,    "minimize-size", "Minimize animation size (0/1)" },
87     { GIMP_PDB_INT32,    "kf-distance",   "Maximum distance between key-frames (>=0)" },
88     { GIMP_PDB_INT32,    "exif",          "Toggle saving exif data (0/1)" },
89     { GIMP_PDB_INT32,    "iptc",          "Toggle saving iptc data (0/1)" },
90     { GIMP_PDB_INT32,    "xmp",           "Toggle saving xmp data (0/1)" },
91     { GIMP_PDB_INT32,    "delay",         "Delay to use when timestamps are not available or forced" },
92     { GIMP_PDB_INT32,    "force-delay",   "Force delay on all frames" }
93   };
94 
95   gimp_install_procedure (LOAD_PROC,
96                           "Loads images in the WebP file format",
97                           "Loads images in the WebP file format",
98                           "Nathan Osman, Ben Touchette",
99                           "(C) 2015-2016 Nathan Osman, (C) 2016 Ben Touchette",
100                           "2015,2016",
101                           N_("WebP image"),
102                           NULL,
103                           GIMP_PLUGIN,
104                           G_N_ELEMENTS (load_arguments),
105                           G_N_ELEMENTS (load_return_values),
106                           load_arguments,
107                           load_return_values);
108 
109   gimp_register_file_handler_mime (LOAD_PROC, "image/webp");
110   gimp_register_load_handler (LOAD_PROC, "webp", "");
111   gimp_register_magic_load_handler (LOAD_PROC,
112                                     "webp",
113                                     "",
114                                     "8,string,WEBP");
115 
116   gimp_install_procedure (SAVE_PROC,
117                           "Saves files in the WebP image format",
118                           "Saves files in the WebP image format",
119                           "Nathan Osman, Ben Touchette",
120                           "(C) 2015-2016 Nathan Osman, (C) 2016 Ben Touchette",
121                           "2015,2016",
122                           N_("WebP image"),
123                           "RGB*, GRAY*, INDEXED*",
124                           GIMP_PLUGIN,
125                           G_N_ELEMENTS (save_arguments),
126                           0,
127                           save_arguments,
128                           NULL);
129 
130   gimp_register_file_handler_mime (SAVE_PROC, "image/webp");
131   gimp_register_save_handler (SAVE_PROC, "webp", "");
132 }
133 
134 static void
run(const gchar * name,gint nparams,const GimpParam * param,gint * nreturn_vals,GimpParam ** return_vals)135 run (const gchar      *name,
136      gint              nparams,
137      const GimpParam  *param,
138      gint             *nreturn_vals,
139      GimpParam       **return_vals)
140 {
141   static GimpParam  values[2];
142   GimpRunMode       run_mode;
143   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
144   gint32            image_ID;
145   gint32            drawable_ID;
146   GError           *error = NULL;
147 
148   INIT_I18N ();
149   gegl_init (NULL, NULL);
150 
151   run_mode = param[0].data.d_int32;
152 
153   *nreturn_vals = 1;
154   *return_vals  = values;
155 
156   values[0].type          = GIMP_PDB_STATUS;
157   values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
158 
159   if (! strcmp (name, LOAD_PROC))
160     {
161       image_ID = load_image (param[1].data.d_string, FALSE, &error);
162 
163       if (image_ID != -1)
164         {
165           /* Return the new image that was loaded */
166           *nreturn_vals = 2;
167           values[1].type         = GIMP_PDB_IMAGE;
168           values[1].data.d_image = image_ID;
169         }
170       else
171         {
172           status = GIMP_PDB_EXECUTION_ERROR;
173         }
174     }
175   else if (! strcmp (name, SAVE_PROC))
176     {
177       GimpMetadata          *metadata = NULL;
178       GimpMetadataSaveFlags  metadata_flags;
179       WebPSaveParams         params;
180       GimpExportReturn       export = GIMP_EXPORT_CANCEL;
181 
182       if (run_mode == GIMP_RUN_INTERACTIVE ||
183           run_mode == GIMP_RUN_WITH_LAST_VALS)
184         gimp_ui_init (PLUG_IN_BINARY, FALSE);
185 
186       image_ID    = param[1].data.d_int32;
187       drawable_ID = param[2].data.d_int32;
188 
189       /* Default settings */
190       params.preset        = WEBP_PRESET_DEFAULT;
191       params.lossless      = FALSE;
192       params.animation     = FALSE;
193       params.loop          = TRUE;
194       params.minimize_size = TRUE;
195       params.kf_distance   = 50;
196       params.quality       = 90.0f;
197       params.alpha_quality = 100.0f;
198       params.exif          = FALSE;
199       params.iptc          = FALSE;
200       params.xmp           = FALSE;
201       params.delay         = 200;
202       params.force_delay   = FALSE;
203 
204       /* Override the defaults with preferences. */
205       metadata = gimp_image_metadata_save_prepare (image_ID,
206                                                    "image/webp",
207                                                    &metadata_flags);
208       params.exif    = (metadata_flags & GIMP_METADATA_SAVE_EXIF) != 0;
209       params.xmp     = (metadata_flags & GIMP_METADATA_SAVE_XMP) != 0;
210       params.iptc    = (metadata_flags & GIMP_METADATA_SAVE_IPTC) != 0;
211       params.profile = (metadata_flags & GIMP_METADATA_SAVE_COLOR_PROFILE) != 0;
212 
213       switch (run_mode)
214         {
215         case GIMP_RUN_WITH_LAST_VALS:
216           /*  Possibly override with session data  */
217           gimp_get_data (SAVE_PROC, &params);
218           break;
219 
220         case GIMP_RUN_INTERACTIVE:
221           /*  Possibly override with session data  */
222           gimp_get_data (SAVE_PROC, &params);
223 
224           if (! save_dialog (&params, image_ID))
225             {
226               status = GIMP_PDB_CANCEL;
227             }
228           break;
229 
230         case GIMP_RUN_NONINTERACTIVE:
231           if (nparams != 18)
232             {
233               status = GIMP_PDB_CALLING_ERROR;
234             }
235           else
236             {
237               if (param[5].data.d_int32 < WEBP_PRESET_DEFAULT ||
238                   param[5].data.d_int32 > WEBP_PRESET_TEXT)
239                 params.preset = WEBP_PRESET_DEFAULT;
240               else
241                 params.preset = param[5].data.d_int32;
242 
243               params.lossless      = param[6].data.d_int32;
244               params.quality       = param[7].data.d_float;
245               params.alpha_quality = param[8].data.d_float;
246               params.animation     = param[9].data.d_int32;
247               params.loop          = param[10].data.d_int32;
248               params.minimize_size = param[11].data.d_int32;
249               params.kf_distance   = param[12].data.d_int32;
250               params.exif          = param[13].data.d_int32;
251               params.iptc          = param[14].data.d_int32;
252               params.xmp           = param[15].data.d_int32;
253               params.delay         = param[16].data.d_int32;
254               params.force_delay   = param[17].data.d_int32;
255             }
256           break;
257 
258         default:
259           break;
260         }
261 
262       if (status == GIMP_PDB_SUCCESS && (run_mode == GIMP_RUN_INTERACTIVE ||
263                                          run_mode == GIMP_RUN_WITH_LAST_VALS))
264         {
265           GimpExportCapabilities capabilities =
266             GIMP_EXPORT_CAN_HANDLE_RGB     |
267             GIMP_EXPORT_CAN_HANDLE_GRAY    |
268             GIMP_EXPORT_CAN_HANDLE_INDEXED |
269             GIMP_EXPORT_CAN_HANDLE_ALPHA;
270 
271           if (params.animation)
272             capabilities |= GIMP_EXPORT_CAN_HANDLE_LAYERS_AS_ANIMATION;
273 
274           export = gimp_export_image (&image_ID, &drawable_ID, "WebP",
275                                       capabilities);
276 
277           if (export == GIMP_EXPORT_CANCEL)
278             {
279               values[0].data.d_status = GIMP_PDB_CANCEL;
280               status = GIMP_PDB_CANCEL;
281             }
282         }
283 
284       if (status == GIMP_PDB_SUCCESS)
285         {
286           if (! save_image (param[3].data.d_string,
287                             image_ID,
288                             drawable_ID,
289                             metadata, metadata_flags,
290                             &params,
291                             &error))
292             {
293               status = GIMP_PDB_EXECUTION_ERROR;
294             }
295         }
296 
297 
298       if (export == GIMP_EXPORT_EXPORT)
299         gimp_image_delete (image_ID);
300 
301       if (metadata)
302         g_object_unref (metadata);
303 
304       if (status == GIMP_PDB_SUCCESS)
305         {
306           /* save parameters for later */
307           gimp_set_data (SAVE_PROC, &params, sizeof (params));
308         }
309     }
310 
311   /* If an error was supplied, include it in the return values */
312   if (status != GIMP_PDB_SUCCESS && error)
313     {
314       *nreturn_vals = 2;
315       values[1].type          = GIMP_PDB_STRING;
316       values[1].data.d_string = error->message;
317     }
318 
319   values[0].data.d_status = status;
320 }
321