1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * GIMP PSD Plug-in
5 * Copyright 2007 by John Marshall
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 #include "psd.h"
29 #include "psd-load.h"
30 #include "psd-save.h"
31 #include "psd-thumb-load.h"
32
33 #include "libgimp/stdplugins-intl.h"
34
35
36 /* Local function prototypes */
37
38 static void query (void);
39 static void run (const gchar *name,
40 gint nparams,
41 const GimpParam *param,
42 gint *nreturn_vals,
43 GimpParam **return_vals);
44
45
46 /* Local variables */
47
48 GimpPlugInInfo PLUG_IN_INFO =
49 {
50 NULL, /* init_proc */
51 NULL, /* quit_proc */
52 query, /* query_proc */
53 run, /* run_proc */
54 };
55
56
MAIN()57 MAIN ()
58
59 static void
60 query (void)
61 {
62 /* File Load */
63 static const GimpParamDef load_args[] =
64 {
65 { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
66 { GIMP_PDB_STRING, "filename", "The name of the file to load" },
67 { GIMP_PDB_STRING, "raw-filename", "The name of the file to load" }
68 };
69
70 static const GimpParamDef load_return_vals[] =
71 {
72 { GIMP_PDB_IMAGE, "image", "Output image" }
73 };
74
75 /* Thumbnail Load */
76 static const GimpParamDef thumb_args[] =
77 {
78 { GIMP_PDB_STRING, "filename", "The name of the file to load" },
79 { GIMP_PDB_INT32, "thumb-size", "Preferred thumbnail size" }
80 };
81
82 static const GimpParamDef thumb_return_vals[] =
83 {
84 { GIMP_PDB_IMAGE, "image", "Thumbnail image" },
85 { GIMP_PDB_INT32, "image-width", "Width of full-sized image" },
86 { GIMP_PDB_INT32, "image-height", "Height of full-sized image" }
87 };
88
89 /* File save */
90 static const GimpParamDef save_args[] =
91 {
92 { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
93 { GIMP_PDB_IMAGE, "image", "Input image" },
94 { GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" },
95 { GIMP_PDB_STRING, "filename", "The name of the file to save the image in" },
96 { GIMP_PDB_STRING, "raw-filename", "The name of the file to save the image in" },
97 { GIMP_PDB_INT32, "compression", "Compression type: { NONE (0), LZW (1), PACKBITS (2)" },
98 { GIMP_PDB_INT32, "fill-order", "Fill Order: { MSB to LSB (0), LSB to MSB (1)" }
99 };
100
101 /* File load */
102 gimp_install_procedure (LOAD_PROC,
103 "Loads images from the Photoshop PSD file format",
104 "This plug-in loads images in Adobe "
105 "Photoshop (TM) native PSD format.",
106 "John Marshall",
107 "John Marshall",
108 "2007",
109 N_("Photoshop image"),
110 NULL,
111 GIMP_PLUGIN,
112 G_N_ELEMENTS (load_args),
113 G_N_ELEMENTS (load_return_vals),
114 load_args, load_return_vals);
115
116 gimp_register_file_handler_mime (LOAD_PROC, "image/x-psd");
117 gimp_register_magic_load_handler (LOAD_PROC,
118 "psd",
119 "",
120 "0,string,8BPS");
121
122 /* File load (merged) */
123 gimp_install_procedure (LOAD_MERGED_PROC,
124 "Loads merged images from the Photoshop PSD file format",
125 "This plug-in loads the merged image data in Adobe "
126 "Photoshop (TM) native PSD format.",
127 "Ell",
128 "Ell",
129 "2018",
130 N_("Photoshop image (merged)"),
131 NULL,
132 GIMP_PLUGIN,
133 G_N_ELEMENTS (load_args),
134 G_N_ELEMENTS (load_return_vals),
135 load_args, load_return_vals);
136
137 gimp_register_file_handler_priority (LOAD_MERGED_PROC, +1);
138 gimp_register_file_handler_mime (LOAD_MERGED_PROC, "image/x-psd");
139 gimp_register_magic_load_handler (LOAD_MERGED_PROC,
140 "psd",
141 "",
142 "0,string,8BPS");
143
144 /* Thumbnail load */
145 gimp_install_procedure (LOAD_THUMB_PROC,
146 "Loads thumbnails from the Photoshop PSD file format",
147 "This plug-in loads thumbnail images from Adobe "
148 "Photoshop (TM) native PSD format files.",
149 "John Marshall",
150 "John Marshall",
151 "2007",
152 NULL,
153 NULL,
154 GIMP_PLUGIN,
155 G_N_ELEMENTS (thumb_args),
156 G_N_ELEMENTS (thumb_return_vals),
157 thumb_args, thumb_return_vals);
158
159 gimp_register_thumbnail_loader (LOAD_PROC, LOAD_THUMB_PROC);
160
161 gimp_install_procedure (SAVE_PROC,
162 "saves files in the Photoshop(tm) PSD file format",
163 "This filter saves files of Adobe Photoshop(tm) native PSD format. These files may be of any image type supported by GIMP, with or without layers, layer masks, aux channels and guides.",
164 "Monigotes",
165 "Monigotes",
166 "2000",
167 N_("Photoshop image"),
168 "RGB*, GRAY*, INDEXED*",
169 GIMP_PLUGIN,
170 G_N_ELEMENTS (save_args), 0,
171 save_args, NULL);
172
173 gimp_register_file_handler_mime (SAVE_PROC, "image/x-psd");
174 gimp_register_save_handler (SAVE_PROC, "psd", "");
175 }
176
177 static void
run(const gchar * name,gint nparams,const GimpParam * param,gint * nreturn_vals,GimpParam ** return_vals)178 run (const gchar *name,
179 gint nparams,
180 const GimpParam *param,
181 gint *nreturn_vals,
182 GimpParam **return_vals)
183 {
184 static GimpParam values[4];
185 GimpRunMode run_mode;
186 GimpPDBStatusType status = GIMP_PDB_SUCCESS;
187 gint32 image_ID;
188 GError *error = NULL;
189
190 run_mode = param[0].data.d_int32;
191
192 INIT_I18N ();
193 gegl_init (NULL, NULL);
194
195 *nreturn_vals = 1;
196 *return_vals = values;
197
198 values[0].type = GIMP_PDB_STATUS;
199 values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
200
201 if (strcmp (name, LOAD_PROC) == 0 ||
202 strcmp (name, LOAD_MERGED_PROC) == 0)
203 {
204 gboolean resolution_loaded = FALSE;
205 gboolean profile_loaded = FALSE;
206 gboolean interactive;
207
208 switch (run_mode)
209 {
210 case GIMP_RUN_INTERACTIVE:
211 case GIMP_RUN_WITH_LAST_VALS:
212 gimp_ui_init (PLUG_IN_BINARY, FALSE);
213 interactive = TRUE;
214 break;
215 default:
216 interactive = FALSE;
217 break;
218 }
219
220 image_ID = load_image (param[1].data.d_string,
221 strcmp (name, LOAD_MERGED_PROC) == 0,
222 &resolution_loaded,
223 &profile_loaded,
224 &error);
225
226 if (image_ID != -1)
227 {
228 GFile *file = g_file_new_for_path (param[1].data.d_string);
229 GimpMetadata *metadata;
230
231 metadata = gimp_image_metadata_load_prepare (image_ID, "image/x-psd",
232 file, NULL);
233
234 if (metadata)
235 {
236 GimpMetadataLoadFlags flags = GIMP_METADATA_LOAD_ALL;
237
238 if (resolution_loaded)
239 flags &= ~GIMP_METADATA_LOAD_RESOLUTION;
240
241 if (profile_loaded)
242 flags &= ~GIMP_METADATA_LOAD_COLORSPACE;
243
244 gimp_image_metadata_load_finish (image_ID, "image/x-psd",
245 metadata, flags,
246 interactive);
247
248 g_object_unref (metadata);
249 }
250
251 g_object_unref (file);
252
253 *nreturn_vals = 2;
254 values[1].type = GIMP_PDB_IMAGE;
255 values[1].data.d_image = image_ID;
256 }
257 else
258 {
259 status = GIMP_PDB_EXECUTION_ERROR;
260 }
261 }
262 else if (strcmp (name, LOAD_THUMB_PROC) == 0)
263 {
264 if (nparams < 2)
265 {
266 status = GIMP_PDB_CALLING_ERROR;
267 }
268 else
269 {
270 const gchar *filename = param[0].data.d_string;
271 gint width = 0;
272 gint height = 0;
273
274 image_ID = load_thumbnail_image (filename, &width, &height, &error);
275
276 if (image_ID != -1)
277 {
278 *nreturn_vals = 4;
279 values[1].type = GIMP_PDB_IMAGE;
280 values[1].data.d_image = image_ID;
281 values[2].type = GIMP_PDB_INT32;
282 values[2].data.d_int32 = width;
283 values[3].type = GIMP_PDB_INT32;
284 values[3].data.d_int32 = height;
285 }
286 else
287 {
288 status = GIMP_PDB_EXECUTION_ERROR;
289 }
290 }
291 }
292 else if (strcmp (name, SAVE_PROC) == 0)
293 {
294 gint32 drawable_id;
295 GimpMetadata *metadata;
296 GimpMetadataSaveFlags metadata_flags;
297 GimpExportReturn export = GIMP_EXPORT_IGNORE;
298
299 IFDBG(2) g_debug ("\n---------------- %s ----------------\n",
300 param[3].data.d_string);
301
302 image_ID = param[1].data.d_int32;
303 drawable_id = param[2].data.d_int32;
304
305 switch (run_mode)
306 {
307 case GIMP_RUN_INTERACTIVE:
308 case GIMP_RUN_WITH_LAST_VALS:
309 gimp_ui_init (PLUG_IN_BINARY, FALSE);
310
311 export = gimp_export_image (&image_ID, &drawable_id, "PSD",
312 GIMP_EXPORT_CAN_HANDLE_RGB |
313 GIMP_EXPORT_CAN_HANDLE_GRAY |
314 GIMP_EXPORT_CAN_HANDLE_INDEXED |
315 GIMP_EXPORT_CAN_HANDLE_ALPHA |
316 GIMP_EXPORT_CAN_HANDLE_LAYERS |
317 GIMP_EXPORT_CAN_HANDLE_LAYER_MASKS);
318
319 if (export == GIMP_EXPORT_CANCEL)
320 {
321 values[0].data.d_status = GIMP_PDB_CANCEL;
322 return;
323 }
324 break;
325
326 default:
327 break;
328 }
329
330 metadata = gimp_image_metadata_save_prepare (image_ID,
331 "image/x-psd",
332 &metadata_flags);
333
334 if (save_image (param[3].data.d_string, image_ID, &error))
335 {
336 if (metadata)
337 {
338 GFile *file;
339
340 gimp_metadata_set_bits_per_sample (metadata, 8);
341
342 file = g_file_new_for_path (param[3].data.d_string);
343 gimp_image_metadata_save_finish (image_ID,
344 "image/x-psd",
345 metadata, metadata_flags,
346 file, NULL);
347 g_object_unref (file);
348 }
349
350 values[0].data.d_status = GIMP_PDB_SUCCESS;
351 }
352 else
353 {
354 values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
355
356 if (error)
357 {
358 *nreturn_vals = 2;
359 values[1].type = GIMP_PDB_STRING;
360 values[1].data.d_string = error->message;
361 }
362 }
363
364 if (export == GIMP_EXPORT_EXPORT)
365 gimp_image_delete (image_ID);
366
367 if (metadata)
368 g_object_unref (metadata);
369 }
370
371 /* Unknown procedure */
372 else
373 {
374 status = GIMP_PDB_CALLING_ERROR;
375 }
376
377 if (status != GIMP_PDB_SUCCESS && error)
378 {
379 *nreturn_vals = 2;
380 values[1].type = GIMP_PDB_STRING;
381 values[1].data.d_string = error->message;
382 }
383
384 values[0].data.d_status = status;
385 }
386