1 /* GIMP plug-in to load and export Paint Shop Pro files (.PSP and .TUB)
2  *
3  * Copyright (C) 1999 Tor Lillqvist
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  */
18 
19 /*
20  *
21  * Work in progress! Doesn't handle exporting yet.
22  *
23  * For a copy of the PSP file format documentation, surf to
24  * http://www.jasc.com.
25  *
26  */
27 
28 #define LOAD_PROC      "file-psp-load"
29 #define SAVE_PROC      "file-psp-save"
30 #define PLUG_IN_BINARY "file-psp"
31 #define PLUG_IN_ROLE   "gimp-file-psp"
32 
33 /* set to the level of debugging output you want, 0 for none */
34 #define PSP_DEBUG 0
35 
36 #define IFDBG(level) if (PSP_DEBUG >= level)
37 
38 #include "config.h"
39 
40 #include <errno.h>
41 #include <string.h>
42 #include <zlib.h>
43 
44 #include <glib/gstdio.h>
45 
46 #include <libgimp/gimp.h>
47 #include <libgimp/gimpui.h>
48 #include <libgimpbase/gimpparasiteio.h>
49 
50 #include "libgimp/stdplugins-intl.h"
51 
52 
53 /* Note that the upcoming PSP version 6 writes PSP file format version
54  * 4.0, but the documentation for that apparently isn't publicly
55  * available (yet). The format is luckily designed to be somwehat
56  * downward compatible, however. The semantics of many of the
57  * additional fields and block types can be relatively easily reverse
58  * engineered.
59  */
60 
61 /* The following was cut and pasted from the PSP file format
62  * documentation version 3.0.(Minor stylistic changes done.)
63  *
64  *
65  * To be on the safe side, here is the whole copyright notice from the
66  * specification:
67  *
68  * The Paint Shop Pro File Format Specification (the Specification) is
69  * copyright 1998 by Jasc Software, Inc. Jasc grants you a
70  * nonexclusive license to use the Specification for the sole purposes
71  * of developing software products(s) incorporating the
72  * Specification. You are also granted the right to identify your
73  * software product(s) as incorporating the Paint Shop Pro Format
74  * (PSP) provided that your software in incorporating the
75  * Specification complies with the terms, definitions, constraints and
76  * specifications contained in the Specification and subject to the
77  * following: DISCLAIMER OF WARRANTIES. THE SPECIFICATION IS PROVIDED
78  * AS IS. JASC DISCLAIMS ALL OTHER WARRANTIES, EXPRESS OR IMPLIED,
79  * INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
80  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
81  * NONINFRINGEMENT.
82  *
83  * You are solely responsible for the selection, use, efficiency and
84  * suitability of the Specification for your software products.  OTHER
85  * WARRANTIES EXCLUDED. JASC SHALL NOT BE LIABLE FOR ANY DIRECT,
86  * INDIRECT, CONSEQUENTIAL, EXEMPLARY, PUNITIVE OR INCIDENTAL DAMAGES
87  * ARISING FROM ANY CAUSE EVEN IF JASC HAS BEEN ADVISED OF THE
88  * POSSIBILITY OF SUCH DAMAGES. CERTAIN JURISDICTIONS DO NOT PERMIT
89  * THE LIMITATION OR EXCLUSION OF INCIDENTAL DAMAGES, SO THIS
90  * LIMITATION MAY NOT APPLY TO YOU.  IN NO EVENT WILL JASC BE LIABLE
91  * FOR ANY AMOUNT GREATER THAN WHAT YOU ACTUALLY PAID FOR THE
92  * SPECIFICATION. Should any warranties be found to exist, such
93  * warranties shall be limited in duration to ninety (90) days
94  * following the date you receive the Specification.
95  *
96  * Indemnification. By your inclusion of the Paint Shop Pro File
97  * Format in your software product(s) you agree to indemnify and hold
98  * Jasc Software, Inc. harmless from any and all claims of any kind or
99  * nature made by any of your customers with respect to your software
100  * product(s).
101  *
102  * Export Laws. You agree that you and your customers will not export
103  * your software or Specification except in compliance with the laws
104  * and regulations of the United States.
105  *
106  * US Government Restricted Rights. The Specification and any
107  * accompanying materials are provided with Restricted Rights. Use,
108  * duplication or disclosure by the Government is subject to
109  * restrictions as set forth in subparagraph (c)(1)(ii) of The Rights
110  * in Technical Data and Computer Software clause at DFARS
111  * 252.227-7013, or subparagraphs (c)(1) and (2) of the Commercial
112  * Computer Software - Restricted Rights at 48 CFR 52.227-19, as
113  * applicable. Contractor/manufacturer is Jasc Software, Inc., PO Box
114  * 44997, Eden Prairie MN 55344.
115  *
116  * Jasc reserves the right to amend, modify, change, revoke or
117  * withdraw the Specification at any time and from time to time. Jasc
118  * shall have no obligation to support or maintain the Specification.
119  */
120 
121 /* Block identifiers.
122  */
123 typedef enum {
124   PSP_IMAGE_BLOCK = 0,                  /* General Image Attributes Block (main) */
125   PSP_CREATOR_BLOCK,                    /* Creator Data Block (main) */
126   PSP_COLOR_BLOCK,                      /* Color Palette Block (main and sub) */
127   PSP_LAYER_START_BLOCK,                /* Layer Bank Block (main) */
128   PSP_LAYER_BLOCK,                      /* Layer Block (sub) */
129   PSP_CHANNEL_BLOCK,                    /* Channel Block (sub) */
130   PSP_SELECTION_BLOCK,                  /* Selection Block (main) */
131   PSP_ALPHA_BANK_BLOCK,                 /* Alpha Bank Block (main) */
132   PSP_ALPHA_CHANNEL_BLOCK,              /* Alpha Channel Block (sub) */
133   PSP_THUMBNAIL_BLOCK,                  /* Thumbnail Block (main) */
134   PSP_EXTENDED_DATA_BLOCK,              /* Extended Data Block (main) */
135   PSP_TUBE_BLOCK,                       /* Picture Tube Data Block (main) */
136   PSP_ADJUSTMENT_EXTENSION_BLOCK,       /* Adjustment Layer Extension Block (sub) (since PSP6)*/
137   PSP_VECTOR_EXTENSION_BLOCK,           /* Vector Layer Extension Block (sub) (since PSP6) */
138   PSP_SHAPE_BLOCK,                      /* Vector Shape Block (sub) (since PSP6) */
139   PSP_PAINTSTYLE_BLOCK,                 /* Paint Style Block (sub) (since PSP6) */
140   PSP_COMPOSITE_IMAGE_BANK_BLOCK,       /* Composite Image Bank (main) (since PSP6) */
141   PSP_COMPOSITE_ATTRIBUTES_BLOCK,       /* Composite Image Attributes (sub) (since PSP6) */
142   PSP_JPEG_BLOCK,                       /* JPEG Image Block (sub) (since PSP6) */
143   PSP_LINESTYLE_BLOCK,                  /* Line Style Block (sub) (since PSP7) */
144   PSP_TABLE_BANK_BLOCK,                 /* Table Bank Block (main) (since PSP7) */
145   PSP_TABLE_BLOCK,                      /* Table Block (sub) (since PSP7) */
146   PSP_PAPER_BLOCK,                      /* Vector Table Paper Block (sub) (since PSP7) */
147   PSP_PATTERN_BLOCK,                    /* Vector Table Pattern Block (sub) (since PSP7) */
148   PSP_GRADIENT_BLOCK,                   /* Vector Table Gradient Block (not used) (since PSP8) */
149   PSP_GROUP_EXTENSION_BLOCK,            /* Group Layer Block (sub) (since PSP8) */
150   PSP_MASK_EXTENSION_BLOCK,             /* Mask Layer Block (sub) (since PSP8) */
151   PSP_BRUSH_BLOCK,                      /* Brush Data Block (main) (since PSP8) */
152   PSP_ART_MEDIA_BLOCK,                  /* Art Media Layer Block (main) (since PSP9) */
153   PSP_ART_MEDIA_MAP_BLOCK,              /* Art Media Layer map data Block (main) (since PSP9) */
154   PSP_ART_MEDIA_TILE_BLOCK,             /* Art Media Layer map tile Block(main) (since PSP9) */
155   PSP_ART_MEDIA_TEXTURE_BLOCK,          /* AM Layer map texture Block (main) (since PSP9) */
156   PSP_COLORPROFILE_BLOCK,               /* ICC Color profile block (since PSP10) */
157   PSP_RASTER_EXTENSION_BLOCK,           /* Assumed name based on usage, probably since PSP11 */
158 } PSPBlockID;
159 
160 /* Bitmap type.
161  */
162 typedef enum {
163   PSP_DIB_IMAGE = 0,            /* Layer color bitmap */
164   PSP_DIB_TRANS_MASK,           /* Layer transparency mask bitmap */
165   PSP_DIB_USER_MASK,            /* Layer user mask bitmap */
166   PSP_DIB_SELECTION,            /* Selection mask bitmap */
167   PSP_DIB_ALPHA_MASK,           /* Alpha channel mask bitmap */
168   PSP_DIB_THUMBNAIL,            /* Thumbnail bitmap */
169   PSP_DIB_THUMBNAIL_TRANS_MASK, /* Thumbnail transparency mask (since PSP6) */
170   PSP_DIB_ADJUSTMENT_LAYER,     /* Adjustment layer bitmap (since PSP6) */
171   PSP_DIB_COMPOSITE,            /* Composite image bitmap (since PSP6) */
172   PSP_DIB_COMPOSITE_TRANS_MASK, /* Composite image transparency (since PSP6) */
173   PSP_DIB_PAPER,                /* Paper bitmap (since PSP7) */
174   PSP_DIB_PATTERN,              /* Pattern bitmap (since PSP7) */
175   PSP_DIB_PATTERN_TRANS_MASK,   /* Pattern transparency mask (since PSP7) */
176 } PSPDIBType;
177 
178 /* Type of image in the composite image bank block. (since PSP6)
179  */
180 typedef enum {
181   PSP_IMAGE_COMPOSITE = 0,      /* Composite Image */
182   PSP_IMAGE_THUMBNAIL,          /* Thumbnail Image */
183 } PSPCompositeImageType;
184 
185 /* Graphic contents flags. (since PSP6)
186  */
187 typedef enum {
188   /* Layer types */
189   keGCRasterLayers     = 0x00000001,    /* At least one raster layer */
190   keGCVectorLayers     = 0x00000002,    /* At least one vector layer */
191   keGCAdjustmentLayers = 0x00000004,    /* At least one adjustment layer */
192   keGCGroupLayers      = 0x00000008,    /* at least one group layer */
193   keGCMaskLayers       = 0x00000010,    /* at least one mask layer */
194   keGCArtMediaLayers   = 0x00000020,    /* at least one art media layer */
195 
196   /* Additional attributes */
197   keGCMergedCache            = 0x00800000,      /* merged cache (composite image) */
198   keGCThumbnail              = 0x01000000,      /* Has a thumbnail */
199   keGCThumbnailTransparency  = 0x02000000,      /* Thumbnail transp. */
200   keGCComposite              = 0x04000000,      /* Has a composite image */
201   keGCCompositeTransparency  = 0x08000000,      /* Composite transp. */
202   keGCFlatImage              = 0x10000000,      /* Just a background */
203   keGCSelection              = 0x20000000,      /* Has a selection */
204   keGCFloatingSelectionLayer = 0x40000000,      /* Has float. selection */
205   keGCAlphaChannels          = 0x80000000,      /* Has alpha channel(s) */
206 } PSPGraphicContents;
207 
208 /* Character style flags. (since PSP6)
209  */
210 typedef enum {
211   keStyleItalic      = 0x00000001,      /* Italic property bit */
212   keStyleStruck      = 0x00000002,      /* Strike­out property bit */
213   keStyleUnderlined  = 0x00000004,      /* Underlined property bit */
214   keStyleWarped      = 0x00000008,      /* Warped property bit (since PSP8) */
215   keStyleAntiAliased = 0x00000010,      /* Anti­aliased property bit (since PSP8) */
216 } PSPCharacterProperties;
217 
218 /* Table type. (since PSP7)
219  */
220 typedef enum {
221   keTTUndefined = 0,     /* Undefined table type */
222   keTTGradientTable,     /* Gradient table type */
223   keTTPaperTable,        /* Paper table type */
224   keTTPatternTable       /* Pattern table type */
225 } PSPTableType;
226 
227 /* Layer flags. (since PSP6)
228  */
229 typedef enum {
230   keVisibleFlag      = 0x00000001,      /* Layer is visible */
231   keMaskPresenceFlag = 0x00000002,      /* Layer has a mask */
232 } PSPLayerProperties;
233 
234 /* Shape property flags. (since PSP6)
235  */
236 typedef enum {
237   keShapeAntiAliased = 0x00000001,      /* Shape is anti­aliased */
238   keShapeSelected    = 0x00000002,      /* Shape is selected */
239   keShapeVisible     = 0x00000004,      /* Shape is visible */
240 } PSPShapeProperties;
241 
242 /* Polyline node type flags. (since PSP7)
243  */
244 typedef enum {
245   keNodeUnconstrained     = 0x0000,     /* Default node type */
246   keNodeSmooth            = 0x0001,     /* Node is smooth */
247   keNodeSymmetric         = 0x0002,     /* Node is symmetric */
248   keNodeAligned           = 0x0004,     /* Node is aligned */
249   keNodeActive            = 0x0008,     /* Node is active */
250   keNodeLocked            = 0x0010,     /* Node is locked */
251   keNodeSelected          = 0x0020,     /* Node is selected */
252   keNodeVisible           = 0x0040,     /* Node is visible */
253   keNodeClosed            = 0x0080,     /* Node is closed */
254 
255   /* TODO: This might be a thinko in the spec document only or in the image
256    *       format itself. Need to investigate that later
257    */
258   keNodeLockedPSP6        = 0x0016,     /* Node is locked */
259   keNodeSelectedPSP6      = 0x0032,     /* Node is selected */
260   keNodeVisiblePSP6       = 0x0064,     /* Node is visible */
261   keNodeClosedPSP6        = 0x0128,     /* Node is closed */
262 
263 } PSPPolylineNodeTypes;
264 
265 /* Blend modes. (since PSP6)
266  */
267 typedef enum {
268   PSP_BLEND_NORMAL,
269   PSP_BLEND_DARKEN,
270   PSP_BLEND_LIGHTEN,
271   PSP_BLEND_HUE,
272   PSP_BLEND_SATURATION,
273   PSP_BLEND_COLOR,
274   PSP_BLEND_LUMINOSITY,
275   PSP_BLEND_MULTIPLY,
276   PSP_BLEND_SCREEN,
277   PSP_BLEND_DISSOLVE,
278   PSP_BLEND_OVERLAY,
279   PSP_BLEND_HARD_LIGHT,
280   PSP_BLEND_SOFT_LIGHT,
281   PSP_BLEND_DIFFERENCE,
282   PSP_BLEND_DODGE,
283   PSP_BLEND_BURN,
284   PSP_BLEND_EXCLUSION,
285   PSP_BLEND_TRUE_HUE, /* since PSP8 */
286   PSP_BLEND_TRUE_SATURATION, /* since PSP8 */
287   PSP_BLEND_TRUE_COLOR, /* since PSP8 */
288   PSP_BLEND_TRUE_LIGHTNESS, /* since PSP8 */
289   PSP_BLEND_ADJUST = 255,
290 } PSPBlendModes;
291 
292 /* Adjustment layer types. (since PSP6)
293  */
294 typedef enum {
295   keAdjNone = 0,        /* Undefined adjustment layer type */
296   keAdjLevel,           /* Level adjustment */
297   keAdjCurve,           /* Curve adjustment */
298   keAdjBrightContrast,  /* Brightness­contrast adjustment */
299   keAdjColorBal,        /* Color balance adjustment */
300   keAdjHSL,             /* HSL adjustment */
301   keAdjChannelMixer,    /* Channel mixer adjustment */
302   keAdjInvert,          /* Invert adjustment */
303   keAdjThreshold,       /* Threshold adjustment */
304   keAdjPoster           /* Posterize adjustment */
305 } PSPAdjustmentLayerType;
306 
307 /* Vector shape types. (since PSP6)
308  */
309 typedef enum {
310   keVSTUnknown = 0,     /* Undefined vector type */
311   keVSTText,            /* Shape represents lines of text */
312   keVSTPolyline,        /* Shape represents a multiple segment line */
313   keVSTEllipse,         /* Shape represents an ellipse (or circle) */
314   keVSTPolygon,         /* Shape represents a closed polygon */
315   keVSTGroup,           /* Shape represents a group shape (since PSP7) */
316 } PSPVectorShapeType;
317 
318 /* Text element types. (since PSP6)
319  */
320 typedef enum {
321   keTextElemUnknown = 0,        /* Undefined text element type */
322   keTextElemChar,               /* A single character code */
323   keTextElemCharStyle,          /* A character style change */
324   keTextElemLineStyle           /* A line style change */
325 } PSPTextElementType;
326 
327 /* Text alignment types. (since PSP6)
328  */
329 typedef enum {
330   keTextAlignmentLeft = 0,      /* Left text alignment */
331   keTextAlignmentCenter,        /* Center text alignment */
332   keTextAlignmentRight          /* Right text alignment */
333 } PSPTextAlignment;
334 
335 /* Text antialias modes. */
336 typedef enum {
337   keNoAntialias = 0,            /* Antialias off */
338   keSharpAntialias,             /* Sharp */
339   keSmoothAntialias             /* Smooth */
340 } PSPAntialiasMode;
341 
342 /* Text flow types */
343 typedef enum {
344   keTFHorizontalDown = 0,       /* Horizontal then down */
345   keTFVerticalLeft,             /* Vertical then left */
346   keTFVerticalRight,            /* Vertical then right */
347   keTFHorizontalUp              /* Horizontal then up */
348 } PSPTextFlow;
349 
350 /* Paint style types. (since PSP6)
351  */
352 typedef enum {
353   keStyleNone     = 0x0000,     /* No paint style info applies */
354   keStyleColor    = 0x0001,     /* Color paint style info */
355   keStyleGradient = 0x0002,     /* Gradient paint style info */
356   keStylePattern  = 0x0004,     /* Pattern paint style info (since PSP7) */
357   keStylePaper    = 0x0008,     /* Paper paint style info (since PSP7) */
358   keStylePen      = 0x0010,     /* Organic pen paint style info (since PSP7) */
359 } PSPPaintStyleType;
360 
361 /* Gradient type. (since PSP7)
362  */
363 typedef enum {
364   keSGTLinear = 0,      /* Linera gradient type */
365   keSGTRadial,          /* Radial gradient type */
366   keSGTRectangular,     /* Rectangulat gradient type */
367   keSGTSunburst         /* Sunburst gradient type */
368 } PSPStyleGradientType;
369 
370 /* Paint Style Cap Type (Start & End). (since PSP7)
371  */
372 typedef enum {
373   keSCTCapFlat = 0,             /* Flat cap type (was round in psp6) */
374   keSCTCapRound,                /* Round cap type (was square in psp6) */
375   keSCTCapSquare,               /* Square cap type (was flat in psp6) */
376   keSCTCapArrow,                /* Arrow cap type */
377   keSCTCapCadArrow,             /* Cad arrow cap type */
378   keSCTCapCurvedTipArrow,       /* Curved tip arrow cap type */
379   keSCTCapRingBaseArrow,        /* Ring base arrow cap type */
380   keSCTCapFluerDelis,           /* Fluer deLis cap type */
381   keSCTCapFootball,             /* Football cap type */
382   keSCTCapXr71Arrow,            /* Xr71 arrow cap type */
383   keSCTCapLilly,                /* Lilly cap type */
384   keSCTCapPinapple,             /* Pinapple cap type */
385   keSCTCapBall,                 /* Ball cap type */
386   keSCTCapTulip                 /* Tulip cap type */
387 } PSPStyleCapType;
388 
389 /* Paint Style Join Type. (since PSP7)
390  */
391 typedef enum {
392   keSJTJoinMiter = 0,
393   keSJTJoinRound,
394   keSJTJoinBevel
395 } PSPStyleJoinType;
396 
397 /* Organic pen type. (since PSP7)
398  */
399 typedef enum {
400   keSPTOrganicPenNone = 0,      /* Undefined pen type */
401   keSPTOrganicPenMesh,          /* Mesh pen type */
402   keSPTOrganicPenSand,          /* Sand pen type */
403   keSPTOrganicPenCurlicues,     /* Curlicues pen type */
404   keSPTOrganicPenRays,          /* Rays pen type */
405   keSPTOrganicPenRipple,        /* Ripple pen type */
406   keSPTOrganicPenWave,          /* Wave pen type */
407   keSPTOrganicPen               /* Generic pen type */
408 } PSPStylePenType;
409 
410 
411 /* Channel types.
412  */
413 typedef enum {
414   PSP_CHANNEL_COMPOSITE = 0,    /* Channel of single channel bitmap */
415   PSP_CHANNEL_RED,              /* Red channel of 24 bit bitmap */
416   PSP_CHANNEL_GREEN,            /* Green channel of 24 bit bitmap */
417   PSP_CHANNEL_BLUE              /* Blue channel of 24 bit bitmap */
418 } PSPChannelType;
419 
420 /* Possible metrics used to measure resolution.
421  */
422 typedef enum {
423   PSP_METRIC_UNDEFINED = 0,     /* Metric unknown */
424   PSP_METRIC_INCH,              /* Resolution is in inches */
425   PSP_METRIC_CM                 /* Resolution is in centimeters */
426 } PSP_METRIC;
427 
428 /* Possible types of compression.
429  */
430 typedef enum {
431   PSP_COMP_NONE = 0,            /* No compression */
432   PSP_COMP_RLE,                 /* RLE compression */
433   PSP_COMP_LZ77,                /* LZ77 compression */
434   PSP_COMP_JPEG                 /* JPEG compression (only used by thumbnail and composite image) (since PSP6) */
435 } PSPCompression;
436 
437 /* Picture tube placement mode.
438  */
439 typedef enum {
440   tpmRandom,                    /* Place tube images in random intervals */
441   tpmConstant                   /* Place tube images in constant intervals */
442 } TubePlacementMode;
443 
444 /* Picture tube selection mode.
445  */
446 typedef enum {
447   tsmRandom,                    /* Randomly select the next image in  */
448                                 /* tube to display */
449   tsmIncremental,               /* Select each tube image in turn */
450   tsmAngular,                   /* Select image based on cursor direction */
451   tsmPressure,                  /* Select image based on pressure  */
452                                 /* (from pressure-sensitive pad) */
453   tsmVelocity                   /* Select image based on cursor speed */
454 } TubeSelectionMode;
455 
456 /* Extended data field types.
457  */
458 typedef enum {
459   PSP_XDATA_TRNS_INDEX = 0,     /* Transparency index field */
460   PSP_XDATA_GRID,               /* Image grid information (since PSP7) */
461   PSP_XDATA_GUIDE,              /* Image guide information (since PSP7) */
462   PSP_XDATA_EXIF,               /* Image Exif information (since PSP8) */
463   PSP_XDATA_IPTC,               /* Image IPTC information (since PSP10) */
464 } PSPExtendedDataID;
465 
466 /* Creator field types.
467  */
468 typedef enum {
469   PSP_CRTR_FLD_TITLE = 0,       /* Image document title field */
470   PSP_CRTR_FLD_CRT_DATE,        /* Creation date field */
471   PSP_CRTR_FLD_MOD_DATE,        /* Modification date field */
472   PSP_CRTR_FLD_ARTIST,          /* Artist name field */
473   PSP_CRTR_FLD_CPYRGHT,         /* Copyright holder name field */
474   PSP_CRTR_FLD_DESC,            /* Image document description field */
475   PSP_CRTR_FLD_APP_ID,          /* Creating app id field */
476   PSP_CRTR_FLD_APP_VER          /* Creating app version field */
477 } PSPCreatorFieldID;
478 
479 /* Grid units type. (since PSP7)
480  */
481 typedef enum {
482   keGridUnitsPixels = 0,        /* Grid units is pixels */
483   keGridUnitsInches,            /* Grid units is inches */
484   keGridUnitsCentimeters        /* Grid units is centimeters */
485 } PSPGridUnitsType;
486 
487 /* Guide orientation type. (since PSP7)
488  */
489 typedef enum  {
490   keHorizontalGuide = 0,
491   keVerticalGuide
492 } PSPGuideOrientationType;
493 
494 /* Creator application identifiers.
495  */
496 typedef enum {
497   PSP_CREATOR_APP_UNKNOWN = 0,  /* Creator application unknown */
498   PSP_CREATOR_APP_PAINT_SHOP_PRO /* Creator is Paint Shop Pro */
499 } PSPCreatorAppID;
500 
501 /* Layer types.
502  */
503 typedef enum {
504   PSP_LAYER_NORMAL = 0,         /* Normal layer */
505   PSP_LAYER_FLOATING_SELECTION  /* Floating selection layer */
506 } PSPLayerTypePSP5;
507 
508 /* Layer types. (since PSP6)
509  */
510 typedef enum {
511   keGLTUndefined = 0,           /* Undefined layer type */
512   keGLTRaster,                  /* Standard raster layer */
513   keGLTFloatingRasterSelection, /* Floating selection (raster layer) */
514   keGLTVector,                  /* Vector layer */
515   keGLTAdjustment,              /* Adjustment layer */
516   keGLTGroup,                   /* Group layer (since PSP8) */
517   keGLTMask,                    /* Mask layer (since PSP8) */
518   keGLTArtMedia                 /* Art media layer (since PSP9) */
519 } PSPLayerTypePSP6;
520 
521 /* Art media layer map types (since PSP7) */
522 typedef enum {
523 keArtMediaColorMap = 0,
524 keArtMediaBumpMap,
525 keArtMediaShininessMap,
526 keArtMediaReflectivityMap,
527 keArtMediaDrynessMap
528 } PSPArtMediaMapType;
529 
530 
531 /* Truth values.
532  */
533 #if 0                           /* FALSE and TRUE taken by GLib */
534 typedef enum {
535   FALSE = 0,
536   TRUE
537 } PSP_BOOLEAN;
538 #else
539 typedef gboolean PSP_BOOLEAN;
540 #endif
541 
542 /* End of cut&paste from psp spec */
543 
544 /* We store the various PSP data in own structures.
545  * We cannot use structs intended to be direct copies of the file block
546  * headers because of struct alignment issues.
547  */
548 typedef struct
549 {
550   guint32           width, height;
551   gdouble           resolution;
552   guchar            metric;
553   guint16           compression;
554   guint16           depth;
555   guchar            grayscale;
556   guint32           active_layer;
557   guint16           layer_count;
558   guint16           bytes_per_sample;
559   GimpImageBaseType base_type;
560   GimpPrecision     precision;
561 } PSPimage;
562 
563 /* Declare some local functions.
564  */
565 static void   query      (void);
566 static void   run        (const gchar      *name,
567                           gint              nparams,
568                           const GimpParam  *param,
569                           gint             *nreturn_vals,
570                           GimpParam       **return_vals);
571 static gint32 load_image (const gchar      *filename,
572                           GError          **error);
573 static gint   save_image (const gchar      *filename,
574                           gint32            image_ID,
575                           gint32            drawable_ID,
576                           GError          **error);
577 
578 /* Various local variables...
579  */
580 const GimpPlugInInfo PLUG_IN_INFO =
581 {
582   NULL,  /* init_proc  */
583   NULL,  /* quit_proc  */
584   query, /* query_proc */
585   run,   /* run_proc   */
586 };
587 
588 /* Save info  */
589 typedef struct
590 {
591   PSPCompression compression;
592 } PSPSaveVals;
593 
594 static PSPSaveVals psvals =
595 {
596   PSP_COMP_LZ77
597 };
598 
599 static guint16 psp_ver_major, psp_ver_minor;
600 
601 
MAIN()602 MAIN ()
603 
604 static void
605 query (void)
606 {
607   static const GimpParamDef load_args[] =
608   {
609     { GIMP_PDB_INT32,  "run-mode",     "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
610     { GIMP_PDB_STRING, "filename",     "The name of the file to load" },
611     { GIMP_PDB_STRING, "raw-filename", "The name of the file to load" }
612   };
613   static const GimpParamDef load_return_vals[] =
614   {
615     { GIMP_PDB_IMAGE, "image", "Output image" }
616   };
617 
618 #if 0
619   static const GimpParamDef save_args[] =
620   {
621     { GIMP_PDB_INT32,    "run-mode",     "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
622     { GIMP_PDB_IMAGE,    "image",        "Input image" },
623     { GIMP_PDB_DRAWABLE, "drawable",     "Drawable to export" },
624     { GIMP_PDB_STRING,   "filename",     "The name of the file to export the image in" },
625     { GIMP_PDB_STRING,   "raw-filename", "The name of the file to export the image in" },
626     { GIMP_PDB_INT32,    "compression",  "Specify 0 for no compression, 1 for RLE, and 2 for LZ77" }
627   };
628 #endif
629 
630   gimp_install_procedure (LOAD_PROC,
631                           "loads images from the Paint Shop Pro PSP file format",
632                           "This plug-in loads and exports images in "
633                           "Paint Shop Pro's native PSP format. "
634                           "Vector layers aren't handled. Exporting isn't "
635                           "yet implemented.",
636                           "Tor Lillqvist",
637                           "Tor Lillqvist",
638                           "1999",
639                           N_("Paint Shop Pro image"),
640                           NULL,
641                           GIMP_PLUGIN,
642                           G_N_ELEMENTS (load_args),
643                           G_N_ELEMENTS (load_return_vals),
644                           load_args, load_return_vals);
645 
646   gimp_register_file_handler_mime (LOAD_PROC, "image/x-psp");
647   gimp_register_magic_load_handler (LOAD_PROC,
648                                     "psp,tub,pspimage",
649                                     "",
650                                     "0,string,Paint\\040Shop\\040Pro\\040Image\\040File\n\032");
651 
652   /* commented out until exporting is implemented */
653 #if 0
654   gimp_install_procedure (SAVE_PROC,
655                           "exports images in the Paint Shop Pro PSP file format",
656                           "This plug-in loads and exports images in "
657                           "Paint Shop Pro's native PSP format. "
658                           "Vector layers aren't handled. Exporting isn't "
659                           "yet implemented.",
660                           "Tor Lillqvist",
661                           "Tor Lillqvist",
662                           "1999",
663                           N_("Paint Shop Pro image"),
664                           "RGB*, GRAY*, INDEXED*",
665                           GIMP_PLUGIN,
666                           G_N_ELEMENTS (save_args), 0,
667                           save_args, NULL);
668 
669   gimp_register_save_handler (SAVE_PROC, "psp,tub", "");
670 #endif
671 }
672 
673 static gboolean
save_dialog(void)674 save_dialog (void)
675 {
676   GtkWidget *dialog;
677   GtkWidget *frame;
678   gint       run;
679 
680   dialog = gimp_export_dialog_new (_("PSP"), PLUG_IN_BINARY, SAVE_PROC);
681 
682   /*  file save type  */
683   frame = gimp_int_radio_group_new (TRUE, _("Data Compression"),
684                                     G_CALLBACK (gimp_radio_button_update),
685                                     &psvals.compression, psvals.compression,
686 
687                                     C_("compression", "None"), PSP_COMP_NONE, NULL,
688                                     _("RLE"),                  PSP_COMP_RLE,  NULL,
689                                     _("LZ77"),                 PSP_COMP_LZ77, NULL,
690 
691                                     NULL);
692 
693   gtk_container_set_border_width (GTK_CONTAINER (frame), 12);
694   gtk_box_pack_start (GTK_BOX (gimp_export_dialog_get_content_area (dialog)),
695                       frame, FALSE, TRUE, 0);
696   gtk_widget_show (frame);
697 
698   gtk_widget_show (dialog);
699 
700   run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
701 
702   gtk_widget_destroy (dialog);
703 
704   return run;
705 }
706 
707 /* This helper method is used to get the name of the block for the known block
708  * types. The enum PSPBlockID must cover the input values.
709  */
710 static const gchar *
block_name(gint id)711 block_name (gint id)
712 {
713   static const gchar *block_names[] =
714   {
715     "IMAGE",
716     "CREATOR",
717     "COLOR",
718     "LAYER_START",
719     "LAYER",
720     "CHANNEL",
721     "SELECTION",
722     "ALPHA_BANK",
723     "ALPHA_CHANNEL",
724     "THUMBNAIL",
725     "EXTENDED_DATA",
726     "TUBE",
727     "ADJUSTMENT_EXTENSION",
728     "VECTOR_EXTENSION_BLOCK",
729     "SHAPE_BLOCK",
730     "PAINTSTYLE_BLOCK",
731     "COMPOSITE_IMAGE_BANK_BLOCK",
732     "COMPOSITE_ATTRIBUTES_BLOCK",
733     "JPEG_BLOCK",
734     "LINESTYLE_BLOCK",
735     "TABLE_BANK_BLOCK",
736     "TABLE_BLOCK",
737     "PAPER_BLOCK",
738     "PATTERN_BLOCK",
739     "GRADIENT_BLOCK",
740     "GROUP_EXTENSION_BLOCK",
741     "MASK_EXTENSION_BLOCK",
742     "BRUSH_BLOCK",
743     "ART_MEDIA_BLOCK",
744     "ART_MEDIA_MAP_BLOCK",
745     "ART_MEDIA_TILE_BLOCK",
746     "ART_MEDIA_TEXTURE_BLOCK",
747     "COLORPROFILE_BLOCK",
748     "RASTER_EXTENSION_BLOCK",
749 };
750   static gchar *err_name = NULL;
751 
752   if (id >= 0 && id <= PSP_RASTER_EXTENSION_BLOCK)
753     return block_names[id];
754 
755   g_free (err_name);
756   err_name = g_strdup_printf ("id=%d", id);
757 
758   return err_name;
759 }
760 
761 /* This helper method is used during loading. It verifies the block we are
762  * reading has a valid header. Fills the variables init_len and total_len
763  */
764 static gint
read_block_header(FILE * f,guint32 * init_len,guint32 * total_len,GError ** error)765 read_block_header (FILE     *f,
766                    guint32  *init_len,
767                    guint32  *total_len,
768                    GError  **error)
769 {
770   guchar buf[4];
771   guint16 id;
772   long header_start;
773   guint32 len;
774 
775   IFDBG(3) header_start = ftell (f);
776 
777   if (fread (buf, 4, 1, f) < 1
778       || fread (&id, 2, 1, f) < 1
779       || fread (&len, 4, 1, f) < 1
780       || (psp_ver_major < 4 && fread (total_len, 4, 1, f) < 1))
781     {
782       g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
783                    _("Error reading block header"));
784       return -1;
785     }
786   if (memcmp (buf, "~BK\0", 4) != 0)
787     {
788       IFDBG(3)
789         g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
790                      _("Invalid block header at %ld"), header_start);
791       else
792         g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
793                      _("Invalid block header"));
794       return -1;
795     }
796 
797   IFDBG(3) g_message ("%s at %ld", block_name (id), header_start);
798 
799   if (psp_ver_major < 4)
800     {
801       *init_len = GUINT32_FROM_LE (len);
802       *total_len = GUINT32_FROM_LE (*total_len);
803     }
804   else
805     {
806       /* Version 4.0 seems to have dropped the initial data chunk length
807        * field.
808        */
809       *init_len = 0xDEADBEEF;   /* Intentionally bogus, should not be used */
810       *total_len = GUINT32_FROM_LE (len);
811     }
812 
813   return GUINT16_FROM_LE (id);
814 }
815 
816 static gint
try_fseek(FILE * f,glong pos,gint whence,GError ** error)817 try_fseek (FILE    *f,
818            glong    pos,
819            gint     whence,
820            GError **error)
821 {
822   if (fseek (f, pos, whence) < 0)
823     {
824       g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
825                    _("Seek error: %s"), g_strerror (errno));
826       fclose (f);
827       return -1;
828     }
829   return 0;
830 }
831 
832 /* Read the PSP_IMAGE_BLOCK */
833 static gint
read_general_image_attribute_block(FILE * f,guint init_len,guint total_len,PSPimage * ia,GError ** error)834 read_general_image_attribute_block (FILE     *f,
835                                     guint     init_len,
836                                     guint     total_len,
837                                     PSPimage *ia,
838                                     GError  **error)
839 {
840   gchar buf[6];
841   guint64 res;
842   gchar graphics_content[4];
843   long chunk_start;
844 
845   if (init_len < 38 || total_len < 38)
846     {
847       g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
848                    _("Invalid general image attribute chunk size."));
849       return -1;
850     }
851 
852   chunk_start = ftell (f);
853   if ((psp_ver_major >= 4
854       && (fread (&init_len, 4, 1, f) < 1 || ((init_len = GUINT32_FROM_LE (init_len)) < 46)))
855       || fread (&ia->width, 4, 1, f) < 1
856       || fread (&ia->height, 4, 1, f) < 1
857       || fread (&res, 8, 1, f) < 1
858       || fread (&ia->metric, 1, 1, f) < 1
859       || fread (&ia->compression, 2, 1, f) < 1
860       || fread (&ia->depth, 2, 1, f) < 1
861       || fread (buf, 2+4, 1, f) < 1 /* Skip plane and color count */
862       || fread (&ia->grayscale, 1, 1, f) < 1
863       || fread (buf, 4, 1, f) < 1 /* Skip total image size */
864       || fread (&ia->active_layer, 4, 1, f) < 1
865       || fread (&ia->layer_count, 2, 1, f) < 1
866       || (psp_ver_major >= 4 && fread (graphics_content, 4, 1, f) < 1)
867       || try_fseek (f, chunk_start + init_len, SEEK_SET, error) < 0)
868     {
869       g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
870                    _("Error reading general image attribute block."));
871       return -1;
872     }
873   ia->width = GUINT32_FROM_LE (ia->width);
874   ia->height = GUINT32_FROM_LE (ia->height);
875 
876   res = GUINT64_FROM_LE (res);
877   memcpy (&ia->resolution, &res, 8);
878   if (ia->metric == PSP_METRIC_CM)
879     ia->resolution /= 2.54;
880 
881   ia->compression = GUINT16_FROM_LE (ia->compression);
882   if (ia->compression > PSP_COMP_LZ77)
883     {
884       g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
885                    _("Unknown compression type %d"), ia->compression);
886       return -1;
887     }
888 
889   ia->depth = GUINT16_FROM_LE (ia->depth);
890   switch (ia->depth)
891     {
892       case 24:
893       case 48:
894         ia->base_type = GIMP_RGB;
895         if (ia->depth == 24)
896           ia->precision = GIMP_PRECISION_U8_GAMMA;
897         else
898           ia->precision = GIMP_PRECISION_U16_GAMMA;
899         break;
900 
901       case 1:
902       case 4:
903       case 8:
904       case 16:
905         if (ia->grayscale && ia->depth >= 8)
906           {
907             ia->base_type = GIMP_GRAY;
908             if (ia->depth == 8)
909               ia->precision = GIMP_PRECISION_U8_GAMMA;
910             else
911               ia->precision = GIMP_PRECISION_U16_GAMMA;
912           }
913         else if (ia->depth <= 8 && ! ia->grayscale)
914           {
915             ia->base_type = GIMP_INDEXED;
916             ia->precision = GIMP_PRECISION_U8_GAMMA;
917           }
918         else
919         {
920           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
921                        _("Unsupported bit depth %d"), ia->depth);
922           return -1;
923         }
924         break;
925 
926       default:
927         g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
928                      _("Unsupported bit depth %d"), ia->depth);
929         return -1;
930         break;
931     }
932 
933     if (ia->precision == GIMP_PRECISION_U16_GAMMA)
934       ia->bytes_per_sample = 2;
935     else
936       ia->bytes_per_sample = 1;
937 
938   ia->active_layer = GUINT32_FROM_LE (ia->active_layer);
939   ia->layer_count = GUINT16_FROM_LE (ia->layer_count);
940 
941   return 0;
942 }
943 
944 static gint
read_creator_block(FILE * f,gint image_ID,guint total_len,PSPimage * ia,GError ** error)945 read_creator_block (FILE      *f,
946                     gint       image_ID,
947                     guint      total_len,
948                     PSPimage  *ia,
949                     GError   **error)
950 {
951   long          data_start;
952   guchar        buf[4];
953   guint16       keyword;
954   guint32       length;
955   gchar        *string;
956   gchar        *title = NULL, *artist = NULL, *copyright = NULL, *description = NULL;
957   guint32       dword;
958   guint32       __attribute__((unused))cdate = 0;
959   guint32       __attribute__((unused))mdate = 0;
960   guint32       __attribute__((unused))appid;
961   guint32       __attribute__((unused))appver;
962   GString      *comment;
963   GimpParasite *comment_parasite;
964 
965   data_start = ftell (f);
966   comment = g_string_new (NULL);
967 
968   while (ftell (f) < data_start + total_len)
969     {
970       if (fread (buf, 4, 1, f) < 1
971           || fread (&keyword, 2, 1, f) < 1
972           || fread (&length, 4, 1, f) < 1)
973         {
974           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
975                        _("Error reading creator keyword chunk"));
976           return -1;
977         }
978       if (memcmp (buf, "~FL\0", 4) != 0)
979         {
980           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
981                        _("Invalid keyword chunk header"));
982           return -1;
983         }
984       keyword = GUINT16_FROM_LE (keyword);
985       length = GUINT32_FROM_LE (length);
986       switch (keyword)
987         {
988         case PSP_CRTR_FLD_TITLE:
989         case PSP_CRTR_FLD_ARTIST:
990         case PSP_CRTR_FLD_CPYRGHT:
991         case PSP_CRTR_FLD_DESC:
992           string = g_malloc (length + 1);
993           if (fread (string, length, 1, f) < 1)
994             {
995               g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
996                            _("Error reading creator keyword data"));
997               g_free (string);
998               return -1;
999             }
1000           /* PSP does not zero terminate strings */
1001           string[length] = '\0';
1002           switch (keyword)
1003             {
1004             case PSP_CRTR_FLD_TITLE:
1005               g_free (title); title = string; break;
1006             case PSP_CRTR_FLD_ARTIST:
1007               g_free (artist); artist = string; break;
1008             case PSP_CRTR_FLD_CPYRGHT:
1009               g_free (copyright); copyright = string; break;
1010             case PSP_CRTR_FLD_DESC:
1011               g_free (description); description = string; break;
1012             default:
1013               g_free (string);
1014             }
1015           break;
1016         case PSP_CRTR_FLD_CRT_DATE:
1017         case PSP_CRTR_FLD_MOD_DATE:
1018         case PSP_CRTR_FLD_APP_ID:
1019         case PSP_CRTR_FLD_APP_VER:
1020           if (fread (&dword, 4, 1, f) < 1)
1021             {
1022               g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1023                            _("Error reading creator keyword data"));
1024               return -1;
1025             }
1026           switch (keyword)
1027             {
1028             case PSP_CRTR_FLD_CRT_DATE:
1029               cdate = dword; break;
1030             case PSP_CRTR_FLD_MOD_DATE:
1031               mdate = dword; break;
1032             case PSP_CRTR_FLD_APP_ID:
1033               appid = dword; break;
1034             case PSP_CRTR_FLD_APP_VER:
1035               appver = dword; break;
1036             }
1037           break;
1038         default:
1039           if (try_fseek (f, length, SEEK_CUR, error) < 0)
1040             {
1041               return -1;
1042             }
1043           break;
1044         }
1045     }
1046 
1047   if (title)
1048     {
1049       g_string_append (comment, title);
1050       g_free (title);
1051       g_string_append (comment, "\n");
1052     }
1053   if (artist)
1054     {
1055       g_string_append (comment, artist);
1056       g_free (artist);
1057       g_string_append (comment, "\n");
1058     }
1059   if (copyright)
1060     {
1061       g_string_append (comment, "Copyright ");
1062       g_string_append (comment, copyright);
1063       g_free (copyright);
1064       g_string_append (comment, "\n");
1065     }
1066   if (description)
1067     {
1068       g_string_append (comment, description);
1069       g_free (description);
1070       g_string_append (comment, "\n");
1071     }
1072   if (comment->len > 0)
1073     {
1074       comment_parasite = gimp_parasite_new ("gimp-comment",
1075                                             GIMP_PARASITE_PERSISTENT,
1076                                             strlen (comment->str) + 1,
1077                                             comment->str);
1078       gimp_image_attach_parasite (image_ID, comment_parasite);
1079       gimp_parasite_free (comment_parasite);
1080     }
1081 
1082   g_string_free (comment, FALSE);
1083 
1084   return 0;
1085 }
1086 
1087 static gint
read_color_block(FILE * f,gint image_ID,guint total_len,PSPimage * ia,GError ** error)1088 read_color_block (FILE      *f,
1089                   gint       image_ID,
1090                   guint      total_len,
1091                   PSPimage  *ia,
1092                   GError   **error)
1093 {
1094   long     block_start;
1095   guint32  chunk_len, entry_count, pal_size;
1096   guint32  color_palette_entries;
1097   guchar  *color_palette;
1098 
1099   block_start = ftell (f);
1100 
1101   if (psp_ver_major >= 4)
1102     {
1103       if (fread (&chunk_len, 4, 1, f) < 1
1104           || fread (&entry_count, 4, 1, f) < 1)
1105         {
1106           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1107                        _("Error reading color block"));
1108           return -1;
1109         }
1110 
1111       chunk_len = GUINT32_FROM_LE (chunk_len);
1112 
1113       if (try_fseek (f, block_start + chunk_len, SEEK_SET, error) < 0)
1114         {
1115           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1116                        _("Error reading color block"));
1117           return -1;
1118         }
1119     }
1120   else
1121     {
1122       if (fread (&entry_count, 4, 1, f) < 1)
1123         {
1124           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1125                        _("Error reading color block"));
1126           return -1;
1127         }
1128     }
1129 
1130   color_palette_entries = GUINT32_FROM_LE (entry_count);
1131   /* psp color palette entries are stored as RGBA so 4 bytes per entry
1132      where the fourth bytes is always zero */
1133   pal_size = color_palette_entries * 4;
1134   color_palette = g_malloc (pal_size);
1135   if (fread (color_palette, pal_size, 1, f) < 1)
1136     {
1137       g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1138                    _("Error reading color palette"));
1139       return -1;
1140     }
1141   else
1142     {
1143       guchar *tmpmap;
1144       gint    i;
1145 
1146       /* Convert to BGR palette */
1147       tmpmap = g_malloc (3 * color_palette_entries);
1148       for (i = 0; i < color_palette_entries; ++i)
1149         {
1150           tmpmap[i*3  ] = color_palette[i*4+2];
1151           tmpmap[i*3+1] = color_palette[i*4+1];
1152           tmpmap[i*3+2] = color_palette[i*4];
1153         }
1154 
1155       memcpy (color_palette, tmpmap, color_palette_entries * 3);
1156       g_free (tmpmap);
1157 
1158       gimp_image_set_colormap (image_ID, color_palette, color_palette_entries);
1159       g_free (color_palette);
1160     }
1161 
1162   return 0;
1163 }
1164 
1165 static void inline
swab_rect(guint32 * rect)1166 swab_rect (guint32 *rect)
1167 {
1168   rect[0] = GUINT32_FROM_LE (rect[0]);
1169   rect[1] = GUINT32_FROM_LE (rect[1]);
1170   rect[2] = GUINT32_FROM_LE (rect[2]);
1171   rect[3] = GUINT32_FROM_LE (rect[3]);
1172 }
1173 
1174 static GimpLayerMode
gimp_layer_mode_from_psp_blend_mode(PSPBlendModes mode)1175 gimp_layer_mode_from_psp_blend_mode (PSPBlendModes mode)
1176 {
1177   switch (mode)
1178     {
1179     case PSP_BLEND_NORMAL:
1180       return GIMP_LAYER_MODE_NORMAL_LEGACY;
1181 
1182     case PSP_BLEND_DARKEN:
1183       return GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY;
1184 
1185     case PSP_BLEND_LIGHTEN:
1186       return GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY;
1187 
1188     case PSP_BLEND_HUE:
1189       return GIMP_LAYER_MODE_HSV_HUE_LEGACY;
1190 
1191     case PSP_BLEND_SATURATION:
1192       return GIMP_LAYER_MODE_HSV_SATURATION_LEGACY;
1193 
1194     case PSP_BLEND_COLOR:
1195       return GIMP_LAYER_MODE_HSL_COLOR_LEGACY;
1196 
1197     case PSP_BLEND_LUMINOSITY:
1198       return GIMP_LAYER_MODE_HSV_VALUE_LEGACY;   /* ??? */
1199 
1200     case PSP_BLEND_MULTIPLY:
1201       return GIMP_LAYER_MODE_MULTIPLY_LEGACY;
1202 
1203     case PSP_BLEND_SCREEN:
1204       return GIMP_LAYER_MODE_SCREEN_LEGACY;
1205 
1206     case PSP_BLEND_DISSOLVE:
1207       return GIMP_LAYER_MODE_DISSOLVE;
1208 
1209     case PSP_BLEND_OVERLAY:
1210       return GIMP_LAYER_MODE_OVERLAY;
1211 
1212     case PSP_BLEND_HARD_LIGHT:
1213       return GIMP_LAYER_MODE_HARDLIGHT_LEGACY;
1214 
1215     case PSP_BLEND_SOFT_LIGHT:
1216       return GIMP_LAYER_MODE_SOFTLIGHT_LEGACY;
1217 
1218     case PSP_BLEND_DIFFERENCE:
1219       return GIMP_LAYER_MODE_DIFFERENCE_LEGACY;
1220 
1221     case PSP_BLEND_DODGE:
1222       return GIMP_LAYER_MODE_DODGE_LEGACY;
1223 
1224     case PSP_BLEND_BURN:
1225       return GIMP_LAYER_MODE_BURN_LEGACY;
1226 
1227     case PSP_BLEND_EXCLUSION:
1228       return GIMP_LAYER_MODE_EXCLUSION;
1229 
1230     case PSP_BLEND_TRUE_HUE:
1231       return GIMP_LAYER_MODE_HSV_HUE;
1232 
1233     case PSP_BLEND_TRUE_SATURATION:
1234       return GIMP_LAYER_MODE_HSV_SATURATION;
1235 
1236     case PSP_BLEND_TRUE_COLOR:
1237       return GIMP_LAYER_MODE_HSL_COLOR;
1238 
1239     case PSP_BLEND_TRUE_LIGHTNESS:
1240       return GIMP_LAYER_MODE_HSV_VALUE;
1241 
1242     case PSP_BLEND_ADJUST:
1243       return -1;                /* ??? */
1244     }
1245   return -1;
1246 }
1247 
1248 static const gchar *
blend_mode_name(PSPBlendModes mode)1249 blend_mode_name (PSPBlendModes mode)
1250 {
1251   static const gchar *blend_mode_names[] =
1252   {
1253     "NORMAL",
1254     "DARKEN",
1255     "LIGHTEN",
1256     "HUE",
1257     "SATURATION",
1258     "COLOR",
1259     "LUMINOSITY",
1260     "MULTIPLY",
1261     "SCREEN",
1262     "DISSOLVE",
1263     "OVERLAY",
1264     "HARD_LIGHT",
1265     "SOFT_LIGHT",
1266     "DIFFERENCE",
1267     "DODGE",
1268     "BURN",
1269     "EXCLUSION",
1270     "TRUE HUE",
1271     "TRUE SATURATION",
1272     "TRUE COLOR",
1273     "TRUE LIGHTNESS",
1274     /* ADJUST should always be the last one. */
1275     "ADJUST"
1276   };
1277   static gchar *err_name = NULL;
1278 
1279   if (mode >= 0 && mode <= PSP_BLEND_TRUE_LIGHTNESS)
1280     return blend_mode_names[mode];
1281   else if (mode == PSP_BLEND_ADJUST)
1282     return blend_mode_names[PSP_BLEND_TRUE_LIGHTNESS+1];
1283 
1284   g_free (err_name);
1285   err_name = g_strdup_printf ("unknown layer blend mode %d", mode);
1286 
1287   return err_name;
1288 }
1289 
1290 static const gchar *
layer_type_name(PSPLayerTypePSP6 type)1291 layer_type_name (PSPLayerTypePSP6 type)
1292 {
1293   static const gchar *layer_type_names[] =
1294   {
1295     "Undefined",
1296     "Raster",
1297     "Floating Raster Selection",
1298     "Vector",
1299     "Adjustment",
1300     "Group",
1301     "Mask",
1302     "Art Media",
1303   };
1304   static gchar *err_name = NULL;
1305 
1306   if (type >= 0 && type <= keGLTArtMedia)
1307     return layer_type_names[type];
1308 
1309   g_free (err_name);
1310   err_name = g_strdup_printf ("unknown layer type %d", type);
1311 
1312   return err_name;
1313 }
1314 
1315 static const gchar *
bitmap_type_name(gint type)1316 bitmap_type_name (gint type)
1317 {
1318   static const gchar *bitmap_type_names[] =
1319   {
1320     "IMAGE",
1321     "TRANS_MASK",
1322     "USER_MASK",
1323     "SELECTION",
1324     "ALPHA_MASK",
1325     "THUMBNAIL"
1326   };
1327   static gchar *err_name = NULL;
1328 
1329   if (type >= 0 && type <= PSP_DIB_THUMBNAIL)
1330     return bitmap_type_names[type];
1331 
1332   g_free (err_name);
1333   err_name = g_strdup_printf ("unknown bitmap type %d", type);
1334 
1335   return err_name;
1336 }
1337 
1338 static const gchar *
channel_type_name(gint type)1339 channel_type_name (gint type)
1340 {
1341   static const gchar *channel_type_names[] =
1342   {
1343     "COMPOSITE",
1344     "RED",
1345     "GREEN",
1346     "BLUE"
1347   };
1348   static gchar *err_name = NULL;
1349 
1350   if (type >= 0 && type <= PSP_CHANNEL_BLUE)
1351     return channel_type_names[type];
1352 
1353   g_free (err_name);
1354   err_name = g_strdup_printf ("unknown channel type %d", type);
1355 
1356   return err_name;
1357 }
1358 
1359 static void *
psp_zalloc(void * opaque,guint items,guint size)1360 psp_zalloc (void  *opaque,
1361             guint  items,
1362             guint  size)
1363 {
1364   return g_malloc (items*size);
1365 }
1366 
1367 static void
psp_zfree(void * opaque,void * ptr)1368 psp_zfree (void *opaque,
1369            void *ptr)
1370 {
1371   g_free (ptr);
1372 }
1373 
1374 static void
upscale_indexed_sub_8(FILE * f,gint width,gint height,gint bpp,guchar * buf)1375 upscale_indexed_sub_8 (FILE    *f,
1376                        gint     width,
1377                        gint     height,
1378                        gint     bpp,
1379                        guchar  *buf)
1380 {
1381   gint     x, y, b, line_width;
1382   gint     bpp_zero_based = bpp - 1;
1383   gint     current_bit = 0;
1384   guchar  *tmpbuf, *buf_start, *src;
1385 
1386   /* Scanlines for 1 and 4 bit only end on a 4-byte boundary. */
1387   line_width = (((width * bpp + 7) / 8) + bpp_zero_based) / 4 * 4;
1388   buf_start = g_malloc0 (width * height);
1389   tmpbuf = buf_start;
1390 
1391   for (y = 0; y < height; tmpbuf += width, ++y)
1392     {
1393       src = buf + y * line_width;
1394       for (x = 0; x < width; ++x)
1395         {
1396           for (b = 0; b < bpp; b++)
1397             {
1398               current_bit = bpp * x + b;
1399               if (src[current_bit / 8] & (128 >> (current_bit % 8)))
1400                 tmpbuf[x] += (1 << (bpp_zero_based - b));
1401             }
1402         }
1403     }
1404 
1405   memcpy (buf, buf_start, width * height);
1406   g_free (buf_start);
1407 }
1408 
1409 static int
read_channel_data(FILE * f,PSPimage * ia,guchar ** pixels,guint bytespp,guint offset,GeglBuffer * buffer,guint32 compressed_len,GError ** error)1410 read_channel_data (FILE        *f,
1411                    PSPimage    *ia,
1412                    guchar     **pixels,
1413                    guint        bytespp,
1414                    guint        offset,
1415                    GeglBuffer  *buffer,
1416                    guint32      compressed_len,
1417                    GError     **error)
1418 {
1419   gint i, y, line_width;
1420   gint width = gegl_buffer_get_width (buffer);
1421   gint height = gegl_buffer_get_height (buffer);
1422   gint npixels = width * height;
1423   guchar *buf;
1424   guchar *buf2 = NULL;  /* please the compiler */
1425   guchar runcount, byte;
1426   z_stream zstream;
1427 
1428   g_assert (ia->bytes_per_sample <= 2);
1429 
1430   if (ia->depth < 8)
1431     {
1432       /* Scanlines for 1 and 4 bit only end on a 4-byte boundary. */
1433       line_width = (((width * ia->depth + 7) / 8) + ia->depth - 1) / 4 * 4;
1434     }
1435   else
1436     {
1437       line_width = width * ia->bytes_per_sample;
1438     }
1439 
1440   switch (ia->compression)
1441     {
1442     case PSP_COMP_NONE:
1443       if (bytespp == 1)
1444         {
1445           fread (pixels[0], height * line_width, 1, f);
1446         }
1447       else
1448         {
1449           buf = g_malloc (line_width);
1450           if (ia->bytes_per_sample == 1)
1451             {
1452               for (y = 0; y < height; y++)
1453                 {
1454                   guchar *p, *q;
1455 
1456                   fread (buf, width, 1, f);
1457                   /* Contrary to what the PSP specification seems to suggest
1458                     scanlines are not stored on a 4-byte boundary. */
1459                   p = buf;
1460                   q = pixels[y] + offset;
1461                   for (i = 0; i < width; i++)
1462                     {
1463                       *q = *p++;
1464                       q += bytespp;
1465                     }
1466                 }
1467             }
1468           else if (ia->bytes_per_sample == 2)
1469             {
1470               for (y = 0; y < height; y++)
1471                 {
1472                   guint16 *p, *q;
1473 
1474                   fread (buf, width * ia->bytes_per_sample, 1, f);
1475                   /* Contrary to what the PSP specification seems to suggest
1476                     scanlines are not stored on a 4-byte boundary. */
1477                   p = (guint16 *) buf;
1478                   q = (guint16 *) (pixels[y] + offset);
1479                   for (i = 0; i < width; i++)
1480                     {
1481                       *q = GUINT16_FROM_LE (*p++);
1482                       q += bytespp / 2;
1483                     }
1484                 }
1485             }
1486 
1487           g_free (buf);
1488         }
1489       break;
1490 
1491     case PSP_COMP_RLE:
1492       {
1493         guchar *q, *endq;
1494 
1495         q = pixels[0] + offset;
1496         if (ia->depth >= 8)
1497           endq = q + npixels * bytespp;
1498         else
1499           endq = q + line_width * height;
1500 
1501         buf = g_malloc (127);
1502         while (q < endq)
1503           {
1504             fread (&runcount, 1, 1, f);
1505             if (runcount > 128)
1506               {
1507                 runcount -= 128;
1508                 fread (&byte, 1, 1, f);
1509                 memset (buf, byte, runcount);
1510               }
1511             else
1512               fread (buf, runcount, 1, f);
1513 
1514             /* prevent buffer overflow for bogus data */
1515             if (runcount > (endq - q) / bytespp + ia->bytes_per_sample - 1)
1516               {
1517                 g_printerr ("Buffer overflow decompressing RLE data.\n");
1518                 break;
1519               }
1520 
1521             if (bytespp == 1)
1522               {
1523                 memmove (q, buf, runcount);
1524                 q += runcount;
1525               }
1526             else if (ia->bytes_per_sample == 1)
1527               {
1528                 guchar *p = buf;
1529 
1530                 for (i = 0; i < runcount; i++)
1531                   {
1532                     *q = *p++;
1533                     q += bytespp;
1534                   }
1535               }
1536             else if (ia->bytes_per_sample == 2)
1537               {
1538                 guint16 *p = (guint16 *) buf;
1539                 guint16 *r = (guint16 *) q;
1540 
1541                 for (i = 0; i < runcount / 2; i++)
1542                   {
1543                     *r = GUINT16_FROM_LE (*p++);
1544                     r += bytespp / 2;
1545                   }
1546                 q = (guchar *) r;
1547               }
1548           }
1549         g_free (buf);
1550       }
1551       break;
1552 
1553     case PSP_COMP_LZ77:
1554       buf = g_malloc (compressed_len);
1555       fread (buf, compressed_len, 1, f);
1556       zstream.next_in = buf;
1557       zstream.avail_in = compressed_len;
1558       zstream.zalloc = psp_zalloc;
1559       zstream.zfree = psp_zfree;
1560       zstream.opaque = f;
1561       if (inflateInit (&zstream) != Z_OK)
1562         {
1563           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1564                        _("zlib error"));
1565           return -1;
1566         }
1567       if (bytespp == 1)
1568         zstream.next_out = pixels[0];
1569       else
1570         {
1571           buf2 = g_malloc (npixels * ia->bytes_per_sample);
1572           zstream.next_out = buf2;
1573         }
1574       zstream.avail_out = npixels * ia->bytes_per_sample;
1575       if (inflate (&zstream, Z_FINISH) != Z_STREAM_END)
1576         {
1577           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1578                        _("zlib error"));
1579           inflateEnd (&zstream);
1580           return -1;
1581         }
1582       inflateEnd (&zstream);
1583       g_free (buf);
1584 
1585       if (bytespp > 1)
1586         {
1587           if (ia->bytes_per_sample == 1)
1588             {
1589               guchar *p, *q;
1590 
1591               p = buf2;
1592               q = pixels[0] + offset;
1593               for (i = 0; i < npixels; i++)
1594                 {
1595                   *q = *p++;
1596                   q += bytespp;
1597                 }
1598               g_free (buf2);
1599             }
1600           else if (ia->bytes_per_sample == 2)
1601             {
1602               guint16 *p, *q;
1603 
1604               p = (guint16 *) buf2;
1605               q = (guint16 *) (pixels[0] + offset);
1606               for (i = 0; i < npixels; i++)
1607                 {
1608                   *q = GUINT16_FROM_LE (*p++);
1609                   q += bytespp / 2;
1610                 }
1611               g_free (buf2);
1612             }
1613         }
1614       break;
1615     }
1616 
1617   if (ia->base_type == GIMP_INDEXED && ia->depth < 8)
1618     {
1619       /* We need to convert 1 and 4 bit to 8 bit indexed */
1620       upscale_indexed_sub_8 (f, width, height, ia->depth, pixels[0]);
1621     }
1622 
1623   return 0;
1624 }
1625 
1626 static gboolean
read_raster_layer_info(FILE * f,long layer_extension_start,guint16 * bitmap_count,guint16 * channel_count,GError ** error)1627 read_raster_layer_info (FILE      *f,
1628                         long       layer_extension_start,
1629                         guint16   *bitmap_count,
1630                         guint16   *channel_count,
1631                         GError   **error)
1632 {
1633   long    block_start;
1634   guint32 layer_extension_len, block_len;
1635   gint    block_id;
1636 
1637   if (fseek (f, layer_extension_start, SEEK_SET) < 0
1638       || fread (&layer_extension_len, 4, 1, f) < 1)
1639     {
1640       g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1641                    _("Error reading layer extension information"));
1642       return FALSE;
1643     }
1644 
1645     /* Newer versions of PSP have an extra block here for raster layers
1646        with block id = 0x21. Most likely this was to fix an oversight in
1647        the specification since vector and adjustment layers already were
1648        using a similar extension block since file version 4.
1649        The old chunk with bitmap_count and channel_count starts after this block.
1650        We do not know starting from which version this change was implemented
1651        but most likely version 9 (could also be version 10) so we can't test
1652        based on version number only.
1653        Although this is kind of a hack we can safely test for the block starting
1654        code since the layer_extension_len here is always a small number.
1655       */
1656     if (psp_ver_major > 8 && memcmp (&layer_extension_len, "~BK\0", 4) == 0)
1657       {
1658         if (fread (&block_id, 2, 1, f) < 1
1659             || fread (&block_len, 4, 1, f) < 1)
1660           {
1661             g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1662                          _("Error reading block information"));
1663             return FALSE;
1664           }
1665         block_id = GUINT16_FROM_LE (block_id);
1666         block_len = GUINT32_FROM_LE (block_len);
1667 
1668         block_start = ftell (f);
1669         layer_extension_start = block_start + block_len;
1670 
1671         if (fseek (f, layer_extension_start, SEEK_SET) < 0
1672             || fread (&layer_extension_len, 4, 1, f) < 1)
1673           {
1674             g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1675                          _("Error reading layer extension information"));
1676             return FALSE;
1677           }
1678       }
1679     layer_extension_len = GUINT32_FROM_LE (layer_extension_len);
1680 
1681     if (fread (bitmap_count, 2, 1, f) < 1
1682         || fread (channel_count, 2, 1, f) < 1)
1683       {
1684         g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1685                      _("Error reading layer extension information"));
1686         return FALSE;
1687       }
1688     if (try_fseek (f, layer_extension_start + layer_extension_len, SEEK_SET, error) < 0)
1689       {
1690         return FALSE;
1691       }
1692 
1693   return TRUE;
1694 }
1695 
1696 static gint
read_layer_block(FILE * f,gint image_ID,guint total_len,PSPimage * ia,GError ** error)1697 read_layer_block (FILE      *f,
1698                   gint       image_ID,
1699                   guint      total_len,
1700                   PSPimage  *ia,
1701                   GError   **error)
1702 {
1703   gint i;
1704   long block_start, sub_block_start, channel_start;
1705   long layer_extension_start;
1706   gint sub_id;
1707   guint32 sub_init_len, sub_total_len;
1708   guint32 chunk_len;
1709   gchar *name = NULL;
1710   gchar *layer_name = NULL;
1711   guint16 namelen;
1712   guchar type, opacity, blend_mode, visibility, transparency_protected;
1713   guchar link_group_id, mask_linked, mask_disabled;
1714   guint32 image_rect[4], saved_image_rect[4], mask_rect[4], saved_mask_rect[4];
1715   gboolean null_layer, can_handle_layer;
1716   guint16 bitmap_count, channel_count;
1717   GimpImageType drawable_type;
1718   guint32 layer_ID = 0;
1719   GimpLayerMode layer_mode;
1720   guint32 channel_init_len, channel_total_len;
1721   guint32 compressed_len, uncompressed_len;
1722   guint16 bitmap_type, channel_type;
1723   gint width, height, bytespp, offset;
1724   guchar **pixels, *pixel;
1725   GeglBuffer *buffer;
1726 
1727   block_start = ftell (f);
1728 
1729   while (ftell (f) < block_start + total_len)
1730     {
1731       null_layer = FALSE;
1732       can_handle_layer = FALSE;
1733 
1734       /* Read the layer sub-block header */
1735       sub_id = read_block_header (f, &sub_init_len, &sub_total_len, error);
1736       if (sub_id == -1)
1737         return -1;
1738 
1739       if (sub_id != PSP_LAYER_BLOCK)
1740         {
1741           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1742                        _("Invalid layer sub-block %s, should be LAYER"),
1743                        block_name (sub_id));
1744           return -1;
1745         }
1746 
1747       sub_block_start = ftell (f);
1748 
1749       /* Read layer information chunk */
1750       if (psp_ver_major >= 4)
1751         {
1752           if (fread (&chunk_len, 4, 1, f) < 1
1753               || fread (&namelen, 2, 1, f) < 1
1754               /* A zero length layer name is apparently valid. To not get a warning for
1755                  namelen < 0 always being false we use this more complicated comparison. */
1756               || ((namelen = GUINT16_FROM_LE (namelen)) && (FALSE || namelen == 0))
1757               || (name = g_malloc (namelen + 1)) == NULL
1758               || (namelen > 0 && fread (name, namelen, 1, f) < 1)
1759               || fread (&type, 1, 1, f) < 1
1760               || fread (&image_rect, 16, 1, f) < 1
1761               || fread (&saved_image_rect, 16, 1, f) < 1
1762               || fread (&opacity, 1, 1, f) < 1
1763               || fread (&blend_mode, 1, 1, f) < 1
1764               || fread (&visibility, 1, 1, f) < 1
1765               || fread (&transparency_protected, 1, 1, f) < 1
1766               || fread (&link_group_id, 1, 1, f) < 1
1767               || fread (&mask_rect, 16, 1, f) < 1
1768               || fread (&saved_mask_rect, 16, 1, f) < 1
1769               || fread (&mask_linked, 1, 1, f) < 1
1770               || fread (&mask_disabled, 1, 1, f) < 1)
1771             {
1772               g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1773                            _("Error reading layer information chunk"));
1774               g_free (name);
1775               return -1;
1776             }
1777 
1778           name[namelen] = 0;
1779           layer_name = g_convert (name, -1, "utf-8", "iso8859-1", NULL, NULL, NULL);
1780           g_free (name);
1781 
1782           chunk_len = GUINT32_FROM_LE (chunk_len);
1783           layer_extension_start = sub_block_start + chunk_len;
1784 
1785           switch (type)
1786             {
1787             case keGLTFloatingRasterSelection:
1788               g_message ("Floating selection restored as normal layer (%s)", layer_name);
1789             case keGLTRaster:
1790               if (! read_raster_layer_info (f, layer_extension_start,
1791                                             &bitmap_count,
1792                                             &channel_count,
1793                                             error))
1794                 {
1795                   g_free (layer_name);
1796                   return -1;
1797                 }
1798               can_handle_layer = TRUE;
1799               break;
1800             default:
1801               bitmap_count = 0;
1802               channel_count = 0;
1803               g_message ("Unsupported layer type %s (%s)", layer_type_name(type), layer_name);
1804               break;
1805             }
1806         }
1807       else
1808         {
1809           name = g_malloc (257);
1810           name[256] = 0;
1811 
1812           if (fread (name, 256, 1, f) < 1
1813               || fread (&type, 1, 1, f) < 1
1814               || fread (&image_rect, 16, 1, f) < 1
1815               || fread (&saved_image_rect, 16, 1, f) < 1
1816               || fread (&opacity, 1, 1, f) < 1
1817               || fread (&blend_mode, 1, 1, f) < 1
1818               || fread (&visibility, 1, 1, f) < 1
1819               || fread (&transparency_protected, 1, 1, f) < 1
1820               || fread (&link_group_id, 1, 1, f) < 1
1821               || fread (&mask_rect, 16, 1, f) < 1
1822               || fread (&saved_mask_rect, 16, 1, f) < 1
1823               || fread (&mask_linked, 1, 1, f) < 1
1824               || fread (&mask_disabled, 1, 1, f) < 1
1825               || fseek (f, 43, SEEK_CUR) < 0
1826               || fread (&bitmap_count, 2, 1, f) < 1
1827               || fread (&channel_count, 2, 1, f) < 1)
1828             {
1829               g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1830                            _("Error reading layer information chunk"));
1831               g_free (name);
1832               return -1;
1833             }
1834           layer_name = g_convert (name, -1, "utf-8", "iso8859-1", NULL, NULL, NULL);
1835           g_free (name);
1836           if (type == PSP_LAYER_FLOATING_SELECTION)
1837             g_message ("Floating selection restored as normal layer");
1838           type = keGLTRaster;
1839           can_handle_layer = TRUE;
1840           if (try_fseek (f, sub_block_start + sub_init_len, SEEK_SET, error) < 0)
1841             {
1842               g_free (layer_name);
1843               return -1;
1844             }
1845         }
1846 
1847       swab_rect (image_rect);
1848       swab_rect (saved_image_rect);
1849       swab_rect (mask_rect);
1850       swab_rect (saved_mask_rect);
1851       bitmap_count = GUINT16_FROM_LE (bitmap_count);
1852       channel_count = GUINT16_FROM_LE (channel_count);
1853 
1854       layer_mode = gimp_layer_mode_from_psp_blend_mode (blend_mode);
1855       if ((int) layer_mode == -1)
1856         {
1857           g_message ("Unsupported PSP layer blend mode %s "
1858                      "for layer %s, setting layer invisible",
1859                      blend_mode_name (blend_mode), layer_name);
1860           layer_mode = GIMP_LAYER_MODE_NORMAL_LEGACY;
1861           visibility = FALSE;
1862         }
1863 
1864       width = saved_image_rect[2] - saved_image_rect[0];
1865       height = saved_image_rect[3] - saved_image_rect[1];
1866 
1867       if ((width < 0) || (width > GIMP_MAX_IMAGE_SIZE)       /* w <= 2^18 */
1868           || (height < 0) || (height > GIMP_MAX_IMAGE_SIZE)  /* h <= 2^18 */
1869           || ((width / 256) * (height / 256) >= 8192))       /* w * h < 2^29 */
1870         {
1871           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1872                        _("Invalid layer dimensions: %dx%d"),
1873                        width, height);
1874           g_free (layer_name);
1875           return -1;
1876         }
1877 
1878       IFDBG(2) g_message
1879         ("layer: %s %dx%d (%dx%d) @%d,%d opacity %d blend_mode %s "
1880          "%d bitmaps %d channels",
1881          layer_name,
1882          image_rect[2] - image_rect[0], image_rect[3] - image_rect[1],
1883          width, height,
1884          image_rect[0]+saved_image_rect[0], image_rect[1]+saved_image_rect[1],
1885          opacity, blend_mode_name (blend_mode),
1886          bitmap_count, channel_count);
1887 
1888       IFDBG(2) g_message
1889         ("mask %dx%d (%dx%d) @%d,%d",
1890          mask_rect[2] - mask_rect[0],
1891          mask_rect[3] - mask_rect[1],
1892          saved_mask_rect[2] - saved_mask_rect[0],
1893          saved_mask_rect[3] - saved_mask_rect[1],
1894          saved_mask_rect[0], saved_mask_rect[1]);
1895 
1896       if (width == 0)
1897         {
1898           width++;
1899           null_layer = TRUE;
1900         }
1901       if (height == 0)
1902         {
1903           height++;
1904           null_layer = TRUE;
1905         }
1906 
1907       if (ia->base_type == GIMP_RGB)
1908         if (bitmap_count == 1)
1909           drawable_type = GIMP_RGB_IMAGE, bytespp = 3;
1910         else
1911           drawable_type = GIMP_RGBA_IMAGE, bytespp = 4;
1912       else if (ia->base_type == GIMP_GRAY)
1913         if (bitmap_count == 1)
1914           drawable_type = GIMP_GRAY_IMAGE, bytespp = 1;
1915         else
1916           drawable_type = GIMP_GRAYA_IMAGE, bytespp = 2;
1917       else
1918         if (bitmap_count == 1)
1919           drawable_type = GIMP_INDEXED_IMAGE, bytespp = 1;
1920         else
1921           drawable_type = GIMP_INDEXEDA_IMAGE, bytespp = 2;
1922       bytespp *= ia->bytes_per_sample;
1923 
1924       layer_ID = gimp_layer_new (image_ID, layer_name,
1925                                  width, height,
1926                                  drawable_type,
1927                                  100.0 * opacity / 255.0,
1928                                  layer_mode);
1929       g_free (layer_name);
1930       if (layer_ID == -1)
1931         {
1932           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1933                        _("Error creating layer"));
1934           return -1;
1935         }
1936 
1937       gimp_image_insert_layer (image_ID, layer_ID, -1, -1);
1938 
1939       if (image_rect[0] != 0 || image_rect[1] != 0 || saved_image_rect[0] != 0 || saved_image_rect[1] != 0)
1940         gimp_layer_set_offsets (layer_ID,
1941                                 image_rect[0] + saved_image_rect[0], image_rect[1] + saved_image_rect[1]);
1942 
1943       if (!visibility)
1944         gimp_item_set_visible (layer_ID, FALSE);
1945 
1946       gimp_layer_set_lock_alpha (layer_ID, transparency_protected);
1947 
1948       if (can_handle_layer)
1949         {
1950           pixel = g_malloc0 (height * width * bytespp);
1951           if (null_layer)
1952             {
1953               pixels = NULL;
1954             }
1955           else
1956             {
1957               pixels = g_new (guchar *, height);
1958               for (i = 0; i < height; i++)
1959                 pixels[i] = pixel + width * bytespp * i;
1960             }
1961 
1962           buffer = gimp_drawable_get_buffer (layer_ID);
1963 
1964           /* Read the layer channel sub-blocks */
1965           while (ftell (f) < sub_block_start + sub_total_len)
1966             {
1967               sub_id = read_block_header (f, &channel_init_len,
1968                                           &channel_total_len, error);
1969               if (sub_id == -1)
1970                 {
1971                   gimp_image_delete (image_ID);
1972                   return -1;
1973                 }
1974 
1975               if (sub_id != PSP_CHANNEL_BLOCK)
1976                 {
1977                   g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1978                               _("Invalid layer sub-block %s, should be CHANNEL"),
1979                               block_name (sub_id));
1980                   return -1;
1981                 }
1982 
1983               channel_start = ftell (f);
1984               chunk_len = channel_init_len; /* init chunk_len for psp_ver_major == 3 */
1985               if ((psp_ver_major >= 4
1986                   && (fread (&chunk_len, 4, 1, f) < 1
1987                   || ((chunk_len = GUINT32_FROM_LE (chunk_len)) < 16)))
1988                   || fread (&compressed_len, 4, 1, f) < 1
1989                   || fread (&uncompressed_len, 4, 1, f) < 1
1990                   || fread (&bitmap_type, 2, 1, f) < 1
1991                   || fread (&channel_type, 2, 1, f) < 1)
1992                 {
1993                   g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1994                               _("Error reading channel information chunk"));
1995                   return -1;
1996                 }
1997 
1998               compressed_len = GUINT32_FROM_LE (compressed_len);
1999               uncompressed_len = GUINT32_FROM_LE (uncompressed_len);
2000               bitmap_type = GUINT16_FROM_LE (bitmap_type);
2001               channel_type = GUINT16_FROM_LE (channel_type);
2002 
2003               if (bitmap_type > PSP_DIB_USER_MASK)
2004                 {
2005                   g_message ("Conversion of bitmap type %d is not supported.", bitmap_type);
2006                 }
2007               else if (bitmap_type == PSP_DIB_USER_MASK)
2008                 {
2009                   /* FIXME: Add as layer mask */
2010                   g_message ("Conversion of layer mask is not supported");
2011                 }
2012               else
2013                 {
2014                   if (channel_type > PSP_CHANNEL_BLUE)
2015                     {
2016                       g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
2017                                   _("Invalid channel type %d in channel information chunk"),
2018                                   channel_type);
2019                       return -1;
2020                     }
2021 
2022                   IFDBG(2) g_message ("channel: %s %s %d (%d) bytes %d bytespp",
2023                                       bitmap_type_name (bitmap_type),
2024                                       channel_type_name (channel_type),
2025                                       uncompressed_len, compressed_len,
2026                                       bytespp);
2027 
2028                   if (bitmap_type == PSP_DIB_TRANS_MASK || channel_type == PSP_CHANNEL_COMPOSITE)
2029                     offset = bytespp - ia->bytes_per_sample;
2030                   else
2031                     offset = (channel_type - PSP_CHANNEL_RED) * ia->bytes_per_sample;
2032 
2033                   if (!null_layer)
2034                     {
2035                       if (try_fseek (f, channel_start + chunk_len, SEEK_SET, error) < 0)
2036                         {
2037                           return -1;
2038                         }
2039 
2040                       if (read_channel_data (f, ia, pixels, bytespp, offset,
2041                                             buffer, compressed_len, error) == -1)
2042                         {
2043                           return -1;
2044                         }
2045                     }
2046                 }
2047               if (try_fseek (f, channel_start + channel_total_len, SEEK_SET, error) < 0)
2048                 {
2049                   return -1;
2050                 }
2051             }
2052 
2053           gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, width, height), 0,
2054                           NULL, pixel, GEGL_AUTO_ROWSTRIDE);
2055 
2056           g_object_unref (buffer);
2057 
2058           g_free (pixels);
2059           g_free (pixel);
2060           if (psp_ver_major >= 4)
2061             {
2062               if (try_fseek (f, sub_block_start + sub_total_len, SEEK_SET, error) < 0)
2063                 {
2064                   return -1;
2065                 }
2066             }
2067         }
2068       else
2069         {
2070           /* Can't handle this type of layer, skip the data so we can read the next layer. */
2071           if (psp_ver_major >= 4)
2072             {
2073               if (try_fseek (f, sub_block_start + sub_total_len, SEEK_SET, error) < 0)
2074                 {
2075                   return -1;
2076                 }
2077             }
2078         }
2079     }
2080 
2081   if (try_fseek (f, block_start + total_len, SEEK_SET, error) < 0)
2082     {
2083       return -1;
2084     }
2085 
2086   return layer_ID;
2087 }
2088 
2089 static gint
read_tube_block(FILE * f,gint image_ID,guint total_len,PSPimage * ia,GError ** error)2090 read_tube_block (FILE      *f,
2091                  gint       image_ID,
2092                  guint      total_len,
2093                  PSPimage  *ia,
2094                  GError   **error)
2095 {
2096   guint16            version;
2097   guchar             name[514];
2098   guint32            step_size, column_count, row_count, cell_count;
2099   guint32            placement_mode, selection_mode;
2100   guint32            chunk_len;
2101   gint               i;
2102   GimpPixPipeParams  params;
2103   GimpParasite      *pipe_parasite;
2104   gchar             *parasite_text;
2105 
2106   gimp_pixpipe_params_init (&params);
2107 
2108   if (psp_ver_major >= 4)
2109     {
2110       name[0] = 0;
2111       if (fread (&chunk_len, 4, 1, f) < 1
2112           || fread (&version, 2, 1, f) < 1
2113           || fread (&step_size, 4, 1, f) < 1
2114           || fread (&column_count, 4, 1, f) < 1
2115           || fread (&row_count, 4, 1, f) < 1
2116           || fread (&cell_count, 4, 1, f) < 1
2117           || fread (&placement_mode, 4, 1, f) < 1
2118           || fread (&selection_mode, 4, 1, f) < 1)
2119         {
2120           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
2121                        _("Error reading tube data chunk"));
2122           return -1;
2123         }
2124     }
2125   else
2126     {
2127       chunk_len = 0;
2128       if (fread (&version, 2, 1, f) < 1
2129           || fread (name, 513, 1, f) < 1
2130           || fread (&step_size, 4, 1, f) < 1
2131           || fread (&column_count, 4, 1, f) < 1
2132           || fread (&row_count, 4, 1, f) < 1
2133           || fread (&cell_count, 4, 1, f) < 1
2134           || fread (&placement_mode, 4, 1, f) < 1
2135           || fread (&selection_mode, 4, 1, f) < 1)
2136         {
2137           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
2138                        _("Error reading tube data chunk"));
2139           return -1;
2140         }
2141       name[513] = 0;
2142     }
2143 
2144   version = GUINT16_FROM_LE (version);
2145   params.step = GUINT32_FROM_LE (step_size);
2146   params.cols = GUINT32_FROM_LE (column_count);
2147   params.rows = GUINT32_FROM_LE (row_count);
2148   params.ncells = GUINT32_FROM_LE (cell_count);
2149   placement_mode = GUINT32_FROM_LE (placement_mode);
2150   selection_mode = GUINT32_FROM_LE (selection_mode);
2151 
2152   for (i = 1; i < params.cols; i++)
2153     gimp_image_add_vguide (image_ID, (ia->width * i)/params.cols);
2154   for (i = 1; i < params.rows; i++)
2155     gimp_image_add_hguide (image_ID, (ia->height * i)/params.rows);
2156 
2157   /* We use a parasite to pass in the tube (pipe) parameters in
2158    * case we will have any use of those, for instance in the gpb
2159    * plug-in that exports a GIMP image pipe.
2160    */
2161   params.dim = 1;
2162   params.cellwidth = ia->width / params.cols;
2163   params.cellheight = ia->height / params.rows;
2164   params.placement = (placement_mode == tpmRandom ? "random" :
2165                       (placement_mode == tpmConstant ? "constant" :
2166                        "default"));
2167   params.rank[0] = params.ncells;
2168   params.selection[0] = (selection_mode == tsmRandom ? "random" :
2169                          (selection_mode == tsmIncremental ? "incremental" :
2170                           (selection_mode == tsmAngular ? "angular" :
2171                            (selection_mode == tsmPressure ? "pressure" :
2172                             (selection_mode == tsmVelocity ? "velocity" :
2173                              "default")))));
2174   parasite_text = gimp_pixpipe_params_build (&params);
2175 
2176   IFDBG(2) g_message ("parasite: %s", parasite_text);
2177 
2178   pipe_parasite = gimp_parasite_new ("gimp-brush-pipe-parameters",
2179                                      GIMP_PARASITE_PERSISTENT,
2180                                      strlen (parasite_text) + 1, parasite_text);
2181   gimp_image_attach_parasite (image_ID, pipe_parasite);
2182   gimp_parasite_free (pipe_parasite);
2183   g_free (parasite_text);
2184 
2185   return 0;
2186 }
2187 
2188 static const gchar *
compression_name(gint compression)2189 compression_name (gint compression)
2190 {
2191   switch (compression)
2192     {
2193     case PSP_COMP_NONE:
2194       return "no compression";
2195     case PSP_COMP_RLE:
2196       return "RLE";
2197     case PSP_COMP_LZ77:
2198       return "LZ77";
2199     }
2200   g_assert_not_reached ();
2201 
2202   return NULL;
2203 }
2204 
2205 /* The main function for loading PSP-images
2206  */
2207 static gint32
load_image(const gchar * filename,GError ** error)2208 load_image (const gchar  *filename,
2209             GError      **error)
2210 {
2211   FILE      *f;
2212   GStatBuf   st;
2213   char       buf[32];
2214   PSPimage   ia;
2215   guint32    block_init_len, block_total_len;
2216   long       block_start;
2217   PSPBlockID id = -1;
2218   gint       block_number;
2219   gint32     image_ID = -1;
2220 
2221   if (g_stat (filename, &st) == -1)
2222     return -1;
2223 
2224   f = g_fopen (filename, "rb");
2225   if (f == NULL)
2226     {
2227       g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
2228                    _("Could not open '%s' for reading: %s"),
2229                    gimp_filename_to_utf8 (filename), g_strerror (errno));
2230       return -1;
2231     }
2232 
2233   /* Read the PSP File Header and determine file version */
2234   if (fread (buf, 32, 1, f) < 1
2235       || fread (&psp_ver_major, 2, 1, f) < 1
2236       || fread (&psp_ver_minor, 2, 1, f) < 1)
2237     {
2238       g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
2239                    _("Error reading file header."));
2240       goto error;
2241     }
2242 
2243   if (memcmp (buf, "Paint Shop Pro Image File\n\032\0\0\0\0\0", 32) != 0)
2244     {
2245       g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
2246                    _("Incorrect file signature."));
2247       goto error;
2248     }
2249 
2250   psp_ver_major = GUINT16_FROM_LE (psp_ver_major);
2251   psp_ver_minor = GUINT16_FROM_LE (psp_ver_minor);
2252 
2253   /* We don't have the documentation for file format versions before 3.0,
2254    * but newer versions should be mostly backwards compatible so that
2255    * we can still read the image and skip unknown parts safely.
2256    */
2257   if (psp_ver_major < 3)
2258     {
2259       g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
2260                    _("Unsupported PSP file format version %d.%d."),
2261                    psp_ver_major, psp_ver_minor);
2262       goto error;
2263     }
2264 
2265   /* Read all the blocks */
2266   block_number = 0;
2267 
2268   IFDBG(3) g_message ("size = %d", (int)st.st_size);
2269   while (ftell (f) != st.st_size
2270          && (id = read_block_header (f, &block_init_len,
2271                                      &block_total_len, error)) != -1)
2272     {
2273       block_start = ftell (f);
2274 
2275       if (block_start + block_total_len > st.st_size)
2276         {
2277           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
2278                        _("Could not open '%s' for reading: %s"),
2279                        gimp_filename_to_utf8 (filename),
2280                        _("invalid block size"));
2281           goto error;
2282         }
2283 
2284       if (id == PSP_IMAGE_BLOCK)
2285         {
2286           if (block_number != 0)
2287             {
2288               g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
2289                            _("Duplicate General Image Attributes block."));
2290               goto error;
2291             }
2292           if (read_general_image_attribute_block (f, block_init_len,
2293                                                   block_total_len, &ia, error) == -1)
2294             {
2295               goto error;
2296             }
2297 
2298           IFDBG(2) g_message ("%d dpi %dx%d %s",
2299                               (int) ia.resolution,
2300                               ia.width, ia.height,
2301                               compression_name (ia.compression));
2302 
2303           image_ID = gimp_image_new_with_precision (ia.width, ia.height,
2304                                                     ia.base_type, ia.precision);
2305           if (image_ID == -1)
2306             {
2307               goto error;
2308             }
2309 
2310           gimp_image_set_filename (image_ID, filename);
2311 
2312           gimp_image_set_resolution (image_ID, ia.resolution, ia.resolution);
2313         }
2314       else
2315         {
2316           if (block_number == 0)
2317             {
2318               g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
2319                            _("Missing General Image Attributes block."));
2320               goto error;
2321             }
2322 
2323           switch (id)
2324             {
2325             case PSP_CREATOR_BLOCK:
2326               if (read_creator_block (f, image_ID, block_total_len, &ia, error) == -1)
2327                 goto error;
2328               break;
2329 
2330             case PSP_COLOR_BLOCK:
2331               if (read_color_block (f, image_ID, block_total_len, &ia, error) == -1)
2332                 goto error;
2333               break;
2334 
2335             case PSP_LAYER_START_BLOCK:
2336               if (read_layer_block (f, image_ID, block_total_len, &ia, error) == -1)
2337                 goto error;
2338               break;
2339 
2340             case PSP_SELECTION_BLOCK:
2341               break;            /* Not yet implemented */
2342 
2343             case PSP_ALPHA_BANK_BLOCK:
2344               break;            /* Not yet implemented */
2345 
2346             case PSP_THUMBNAIL_BLOCK:
2347               break;            /* No use for it */
2348 
2349             case PSP_EXTENDED_DATA_BLOCK:
2350               break;            /* Not yet implemented */
2351 
2352             case PSP_TUBE_BLOCK:
2353               if (read_tube_block (f, image_ID, block_total_len, &ia, error) == -1)
2354                 goto error;
2355               break;
2356 
2357             case PSP_COMPOSITE_IMAGE_BANK_BLOCK:
2358               break;            /* Not yet implemented */
2359 
2360             case PSP_TABLE_BANK_BLOCK:
2361               break;            /* Not yet implemented */
2362 
2363             case PSP_BRUSH_BLOCK:
2364               break;            /* Not yet implemented */
2365 
2366             case PSP_ART_MEDIA_BLOCK:
2367             case PSP_ART_MEDIA_MAP_BLOCK:
2368             case PSP_ART_MEDIA_TILE_BLOCK:
2369             case PSP_ART_MEDIA_TEXTURE_BLOCK:
2370               break;            /* Not yet implemented */
2371 
2372             case PSP_COLORPROFILE_BLOCK:
2373               break;            /* Not yet implemented */
2374 
2375             case PSP_LAYER_BLOCK:
2376             case PSP_CHANNEL_BLOCK:
2377             case PSP_ALPHA_CHANNEL_BLOCK:
2378             case PSP_ADJUSTMENT_EXTENSION_BLOCK:
2379             case PSP_VECTOR_EXTENSION_BLOCK:
2380             case PSP_SHAPE_BLOCK:
2381             case PSP_PAINTSTYLE_BLOCK:
2382             case PSP_COMPOSITE_ATTRIBUTES_BLOCK:
2383             case PSP_JPEG_BLOCK:
2384             case PSP_LINESTYLE_BLOCK:
2385             case PSP_TABLE_BLOCK:
2386             case PSP_PAPER_BLOCK:
2387             case PSP_PATTERN_BLOCK:
2388             case PSP_GRADIENT_BLOCK:
2389             case PSP_GROUP_EXTENSION_BLOCK:
2390             case PSP_MASK_EXTENSION_BLOCK:
2391             case PSP_RASTER_EXTENSION_BLOCK:
2392               g_message ("Sub-block %s should not occur "
2393                          "at main level of file",
2394                          block_name (id));
2395               break;
2396 
2397             default:
2398               g_message ("Unrecognized block id %d", id);
2399               break;
2400             }
2401         }
2402 
2403       if (block_start + block_total_len >= st.st_size)
2404         break;
2405 
2406       if (try_fseek (f, block_start + block_total_len, SEEK_SET, error) < 0)
2407         goto error;
2408 
2409       block_number++;
2410     }
2411 
2412   if (id == -1)
2413     {
2414     error:
2415       fclose (f);
2416       if (image_ID != -1)
2417         gimp_image_delete (image_ID);
2418       return -1;
2419     }
2420 
2421   fclose (f);
2422 
2423   return image_ID;
2424 }
2425 
2426 static gint
save_image(const gchar * filename,gint32 image_ID,gint32 drawable_ID,GError ** error)2427 save_image (const gchar  *filename,
2428             gint32        image_ID,
2429             gint32        drawable_ID,
2430             GError      **error)
2431 {
2432   g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
2433                _("Exporting not implemented yet."));
2434 
2435   return FALSE;
2436 }
2437 
2438 static void
run(const gchar * name,gint nparams,const GimpParam * param,gint * nreturn_vals,GimpParam ** return_vals)2439 run (const gchar      *name,
2440      gint              nparams,
2441      const GimpParam  *param,
2442      gint             *nreturn_vals,
2443      GimpParam       **return_vals)
2444 {
2445   static GimpParam   values[2];
2446   GimpRunMode        run_mode;
2447   GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
2448   gint32             image_ID;
2449   gint32             drawable_ID;
2450   GimpExportReturn   export = GIMP_EXPORT_CANCEL;
2451   GError            *error  = NULL;
2452 
2453   INIT_I18N ();
2454   gegl_init (NULL, NULL);
2455 
2456   run_mode = param[0].data.d_int32;
2457 
2458   *nreturn_vals = 1;
2459   *return_vals  = values;
2460 
2461   values[0].type          = GIMP_PDB_STATUS;
2462   values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
2463 
2464   if (strcmp (name, LOAD_PROC) == 0)
2465     {
2466       image_ID = load_image (param[1].data.d_string, &error);
2467 
2468       if (image_ID != -1)
2469         {
2470           *nreturn_vals = 2;
2471           values[1].type         = GIMP_PDB_IMAGE;
2472           values[1].data.d_image = image_ID;
2473         }
2474       else
2475         {
2476           status = GIMP_PDB_EXECUTION_ERROR;
2477         }
2478     }
2479   else if (strcmp (name, SAVE_PROC) == 0)
2480     {
2481       image_ID = param[1].data.d_int32;
2482       drawable_ID = param[2].data.d_int32;
2483 
2484       /*  eventually export the image */
2485       switch (run_mode)
2486         {
2487         case GIMP_RUN_INTERACTIVE:
2488         case GIMP_RUN_WITH_LAST_VALS:
2489           gimp_ui_init (PLUG_IN_BINARY, FALSE);
2490 
2491           export = gimp_export_image (&image_ID, &drawable_ID, "PSP",
2492                                       GIMP_EXPORT_CAN_HANDLE_RGB     |
2493                                       GIMP_EXPORT_CAN_HANDLE_GRAY    |
2494                                       GIMP_EXPORT_CAN_HANDLE_INDEXED |
2495                                       GIMP_EXPORT_CAN_HANDLE_ALPHA   |
2496                                       GIMP_EXPORT_CAN_HANDLE_LAYERS);
2497 
2498           if (export == GIMP_EXPORT_CANCEL)
2499             {
2500               values[0].data.d_status = GIMP_PDB_CANCEL;
2501               return;
2502             }
2503           break;
2504         default:
2505           break;
2506         }
2507 
2508       switch (run_mode)
2509         {
2510         case GIMP_RUN_INTERACTIVE:
2511           /*  Possibly retrieve data  */
2512           gimp_get_data (SAVE_PROC, &psvals);
2513 
2514           /*  First acquire information with a dialog  */
2515           if (! save_dialog ())
2516             status = GIMP_PDB_CANCEL;
2517           break;
2518 
2519         case GIMP_RUN_NONINTERACTIVE:
2520           /*  Make sure all the arguments are there!  */
2521           if (nparams != 6)
2522             {
2523               status = GIMP_PDB_CALLING_ERROR;
2524             }
2525           else
2526             {
2527               psvals.compression = (param[5].data.d_int32) ? TRUE : FALSE;
2528 
2529               if (param[5].data.d_int32 < 0 ||
2530                   param[5].data.d_int32 > PSP_COMP_LZ77)
2531                 status = GIMP_PDB_CALLING_ERROR;
2532             }
2533 
2534         case GIMP_RUN_WITH_LAST_VALS:
2535           gimp_get_data (SAVE_PROC, &psvals);
2536           break;
2537 
2538         default:
2539           break;
2540         }
2541 
2542       if (status == GIMP_PDB_SUCCESS)
2543         {
2544           if (save_image (param[3].data.d_string, image_ID, drawable_ID,
2545                           &error))
2546             {
2547               gimp_set_data (SAVE_PROC, &psvals, sizeof (PSPSaveVals));
2548             }
2549           else
2550             {
2551               status = GIMP_PDB_EXECUTION_ERROR;
2552             }
2553         }
2554 
2555       if (export == GIMP_EXPORT_EXPORT)
2556         gimp_image_delete (image_ID);
2557     }
2558   else
2559     {
2560       status = GIMP_PDB_CALLING_ERROR;
2561     }
2562 
2563   if (status != GIMP_PDB_SUCCESS && error)
2564     {
2565       *nreturn_vals = 2;
2566       values[1].type          = GIMP_PDB_STRING;
2567       values[1].data.d_string = error->message;
2568     }
2569 
2570   values[0].data.d_status = status;
2571 }
2572