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, /* Strikeout property bit */
213 keStyleUnderlined = 0x00000004, /* Underlined property bit */
214 keStyleWarped = 0x00000008, /* Warped property bit (since PSP8) */
215 keStyleAntiAliased = 0x00000010, /* Antialiased 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 antialiased */
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, /* Brightnesscontrast 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 (¶ms);
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 (¶ms);
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