1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
3 *
4 * GIMP Plug-in for Windows Icon files.
5 * Copyright (C) 2002 Christian Kreibich <christian@whoop.org>.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (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
15 * GNU 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. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <string.h>
24
25 #include <libgimp/gimp.h>
26 #include <libgimp/gimpui.h>
27
28 /* #define ICO_DBG */
29
30 #include "ico.h"
31 #include "ico-load.h"
32 #include "ico-save.h"
33
34 #include "libgimp/stdplugins-intl.h"
35
36 #define LOAD_PROC "file-ico-load"
37 #define LOAD_THUMB_PROC "file-ico-load-thumb"
38 #define SAVE_PROC "file-ico-save"
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 const GimpPlugInInfo PLUG_IN_INFO =
50 {
51 NULL, /* init_proc */
52 NULL, /* quit_proc */
53 query, /* query_proc */
54 run, /* run_proc */
55 };
56
57
MAIN()58 MAIN ()
59
60
61 static void
62 query (void)
63 {
64 static const GimpParamDef load_args[] =
65 {
66 { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
67 { GIMP_PDB_STRING, "filename", "The name of the file to load" },
68 { GIMP_PDB_STRING, "raw-filename", "The name entered" }
69 };
70 static const GimpParamDef load_return_vals[] =
71 {
72 { GIMP_PDB_IMAGE, "image", "Output image" },
73 };
74
75 static const GimpParamDef thumb_args[] =
76 {
77 { GIMP_PDB_STRING, "filename", "The name of the file to load" },
78 { GIMP_PDB_INT32, "thumb-size", "Preferred thumbnail size" }
79 };
80 static const GimpParamDef thumb_return_vals[] =
81 {
82 { GIMP_PDB_IMAGE, "image", "Thumbnail image" },
83 { GIMP_PDB_INT32, "image-width", "Width of full-sized image" },
84 { GIMP_PDB_INT32, "image-height", "Height of full-sized image" }
85 };
86
87 static const GimpParamDef save_args[] =
88 {
89 { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
90 { GIMP_PDB_IMAGE, "image", "Input image" },
91 { GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" },
92 { GIMP_PDB_STRING, "filename", "The name of the file to save the image in" },
93 { GIMP_PDB_STRING, "raw-filename", "The name entered" },
94 };
95
96 gimp_install_procedure (LOAD_PROC,
97 "Loads files of Windows ICO file format",
98 "Loads files of Windows ICO file format",
99 "Christian Kreibich <christian@whoop.org>",
100 "Christian Kreibich <christian@whoop.org>",
101 "2002",
102 N_("Microsoft Windows icon"),
103 NULL,
104 GIMP_PLUGIN,
105 G_N_ELEMENTS (load_args),
106 G_N_ELEMENTS (load_return_vals),
107 load_args, load_return_vals);
108
109 gimp_register_file_handler_mime (LOAD_PROC, "image/x-ico");
110 gimp_register_magic_load_handler (LOAD_PROC,
111 "ico",
112 "",
113 "0,string,\\000\\001\\000\\000,0,string,\\000\\002\\000\\000");
114
115 gimp_install_procedure (LOAD_THUMB_PROC,
116 "Loads a preview from an Windows ICO file",
117 "",
118 "Dom Lachowicz, Sven Neumann",
119 "Sven Neumann <sven@gimp.org>",
120 "2005",
121 NULL,
122 NULL,
123 GIMP_PLUGIN,
124 G_N_ELEMENTS (thumb_args),
125 G_N_ELEMENTS (thumb_return_vals),
126 thumb_args, thumb_return_vals);
127
128 gimp_register_thumbnail_loader (LOAD_PROC, LOAD_THUMB_PROC);
129
130 gimp_install_procedure (SAVE_PROC,
131 "Saves files in Windows ICO file format",
132 "Saves files in Windows ICO file format",
133 "Christian Kreibich <christian@whoop.org>",
134 "Christian Kreibich <christian@whoop.org>",
135 "2002",
136 N_("Microsoft Windows icon"),
137 "*",
138 GIMP_PLUGIN,
139 G_N_ELEMENTS (save_args), 0,
140 save_args, NULL);
141
142 gimp_register_file_handler_mime (SAVE_PROC, "image/x-ico");
143 gimp_register_save_handler (SAVE_PROC, "ico", "");
144 }
145
146 static void
run(const gchar * name,gint nparams,const GimpParam * param,gint * nreturn_vals,GimpParam ** return_vals)147 run (const gchar *name,
148 gint nparams,
149 const GimpParam *param,
150 gint *nreturn_vals,
151 GimpParam **return_vals)
152 {
153 static GimpParam values[4];
154 GimpRunMode run_mode;
155 GimpPDBStatusType status = GIMP_PDB_SUCCESS;
156 GimpExportReturn export = GIMP_EXPORT_CANCEL;
157 GError *error = NULL;
158
159 INIT_I18N ();
160 gegl_init (NULL, NULL);
161
162 run_mode = param[0].data.d_int32;
163
164 *nreturn_vals = 1;
165 *return_vals = values;
166
167 values[0].type = GIMP_PDB_STATUS;
168 values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
169
170 if (strcmp (name, LOAD_PROC) == 0)
171 {
172 switch (run_mode)
173 {
174 case GIMP_RUN_INTERACTIVE:
175 break;
176
177 case GIMP_RUN_NONINTERACTIVE:
178 if (nparams != 3)
179 status = GIMP_PDB_CALLING_ERROR;
180 break;
181
182 default:
183 break;
184 }
185
186 if (status == GIMP_PDB_SUCCESS)
187 {
188 gint32 image_ID;
189
190 image_ID = ico_load_image (param[1].data.d_string, &error);
191 if (image_ID != -1)
192 {
193 *nreturn_vals = 2;
194 values[1].type = GIMP_PDB_IMAGE;
195 values[1].data.d_image = image_ID;
196 }
197 else
198 {
199 status = GIMP_PDB_EXECUTION_ERROR;
200 }
201 }
202 }
203 else if (strcmp (name, LOAD_THUMB_PROC) == 0)
204 {
205 if (nparams < 2)
206 {
207 status = GIMP_PDB_CALLING_ERROR;
208 }
209 else
210 {
211 const gchar *filename = param[0].data.d_string;
212 gint width = param[1].data.d_int32;
213 gint height = param[1].data.d_int32;
214 gint32 image_ID;
215
216 image_ID = ico_load_thumbnail_image (filename,
217 &width, &height, &error);
218
219 if (image_ID != -1)
220 {
221 *nreturn_vals = 4;
222
223 values[1].type = GIMP_PDB_IMAGE;
224 values[1].data.d_image = image_ID;
225 values[2].type = GIMP_PDB_INT32;
226 values[2].data.d_int32 = width;
227 values[3].type = GIMP_PDB_INT32;
228 values[3].data.d_int32 = height;
229 }
230 else
231 {
232 status = GIMP_PDB_EXECUTION_ERROR;
233 }
234 }
235 }
236 else if (strcmp (name, SAVE_PROC) == 0)
237 {
238 gchar *file_name;
239 gint32 image_ID;
240
241 image_ID = param[1].data.d_int32;
242 file_name = param[3].data.d_string;
243
244 switch (run_mode)
245 {
246 case GIMP_RUN_INTERACTIVE:
247 break;
248
249 case GIMP_RUN_NONINTERACTIVE:
250 /* Make sure all the arguments are there! */
251 if (nparams < 5)
252 status = GIMP_PDB_CALLING_ERROR;
253 break;
254
255 case GIMP_RUN_WITH_LAST_VALS:
256 break;
257
258 default:
259 break;
260 }
261
262 if (status == GIMP_PDB_SUCCESS)
263 {
264 status = ico_save_image (file_name, image_ID, run_mode, &error);
265 }
266
267 if (export == GIMP_EXPORT_EXPORT)
268 gimp_image_delete (image_ID);
269 }
270 else
271 {
272 status = GIMP_PDB_CALLING_ERROR;
273 }
274
275 if (status != GIMP_PDB_SUCCESS && error)
276 {
277 *nreturn_vals = 2;
278 values[1].type = GIMP_PDB_STRING;
279 values[1].data.d_string = error->message;
280 }
281
282 values[0].data.d_status = status;
283 }
284
285
286 gint
ico_rowstride(gint width,gint bpp)287 ico_rowstride (gint width,
288 gint bpp)
289 {
290 switch (bpp)
291 {
292 case 1:
293 if ((width % 32) == 0)
294 return width / 8;
295 else
296 return 4 * (width/32 + 1);
297 break;
298
299 case 4:
300 if ((width % 8) == 0)
301 return width / 2;
302 else
303 return 4 * (width/8 + 1);
304 break;
305
306 case 8:
307 if ((width % 4) == 0)
308 return width;
309 else
310 return 4 * (width/4 + 1);
311 break;
312
313 case 24:
314 if (((width*3) % 4) == 0)
315 return width * 3;
316 else
317 return 4 * (width*3/4+1);
318
319 case 32:
320 return width * 4;
321
322 default:
323 g_warning ("invalid bitrate: %d\n", bpp);
324 g_assert_not_reached ();
325 return width * (bpp/8);
326 }
327 }
328
329 guint8 *
ico_alloc_map(gint width,gint height,gint bpp,gint * length)330 ico_alloc_map (gint width,
331 gint height,
332 gint bpp,
333 gint *length)
334 {
335 gint len = 0;
336 guint8 *map = NULL;
337
338 len = ico_rowstride (width, bpp) * height;
339
340 *length = len;
341 map = g_new0 (guint8, len);
342
343 return map;
344 }
345