1 /*
2 * DDS GIMP plugin
3 *
4 * Copyright (C) 2004-2012 Shawn Kirst <skirst@gmail.com>,
5 * with parts (C) 2003 Arne Reuter <homepage@arnereuter.de> where specified.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; see the file COPYING. If not, write to
19 * the Free Software Foundation, 51 Franklin Street, Fifth Floor
20 * Boston, MA 02110-1301, USA.
21 */
22
23 #include "config.h"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include <gtk/gtk.h>
30
31 #include <libgimp/gimp.h>
32 #include <libgimp/gimpui.h>
33
34 #include <libgimp/stdplugins-intl.h>
35
36 #include "ddsplugin.h"
37 #include "dds.h"
38 #include "misc.h"
39
40
41 static void query (void);
42 static void run (const gchar *name,
43 gint nparams,
44 const GimpParam *param,
45 gint *nreturn_vals,
46 GimpParam **return_vals);
47
48
49 GimpPlugInInfo PLUG_IN_INFO =
50 {
51 0,
52 0,
53 query,
54 run
55 };
56
57 DDSWriteVals dds_write_vals =
58 {
59 DDS_COMPRESS_NONE,
60 DDS_MIPMAP_NONE,
61 DDS_SAVE_SELECTED_LAYER,
62 DDS_FORMAT_DEFAULT,
63 -1,
64 DDS_MIPMAP_FILTER_DEFAULT,
65 DDS_MIPMAP_WRAP_DEFAULT,
66 0,
67 0,
68 0.0,
69 0,
70 0,
71 0,
72 0.5
73 };
74
75 DDSReadVals dds_read_vals =
76 {
77 1,
78 1
79 };
80
81 static GimpParamDef load_args[] =
82 {
83 { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"},
84 { GIMP_PDB_STRING, "filename", "The name of the file to load"},
85 { GIMP_PDB_STRING, "raw_filename", "The name entered"},
86 { GIMP_PDB_INT32, "load_mipmaps", "Load mipmaps if present"},
87 { GIMP_PDB_INT32, "decode_images", "Decode YCoCg/AExp images when detected"}
88 };
89
90 static GimpParamDef load_return_vals[] =
91 {
92 { GIMP_PDB_IMAGE, "image", "Output image"}
93 };
94
95 static GimpParamDef save_args[] =
96 {
97 { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"},
98 { GIMP_PDB_IMAGE, "image", "Input image"},
99 { GIMP_PDB_DRAWABLE, "drawable", "Drawable to save"},
100 { GIMP_PDB_STRING, "filename", "The name of the file to save the image as"},
101 { GIMP_PDB_STRING, "raw_filename", "The name entered"},
102 { GIMP_PDB_INT32, "compression_format", "Compression format (0 = None, 1 = BC1/DXT1, 2 = BC2/DXT3, 3 = BC3/DXT5, 4 = BC3n/DXT5nm, 5 = BC4/ATI1N, 6 = BC5/ATI2N, 7 = RXGB (DXT5), 8 = Alpha Exponent (DXT5), 9 = YCoCg (DXT5), 10 = YCoCg scaled (DXT5))"},
103 { GIMP_PDB_INT32, "mipmaps", "How to handle mipmaps (0 = No mipmaps, 1 = Generate mipmaps, 2 = Use existing mipmaps (layers)"},
104 { GIMP_PDB_INT32, "savetype", "How to save the image (0 = selected layer, 1 = cube map, 2 = volume map, 3 = texture array"},
105 { GIMP_PDB_INT32, "format", "Custom pixel format (0 = default, 1 = R5G6B5, 2 = RGBA4, 3 = RGB5A1, 4 = RGB10A2)"},
106 { GIMP_PDB_INT32, "transparent_index", "Index of transparent color or -1 to disable (for indexed images only)."},
107 { GIMP_PDB_INT32, "mipmap_filter", "Filtering to use when generating mipmaps (0 = default, 1 = nearest, 2 = box, 3 = triangle, 4 = quadratic, 5 = bspline, 6 = mitchell, 7 = lanczos, 8 = kaiser)"},
108 { GIMP_PDB_INT32, "mipmap_wrap", "Wrap mode to use when generating mipmaps (0 = default, 1 = mirror, 2 = repeat, 3 = clamp)"},
109 { GIMP_PDB_INT32, "gamma_correct", "Use gamma correct mipmap filtering"},
110 { GIMP_PDB_INT32, "srgb", "Use sRGB colorspace for gamma correction"},
111 { GIMP_PDB_FLOAT, "gamma", "Gamma value to use for gamma correction (i.e. 2.2)"},
112 { GIMP_PDB_INT32, "perceptual_metric", "Use a perceptual error metric during compression"},
113 { GIMP_PDB_INT32, "preserve_alpha_coverage", "Preserve alpha test converage for alpha channel maps"},
114 { GIMP_PDB_FLOAT, "alpha_test_threshold", "Alpha test threshold value for which alpha test converage should be preserved"}
115 };
116
117 #if 0
118 static GimpParamDef decode_args[] =
119 {
120 { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"},
121 { GIMP_PDB_IMAGE, "image", "Input image"},
122 { GIMP_PDB_DRAWABLE, "drawable", "Drawable to save"}
123 };
124 #endif
125
126
MAIN()127 MAIN ()
128
129
130 static void
131 query (void)
132 {
133 gimp_install_procedure (LOAD_PROC,
134 "Loads files in DDS image format",
135 "Loads files in DDS image format",
136 "Shawn Kirst",
137 "Shawn Kirst",
138 "2008",
139 N_("DDS image"),
140 0,
141 GIMP_PLUGIN,
142 G_N_ELEMENTS (load_args),
143 G_N_ELEMENTS (load_return_vals),
144 load_args, load_return_vals);
145
146 gimp_register_file_handler_mime (LOAD_PROC, "image/dds");
147 gimp_register_magic_load_handler (LOAD_PROC,
148 "dds",
149 "",
150 "0,string,DDS");
151
152 gimp_install_procedure (SAVE_PROC,
153 "Saves files in DDS image format",
154 "Saves files in DDS image format",
155 "Shawn Kirst",
156 "Shawn Kirst",
157 "2008",
158 N_("DDS image"),
159 "INDEXED, GRAY, RGB",
160 GIMP_PLUGIN,
161 G_N_ELEMENTS (save_args), 0,
162 save_args, 0);
163
164 gimp_register_file_handler_mime (SAVE_PROC, "image/dds");
165 gimp_register_save_handler (SAVE_PROC,
166 "dds",
167 "");
168
169 #if 0
170 gimp_install_procedure (DECODE_YCOCG_PROC,
171 "Converts YCoCg encoded pixels to RGB",
172 "Converts YCoCg encoded pixels to RGB",
173 "Shawn Kirst",
174 "Shawn Kirst",
175 "2008",
176 N_("Decode YCoCg"),
177 "RGBA",
178 GIMP_PLUGIN,
179 G_N_ELEMENTS (decode_args), 0,
180 decode_args, 0);
181 /*gimp_plugin_menu_register (DECODE_YCOCG_PROC, "<Image>/Filters/Colors");*/
182
183 gimp_install_procedure (DECODE_YCOCG_SCALED_PROC,
184 "Converts YCoCg (scaled) encoded pixels to RGB",
185 "Converts YCoCg (scaled) encoded pixels to RGB",
186 "Shawn Kirst",
187 "Shawn Kirst",
188 "2008",
189 N_("Decode YCoCg (scaled)"),
190 "RGBA",
191 GIMP_PLUGIN,
192 G_N_ELEMENTS (decode_args), 0,
193 decode_args, 0);
194 /*gimp_plugin_menu_register (DECODE_YCOCG_SCALED_PROC, "<Image>/Filters/Colors");*/
195
196 gimp_install_procedure (DECODE_ALPHA_EXP_PROC,
197 "Converts alpha exponent encoded pixels to RGB",
198 "Converts alpha exponent encoded pixels to RGB",
199 "Shawn Kirst",
200 "Shawn Kirst",
201 "2008",
202 N_("Decode Alpha exponent"),
203 "RGBA",
204 GIMP_PLUGIN,
205 G_N_ELEMENTS (decode_args), 0,
206 decode_args, 0);
207 /*gimp_plugin_menu_register (DECODE_ALPHA_EXP_PROC, "<Image>/Filters/Colors");*/
208 #endif
209 }
210
211 static void
run(const gchar * name,gint nparams,const GimpParam * param,gint * nreturn_vals,GimpParam ** return_vals)212 run (const gchar *name,
213 gint nparams,
214 const GimpParam *param,
215 gint *nreturn_vals,
216 GimpParam **return_vals)
217 {
218 static GimpParam values[2];
219 GimpRunMode run_mode;
220 GimpPDBStatusType status = GIMP_PDB_SUCCESS;
221 gint32 imageID;
222 gint32 drawableID;
223 GimpExportReturn export = GIMP_EXPORT_CANCEL;
224
225 gegl_init (NULL, NULL);
226
227 run_mode = param[0].data.d_int32;
228
229 *nreturn_vals = 1;
230 *return_vals = values;
231
232 values[0].type = GIMP_PDB_STATUS;
233 values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
234
235 if (! strcmp (name, LOAD_PROC))
236 {
237 switch (run_mode)
238 {
239 case GIMP_RUN_INTERACTIVE:
240 gimp_ui_init ("dds", 0);
241 gimp_get_data (LOAD_PROC, &dds_read_vals);
242 break;
243
244 case GIMP_RUN_NONINTERACTIVE:
245 dds_read_vals.mipmaps = param[3].data.d_int32;
246 dds_read_vals.decode_images = param[4].data.d_int32;
247 if (nparams != G_N_ELEMENTS (load_args))
248 status = GIMP_PDB_CALLING_ERROR;
249 break;
250
251 default:
252 break;
253 }
254
255 if (status == GIMP_PDB_SUCCESS)
256 {
257 status = read_dds (param[1].data.d_string, &imageID,
258 run_mode == GIMP_RUN_INTERACTIVE);
259 if (status == GIMP_PDB_SUCCESS && imageID != -1)
260 {
261 *nreturn_vals = 2;
262 values[1].type = GIMP_PDB_IMAGE;
263 values[1].data.d_image = imageID;
264 if (run_mode == GIMP_RUN_INTERACTIVE)
265 gimp_set_data (LOAD_PROC, &dds_read_vals, sizeof (dds_read_vals));
266 }
267 else if (status != GIMP_PDB_CANCEL)
268 {
269 status = GIMP_PDB_EXECUTION_ERROR;
270 }
271 }
272 }
273 else if (! strcmp (name, SAVE_PROC))
274 {
275 imageID = param[1].data.d_int32;
276 drawableID = param[2].data.d_int32;
277
278 switch (run_mode)
279 {
280 case GIMP_RUN_INTERACTIVE:
281 case GIMP_RUN_WITH_LAST_VALS:
282 gimp_ui_init ("dds", 0);
283 export = gimp_export_image (&imageID, &drawableID, "DDS",
284 (GIMP_EXPORT_CAN_HANDLE_RGB |
285 GIMP_EXPORT_CAN_HANDLE_GRAY |
286 GIMP_EXPORT_CAN_HANDLE_INDEXED |
287 GIMP_EXPORT_CAN_HANDLE_ALPHA |
288 GIMP_EXPORT_CAN_HANDLE_LAYERS));
289 if (export == GIMP_EXPORT_CANCEL)
290 {
291 values[0].data.d_status = GIMP_PDB_CANCEL;
292 return;
293 }
294
295 default:
296 break;
297 }
298
299 switch (run_mode)
300 {
301 case GIMP_RUN_INTERACTIVE:
302 gimp_get_data (SAVE_PROC, &dds_write_vals);
303 break;
304
305 case GIMP_RUN_NONINTERACTIVE:
306 if (nparams != G_N_ELEMENTS (save_args))
307 {
308 status = GIMP_PDB_CALLING_ERROR;
309 }
310 else
311 {
312 dds_write_vals.compression = param[5].data.d_int32;
313 dds_write_vals.mipmaps = param[6].data.d_int32;
314 dds_write_vals.savetype = param[7].data.d_int32;
315 dds_write_vals.format = param[8].data.d_int32;
316 dds_write_vals.transindex = param[9].data.d_int32;
317 dds_write_vals.mipmap_filter = param[10].data.d_int32;
318 dds_write_vals.mipmap_wrap = param[11].data.d_int32;
319 dds_write_vals.gamma_correct = param[12].data.d_int32;
320 dds_write_vals.srgb = param[13].data.d_int32;
321 dds_write_vals.gamma = param[14].data.d_float;
322 dds_write_vals.perceptual_metric = param[15].data.d_int32;
323 dds_write_vals.preserve_alpha_coverage = param[16].data.d_int32;
324 dds_write_vals.alpha_test_threshold = param[17].data.d_float;
325
326 if ((dds_write_vals.compression < DDS_COMPRESS_NONE) ||
327 (dds_write_vals.compression >= DDS_COMPRESS_MAX))
328 {
329 status = GIMP_PDB_CALLING_ERROR;
330 }
331
332 if ((dds_write_vals.mipmaps < DDS_MIPMAP_NONE) ||
333 (dds_write_vals.mipmaps >= DDS_MIPMAP_MAX))
334 {
335 status = GIMP_PDB_CALLING_ERROR;
336 }
337
338 if ((dds_write_vals.savetype < DDS_SAVE_SELECTED_LAYER) ||
339 (dds_write_vals.savetype >= DDS_SAVE_MAX))
340 {
341 status = GIMP_PDB_CALLING_ERROR;
342 }
343
344 if ((dds_write_vals.format < DDS_FORMAT_DEFAULT) ||
345 (dds_write_vals.format >= DDS_FORMAT_MAX))
346 {
347 status = GIMP_PDB_CALLING_ERROR;
348 }
349
350 if ((dds_write_vals.mipmap_filter < DDS_MIPMAP_FILTER_DEFAULT) ||
351 (dds_write_vals.mipmap_filter >= DDS_MIPMAP_FILTER_MAX))
352 {
353 status = GIMP_PDB_CALLING_ERROR;
354 }
355
356 if ((dds_write_vals.mipmap_wrap < DDS_MIPMAP_WRAP_DEFAULT) ||
357 (dds_write_vals.mipmap_wrap >= DDS_MIPMAP_WRAP_MAX))
358 {
359 status = GIMP_PDB_CALLING_ERROR;
360 }
361 }
362 break;
363
364 case GIMP_RUN_WITH_LAST_VALS:
365 gimp_get_data (SAVE_PROC, &dds_write_vals);
366 break;
367
368 default:
369 break;
370 }
371
372 if (dds_write_vals.gamma < 1e-04f)
373 /* gimp_gamma () got removed and was always returning 2.2 anyway.
374 * XXX Review this piece of code if we expect gamma value could
375 * be parameterized.
376 */
377 dds_write_vals.gamma = 2.2;
378
379 if (status == GIMP_PDB_SUCCESS)
380 {
381 status = write_dds (param[3].data.d_string, imageID, drawableID,
382 run_mode == GIMP_RUN_INTERACTIVE);
383 if (status == GIMP_PDB_SUCCESS)
384 gimp_set_data (SAVE_PROC, &dds_write_vals, sizeof (dds_write_vals));
385 }
386
387 if (export == GIMP_EXPORT_EXPORT)
388 gimp_image_delete (imageID);
389 }
390 #if 0
391 else if (! strcmp (name, DECODE_YCOCG_PROC))
392 {
393 imageID = param[1].data.d_int32;
394 drawableID = param[2].data.d_int32;
395
396 decode_ycocg_image (drawableID, TRUE);
397
398 status = GIMP_PDB_SUCCESS;
399
400 if (run_mode != GIMP_RUN_NONINTERACTIVE)
401 gimp_displays_flush ();
402 }
403 else if (! strcmp (name, DECODE_YCOCG_SCALED_PROC))
404 {
405 imageID = param[1].data.d_int32;
406 drawableID = param[2].data.d_int32;
407
408 decode_ycocg_scaled_image (drawableID, TRUE);
409
410 status = GIMP_PDB_SUCCESS;
411
412 if (run_mode != GIMP_RUN_NONINTERACTIVE)
413 gimp_displays_flush ();
414 }
415 else if (! strcmp (name, DECODE_ALPHA_EXP_PROC))
416 {
417 imageID = param[1].data.d_int32;
418 drawableID = param[2].data.d_int32;
419
420 decode_alpha_exp_image (drawableID, TRUE);
421
422 status = GIMP_PDB_SUCCESS;
423
424 if (run_mode != GIMP_RUN_NONINTERACTIVE)
425 gimp_displays_flush ();
426 }
427 #endif
428 else
429 {
430 status = GIMP_PDB_CALLING_ERROR;
431 }
432
433 values[0].data.d_status = status;
434 }
435