Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP4:Update
gimp
gimp-CVE-2017-17787.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File gimp-CVE-2017-17787.patch of Package gimp
diff -Nura gimp-2.8.18/plug-ins/common/file-psp.c gimp-2.8.18_new/plug-ins/common/file-psp.c --- gimp-2.8.18/plug-ins/common/file-psp.c 2020-12-20 23:28:21.039628057 +0800 +++ gimp-2.8.18_new/plug-ins/common/file-psp.c 2020-12-21 00:09:46.928196856 +0800 @@ -890,6 +890,12 @@ g_free (string); return -1; } + if (string[length - 1] != '\0') + { + g_message ("Creator keyword data not nul-terminated"); + g_free (string); + return -1; + } switch (keyword) { case PSP_CRTR_FLD_TITLE: diff -Nura gimp-2.8.18/plug-ins/common/file-psp.c.orig gimp-2.8.18_new/plug-ins/common/file-psp.c.orig --- gimp-2.8.18/plug-ins/common/file-psp.c.orig 2015-08-21 06:57:28.000000000 +0800 +++ gimp-2.8.18_new/plug-ins/common/file-psp.c.orig 1970-01-01 08:00:00.000000000 +0800 @@ -1,2032 +0,0 @@ -/* GIMP plug-in to load and save Paint Shop Pro files (.PSP and .TUB) - * - * Copyright (C) 1999 Tor Lillqvist - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* - * - * Work in progress! Doesn't handle saving yet. - * - * For a copy of the PSP file format documentation, surf to - * http://www.jasc.com. - * - */ - -#define LOAD_PROC "file-psp-load" -#define SAVE_PROC "file-psp-save" -#define PLUG_IN_BINARY "file-psp" -#define PLUG_IN_ROLE "gimp-file-psp" - -/* set to the level of debugging output you want, 0 for none */ -#define PSP_DEBUG 0 - -#define IFDBG(level) if (PSP_DEBUG >= level) - -#include "config.h" - -#include <errno.h> -#include <string.h> -#include <zlib.h> - -#include <glib/gstdio.h> - -#include <libgimp/gimp.h> -#include <libgimp/gimpui.h> -#include <libgimpbase/gimpparasiteio.h> - -#include "libgimp/stdplugins-intl.h" - - -/* Note that the upcoming PSP version 6 writes PSP file format version - * 4.0, but the documentation for that apparently isn't publicly - * available (yet). The format is luckily designed to be somwehat - * downward compatible, however. The semantics of many of the - * additional fields and block types can be relatively easily reverse - * engineered. - */ - -/* The following was cut and pasted from the PSP file format - * documentation version 3.0.(Minor stylistic changes done.) - * - * - * To be on the safe side, here is the whole copyright notice from the - * specification: - * - * The Paint Shop Pro File Format Specification (the Specification) is - * copyright 1998 by Jasc Software, Inc. Jasc grants you a - * nonexclusive license to use the Specification for the sole purposes - * of developing software products(s) incorporating the - * Specification. You are also granted the right to identify your - * software product(s) as incorporating the Paint Shop Pro Format - * (PSP) provided that your software in incorporating the - * Specification complies with the terms, definitions, constraints and - * specifications contained in the Specification and subject to the - * following: DISCLAIMER OF WARRANTIES. THE SPECIFICATION IS PROVIDED - * AS IS. JASC DISCLAIMS ALL OTHER WARRANTIES, EXPRESS OR IMPLIED, - * INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. - * - * You are solely responsible for the selection, use, efficiency and - * suitability of the Specification for your software products. OTHER - * WARRANTIES EXCLUDED. JASC SHALL NOT BE LIABLE FOR ANY DIRECT, - * INDIRECT, CONSEQUENTIAL, EXEMPLARY, PUNITIVE OR INCIDENTAL DAMAGES - * ARISING FROM ANY CAUSE EVEN IF JASC HAS BEEN ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. CERTAIN JURISDICTIONS DO NOT PERMIT - * THE LIMITATION OR EXCLUSION OF INCIDENTAL DAMAGES, SO THIS - * LIMITATION MAY NOT APPLY TO YOU. IN NO EVENT WILL JASC BE LIABLE - * FOR ANY AMOUNT GREATER THAN WHAT YOU ACTUALLY PAID FOR THE - * SPECIFICATION. Should any warranties be found to exist, such - * warranties shall be limited in duration to ninety (90) days - * following the date you receive the Specification. - * - * Indemnification. By your inclusion of the Paint Shop Pro File - * Format in your software product(s) you agree to indemnify and hold - * Jasc Software, Inc. harmless from any and all claims of any kind or - * nature made by any of your customers with respect to your software - * product(s). - * - * Export Laws. You agree that you and your customers will not export - * your software or Specification except in compliance with the laws - * and regulations of the United States. - * - * US Government Restricted Rights. The Specification and any - * accompanying materials are provided with Restricted Rights. Use, - * duplication or disclosure by the Government is subject to - * restrictions as set forth in subparagraph (c)(1)(ii) of The Rights - * in Technical Data and Computer Software clause at DFARS - * 252.227-7013, or subparagraphs (c)(1) and (2) of the Commercial - * Computer Software - Restricted Rights at 48 CFR 52.227-19, as - * applicable. Contractor/manufacturer is Jasc Software, Inc., PO Box - * 44997, Eden Prairie MN 55344. - * - * Jasc reserves the right to amend, modify, change, revoke or - * withdraw the Specification at any time and from time to time. Jasc - * shall have no obligation to support or maintain the Specification. - */ - -/* Block identifiers. - */ -typedef enum { - PSP_IMAGE_BLOCK = 0, /* General Image Attributes Block (main) */ - PSP_CREATOR_BLOCK, /* Creator Data Block (main) */ - PSP_COLOR_BLOCK, /* Color Palette Block (main and sub) */ - PSP_LAYER_START_BLOCK, /* Layer Bank Block (main) */ - PSP_LAYER_BLOCK, /* Layer Block (sub) */ - PSP_CHANNEL_BLOCK, /* Channel Block (sub) */ - PSP_SELECTION_BLOCK, /* Selection Block (main) */ - PSP_ALPHA_BANK_BLOCK, /* Alpha Bank Block (main) */ - PSP_ALPHA_CHANNEL_BLOCK, /* Alpha Channel Block (sub) */ - PSP_THUMBNAIL_BLOCK, /* Thumbnail Block (main) */ - PSP_EXTENDED_DATA_BLOCK, /* Extended Data Block (main) */ - PSP_TUBE_BLOCK, /* Picture Tube Data Block (main) */ - PSP_ADJUSTMENT_EXTENSION_BLOCK, /* Adjustment Layer Extension Block (sub) (since PSP6)*/ - PSP_VECTOR_EXTENSION_BLOCK, /* Vector Layer Extension Block (sub) (since PSP6) */ - PSP_SHAPE_BLOCK, /* Vector Shape Block (sub) (since PSP6) */ - PSP_PAINTSTYLE_BLOCK, /* Paint Style Block (sub) (since PSP6) */ - PSP_COMPOSITE_IMAGE_BANK_BLOCK, /* Composite Image Bank (main) (since PSP6) */ - PSP_COMPOSITE_ATTRIBUTES_BLOCK, /* Composite Image Attributes (sub) (since PSP6) */ - PSP_JPEG_BLOCK, /* JPEG Image Block (sub) (since PSP6) */ - PSP_LINESTYLE_BLOCK, /* Line Style Block (sub) (since PSP7) */ - PSP_TABLE_BANK_BLOCK, /* Table Bank Block (main) (since PSP7) */ - PSP_TABLE_BLOCK, /* Table Block (sub) (since PSP7) */ - PSP_PAPER_BLOCK, /* Vector Table Paper Block (sub) (since PSP7) */ - PSP_PATTERN_BLOCK, /* Vector Table Pattern Block (sub) (since PSP7) */ - PSP_GRADIENT_BLOCK, /* Vector Table Gradient Block (not used) (since PSP8) */ - PSP_GROUP_EXTENSION_BLOCK, /* Group Layer Block (sub) (since PSP8) */ - PSP_MASK_EXTENSION_BLOCK, /* Mask Layer Block (sub) (since PSP8) */ - PSP_BRUSH_BLOCK, /* Brush Data Block (main) (since PSP8) */ -} PSPBlockID; - -/* Bitmap type. - */ -typedef enum { - PSP_DIB_IMAGE = 0, /* Layer color bitmap */ - PSP_DIB_TRANS_MASK, /* Layer transparency mask bitmap */ - PSP_DIB_USER_MASK, /* Layer user mask bitmap */ - PSP_DIB_SELECTION, /* Selection mask bitmap */ - PSP_DIB_ALPHA_MASK, /* Alpha channel mask bitmap */ - PSP_DIB_THUMBNAIL, /* Thumbnail bitmap */ - PSP_DIB_THUMBNAIL_TRANS_MASK, /* Thumbnail transparency mask (since PSP6) */ - PSP_DIB_ADJUSTMENT_LAYER, /* Adjustment layer bitmap (since PSP6) */ - PSP_DIB_COMPOSITE, /* Composite image bitmap (since PSP6) */ - PSP_DIB_COMPOSITE_TRANS_MASK, /* Composite image transparency (since PSP6) */ - PSP_DIB_PAPER, /* Paper bitmap (since PSP7) */ - PSP_DIB_PATTERN, /* Pattern bitmap (since PSP7) */ - PSP_DIB_PATTERN_TRANS_MASK, /* Pattern transparency mask (since PSP7) */ -} PSPDIBType; - -/* Type of image in the composite image bank block. (since PSP6) - */ -typedef enum { - PSP_IMAGE_COMPOSITE = 0, /* Composite Image */ - PSP_IMAGE_THUMBNAIL, /* Thumbnail Image */ -} PSPCompositeImageType; - -/* Graphic contents flags. (since PSP6) - */ -typedef enum { - /* Layer types */ - keGCRasterLayers = 0x00000001, /* At least one raster layer */ - keGCVectorLayers = 0x00000002, /* At least one vector layer */ - keGCAdjustmentLayers = 0x00000004, /* At least one adjustment layer */ - - /* Additional attributes */ - keGCThumbnail = 0x01000000, /* Has a thumbnail */ - keGCThumbnailTransparency = 0x02000000, /* Thumbnail transp. */ - keGCComposite = 0x04000000, /* Has a composite image */ - keGCCompositeTransparency = 0x08000000, /* Composite transp. */ - keGCFlatImage = 0x10000000, /* Just a background */ - keGCSelection = 0x20000000, /* Has a selection */ - keGCFloatingSelectionLayer = 0x40000000, /* Has float. selection */ - keGCAlphaChannels = 0x80000000, /* Has alpha channel(s) */ -} PSPGraphicContents; - -/* Character style flags. (since PSP6) - */ -typedef enum { - keStyleItalic = 0x00000001, /* Italic property bit */ - keStyleStruck = 0x00000002, /* Strikeout property bit */ - keStyleUnderlined = 0x00000004, /* Underlined property bit */ - keStyleWarped = 0x00000008, /* Warped property bit (since PSP8) */ - keStyleAntiAliased = 0x00000010, /* Antialiased property bit (since PSP8) */ -} PSPCharacterProperties; - -/* Table type. (since PSP7) - */ -typedef enum { - keTTUndefined = 0, /* Undefined table type */ - keTTGradientTable, /* Gradient table type */ - keTTPaperTable, /* Paper table type */ - keTTPatternTable /* Pattern table type */ -} PSPTableType; - -/* Layer flags. (since PSP6) - */ -typedef enum { - keVisibleFlag = 0x00000001, /* Layer is visible */ - keMaskPresenceFlag = 0x00000002, /* Layer has a mask */ -} PSPLayerProperties; - -/* Shape property flags. (since PSP6) - */ -typedef enum { - keShapeAntiAliased = 0x00000001, /* Shape is antialiased */ - keShapeSelected = 0x00000002, /* Shape is selected */ - keShapeVisible = 0x00000004, /* Shape is visible */ -} PSPShapeProperties; - -/* Polyline node type flags. (since PSP7) - */ -typedef enum { - keNodeUnconstrained = 0x0000, /* Default node type */ - keNodeSmooth = 0x0001, /* Node is smooth */ - keNodeSymmetric = 0x0002, /* Node is symmetric */ - keNodeAligned = 0x0004, /* Node is aligned */ - keNodeActive = 0x0008, /* Node is active */ - keNodeLocked = 0x0010, /* Node is locked */ - keNodeSelected = 0x0020, /* Node is selected */ - keNodeVisible = 0x0040, /* Node is visible */ - keNodeClosed = 0x0080, /* Node is closed */ - - /* TODO: This might be a thinko in the spec document only or in the image - * format itself. Need to investigate that later - */ - keNodeLockedPSP6 = 0x0016, /* Node is locked */ - keNodeSelectedPSP6 = 0x0032, /* Node is selected */ - keNodeVisiblePSP6 = 0x0064, /* Node is visible */ - keNodeClosedPSP6 = 0x0128, /* Node is closed */ - -} PSPPolylineNodeTypes; - -/* Blend modes. (since PSP6) - */ -typedef enum { - PSP_BLEND_NORMAL, - PSP_BLEND_DARKEN, - PSP_BLEND_LIGHTEN, - PSP_BLEND_HUE, - PSP_BLEND_SATURATION, - PSP_BLEND_COLOR, - PSP_BLEND_LUMINOSITY, - PSP_BLEND_MULTIPLY, - PSP_BLEND_SCREEN, - PSP_BLEND_DISSOLVE, - PSP_BLEND_OVERLAY, - PSP_BLEND_HARD_LIGHT, - PSP_BLEND_SOFT_LIGHT, - PSP_BLEND_DIFFERENCE, - PSP_BLEND_DODGE, - PSP_BLEND_BURN, - PSP_BLEND_EXCLUSION, - PSP_BLEND_TRUE_HUE, /* since PSP8 */ - PSP_BLEND_TRUE_SATURATION, /* since PSP8 */ - PSP_BLEND_TRUE_COLOR, /* since PSP8 */ - PSP_BLEND_TRUE_LIGHTNESS, /* since PSP8 */ - PSP_BLEND_ADJUST = 255, -} PSPBlendModes; - -/* Adjustment layer types. (since PSP6) - */ -typedef enum { - keAdjNone = 0, /* Undefined adjustment layer type */ - keAdjLevel, /* Level adjustment */ - keAdjCurve, /* Curve adjustment */ - keAdjBrightContrast, /* Brightnesscontrast adjustment */ - keAdjColorBal, /* Color balance adjustment */ - keAdjHSL, /* HSL adjustment */ - keAdjChannelMixer, /* Channel mixer adjustment */ - keAdjInvert, /* Invert adjustment */ - keAdjThreshold, /* Threshold adjustment */ - keAdjPoster /* Posterize adjustment */ -} PSPAdjustmentLayerType; - -/* Vector shape types. (since PSP6) - */ -typedef enum { - keVSTUnknown = 0, /* Undefined vector type */ - keVSTText, /* Shape represents lines of text */ - keVSTPolyline, /* Shape represents a multiple segment line */ - keVSTEllipse, /* Shape represents an ellipse (or circle) */ - keVSTPolygon, /* Shape represents a closed polygon */ - keVSTGroup, /* Shape represents a group shape (since PSP7) */ -} PSPVectorShapeType; - -/* Text element types. (since PSP6) - */ -typedef enum { - keTextElemUnknown = 0, /* Undefined text element type */ - keTextElemChar, /* A single character code */ - keTextElemCharStyle, /* A character style change */ - keTextElemLineStyle /* A line style change */ -} PSPTextElementType; - -/* Text alignment types. (since PSP6) - */ -typedef enum { - keTextAlignmentLeft = 0, /* Left text alignment */ - keTextAlignmentCenter, /* Center text alignment */ - keTextAlignmentRight /* Right text alignment */ -} PSPTextAlignment; - -/* Paint style types. (since PSP6) - */ -typedef enum { - keStyleNone = 0x0000, /* No paint style info applies */ - keStyleColor = 0x0001, /* Color paint style info */ - keStyleGradient = 0x0002, /* Gradient paint style info */ - keStylePattern = 0x0004, /* Pattern paint style info (since PSP7) */ - keStylePaper = 0x0008, /* Paper paint style info (since PSP7) */ - keStylePen = 0x0010, /* Organic pen paint style info (since PSP7) */ -} PSPPaintStyleType; - -/* Gradient type. (since PSP7) - */ -typedef enum { - keSGTLinear = 0, /* Linera gradient type */ - keSGTRadial, /* Radial gradient type */ - keSGTRectangular, /* Rectangulat gradient type */ - keSGTSunburst /* Sunburst gradient type */ -} PSPStyleGradientType; - -/* Paint Style Cap Type (Start & End). (since PSP7) - */ -typedef enum { - keSCTCapFlat = 0, /* Flat cap type (was round in psp6) */ - keSCTCapRound, /* Round cap type (was square in psp6) */ - keSCTCapSquare, /* Square cap type (was flat in psp6) */ - keSCTCapArrow, /* Arrow cap type */ - keSCTCapCadArrow, /* Cad arrow cap type */ - keSCTCapCurvedTipArrow, /* Curved tip arrow cap type */ - keSCTCapRingBaseArrow, /* Ring base arrow cap type */ - keSCTCapFluerDelis, /* Fluer deLis cap type */ - keSCTCapFootball, /* Football cap type */ - keSCTCapXr71Arrow, /* Xr71 arrow cap type */ - keSCTCapLilly, /* Lilly cap type */ - keSCTCapPinapple, /* Pinapple cap type */ - keSCTCapBall, /* Ball cap type */ - keSCTCapTulip /* Tulip cap type */ -} PSPStyleCapType; - -/* Paint Style Join Type. (since PSP7) - */ -typedef enum { - keSJTJoinMiter = 0, - keSJTJoinRound, - keSJTJoinBevel -} PSPStyleJoinType; - -/* Organic pen type. (since PSP7) - */ -typedef enum { - keSPTOrganicPenNone = 0, /* Undefined pen type */ - keSPTOrganicPenMesh, /* Mesh pen type */ - keSPTOrganicPenSand, /* Sand pen type */ - keSPTOrganicPenCurlicues, /* Curlicues pen type */ - keSPTOrganicPenRays, /* Rays pen type */ - keSPTOrganicPenRipple, /* Ripple pen type */ - keSPTOrganicPenWave, /* Wave pen type */ - keSPTOrganicPen /* Generic pen type */ -} PSPStylePenType; - - -/* Channel types. - */ -typedef enum { - PSP_CHANNEL_COMPOSITE = 0, /* Channel of single channel bitmap */ - PSP_CHANNEL_RED, /* Red channel of 24 bit bitmap */ - PSP_CHANNEL_GREEN, /* Green channel of 24 bit bitmap */ - PSP_CHANNEL_BLUE /* Blue channel of 24 bit bitmap */ -} PSPChannelType; - -/* Possible metrics used to measure resolution. - */ -typedef enum { - PSP_METRIC_UNDEFINED = 0, /* Metric unknown */ - PSP_METRIC_INCH, /* Resolution is in inches */ - PSP_METRIC_CM /* Resolution is in centimeters */ -} PSP_METRIC; - -/* Possible types of compression. - */ -typedef enum { - PSP_COMP_NONE = 0, /* No compression */ - PSP_COMP_RLE, /* RLE compression */ - PSP_COMP_LZ77, /* LZ77 compression */ - PSP_COMP_JPEG /* JPEG compression (only used by thumbnail and composite image) (since PSP6) */ -} PSPCompression; - -/* Picture tube placement mode. - */ -typedef enum { - tpmRandom, /* Place tube images in random intervals */ - tpmConstant /* Place tube images in constant intervals */ -} TubePlacementMode; - -/* Picture tube selection mode. - */ -typedef enum { - tsmRandom, /* Randomly select the next image in */ - /* tube to display */ - tsmIncremental, /* Select each tube image in turn */ - tsmAngular, /* Select image based on cursor direction */ - tsmPressure, /* Select image based on pressure */ - /* (from pressure-sensitive pad) */ - tsmVelocity /* Select image based on cursor speed */ -} TubeSelectionMode; - -/* Extended data field types. - */ -typedef enum { - PSP_XDATA_TRNS_INDEX = 0, /* Transparency index field */ - PSP_XDATA_GRID, /* Image grid information (since PSP7) */ - PSP_XDATA_GUIDE, /* Image guide information (since PSP7) */ - PSP_XDATA_EXIF, /* Image EXIF information (since PSP8) */ -} PSPExtendedDataID; - -/* Creator field types. - */ -typedef enum { - PSP_CRTR_FLD_TITLE = 0, /* Image document title field */ - PSP_CRTR_FLD_CRT_DATE, /* Creation date field */ - PSP_CRTR_FLD_MOD_DATE, /* Modification date field */ - PSP_CRTR_FLD_ARTIST, /* Artist name field */ - PSP_CRTR_FLD_CPYRGHT, /* Copyright holder name field */ - PSP_CRTR_FLD_DESC, /* Image document description field */ - PSP_CRTR_FLD_APP_ID, /* Creating app id field */ - PSP_CRTR_FLD_APP_VER /* Creating app version field */ -} PSPCreatorFieldID; - -/* Grid units type. (since PSP7) - */ -typedef enum { - keGridUnitsPixels = 0, /* Grid units is pixels */ - keGridUnitsInches, /* Grid units is inches */ - keGridUnitsCentimeters /* Grid units is centimeters */ -} PSPGridUnitsType; - -/* Guide orientation type. (since PSP7) - */ -typedef enum { - keHorizontalGuide = 0, - keVerticalGuide -} PSPGuideOrientationType; - -/* Creator application identifiers. - */ -typedef enum { - PSP_CREATOR_APP_UNKNOWN = 0, /* Creator application unknown */ - PSP_CREATOR_APP_PAINT_SHOP_PRO /* Creator is Paint Shop Pro */ -} PSPCreatorAppID; - -/* Layer types. - */ -typedef enum { - PSP_LAYER_NORMAL = 0, /* Normal layer */ - PSP_LAYER_FLOATING_SELECTION /* Floating selection layer */ -} PSPLayerTypePSP5; - -/* Layer types. (since PSP6) - */ -typedef enum { - keGLTUndefined = 0, /* Undefined layer type */ - keGLTRaster, /* Standard raster layer */ - keGLTFloatingRasterSelection, /* Floating selection (raster layer) */ - keGLTVector, /* Vector layer */ - keGLTAdjustment, /* Adjustment layer */ - keGLTMask /* Mask layer (since PSP8) */ -} PSPLayerTypePSP6; - - -/* Truth values. - */ -#if 0 /* FALSE and TRUE taken by GLib */ -typedef enum { - FALSE = 0, - TRUE -} PSP_BOOLEAN; -#else -typedef gboolean PSP_BOOLEAN; -#endif - -/* End of cut&paste from psp spec */ - -/* We store the various PSP data in own structures. - * We cannot use structs intended to be direct copies of the file block - * headers because of struct alignment issues. - */ -typedef struct -{ - guint32 width, height; - gdouble resolution; - guchar metric; - guint16 compression; - guint16 depth; - guchar greyscale; - guint32 active_layer; - guint16 layer_count; -} PSPimage; - -/* Declare some local functions. - */ -static void query (void); -static void run (const gchar *name, - gint nparams, - const GimpParam *param, - gint *nreturn_vals, - GimpParam **return_vals); -static gint32 load_image (const gchar *filename, - GError **error); -static gint save_image (const gchar *filename, - gint32 image_ID, - gint32 drawable_ID, - GError **error); - -/* Various local variables... - */ -const GimpPlugInInfo PLUG_IN_INFO = -{ - NULL, /* init_proc */ - NULL, /* quit_proc */ - query, /* query_proc */ - run, /* run_proc */ -}; - -/* Save info */ -typedef struct -{ - PSPCompression compression; -} PSPSaveVals; - -static PSPSaveVals psvals = -{ - PSP_COMP_LZ77 -}; - -static guint16 psp_ver_major, psp_ver_minor; - - -MAIN () - -static void -query (void) -{ - static const GimpParamDef load_args[] = - { - { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" }, - { GIMP_PDB_STRING, "filename", "The name of the file to load" }, - { GIMP_PDB_STRING, "raw-filename", "The name of the file to load" } - }; - static const GimpParamDef load_return_vals[] = - { - { GIMP_PDB_IMAGE, "image", "Output image" } - }; - -#if 0 - static const GimpParamDef save_args[] = - { - { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" }, - { GIMP_PDB_IMAGE, "image", "Input image" }, - { GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" }, - { GIMP_PDB_STRING, "filename", "The name of the file to save the image in" }, - { GIMP_PDB_STRING, "raw-filename", "The name of the file to save the image in" }, - { GIMP_PDB_INT32, "compression", "Specify 0 for no compression, 1 for RLE, and 2 for LZ77" } - }; -#endif - - gimp_install_procedure (LOAD_PROC, - "loads images from the Paint Shop Pro PSP file format", - "This plug-in loads and saves images in " - "Paint Shop Pro's native PSP format. " - "Vector layers aren't handled. Saving isn't " - "yet implemented.", - "Tor Lillqvist", - "Tor Lillqvist", - "1999", - N_("Paint Shop Pro image"), - NULL, - GIMP_PLUGIN, - G_N_ELEMENTS (load_args), - G_N_ELEMENTS (load_return_vals), - load_args, load_return_vals); - - gimp_register_file_handler_mime (LOAD_PROC, "image/x-psp"); - gimp_register_magic_load_handler (LOAD_PROC, - "psp,tub,pspimage", - "", - "0,string,Paint\\040Shop\\040Pro\\040Image\\040File\n\032"); - - /* commented out until saving is implemented */ -#if 0 - gimp_install_procedure (SAVE_PROC, - "saves images in the Paint Shop Pro PSP file format", - "This plug-in loads and saves images in " - "Paint Shop Pro's native PSP format. " - "Vector layers aren't handled. Saving isn't " - "yet implemented.", - "Tor Lillqvist", - "Tor Lillqvist", - "1999", - N_("Paint Shop Pro image"), - "RGB*, GRAY*, INDEXED*", - GIMP_PLUGIN, - G_N_ELEMENTS (save_args), 0, - save_args, NULL); - - gimp_register_save_handler (SAVE_PROC, "psp,tub", ""); -#endif -} - -static gboolean -save_dialog (void) -{ - GtkWidget *dialog; - GtkWidget *frame; - gint run; - - dialog = gimp_export_dialog_new (_("PSP"), PLUG_IN_BINARY, SAVE_PROC); - - /* file save type */ - frame = gimp_int_radio_group_new (TRUE, _("Data Compression"), - G_CALLBACK (gimp_radio_button_update), - &psvals.compression, psvals.compression, - - C_("compression", "None"), PSP_COMP_NONE, NULL, - _("RLE"), PSP_COMP_RLE, NULL, - _("LZ77"), PSP_COMP_LZ77, NULL, - - NULL); - - gtk_container_set_border_width (GTK_CONTAINER (frame), 12); - gtk_box_pack_start (GTK_BOX (gimp_export_dialog_get_content_area (dialog)), - frame, FALSE, TRUE, 0); - gtk_widget_show (frame); - - gtk_widget_show (dialog); - - run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK); - - gtk_widget_destroy (dialog); - - return run; -} - -/* This helper method is used to get the name of the block for the known block - * types. The enum PSPBlockID must cover the input values. - */ -static const gchar * -block_name (gint id) -{ - static const gchar *block_names[] = - { - "IMAGE", - "CREATOR", - "COLOR", - "LAYER_START", - "LAYER", - "CHANNEL", - "SELECTION", - "ALPHA_BANK", - "ALPHA_CHANNEL", - "THUMBNAIL", - "EXTENDED_DATA", - "TUBE", - "ADJUSTMENT_EXTENSION", - "VECTOR_EXTENSION_BLOCK", - "SHAPE_BLOCK", - "PAINTSTYLE_BLOCK", - "COMPOSITE_IMAGE_BANK_BLOCK", - "COMPOSITE_ATTRIBUTES_BLOCK", - "JPEG_BLOCK", - }; - static gchar *err_name = NULL; - - if (id >= 0 && id <= PSP_JPEG_BLOCK) - return block_names[id]; - - g_free (err_name); - err_name = g_strdup_printf ("id=%d", id); - - return err_name; -} - -/* This helper method is used during loading. It verifies the block we are - * reading has a valid header. Fills the variables init_len and total_len - */ -static gint -read_block_header (FILE *f, - guint32 *init_len, - guint32 *total_len) -{ - guchar buf[4]; - guint16 id; - long header_start; - guint32 len; - - IFDBG(3) header_start = ftell (f); - - if (fread (buf, 4, 1, f) < 1 - || fread (&id, 2, 1, f) < 1 - || fread (&len, 4, 1, f) < 1 - || (psp_ver_major < 4 && fread (total_len, 4, 1, f) < 1)) - { - g_message ("Error reading block header"); - return -1; - } - if (memcmp (buf, "~BK\0", 4) != 0) - { - IFDBG(3) - g_message ("Invalid block header at %ld", header_start); - else - g_message ("Invalid block header"); - return -1; - } - - IFDBG(3) g_message ("%s at %ld", block_name (id), header_start); - - if (psp_ver_major < 4) - { - *init_len = GUINT32_FROM_LE (len); - *total_len = GUINT32_FROM_LE (*total_len); - } - else - { - /* Version 4.0 seems to have dropped the initial data chunk length - * field. - */ - *init_len = 0xDEADBEEF; /* Intentionally bogus, should not be used */ - *total_len = GUINT32_FROM_LE (len); - } - - return GUINT16_FROM_LE (id); -} - -/* Read the PSP_IMAGE_BLOCK */ -static gint -read_general_image_attribute_block (FILE *f, - guint init_len, - guint total_len, - PSPimage *ia) -{ - gchar buf[6]; - guint64 res; - gchar graphics_content[4]; - - if (init_len < 38 || total_len < 38) - { - g_message ("Invalid general image attribute chunk size"); - return -1; - } - - if (psp_ver_major >= 4) - { - /* TODO: This causes the chunk size to be ignored. Better verify if it is - * valid since it might create read offset problems with the - * "expansion field" (which follows after the "graphics content" and - * is of unkown size). - */ - fseek (f, 4, SEEK_CUR); - } - - if (fread (&ia->width, 4, 1, f) < 1 - || fread (&ia->height, 4, 1, f) < 1 - || fread (&res, 8, 1, f) < 1 - || fread (&ia->metric, 1, 1, f) < 1 - || fread (&ia->compression, 2, 1, f) < 1 - || fread (&ia->depth, 2, 1, f) < 1 - || fread (buf, 2+4, 1, f) < 1 /* Skip plane and colour count */ - || fread (&ia->greyscale, 1, 1, f) < 1 - || fread (buf, 4, 1, f) < 1 /* Skip total image size */ - || fread (&ia->active_layer, 4, 1, f) < 1 - || fread (&ia->layer_count, 2, 1, f) < 1 - || (psp_ver_major >= 4 && fread (graphics_content, 4, 1, f) < 1)) - { - g_message ("Error reading general image attribute block"); - return -1; - } - ia->width = GUINT32_FROM_LE (ia->width); - ia->height = GUINT32_FROM_LE (ia->height); - - res = GUINT64_FROM_LE (res); - memcpy (&ia->resolution, &res, 8); - if (ia->metric == PSP_METRIC_CM) - ia->resolution /= 2.54; - - ia->compression = GUINT16_FROM_LE (ia->compression); - if (ia->compression > PSP_COMP_LZ77) - { - g_message ("Unknown compression type %d", ia->compression); - return -1; - } - - ia->depth = GUINT16_FROM_LE (ia->depth); - if (ia->depth != 24) - { - g_message ("Unsupported bit depth %d", ia->depth); - return -1; - } - - ia->active_layer = GUINT32_FROM_LE (ia->active_layer); - ia->layer_count = GUINT16_FROM_LE (ia->layer_count); - - return 0; -} - -static gint -try_fseek (FILE *f, - glong pos, - gint whence) -{ - if (fseek (f, pos, whence) < 0) - { - g_message ("Seek error: %s", g_strerror (errno)); - fclose (f); - return -1; - } - return 0; -} - - - -static gint -read_creator_block (FILE *f, - gint image_ID, - guint total_len, - PSPimage *ia) -{ - long data_start; - guchar buf[4]; - guint16 keyword; - guint32 length; - gchar *string; - gchar *title = NULL, *artist = NULL, *copyright = NULL, *description = NULL; - guint32 dword; - guint32 cdate = 0, mdate = 0, appid, appver; - GString *comment; - GimpParasite *comment_parasite; - - data_start = ftell (f); - comment = g_string_new (NULL); - - while (ftell (f) < data_start + total_len) - { - if (fread (buf, 4, 1, f) < 1 - || fread (&keyword, 2, 1, f) < 1 - || fread (&length, 4, 1, f) < 1) - { - g_message ("Error reading creator keyword chunk"); - return -1; - } - if (memcmp (buf, "~FL\0", 4) != 0) - { - g_message ("Invalid keyword chunk header"); - return -1; - } - keyword = GUINT16_FROM_LE (keyword); - length = GUINT32_FROM_LE (length); - switch (keyword) - { - case PSP_CRTR_FLD_TITLE: - case PSP_CRTR_FLD_ARTIST: - case PSP_CRTR_FLD_CPYRGHT: - case PSP_CRTR_FLD_DESC: - string = g_malloc (length + 1); - if (fread (string, length, 1, f) < 1) - { - g_message ("Error reading creator keyword data"); - g_free (string); - return -1; - } - switch (keyword) - { - case PSP_CRTR_FLD_TITLE: - g_free (title); title = string; break; - case PSP_CRTR_FLD_ARTIST: - g_free (artist); artist = string; break; - case PSP_CRTR_FLD_CPYRGHT: - g_free (copyright); copyright = string; break; - case PSP_CRTR_FLD_DESC: - g_free (description); description = string; break; - default: - g_free (string); - } - break; - case PSP_CRTR_FLD_CRT_DATE: - case PSP_CRTR_FLD_MOD_DATE: - case PSP_CRTR_FLD_APP_ID: - case PSP_CRTR_FLD_APP_VER: - if (fread (&dword, 4, 1, f) < 1) - { - g_message ("Error reading creator keyword data"); - return -1; - } - switch (keyword) - { - case PSP_CRTR_FLD_CRT_DATE: - cdate = dword; break; - case PSP_CRTR_FLD_MOD_DATE: - mdate = dword; break; - case PSP_CRTR_FLD_APP_ID: - appid = dword; break; - case PSP_CRTR_FLD_APP_VER: - appver = dword; break; - } - break; - default: - if (try_fseek (f, length, SEEK_CUR) < 0) - { - return -1; - } - break; - } - } - - if (title) - { - g_string_append (comment, title); - g_free (title); - g_string_append (comment, "\n"); - } - if (artist) - { - g_string_append (comment, artist); - g_free (artist); - g_string_append (comment, "\n"); - } - if (copyright) - { - g_string_append (comment, "Copyright "); - g_string_append (comment, copyright); - g_free (copyright); - g_string_append (comment, "\n"); - } - if (description) - { - g_string_append (comment, description); - g_free (description); - g_string_append (comment, "\n"); - } - if (comment->len > 0) - { - comment_parasite = gimp_parasite_new ("gimp-comment", - GIMP_PARASITE_PERSISTENT, - strlen (comment->str) + 1, - comment->str); - gimp_image_attach_parasite (image_ID, comment_parasite); - gimp_parasite_free (comment_parasite); - } - - g_string_free (comment, FALSE); - - return 0; -} - -static void inline -swab_rect (guint32 *rect) -{ - rect[0] = GUINT32_FROM_LE (rect[0]); - rect[1] = GUINT32_FROM_LE (rect[1]); - rect[2] = GUINT32_FROM_LE (rect[2]); - rect[3] = GUINT32_FROM_LE (rect[3]); -} - -static GimpLayerModeEffects -gimp_layer_mode_from_psp_blend_mode (PSPBlendModes mode) -{ - switch (mode) - { - case PSP_BLEND_NORMAL: - return GIMP_NORMAL_MODE; - case PSP_BLEND_DARKEN: - return GIMP_DARKEN_ONLY_MODE; - case PSP_BLEND_LIGHTEN: - return GIMP_LIGHTEN_ONLY_MODE; - case PSP_BLEND_HUE: - return GIMP_HUE_MODE; - case PSP_BLEND_SATURATION: - return GIMP_SATURATION_MODE; - case PSP_BLEND_COLOR: - return GIMP_COLOR_MODE; - case PSP_BLEND_LUMINOSITY: - return GIMP_VALUE_MODE; /* ??? */ - case PSP_BLEND_MULTIPLY: - return GIMP_MULTIPLY_MODE; - case PSP_BLEND_SCREEN: - return GIMP_SCREEN_MODE; - case PSP_BLEND_DISSOLVE: - return GIMP_DISSOLVE_MODE; - case PSP_BLEND_OVERLAY: - return GIMP_OVERLAY_MODE; - case PSP_BLEND_HARD_LIGHT: - return GIMP_HARDLIGHT_MODE; - case PSP_BLEND_SOFT_LIGHT: - return GIMP_SOFTLIGHT_MODE; - case PSP_BLEND_DIFFERENCE: - return GIMP_DIFFERENCE_MODE; - case PSP_BLEND_DODGE: - return GIMP_DODGE_MODE; - case PSP_BLEND_BURN: - return GIMP_BURN_MODE; - case PSP_BLEND_EXCLUSION: - return -1; /* ??? */ - case PSP_BLEND_ADJUST: - return -1; /* ??? */ - case PSP_BLEND_TRUE_HUE: - return -1; /* ??? */ - case PSP_BLEND_TRUE_SATURATION: - return -1; /* ??? */ - case PSP_BLEND_TRUE_COLOR: - return -1; /* ??? */ - case PSP_BLEND_TRUE_LIGHTNESS: - return -1; /* ??? */ - } - return -1; -} - -static const gchar * -blend_mode_name (PSPBlendModes mode) -{ - static const gchar *blend_mode_names[] = - { - "NORMAL", - "DARKEN", - "LIGHTEN", - "HUE", - "SATURATION", - "COLOR", - "LUMINOSITY", - "MULTIPLY", - "SCREEN", - "DISSOLVE", - "OVERLAY", - "HARD_LIGHT", - "SOFT_LIGHT", - "DIFFERENCE", - "DODGE", - "BURN", - "EXCLUSION" - }; - static gchar *err_name = NULL; - - /* TODO: what about PSP_BLEND_ADJUST? */ - if (mode >= 0 && mode <= PSP_BLEND_EXCLUSION) - return blend_mode_names[mode]; - - g_free (err_name); - err_name = g_strdup_printf ("unknown layer blend mode %d", mode); - - return err_name; -} - -static const gchar * -bitmap_type_name (gint type) -{ - static const gchar *bitmap_type_names[] = - { - "IMAGE", - "TRANS_MASK", - "USER_MASK", - "SELECTION", - "ALPHA_MASK", - "THUMBNAIL" - }; - static gchar *err_name = NULL; - - if (type >= 0 && type <= PSP_DIB_THUMBNAIL) - return bitmap_type_names[type]; - - g_free (err_name); - err_name = g_strdup_printf ("unknown bitmap type %d", type); - - return err_name; -} - -static const gchar * -channel_type_name (gint type) -{ - static const gchar *channel_type_names[] = - { - "COMPOSITE", - "RED", - "GREEN", - "BLUE" - }; - static gchar *err_name = NULL; - - if (type >= 0 && type <= PSP_CHANNEL_BLUE) - return channel_type_names[type]; - - g_free (err_name); - err_name = g_strdup_printf ("unknown channel type %d", type); - - return err_name; -} - -static void * -psp_zalloc (void *opaque, - guint items, - guint size) -{ - return g_malloc (items*size); -} - -static void -psp_zfree (void *opaque, - void *ptr) -{ - g_free (ptr); -} - -static int -read_channel_data (FILE *f, - PSPimage *ia, - guchar **pixels, - guint bytespp, - guint offset, - GimpDrawable *drawable, - guint32 compressed_len) -{ - gint i, y, width = drawable->width, height = drawable->height; - gint npixels = width * height; - guchar *buf; - guchar *buf2 = NULL; /* please the compiler */ - guchar runcount, byte; - z_stream zstream; - - switch (ia->compression) - { - case PSP_COMP_NONE: - if (bytespp == 1) - { - if ((width % 4) == 0) - fread (pixels[0], height * width, 1, f); - else - { - for (y = 0; y < height; y++) - { - fread (pixels[y], width, 1, f); - fseek (f, 4 - (width % 4), SEEK_CUR); - } - } - } - else - { - buf = g_malloc (width); - for (y = 0; y < height; y++) - { - guchar *p, *q; - - fread (buf, width, 1, f); - if (width % 4) - fseek (f, 4 - (width % 4), SEEK_CUR); - p = buf; - q = pixels[y] + offset; - for (i = 0; i < width; i++) - { - *q = *p++; - q += bytespp; - } - } - g_free (buf); - } - break; - - case PSP_COMP_RLE: - { - guchar *q, *endq; - - q = pixels[0] + offset; - endq = q + npixels * bytespp; - buf = g_malloc (127); - while (q < endq) - { - fread (&runcount, 1, 1, f); - if (runcount > 128) - { - runcount -= 128; - fread (&byte, 1, 1, f); - memset (buf, byte, runcount); - } - else - fread (buf, runcount, 1, f); - - /* prevent buffer overflow for bogus data */ - runcount = MIN (runcount, (endq - q) / bytespp); - - if (bytespp == 1) - { - memmove (q, buf, runcount); - q += runcount; - } - else - { - guchar *p = buf; - - for (i = 0; i < runcount; i++) - { - *q = *p++; - q += bytespp; - } - } - } - g_free (buf); - } - break; - - case PSP_COMP_LZ77: - buf = g_malloc (compressed_len); - fread (buf, compressed_len, 1, f); - zstream.next_in = buf; - zstream.avail_in = compressed_len; - zstream.zalloc = psp_zalloc; - zstream.zfree = psp_zfree; - zstream.opaque = f; - if (inflateInit (&zstream) != Z_OK) - { - g_message ("zlib error"); - return -1; - } - if (bytespp == 1) - zstream.next_out = pixels[0]; - else - { - buf2 = g_malloc (npixels); - zstream.next_out = buf2; - } - zstream.avail_out = npixels; - if (inflate (&zstream, Z_FINISH) != Z_STREAM_END) - { - g_message ("zlib error"); - inflateEnd (&zstream); - return -1; - } - inflateEnd (&zstream); - g_free (buf); - - if (bytespp > 1) - { - guchar *p, *q; - - p = buf2; - q = pixels[0] + offset; - for (i = 0; i < npixels; i++) - { - *q = *p++; - q += bytespp; - } - g_free (buf2); - } - break; - } - - return 0; -} - -static gint -read_layer_block (FILE *f, - gint image_ID, - guint total_len, - PSPimage *ia) -{ - gint i; - long block_start, sub_block_start, channel_start; - gint sub_id; - guint32 sub_init_len, sub_total_len; - gchar *name = NULL; - guint16 namelen; - guchar type, opacity, blend_mode, visibility, transparency_protected; - guchar link_group_id, mask_linked, mask_disabled; - guint32 image_rect[4], saved_image_rect[4], mask_rect[4], saved_mask_rect[4]; - gboolean null_layer = FALSE; - guint16 bitmap_count, channel_count; - GimpImageType drawable_type; - guint32 layer_ID = 0; - GimpLayerModeEffects layer_mode; - guint32 channel_init_len, channel_total_len; - guint32 compressed_len, uncompressed_len; - guint16 bitmap_type, channel_type; - gint width, height, bytespp, offset; - guchar **pixels, *pixel; - GimpDrawable *drawable; - GimpPixelRgn pixel_rgn; - - block_start = ftell (f); - - while (ftell (f) < block_start + total_len) - { - /* Read the layer sub-block header */ - sub_id = read_block_header (f, &sub_init_len, &sub_total_len); - if (sub_id == -1) - return -1; - - if (sub_id != PSP_LAYER_BLOCK) - { - g_message ("Invalid layer sub-block %s, should be LAYER", - block_name (sub_id)); - return -1; - } - - sub_block_start = ftell (f); - - /* Read layer information chunk */ - if (psp_ver_major >= 4) - { - if (fseek (f, 4, SEEK_CUR) < 0 - || fread (&namelen, 2, 1, f) < 1 - || ((namelen = GUINT16_FROM_LE (namelen)) && FALSE) - || (name = g_malloc (namelen + 1)) == NULL - || fread (name, namelen, 1, f) < 1 - || fread (&type, 1, 1, f) < 1 - || fread (&image_rect, 16, 1, f) < 1 - || fread (&saved_image_rect, 16, 1, f) < 1 - || fread (&opacity, 1, 1, f) < 1 - || fread (&blend_mode, 1, 1, f) < 1 - || fread (&visibility, 1, 1, f) < 1 - || fread (&transparency_protected, 1, 1, f) < 1 - || fread (&link_group_id, 1, 1, f) < 1 - || fread (&mask_rect, 16, 1, f) < 1 - || fread (&saved_mask_rect, 16, 1, f) < 1 - || fread (&mask_linked, 1, 1, f) < 1 - || fread (&mask_disabled, 1, 1, f) < 1 - || fseek (f, 47, SEEK_CUR) < 0 - || fread (&bitmap_count, 2, 1, f) < 1 - || fread (&channel_count, 2, 1, f) < 1) - { - g_message ("Error reading layer information chunk"); - g_free (name); - return -1; - } - - name[namelen] = 0; - type = PSP_LAYER_NORMAL; /* ??? */ - } - else - { - name = g_malloc (257); - name[256] = 0; - - if (fread (name, 256, 1, f) < 1 - || fread (&type, 1, 1, f) < 1 - || fread (&image_rect, 16, 1, f) < 1 - || fread (&saved_image_rect, 16, 1, f) < 1 - || fread (&opacity, 1, 1, f) < 1 - || fread (&blend_mode, 1, 1, f) < 1 - || fread (&visibility, 1, 1, f) < 1 - || fread (&transparency_protected, 1, 1, f) < 1 - || fread (&link_group_id, 1, 1, f) < 1 - || fread (&mask_rect, 16, 1, f) < 1 - || fread (&saved_mask_rect, 16, 1, f) < 1 - || fread (&mask_linked, 1, 1, f) < 1 - || fread (&mask_disabled, 1, 1, f) < 1 - || fseek (f, 43, SEEK_CUR) < 0 - || fread (&bitmap_count, 2, 1, f) < 1 - || fread (&channel_count, 2, 1, f) < 1) - { - g_message ("Error reading layer information chunk"); - g_free (name); - return -1; - } - } - - if (type == PSP_LAYER_FLOATING_SELECTION) - g_message ("Floating selection restored as normal layer"); - - swab_rect (image_rect); - swab_rect (saved_image_rect); - swab_rect (mask_rect); - swab_rect (saved_mask_rect); - bitmap_count = GUINT16_FROM_LE (bitmap_count); - channel_count = GUINT16_FROM_LE (channel_count); - - layer_mode = gimp_layer_mode_from_psp_blend_mode (blend_mode); - if ((int) layer_mode == -1) - { - g_message ("Unsupported PSP layer blend mode %s " - "for layer %s, setting layer invisible", - blend_mode_name (blend_mode), name); - layer_mode = GIMP_NORMAL_MODE; - visibility = FALSE; - } - - width = saved_image_rect[2] - saved_image_rect[0]; - height = saved_image_rect[3] - saved_image_rect[1]; - - if ((width < 0) || (width > GIMP_MAX_IMAGE_SIZE) /* w <= 2^18 */ - || (height < 0) || (height > GIMP_MAX_IMAGE_SIZE) /* h <= 2^18 */ - || ((width / 256) * (height / 256) >= 8192)) /* w * h < 2^29 */ - { - g_message ("Invalid layer dimensions: %dx%d", width, height); - return -1; - } - - IFDBG(2) g_message - ("layer: %s %dx%d (%dx%d) @%d,%d opacity %d blend_mode %s " - "%d bitmaps %d channels", - name, - image_rect[2] - image_rect[0], image_rect[3] - image_rect[1], - width, height, - saved_image_rect[0], saved_image_rect[1], - opacity, blend_mode_name (blend_mode), - bitmap_count, channel_count); - - IFDBG(2) g_message - ("mask %dx%d (%dx%d) @%d,%d", - mask_rect[2] - mask_rect[0], - mask_rect[3] - mask_rect[1], - saved_mask_rect[2] - saved_mask_rect[0], - saved_mask_rect[3] - saved_mask_rect[1], - saved_mask_rect[0], saved_mask_rect[1]); - - if (width == 0) - { - width++; - null_layer = TRUE; - } - if (height == 0) - { - height++; - null_layer = TRUE; - } - - if (ia->greyscale) - if (!null_layer && bitmap_count == 1) - drawable_type = GIMP_GRAY_IMAGE, bytespp = 1; - else - drawable_type = GIMP_GRAYA_IMAGE, bytespp = 1; - else - if (!null_layer && bitmap_count == 1) - drawable_type = GIMP_RGB_IMAGE, bytespp = 3; - else - drawable_type = GIMP_RGBA_IMAGE, bytespp = 4; - - layer_ID = gimp_layer_new (image_ID, name, - width, height, - drawable_type, - 100.0 * opacity / 255.0, - layer_mode); - if (layer_ID == -1) - { - g_message ("Error creating layer"); - return -1; - } - - g_free (name); - - gimp_image_insert_layer (image_ID, layer_ID, -1, -1); - - if (saved_image_rect[0] != 0 || saved_image_rect[1] != 0) - gimp_layer_set_offsets (layer_ID, - saved_image_rect[0], saved_image_rect[1]); - - if (!visibility) - gimp_item_set_visible (layer_ID, FALSE); - - gimp_layer_set_lock_alpha (layer_ID, transparency_protected); - - if (psp_ver_major < 4) - if (try_fseek (f, sub_block_start + sub_init_len, SEEK_SET) < 0) - { - return -1; - } - - pixel = g_malloc0 (height * width * bytespp); - if (null_layer) - { - pixels = NULL; - } - else - { - pixels = g_new (guchar *, height); - for (i = 0; i < height; i++) - pixels[i] = pixel + width * bytespp * i; - } - - drawable = gimp_drawable_get (layer_ID); - gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, - width, height, TRUE, FALSE); - - gimp_tile_cache_size (gimp_tile_height () * width * bytespp); - - /* Read the layer channel sub-blocks */ - while (ftell (f) < sub_block_start + sub_total_len) - { - sub_id = read_block_header (f, &channel_init_len, - &channel_total_len); - if (sub_id == -1) - { - gimp_image_delete (image_ID); - return -1; - } - - if (sub_id != PSP_CHANNEL_BLOCK) - { - g_message ("Invalid layer sub-block %s, should be CHANNEL", - block_name (sub_id)); - return -1; - } - - channel_start = ftell (f); - - if (psp_ver_major == 4) - fseek (f, 4, SEEK_CUR); /* Unknown field */ - - if (fread (&compressed_len, 4, 1, f) < 1 - || fread (&uncompressed_len, 4, 1, f) < 1 - || fread (&bitmap_type, 2, 1, f) < 1 - || fread (&channel_type, 2, 1, f) < 1) - { - g_message ("Error reading channel information chunk"); - return -1; - } - - compressed_len = GUINT32_FROM_LE (compressed_len); - uncompressed_len = GUINT32_FROM_LE (uncompressed_len); - bitmap_type = GUINT16_FROM_LE (bitmap_type); - channel_type = GUINT16_FROM_LE (channel_type); - - if (bitmap_type > PSP_DIB_USER_MASK) - { - g_message ("Invalid bitmap type %d in channel information chunk", - bitmap_type); - return -1; - } - - if (channel_type > PSP_CHANNEL_BLUE) - { - g_message ("Invalid channel type %d in channel information chunk", - channel_type); - return -1; - } - - IFDBG(2) g_message ("channel: %s %s %d (%d) bytes %d bytespp", - bitmap_type_name (bitmap_type), - channel_type_name (channel_type), - uncompressed_len, compressed_len, - bytespp); - - if (bitmap_type == PSP_DIB_TRANS_MASK) - offset = 3; - else - offset = channel_type - PSP_CHANNEL_RED; - - if (psp_ver_major < 4) - if (try_fseek (f, channel_start + channel_init_len, SEEK_SET) < 0) - { - return -1; - } - - if (!null_layer) - if (read_channel_data (f, ia, pixels, bytespp, - offset, drawable, compressed_len) == -1) - { - return -1; - } - - if (try_fseek (f, channel_start + channel_total_len, SEEK_SET) < 0) - { - return -1; - } - } - - gimp_pixel_rgn_set_rect (&pixel_rgn, pixel, 0, 0, width, height); - - gimp_drawable_flush (drawable); - gimp_drawable_detach (drawable); - - g_free (pixels); - g_free (pixel); - } - - if (try_fseek (f, block_start + total_len, SEEK_SET) < 0) - { - return -1; - } - - return layer_ID; -} - -static gint -read_tube_block (FILE *f, - gint image_ID, - guint total_len, - PSPimage *ia) -{ - guint16 version; - guchar name[514]; - guint32 step_size, column_count, row_count, cell_count; - guint32 placement_mode, selection_mode; - gint i; - GimpPixPipeParams params; - GimpParasite *pipe_parasite; - gchar *parasite_text; - - gimp_pixpipe_params_init (¶ms); - - if (fread (&version, 2, 1, f) < 1 - || fread (name, 513, 1, f) < 1 - || fread (&step_size, 4, 1, f) < 1 - || fread (&column_count, 4, 1, f) < 1 - || fread (&row_count, 4, 1, f) < 1 - || fread (&cell_count, 4, 1, f) < 1 - || fread (&placement_mode, 4, 1, f) < 1 - || fread (&selection_mode, 4, 1, f) < 1) - { - g_message ("Error reading tube data chunk"); - return -1; - } - - name[513] = 0; - version = GUINT16_FROM_LE (version); - params.step = GUINT32_FROM_LE (step_size); - params.cols = GUINT32_FROM_LE (column_count); - params.rows = GUINT32_FROM_LE (row_count); - params.ncells = GUINT32_FROM_LE (cell_count); - placement_mode = GUINT32_FROM_LE (placement_mode); - selection_mode = GUINT32_FROM_LE (selection_mode); - - for (i = 1; i < params.cols; i++) - gimp_image_add_vguide (image_ID, (ia->width * i)/params.cols); - for (i = 1; i < params.rows; i++) - gimp_image_add_hguide (image_ID, (ia->height * i)/params.rows); - - /* We use a parasite to pass in the tube (pipe) parameters in - * case we will have any use of those, for instance in the gpb - * plug-in that saves a GIMP image pipe. - */ - params.dim = 1; - params.cellwidth = ia->width / params.cols; - params.cellheight = ia->height / params.rows; - params.placement = (placement_mode == tpmRandom ? "random" : - (placement_mode == tpmConstant ? "constant" : - "default")); - params.rank[0] = params.ncells; - params.selection[0] = (selection_mode == tsmRandom ? "random" : - (selection_mode == tsmIncremental ? "incremental" : - (selection_mode == tsmAngular ? "angular" : - (selection_mode == tsmPressure ? "pressure" : - (selection_mode == tsmVelocity ? "velocity" : - "default"))))); - parasite_text = gimp_pixpipe_params_build (¶ms); - - IFDBG(2) g_message ("parasite: %s", parasite_text); - - pipe_parasite = gimp_parasite_new ("gimp-brush-pipe-parameters", - GIMP_PARASITE_PERSISTENT, - strlen (parasite_text) + 1, parasite_text); - gimp_image_attach_parasite (image_ID, pipe_parasite); - gimp_parasite_free (pipe_parasite); - g_free (parasite_text); - - return 0; -} - -static const gchar * -compression_name (gint compression) -{ - switch (compression) - { - case PSP_COMP_NONE: - return "no compression"; - case PSP_COMP_RLE: - return "RLE"; - case PSP_COMP_LZ77: - return "LZ77"; - } - g_assert_not_reached (); - - return NULL; -} - -/* The main function for loading PSP-images - */ -static gint32 -load_image (const gchar *filename, - GError **error) -{ - FILE *f; - struct stat st; - char buf[32]; - PSPimage ia; - guint32 block_init_len, block_total_len; - long block_start; - PSPBlockID id = -1; - gint block_number; - - gint32 image_ID = -1; - - if (g_stat (filename, &st) == -1) - return -1; - - f = g_fopen (filename, "rb"); - if (f == NULL) - { - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), - _("Could not open '%s' for reading: %s"), - gimp_filename_to_utf8 (filename), g_strerror (errno)); - return -1; - } - - /* Read the PSP File Header and determine file version */ - if (fread (buf, 32, 1, f) < 1 - || fread (&psp_ver_major, 2, 1, f) < 1 - || fread (&psp_ver_minor, 2, 1, f) < 1) - { - g_message ("Error reading file header"); - goto error; - } - - if (memcmp (buf, "Paint Shop Pro Image File\n\032\0\0\0\0\0", 32) != 0) - { - g_message ("Incorrect file signature"); - goto error; - } - - psp_ver_major = GUINT16_FROM_LE (psp_ver_major); - psp_ver_minor = GUINT16_FROM_LE (psp_ver_minor); - - /* I only have the documentation for file format version 3.0, - * but PSP 6 writes version 4.0. Let's hope it's backwards compatible. - * Earlier versions probably don't have all the fields I expect - * so don't accept those. - */ - if (psp_ver_major < 3) - { - g_message ("Unsupported PSP file format version " - "%d.%d, only knows 3.0 (and later?)", - psp_ver_major, psp_ver_minor); - goto error; - } - else if ((psp_ver_major == 3) - || (psp_ver_major == 4) - || (psp_ver_major == 5) - || (psp_ver_major == 6)) - ; /* OK */ - else - { - g_message ("Unsupported PSP file format version %d.%d", - psp_ver_major, psp_ver_minor); - goto error; - } - - /* Read all the blocks */ - block_number = 0; - - IFDBG(3) g_message ("size = %d", (int)st.st_size); - while (ftell (f) != st.st_size - && (id = read_block_header (f, &block_init_len, - &block_total_len)) != -1) - { - block_start = ftell (f); - - if (id == PSP_IMAGE_BLOCK) - { - if (block_number != 0) - { - g_message ("Duplicate General Image Attributes block"); - goto error; - } - if (read_general_image_attribute_block (f, block_init_len, - block_total_len, &ia) == -1) - { - goto error; - } - - IFDBG(2) g_message ("%d dpi %dx%d %s", - (int) ia.resolution, - ia.width, ia.height, - compression_name (ia.compression)); - - image_ID = gimp_image_new (ia.width, ia.height, - ia.greyscale ? GIMP_GRAY : GIMP_RGB); - if (image_ID == -1) - { - goto error; - } - - gimp_image_set_filename (image_ID, filename); - - gimp_image_set_resolution (image_ID, ia.resolution, ia.resolution); - } - else - { - if (block_number == 0) - { - g_message ("Missing General Image Attributes block"); - goto error; - } - - switch (id) - { - case PSP_CREATOR_BLOCK: - if (read_creator_block (f, image_ID, block_total_len, &ia) == -1) - goto error; - break; - - case PSP_COLOR_BLOCK: - break; /* Not yet implemented */ - - case PSP_LAYER_START_BLOCK: - if (read_layer_block (f, image_ID, block_total_len, &ia) == -1) - goto error; - break; - - case PSP_SELECTION_BLOCK: - break; /* Not yet implemented */ - - case PSP_ALPHA_BANK_BLOCK: - break; /* Not yet implemented */ - - case PSP_THUMBNAIL_BLOCK: - break; /* No use for it */ - - case PSP_EXTENDED_DATA_BLOCK: - break; /* Not yet implemented */ - - case PSP_TUBE_BLOCK: - if (read_tube_block (f, image_ID, block_total_len, &ia) == -1) - goto error; - break; - - case PSP_COMPOSITE_IMAGE_BANK_BLOCK: - break; /* Not yet implemented */ - - case PSP_LAYER_BLOCK: - case PSP_CHANNEL_BLOCK: - case PSP_ALPHA_CHANNEL_BLOCK: - case PSP_ADJUSTMENT_EXTENSION_BLOCK: - case PSP_VECTOR_EXTENSION_BLOCK: - case PSP_SHAPE_BLOCK: - case PSP_PAINTSTYLE_BLOCK: - case PSP_COMPOSITE_ATTRIBUTES_BLOCK: - case PSP_JPEG_BLOCK: - g_message ("Sub-block %s should not occur " - "at main level of file", - block_name (id)); - break; - - default: - g_message ("Unrecognized block id %d", id); - break; - } - } - - if (block_start + block_total_len >= st.st_size) - break; - - if (try_fseek (f, block_start + block_total_len, SEEK_SET) < 0) - goto error; - - block_number++; - } - - if (id == -1) - { - error: - fclose (f); - if (image_ID != -1) - gimp_image_delete (image_ID); - return -1; - } - - fclose (f); - - return image_ID; -} - -static gint -save_image (const gchar *filename, - gint32 image_ID, - gint32 drawable_ID, - GError **error) -{ - g_message ("Saving not implemented yet"); - - return FALSE; -} - -static void -run (const gchar *name, - gint nparams, - const GimpParam *param, - gint *nreturn_vals, - GimpParam **return_vals) -{ - static GimpParam values[2]; - GimpRunMode run_mode; - GimpPDBStatusType status = GIMP_PDB_SUCCESS; - gint32 image_ID; - gint32 drawable_ID; - GimpExportReturn export = GIMP_EXPORT_CANCEL; - GError *error = NULL; - - INIT_I18N (); - - run_mode = param[0].data.d_int32; - - *nreturn_vals = 1; - *return_vals = values; - - values[0].type = GIMP_PDB_STATUS; - values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; - - if (strcmp (name, LOAD_PROC) == 0) - { - image_ID = load_image (param[1].data.d_string, &error); - - if (image_ID != -1) - { - *nreturn_vals = 2; - values[1].type = GIMP_PDB_IMAGE; - values[1].data.d_image = image_ID; - } - else - { - status = GIMP_PDB_EXECUTION_ERROR; - } - } - else if (strcmp (name, SAVE_PROC) == 0) - { - image_ID = param[1].data.d_int32; - drawable_ID = param[2].data.d_int32; - - /* eventually export the image */ - switch (run_mode) - { - case GIMP_RUN_INTERACTIVE: - case GIMP_RUN_WITH_LAST_VALS: - gimp_ui_init (PLUG_IN_BINARY, FALSE); - - export = gimp_export_image (&image_ID, &drawable_ID, "PSP", - GIMP_EXPORT_CAN_HANDLE_RGB | - GIMP_EXPORT_CAN_HANDLE_GRAY | - GIMP_EXPORT_CAN_HANDLE_INDEXED | - GIMP_EXPORT_CAN_HANDLE_ALPHA | - GIMP_EXPORT_CAN_HANDLE_LAYERS); - - if (export == GIMP_EXPORT_CANCEL) - { - values[0].data.d_status = GIMP_PDB_CANCEL; - return; - } - break; - default: - break; - } - - switch (run_mode) - { - case GIMP_RUN_INTERACTIVE: - /* Possibly retrieve data */ - gimp_get_data (SAVE_PROC, &psvals); - - /* First acquire information with a dialog */ - if (! save_dialog ()) - status = GIMP_PDB_CANCEL; - break; - - case GIMP_RUN_NONINTERACTIVE: - /* Make sure all the arguments are there! */ - if (nparams != 6) - { - status = GIMP_PDB_CALLING_ERROR; - } - else - { - psvals.compression = (param[5].data.d_int32) ? TRUE : FALSE; - - if (param[5].data.d_int32 < 0 || - param[5].data.d_int32 > PSP_COMP_LZ77) - status = GIMP_PDB_CALLING_ERROR; - } - - case GIMP_RUN_WITH_LAST_VALS: - gimp_get_data (SAVE_PROC, &psvals); - break; - - default: - break; - } - - if (status == GIMP_PDB_SUCCESS) - { - if (save_image (param[3].data.d_string, image_ID, drawable_ID, - &error)) - { - gimp_set_data (SAVE_PROC, &psvals, sizeof (PSPSaveVals)); - } - else - { - status = GIMP_PDB_EXECUTION_ERROR; - } - } - - if (export == GIMP_EXPORT_EXPORT) - gimp_image_delete (image_ID); - } - else - { - status = GIMP_PDB_CALLING_ERROR; - } - - if (status != GIMP_PDB_SUCCESS && error) - { - *nreturn_vals = 2; - values[1].type = GIMP_PDB_STRING; - values[1].data.d_string = error->message; - } - - values[0].data.d_status = status; -}
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor