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, ¶ms);
218 break;
219
220 case GIMP_RUN_INTERACTIVE:
221 /* Possibly override with session data */
222 gimp_get_data (SAVE_PROC, ¶ms);
223
224 if (! save_dialog (¶ms, 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 ¶ms,
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, ¶ms, 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