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