2007-12-20 19:12:05 +08:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* GIMP PSD Plug-in
|
|
|
|
* Copyright 2007 by John Marshall
|
|
|
|
*
|
2009-01-18 06:28:01 +08:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
2007-12-20 19:12:05 +08:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-18 06:28:01 +08:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2007-12-20 19:12:05 +08:00
|
|
|
* (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
|
2018-07-12 05:27:07 +08:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2007-12-20 19:12:05 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* ----- Known Image Resource Block Types -----
|
|
|
|
All image resources not otherwise handled, including unknown types
|
|
|
|
are added as image parasites.
|
|
|
|
The data is attached as-is from the file (i.e. in big endian order).
|
|
|
|
|
|
|
|
PSD_PS2_IMAGE_INFO = 1000, Dropped * 0x03e8 - Obsolete - ps 2.0 image info *
|
|
|
|
PSD_MAC_PRINT_INFO = 1001, PS Only * 0x03e9 - Optional - Mac print manager print info record *
|
2013-06-07 05:26:16 +08:00
|
|
|
PSD_PS2_COLOR_TAB = 1003, Dropped * 0x03eb - Obsolete - ps 2.0 indexed color table *
|
2007-12-20 19:12:05 +08:00
|
|
|
PSD_RESN_INFO = 1005, Loaded * 0x03ed - ResolutionInfo structure *
|
|
|
|
PSD_ALPHA_NAMES = 1006, Loaded * 0x03ee - Alpha channel names *
|
|
|
|
PSD_DISPLAY_INFO = 1007, Loaded * 0x03ef - DisplayInfo structure *
|
|
|
|
PSD_CAPTION = 1008, Loaded * 0x03f0 - Optional - Caption string *
|
|
|
|
PSD_BORDER_INFO = 1009, * 0x03f1 - Border info *
|
2013-06-07 05:26:16 +08:00
|
|
|
PSD_BACKGROUND_COL = 1010, * 0x03f2 - Background color *
|
2007-12-20 19:12:05 +08:00
|
|
|
PSD_PRINT_FLAGS = 1011, * 0x03f3 - Print flags *
|
|
|
|
PSD_GREY_HALFTONE = 1012, * 0x03f4 - Greyscale and multichannel halftoning info *
|
2013-06-07 05:26:16 +08:00
|
|
|
PSD_COLOR_HALFTONE = 1013, * 0x03f5 - Color halftoning info *
|
2007-12-20 19:12:05 +08:00
|
|
|
PSD_DUOTONE_HALFTONE = 1014, * 0x03f6 - Duotone halftoning info *
|
|
|
|
PSD_GREY_XFER = 1015, * 0x03f7 - Greyscale and multichannel transfer functions *
|
2013-06-07 05:26:16 +08:00
|
|
|
PSD_COLOR_XFER = 1016, * 0x03f8 - Color transfer functions *
|
2007-12-20 19:12:05 +08:00
|
|
|
PSD_DUOTONE_XFER = 1017, * 0x03f9 - Duotone transfer functions *
|
|
|
|
PSD_DUOTONE_INFO = 1018, * 0x03fa - Duotone image information *
|
|
|
|
PSD_EFFECTIVE_BW = 1019, * 0x03fb - Effective black & white values for dot range *
|
|
|
|
PSD_OBSOLETE_01 = 1020, Dropped * 0x03fc - Obsolete *
|
|
|
|
PSD_EPS_OPT = 1021, * 0x03fd - EPS options *
|
|
|
|
PSD_QUICK_MASK = 1022, Loaded * 0x03fe - Quick mask info *
|
|
|
|
PSD_OBSOLETE_02 = 1023, Dropped * 0x03ff - Obsolete *
|
|
|
|
PSD_LAYER_STATE = 1024, Loaded * 0x0400 - Layer state info *
|
|
|
|
PSD_WORKING_PATH = 1025, * 0x0401 - Working path (not saved) *
|
|
|
|
PSD_LAYER_GROUP = 1026, * 0x0402 - Layers group info *
|
|
|
|
PSD_OBSOLETE_03 = 1027, Dropped * 0x0403 - Obsolete *
|
|
|
|
PSD_IPTC_NAA_DATA = 1028, Loaded * 0x0404 - IPTC-NAA record (IMV4.pdf) *
|
|
|
|
PSD_IMAGE_MODE_RAW = 1029, * 0x0405 - Image mode for raw format files *
|
|
|
|
PSD_JPEG_QUAL = 1030, PS Only * 0x0406 - JPEG quality *
|
|
|
|
PSD_GRID_GUIDE = 1032, Loaded * 0x0408 - Grid & guide info *
|
|
|
|
PSD_THUMB_RES = 1033, Special * 0x0409 - Thumbnail resource *
|
|
|
|
PSD_COPYRIGHT_FLG = 1034, * 0x040a - Copyright flag *
|
|
|
|
PSD_URL = 1035, * 0x040b - URL string *
|
|
|
|
PSD_THUMB_RES2 = 1036, Special * 0x040c - Thumbnail resource *
|
|
|
|
PSD_GLOBAL_ANGLE = 1037, * 0x040d - Global angle *
|
2013-06-07 05:26:16 +08:00
|
|
|
PSD_COLOR_SAMPLER = 1038, * 0x040e - Color samplers resource *
|
2007-12-20 19:12:05 +08:00
|
|
|
PSD_ICC_PROFILE = 1039, Loaded * 0x040f - ICC Profile *
|
|
|
|
PSD_WATERMARK = 1040, * 0x0410 - Watermark *
|
|
|
|
PSD_ICC_UNTAGGED = 1041, * 0x0411 - Do not use ICC profile flag *
|
|
|
|
PSD_EFFECTS_VISIBLE = 1042, * 0x0412 - Show hide all effects layers *
|
|
|
|
PSD_SPOT_HALFTONE = 1043, * 0x0413 - Spot halftone *
|
|
|
|
PSD_DOC_IDS = 1044, * 0x0414 - Document specific IDs *
|
|
|
|
PSD_ALPHA_NAMES_UNI = 1045, Loaded * 0x0415 - Unicode alpha names *
|
2013-06-07 05:26:16 +08:00
|
|
|
PSD_IDX_COL_TAB_CNT = 1046, Loaded * 0x0416 - Indexed color table count *
|
|
|
|
PSD_IDX_TRANSPARENT = 1047, * 0x0417 - Index of transparent color (if any) *
|
2007-12-20 19:12:05 +08:00
|
|
|
PSD_GLOBAL_ALT = 1049, * 0x0419 - Global altitude *
|
|
|
|
PSD_SLICES = 1050, * 0x041a - Slices *
|
|
|
|
PSD_WORKFLOW_URL_UNI = 1051, * 0x041b - Workflow URL - Unicode string *
|
|
|
|
PSD_JUMP_TO_XPEP = 1052, * 0x041c - Jump to XPEP (?) *
|
|
|
|
PSD_ALPHA_ID = 1053, Loaded * 0x041d - Alpha IDs *
|
|
|
|
PSD_URL_LIST_UNI = 1054, * 0x041e - URL list - unicode *
|
|
|
|
PSD_VERSION_INFO = 1057, * 0x0421 - Version info *
|
2013-06-20 01:15:52 +08:00
|
|
|
PSD_EXIF_DATA = 1058, Loaded * 0x0422 - Exif data block 1 *
|
|
|
|
PSD_EXIF_DATA_3 = 1059 * 0X0423 - Exif data block 3 (?) *
|
2007-12-20 19:12:05 +08:00
|
|
|
PSD_XMP_DATA = 1060, Loaded * 0x0424 - XMP data block *
|
2013-06-20 01:15:52 +08:00
|
|
|
PSD_CAPTION_DIGEST = 1061, * 0x0425 - Caption digest *
|
|
|
|
PSD_PRINT_SCALE = 1062, * 0x0426 - Print scale *
|
|
|
|
PSD_PIXEL_AR = 1064, * 0x0428 - Pixel aspect ratio *
|
|
|
|
PSD_LAYER_COMPS = 1065, * 0x0429 - Layer comps *
|
|
|
|
PSD_ALT_DUOTONE_COLOR = 1066, * 0x042A - Alternative Duotone colors *
|
|
|
|
PSD_ALT_SPOT_COLOR = 1067, * 0x042B - Alternative Spot colors *
|
|
|
|
PSD_LAYER_SELECT_ID = 1069, * 0x042D - Layer selection ID *
|
|
|
|
PSD_HDR_TONING_INFO = 1070, * 0x042E - HDR toning information *
|
|
|
|
PSD_PRINT_INFO_SCALE = 1071, * 0x042F - Print scale *
|
|
|
|
PSD_LAYER_GROUP_E_ID = 1072, * 0x0430 - Layer group(s) enabled ID *
|
|
|
|
PSD_COLOR_SAMPLER_NEW = 1073, * 0x0431 - Color sampler resource for ps CS3 and higher PSD files *
|
|
|
|
PSD_MEASURE_SCALE = 1074, * 0x0432 - Measurement scale *
|
|
|
|
PSD_TIMELINE_INFO = 1075, * 0x0433 - Timeline information *
|
|
|
|
PSD_SHEET_DISCLOSE = 1076, * 0x0434 - Sheet discloser *
|
|
|
|
PSD_DISPLAY_INFO_NEW = 1077, Loaded * 0x0435 - DisplayInfo structure for ps CS3 and higher PSD files *
|
|
|
|
PSD_ONION_SKINS = 1078, * 0x0436 - Onion skins *
|
|
|
|
PSD_COUNT_INFO = 1080, * 0x0438 - Count information*
|
|
|
|
PSD_PRINT_INFO = 1082, * 0x043A - Print information added in ps CS5*
|
|
|
|
PSD_PRINT_STYLE = 1083, * 0x043B - Print style *
|
|
|
|
PSD_MAC_NSPRINTINFO = 1084, * 0x043C - Mac NSPrintInfo*
|
|
|
|
PSD_WIN_DEVMODE = 1085, * 0x043D - Windows DEVMODE *
|
|
|
|
PSD_AUTO_SAVE_PATH = 1086, * 0x043E - Auto save file path *
|
|
|
|
PSD_AUTO_SAVE_FORMAT = 1087, * 0x043F - Auto save format *
|
2007-12-20 19:12:05 +08:00
|
|
|
PSD_PATH_INFO_FIRST = 2000, Loaded * 0x07d0 - First path info block *
|
|
|
|
PSD_PATH_INFO_LAST = 2998, Loaded * 0x0bb6 - Last path info block *
|
|
|
|
PSD_CLIPPING_PATH = 2999, * 0x0bb7 - Name of clipping path *
|
2013-06-20 01:15:52 +08:00
|
|
|
PSD_PLUGIN_R_FIRST = 4000, * 0x0FA0 - First plugin resource *
|
|
|
|
PSD_PLUGIN_R_LAST = 4999, * 0x1387 - Last plugin resource *
|
|
|
|
PSD_IMAGEREADY_VARS = 7000, PS Only * 0x1B58 - Imageready variables *
|
|
|
|
PSD_IMAGEREADY_DATA = 7001, PS Only * 0x1B59 - Imageready data sets *
|
|
|
|
PSD_LIGHTROOM_WORK = 8000, PS Only * 0x1F40 - Lightroom workflow *
|
2007-12-20 19:12:05 +08:00
|
|
|
PSD_PRINT_FLAGS_2 = 10000 * 0x2710 - Print flags *
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <string.h>
|
2008-01-09 05:02:56 +08:00
|
|
|
#include <errno.h>
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
#include <glib/gstdio.h>
|
|
|
|
#include <libgimp/gimp.h>
|
|
|
|
|
|
|
|
#include <jpeglib.h>
|
|
|
|
#include <jerror.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_IPTCDATA
|
|
|
|
#include <libiptcdata/iptc-data.h>
|
|
|
|
#endif /* HAVE_IPTCDATA */
|
|
|
|
|
|
|
|
#include "psd.h"
|
|
|
|
#include "psd-util.h"
|
|
|
|
#include "psd-image-res-load.h"
|
|
|
|
|
|
|
|
#include "libgimp/stdplugins-intl.h"
|
|
|
|
|
|
|
|
#define EXIF_HEADER_SIZE 8
|
|
|
|
|
|
|
|
/* Local function prototypes */
|
|
|
|
static gint load_resource_unknown (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
static gint load_resource_ps_only (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
static gint load_resource_1005 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
static gint load_resource_1006 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2007-12-20 19:12:05 +08:00
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
static gint load_resource_1007 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2007-12-20 19:12:05 +08:00
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
static gint load_resource_1008 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
static gint load_resource_1022 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2007-12-20 19:12:05 +08:00
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
static gint load_resource_1024 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2007-12-20 19:12:05 +08:00
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
static gint load_resource_1028 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
static gint load_resource_1032 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
/* 1033 - Thumbnail needs special handling since it calls the jpeg library
|
|
|
|
* which needs a classic FILE. */
|
2007-12-20 19:12:05 +08:00
|
|
|
static gint load_resource_1033 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GFile *file,
|
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
static gint load_resource_1039 (const PSDimageres *res_a,
|
2020-02-21 19:08:19 +08:00
|
|
|
PSDimage *img_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
static gint load_resource_1045 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2007-12-20 19:12:05 +08:00
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
static gint load_resource_1046 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
static gint load_resource_1053 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2007-12-20 19:12:05 +08:00
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
static gint load_resource_1058 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2021-02-22 06:24:54 +08:00
|
|
|
static gint load_resource_1069 (const PSDimageres *res_a,
|
|
|
|
GimpImage *image,
|
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2021-02-22 06:24:54 +08:00
|
|
|
GError **error);
|
|
|
|
|
2013-06-20 01:15:52 +08:00
|
|
|
static gint load_resource_1077 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2013-06-20 01:15:52 +08:00
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2013-06-20 01:15:52 +08:00
|
|
|
GError **error);
|
|
|
|
|
2007-12-20 19:12:05 +08:00
|
|
|
static gint load_resource_2000 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2022-10-29 02:01:48 +08:00
|
|
|
static gint load_resource_2999 (const PSDimageres *res_a,
|
|
|
|
GimpImage *image,
|
|
|
|
GInputStream *input,
|
|
|
|
GError **error);
|
|
|
|
|
2007-12-20 19:12:05 +08:00
|
|
|
/* Public Functions */
|
|
|
|
gint
|
2021-05-10 11:21:02 +08:00
|
|
|
get_image_resource_header (PSDimageres *res_a,
|
|
|
|
GInputStream *input,
|
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2008-01-09 05:02:56 +08:00
|
|
|
gint32 read_len;
|
|
|
|
gint32 write_len;
|
|
|
|
gchar *name;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &res_a->type, 4, error) < 4 ||
|
|
|
|
psd_read (input, &res_a->id, 2, error) < 2)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
res_a->id = GUINT16_FROM_BE (res_a->id);
|
2021-05-10 11:21:02 +08:00
|
|
|
name = fread_pascal_string (&read_len, &write_len, 2, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
if (*error)
|
|
|
|
return -1;
|
2007-12-20 19:12:05 +08:00
|
|
|
if (name != NULL)
|
|
|
|
g_strlcpy (res_a->name, name, write_len + 1);
|
|
|
|
else
|
2008-01-09 05:02:56 +08:00
|
|
|
res_a->name[0] = 0x0;
|
2007-12-20 19:12:05 +08:00
|
|
|
g_free (name);
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &res_a->data_len, 4, error) < 4)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
res_a->data_len = GUINT32_FROM_BE (res_a->data_len);
|
2021-05-10 11:21:02 +08:00
|
|
|
res_a->data_start = g_seekable_tell (G_SEEKABLE (input));
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
IFDBG(2) g_debug ("Type: %.4s, id: %d, start: %" G_GOFFSET_FORMAT ", len: %" G_GSIZE_FORMAT,
|
2008-01-09 05:02:56 +08:00
|
|
|
res_a->type, res_a->id, res_a->data_start, res_a->data_len);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
2014-02-10 02:38:19 +08:00
|
|
|
load_image_resource (PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2014-02-10 02:38:19 +08:00
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2014-02-10 02:38:19 +08:00
|
|
|
gboolean *resolution_loaded,
|
2019-06-21 00:08:59 +08:00
|
|
|
gboolean *profile_loaded,
|
2014-02-10 02:38:19 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
gint pad;
|
|
|
|
|
|
|
|
/* Set file position to start of image resource data block */
|
2021-05-10 11:21:02 +08:00
|
|
|
if (! psd_seek (input, res_a->data_start, G_SEEK_SET, error))
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-06-20 01:15:52 +08:00
|
|
|
/* Process image resource blocks */
|
2007-12-20 19:12:05 +08:00
|
|
|
if (memcmp (res_a->type, "8BIM", 4) != 0 &&
|
|
|
|
memcmp (res_a->type, "MeSa", 4) !=0)
|
|
|
|
{
|
2008-01-09 05:02:56 +08:00
|
|
|
IFDBG(1) g_debug ("Unknown image resource type signature %.4s",
|
|
|
|
res_a->type);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (res_a->id)
|
|
|
|
{
|
|
|
|
case PSD_PS2_IMAGE_INFO:
|
|
|
|
case PSD_PS2_COLOR_TAB:
|
|
|
|
case PSD_OBSOLETE_01:
|
|
|
|
case PSD_OBSOLETE_02:
|
|
|
|
case PSD_OBSOLETE_03:
|
|
|
|
/* Drop obsolete image resource blocks */
|
|
|
|
IFDBG(2) g_debug ("Obsolete image resource block: %d",
|
|
|
|
res_a->id);
|
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_THUMB_RES:
|
|
|
|
case PSD_THUMB_RES2:
|
|
|
|
/* Drop thumbnails from standard file load */
|
|
|
|
IFDBG(2) g_debug ("Thumbnail resource block: %d",
|
|
|
|
res_a->id);
|
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_MAC_PRINT_INFO:
|
|
|
|
case PSD_JPEG_QUAL:
|
|
|
|
/* Save photoshop resources with no meaning for GIMP
|
|
|
|
as image parasites */
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_ps_only (res_a, image, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_RESN_INFO:
|
2021-05-10 11:21:02 +08:00
|
|
|
if (! load_resource_1005 (res_a, image, input, error))
|
2013-10-28 02:01:22 +08:00
|
|
|
*resolution_loaded = TRUE;
|
2008-01-09 05:02:56 +08:00
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_ALPHA_NAMES:
|
2021-11-09 11:36:49 +08:00
|
|
|
load_resource_1006 (res_a, image, img_a, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_DISPLAY_INFO:
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_1007 (res_a, image, img_a, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_CAPTION:
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_1008 (res_a, image, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_QUICK_MASK:
|
plug-ins: add support for loading merged image data from PSD files
PSD files may include a "merged", pre-composited, version of the
image (in Photoshop, this is the case when saving files with
"Maximize Compatibility" enabled; GIMP always saves the merged
image data in exported PSD files.) This commit adds support for
loading the merged image version from PSDs, instead of the full
layer hierarchy. This is useful when loading PSD files that use
features that we don't currently support, and therefore can't
render correctly, such as adjustment layers.
When loading the merged image version, we avoid loading certain
additional data from the file, such as channels, paths, and
guides, while still loading metadata, making this akin to loading
other "flat" image formats.
This option is currently exposed as an additional file type
("Photoshop image (merged)"), which has to be explicitly selected
from the file-type list when opening the image.
2018-06-18 18:17:04 +08:00
|
|
|
if (! img_a->merged_image_only)
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_1022 (res_a, image, img_a, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_LAYER_STATE:
|
plug-ins: add support for loading merged image data from PSD files
PSD files may include a "merged", pre-composited, version of the
image (in Photoshop, this is the case when saving files with
"Maximize Compatibility" enabled; GIMP always saves the merged
image data in exported PSD files.) This commit adds support for
loading the merged image version from PSDs, instead of the full
layer hierarchy. This is useful when loading PSD files that use
features that we don't currently support, and therefore can't
render correctly, such as adjustment layers.
When loading the merged image version, we avoid loading certain
additional data from the file, such as channels, paths, and
guides, while still loading metadata, making this akin to loading
other "flat" image formats.
This option is currently exposed as an additional file type
("Photoshop image (merged)"), which has to be explicitly selected
from the file-type list when opening the image.
2018-06-18 18:17:04 +08:00
|
|
|
if (! img_a->merged_image_only)
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_1024 (res_a, image, img_a, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2011-12-01 06:17:09 +08:00
|
|
|
case PSD_WORKING_PATH:
|
plug-ins: add support for loading merged image data from PSD files
PSD files may include a "merged", pre-composited, version of the
image (in Photoshop, this is the case when saving files with
"Maximize Compatibility" enabled; GIMP always saves the merged
image data in exported PSD files.) This commit adds support for
loading the merged image version from PSDs, instead of the full
layer hierarchy. This is useful when loading PSD files that use
features that we don't currently support, and therefore can't
render correctly, such as adjustment layers.
When loading the merged image version, we avoid loading certain
additional data from the file, such as channels, paths, and
guides, while still loading metadata, making this akin to loading
other "flat" image formats.
This option is currently exposed as an additional file type
("Photoshop image (merged)"), which has to be explicitly selected
from the file-type list when opening the image.
2018-06-18 18:17:04 +08:00
|
|
|
if (! img_a->merged_image_only)
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_2000 (res_a, image, input, error);
|
2011-12-01 06:17:09 +08:00
|
|
|
break;
|
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_IPTC_NAA_DATA:
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_1028 (res_a, image, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_GRID_GUIDE:
|
plug-ins: add support for loading merged image data from PSD files
PSD files may include a "merged", pre-composited, version of the
image (in Photoshop, this is the case when saving files with
"Maximize Compatibility" enabled; GIMP always saves the merged
image data in exported PSD files.) This commit adds support for
loading the merged image version from PSDs, instead of the full
layer hierarchy. This is useful when loading PSD files that use
features that we don't currently support, and therefore can't
render correctly, such as adjustment layers.
When loading the merged image version, we avoid loading certain
additional data from the file, such as channels, paths, and
guides, while still loading metadata, making this akin to loading
other "flat" image formats.
This option is currently exposed as an additional file type
("Photoshop image (merged)"), which has to be explicitly selected
from the file-type list when opening the image.
2018-06-18 18:17:04 +08:00
|
|
|
if (! img_a->merged_image_only)
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_1032 (res_a, image, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_ICC_PROFILE:
|
2021-05-10 11:21:02 +08:00
|
|
|
if (! load_resource_1039 (res_a, img_a, image, input, error))
|
2019-06-21 00:08:59 +08:00
|
|
|
*profile_loaded = TRUE;
|
2008-01-09 05:02:56 +08:00
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_ALPHA_NAMES_UNI:
|
2021-11-09 11:36:49 +08:00
|
|
|
load_resource_1045 (res_a, image, img_a, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_IDX_COL_TAB_CNT:
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_1046 (res_a, image, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_ALPHA_ID:
|
plug-ins: add support for loading merged image data from PSD files
PSD files may include a "merged", pre-composited, version of the
image (in Photoshop, this is the case when saving files with
"Maximize Compatibility" enabled; GIMP always saves the merged
image data in exported PSD files.) This commit adds support for
loading the merged image version from PSDs, instead of the full
layer hierarchy. This is useful when loading PSD files that use
features that we don't currently support, and therefore can't
render correctly, such as adjustment layers.
When loading the merged image version, we avoid loading certain
additional data from the file, such as channels, paths, and
guides, while still loading metadata, making this akin to loading
other "flat" image formats.
This option is currently exposed as an additional file type
("Photoshop image (merged)"), which has to be explicitly selected
from the file-type list when opening the image.
2018-06-18 18:17:04 +08:00
|
|
|
if (! img_a->merged_image_only)
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_1053 (res_a, image, img_a, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_EXIF_DATA:
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_1058 (res_a, image, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2021-02-22 06:24:54 +08:00
|
|
|
case PSD_LAYER_SELECT_ID:
|
|
|
|
if (! img_a->merged_image_only)
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_1069 (res_a, image, img_a, input, error);
|
2021-02-22 06:24:54 +08:00
|
|
|
break;
|
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
case PSD_XMP_DATA:
|
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2013-06-20 01:15:52 +08:00
|
|
|
case PSD_DISPLAY_INFO_NEW:
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_1077 (res_a, image, img_a, input, error);
|
2013-06-20 01:15:52 +08:00
|
|
|
break;
|
|
|
|
|
2022-10-29 02:01:48 +08:00
|
|
|
case PSD_CLIPPING_PATH:
|
|
|
|
load_resource_2999 (res_a, image, input, error);
|
|
|
|
break;
|
|
|
|
|
2023-01-23 12:05:53 +08:00
|
|
|
case PSD_LAYER_COMPS:
|
|
|
|
img_a->unsupported_features->layer_comp = TRUE;
|
|
|
|
img_a->unsupported_features->show_gui = TRUE;
|
|
|
|
load_resource_unknown (res_a, image, input, error);
|
|
|
|
break;
|
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
default:
|
|
|
|
if (res_a->id >= 2000 &&
|
|
|
|
res_a->id < 2999)
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_2000 (res_a, image, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
else
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_unknown (res_a, image, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
}
|
2007-12-20 19:12:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Image blocks are null padded to even length */
|
|
|
|
if (res_a->data_len % 2 == 0)
|
|
|
|
pad = 0;
|
|
|
|
else
|
|
|
|
pad = 1;
|
|
|
|
|
|
|
|
/* Set file position to end of image resource block */
|
2021-05-10 11:21:02 +08:00
|
|
|
if (! psd_seek (input, res_a->data_start + res_a->data_len + pad, G_SEEK_SET, error))
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
2021-05-10 11:21:02 +08:00
|
|
|
load_thumbnail_resource (PSDimageres *res_a,
|
|
|
|
GimpImage *image,
|
|
|
|
GFile *file,
|
|
|
|
GInputStream *input,
|
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
gint rtn = 0;
|
|
|
|
gint pad;
|
|
|
|
|
|
|
|
/* Set file position to start of image resource data block */
|
2021-05-10 11:21:02 +08:00
|
|
|
if (! psd_seek (input, res_a->data_start, G_SEEK_SET, error))
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-06-20 01:15:52 +08:00
|
|
|
/* Process image resource blocks */
|
|
|
|
if (res_a->id == PSD_THUMB_RES
|
|
|
|
|| res_a->id == PSD_THUMB_RES2)
|
|
|
|
{
|
|
|
|
/* Load thumbnails from standard file load */
|
2021-05-10 11:21:02 +08:00
|
|
|
load_resource_1033 (res_a, image, file, input, error);
|
2013-06-20 01:15:52 +08:00
|
|
|
rtn = 1;
|
|
|
|
}
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
/* Image blocks are null padded to even length */
|
|
|
|
if (res_a->data_len % 2 == 0)
|
|
|
|
pad = 0;
|
|
|
|
else
|
|
|
|
pad = 1;
|
|
|
|
|
|
|
|
/* Set file position to end of image resource block */
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_seek (input, res_a->data_start + res_a->data_len + pad, G_SEEK_SET, error))
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rtn;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Private Functions */
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_unknown (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
/* Unknown image resources attached as parasites to re-save later */
|
|
|
|
GimpParasite *parasite;
|
|
|
|
gchar *data;
|
|
|
|
gchar *name;
|
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process unknown image resource block: %d", res_a->id);
|
|
|
|
|
|
|
|
data = g_malloc (res_a->data_len);
|
2021-05-10 11:21:02 +08:00
|
|
|
if (res_a->data_len > 0 && psd_read (input, data, res_a->data_len, error) < res_a->data_len)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2010-11-10 02:03:47 +08:00
|
|
|
g_free (data);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
name = g_strdup_printf ("psd-image-resource-%.4s-%.4x",
|
2013-06-20 01:15:52 +08:00
|
|
|
res_a->type, res_a->id);
|
2007-12-20 19:12:05 +08:00
|
|
|
IFDBG(2) g_debug ("Parasite name: %s", name);
|
|
|
|
|
|
|
|
parasite = gimp_parasite_new (name, 0, res_a->data_len, data);
|
2019-08-19 22:04:15 +08:00
|
|
|
gimp_image_attach_parasite (image, parasite);
|
2007-12-20 19:12:05 +08:00
|
|
|
gimp_parasite_free (parasite);
|
|
|
|
g_free (data);
|
|
|
|
g_free (name);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_ps_only (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
/* Save photoshop resources with no meaning for GIMP as image parasites
|
|
|
|
to re-save later */
|
|
|
|
GimpParasite *parasite;
|
|
|
|
gchar *data;
|
|
|
|
gchar *name;
|
|
|
|
|
|
|
|
IFDBG(3) g_debug ("Process image resource block: %d", res_a->id);
|
|
|
|
|
|
|
|
data = g_malloc (res_a->data_len);
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, data, res_a->data_len, error) < res_a->data_len)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2010-11-10 02:03:47 +08:00
|
|
|
g_free (data);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
name = g_strdup_printf ("psd-image-resource-%.4s-%.4x",
|
2013-06-20 01:15:52 +08:00
|
|
|
res_a->type, res_a->id);
|
2007-12-20 19:12:05 +08:00
|
|
|
IFDBG(2) g_debug ("Parasite name: %s", name);
|
|
|
|
|
|
|
|
parasite = gimp_parasite_new (name, 0, res_a->data_len, data);
|
2019-08-19 22:04:15 +08:00
|
|
|
gimp_image_attach_parasite (image, parasite);
|
2007-12-20 19:12:05 +08:00
|
|
|
gimp_parasite_free (parasite);
|
|
|
|
g_free (data);
|
|
|
|
g_free (name);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_1005 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
/* Load image resolution and unit of measure */
|
|
|
|
|
|
|
|
/* FIXME width unit and height unit unused at present */
|
|
|
|
|
|
|
|
ResolutionInfo res_info;
|
|
|
|
GimpUnit image_unit;
|
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process image resource block 1005: Resolution Info");
|
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &res_info.hRes, 4, error) < 4 ||
|
|
|
|
psd_read (input, &res_info.hResUnit, 2, error) < 2 ||
|
|
|
|
psd_read (input, &res_info.widthUnit, 2, error) < 2 ||
|
|
|
|
psd_read (input, &res_info.vRes, 4, error) < 4 ||
|
|
|
|
psd_read (input, &res_info.vResUnit, 2, error) < 2 ||
|
|
|
|
psd_read (input, &res_info.heightUnit, 2, error) < 2)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
res_info.hRes = GINT32_FROM_BE (res_info.hRes);
|
|
|
|
res_info.hResUnit = GINT16_FROM_BE (res_info.hResUnit);
|
|
|
|
res_info.widthUnit = GINT16_FROM_BE (res_info.widthUnit);
|
|
|
|
res_info.vRes = GINT32_FROM_BE (res_info.vRes);
|
|
|
|
res_info.vResUnit = GINT16_FROM_BE (res_info.vResUnit);
|
|
|
|
res_info.heightUnit = GINT16_FROM_BE (res_info.heightUnit);
|
|
|
|
|
|
|
|
IFDBG(3) g_debug ("Resolution: %d, %d, %d, %d, %d, %d",
|
2013-06-20 01:15:52 +08:00
|
|
|
res_info.hRes,
|
|
|
|
res_info.hResUnit,
|
|
|
|
res_info.widthUnit,
|
|
|
|
res_info.vRes,
|
|
|
|
res_info.vResUnit,
|
|
|
|
res_info.heightUnit);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
/* Resolution always recorded as pixels / inch in a fixed point implied
|
2007-12-20 19:12:05 +08:00
|
|
|
decimal int32 with 16 bits before point and 16 after (i.e. cast as
|
|
|
|
double and divide resolution by 2^16 */
|
2019-08-19 22:04:15 +08:00
|
|
|
gimp_image_set_resolution (image,
|
2007-12-20 19:12:05 +08:00
|
|
|
res_info.hRes / 65536.0, res_info.vRes / 65536.0);
|
|
|
|
|
|
|
|
/* GIMP only has one display unit so use ps horizontal resolution unit */
|
|
|
|
switch (res_info.hResUnit)
|
|
|
|
{
|
2013-06-20 01:15:52 +08:00
|
|
|
case PSD_RES_INCH:
|
|
|
|
image_unit = GIMP_UNIT_INCH;
|
|
|
|
break;
|
|
|
|
case PSD_RES_CM:
|
|
|
|
image_unit = GIMP_UNIT_MM;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
image_unit = GIMP_UNIT_INCH;
|
2007-12-20 19:12:05 +08:00
|
|
|
}
|
|
|
|
|
2019-08-19 22:04:15 +08:00
|
|
|
gimp_image_set_unit (image, image_unit);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_1006 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2008-01-09 05:02:56 +08:00
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
/* Load alpha channel names stored as a series of pascal strings
|
|
|
|
unpadded between strings */
|
|
|
|
|
|
|
|
gchar *str;
|
2008-01-09 05:02:56 +08:00
|
|
|
gint32 block_rem;
|
|
|
|
gint32 read_len;
|
|
|
|
gint32 write_len;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process image resource block 1006: Alpha Channel Names");
|
|
|
|
|
|
|
|
if (img_a->alpha_names)
|
|
|
|
{
|
2008-01-09 05:02:56 +08:00
|
|
|
IFDBG(3) g_debug ("Alpha names loaded from unicode resource block");
|
2007-12-20 19:12:05 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
img_a->alpha_names = g_ptr_array_new ();
|
|
|
|
|
|
|
|
block_rem = res_a->data_len;
|
|
|
|
while (block_rem > 1)
|
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
str = fread_pascal_string (&read_len, &write_len, 1, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
if (*error)
|
|
|
|
return -1;
|
|
|
|
IFDBG(3) g_debug ("String: %s, %d, %d", str, read_len, write_len);
|
2007-12-20 19:12:05 +08:00
|
|
|
if (write_len >= 0)
|
|
|
|
{
|
2008-01-09 05:02:56 +08:00
|
|
|
g_ptr_array_add (img_a->alpha_names, (gpointer) str);
|
2007-12-20 19:12:05 +08:00
|
|
|
}
|
|
|
|
block_rem -= read_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_1007 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2008-01-09 05:02:56 +08:00
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
/* Load alpha channel display info */
|
|
|
|
|
|
|
|
DisplayInfo dsp_info;
|
|
|
|
CMColor ps_color;
|
|
|
|
gint16 tot_rec;
|
|
|
|
gint cidx;
|
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process image resource block 1007: Display Info");
|
|
|
|
tot_rec = res_a->data_len / 14;
|
|
|
|
if (tot_rec == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
img_a->alpha_display_info = g_new (PSDchanneldata *, tot_rec);
|
|
|
|
img_a->alpha_display_count = tot_rec;
|
|
|
|
for (cidx = 0; cidx < tot_rec; ++cidx)
|
|
|
|
{
|
2023-11-20 07:20:03 +08:00
|
|
|
GeglColor *color;
|
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &dsp_info.colorSpace, 2, error) < 2 ||
|
|
|
|
psd_read (input, &dsp_info.color, 8, error) < 8 ||
|
|
|
|
psd_read (input, &dsp_info.opacity, 2, error) < 2 ||
|
|
|
|
psd_read (input, &dsp_info.kind, 1, error) < 1 ||
|
|
|
|
psd_read (input, &dsp_info.padding, 1, error) < 1)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
dsp_info.colorSpace = GINT16_FROM_BE (dsp_info.colorSpace);
|
|
|
|
ps_color.cmyk.cyan = GUINT16_FROM_BE (dsp_info.color[0]);
|
|
|
|
ps_color.cmyk.magenta = GUINT16_FROM_BE (dsp_info.color[1]);
|
|
|
|
ps_color.cmyk.yellow = GUINT16_FROM_BE (dsp_info.color[2]);
|
|
|
|
ps_color.cmyk.black = GUINT16_FROM_BE (dsp_info.color[3]);
|
|
|
|
dsp_info.opacity = GINT16_FROM_BE (dsp_info.opacity);
|
|
|
|
|
2023-11-20 07:20:03 +08:00
|
|
|
color = gegl_color_new ("red");
|
|
|
|
|
2007-12-20 19:12:05 +08:00
|
|
|
switch (dsp_info.colorSpace)
|
|
|
|
{
|
|
|
|
case PSD_CS_RGB:
|
2023-11-20 07:20:03 +08:00
|
|
|
/* TODO: which space should we use? */
|
|
|
|
gegl_color_set_rgba_with_space (color,
|
|
|
|
ps_color.rgb.red / 65535.0,
|
|
|
|
ps_color.rgb.green / 65535.0,
|
|
|
|
ps_color.rgb.blue / 65535.0,
|
|
|
|
1.0, NULL);
|
2007-12-20 19:12:05 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PSD_CS_HSB:
|
2023-11-20 07:20:03 +08:00
|
|
|
{
|
2024-04-21 11:42:27 +08:00
|
|
|
gfloat hsv[3] =
|
2023-11-20 07:20:03 +08:00
|
|
|
{
|
2024-04-21 11:42:27 +08:00
|
|
|
ps_color.hsv.hue / 65535.0f,
|
|
|
|
ps_color.hsv.saturation / 65535.0f,
|
|
|
|
ps_color.hsv.value / 65535.0f
|
2023-11-20 07:20:03 +08:00
|
|
|
};
|
|
|
|
|
2024-04-21 11:42:27 +08:00
|
|
|
gegl_color_set_pixel (color, babl_format ("HSV float"), hsv);
|
2023-11-20 07:20:03 +08:00
|
|
|
}
|
|
|
|
break;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
case PSD_CS_CMYK:
|
2023-11-20 07:20:03 +08:00
|
|
|
/* TODO: again, which space? */
|
|
|
|
gegl_color_set_cmyk (color,
|
|
|
|
1.0 - ps_color.cmyk.cyan / 65535.0,
|
|
|
|
1.0 - ps_color.cmyk.magenta / 65535.0,
|
|
|
|
1.0 - ps_color.cmyk.yellow / 65535.0,
|
|
|
|
1.0 - ps_color.cmyk.black / 65535.0,
|
|
|
|
1.0, NULL);
|
2007-12-20 19:12:05 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PSD_CS_GRAYSCALE:
|
2023-11-20 07:20:03 +08:00
|
|
|
{
|
|
|
|
gdouble gray = ps_color.gray.gray / 10000.0;
|
|
|
|
|
|
|
|
/* TODO: which space? */
|
|
|
|
gegl_color_set_pixel (color, babl_format_with_space ("Y' double", NULL), &gray);
|
|
|
|
}
|
2007-12-20 19:12:05 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PSD_CS_FOCOLTONE:
|
|
|
|
case PSD_CS_TRUMATCH:
|
|
|
|
case PSD_CS_HKS:
|
|
|
|
case PSD_CS_LAB:
|
|
|
|
case PSD_CS_PANTONE:
|
|
|
|
case PSD_CS_TOYO:
|
|
|
|
case PSD_CS_DIC:
|
|
|
|
case PSD_CS_ANPA:
|
|
|
|
default:
|
2008-01-09 05:02:56 +08:00
|
|
|
if (CONVERSION_WARNINGS)
|
|
|
|
g_message ("Unsupported color space: %d",
|
|
|
|
dsp_info.colorSpace);
|
2007-12-20 19:12:05 +08:00
|
|
|
}
|
2008-01-09 05:02:56 +08:00
|
|
|
|
2007-12-20 19:12:05 +08:00
|
|
|
IFDBG(2) g_debug ("PS cSpace: %d, col: %d %d %d %d, opacity: %d, kind: %d",
|
2013-06-20 01:15:52 +08:00
|
|
|
dsp_info.colorSpace, ps_color.cmyk.cyan, ps_color.cmyk.magenta,
|
|
|
|
ps_color.cmyk.yellow, ps_color.cmyk.black, dsp_info.opacity,
|
|
|
|
dsp_info.kind);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2023-11-20 07:20:03 +08:00
|
|
|
IFDBG(2) g_debug ("cSpace: %d, opacity: %d, kind: %d",
|
|
|
|
dsp_info.colorSpace, dsp_info.opacity, dsp_info.kind);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2020-04-27 03:45:44 +08:00
|
|
|
img_a->alpha_display_info[cidx] = g_malloc0 (sizeof (PSDchanneldata));
|
2023-11-20 07:20:03 +08:00
|
|
|
img_a->alpha_display_info[cidx]->gimp_color = color;
|
2007-12-20 19:12:05 +08:00
|
|
|
img_a->alpha_display_info[cidx]->opacity = dsp_info.opacity;
|
|
|
|
img_a->alpha_display_info[cidx]->ps_kind = dsp_info.kind;
|
|
|
|
img_a->alpha_display_info[cidx]->ps_cspace = dsp_info.colorSpace;
|
|
|
|
img_a->alpha_display_info[cidx]->ps_color = ps_color;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_1008 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
/* Load image caption */
|
|
|
|
GimpParasite *parasite;
|
|
|
|
gchar *caption;
|
2008-01-09 05:02:56 +08:00
|
|
|
gint32 read_len;
|
|
|
|
gint32 write_len;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process image resource block: 1008: Caption");
|
2021-05-10 11:21:02 +08:00
|
|
|
caption = fread_pascal_string (&read_len, &write_len, 1, input, error);
|
2008-01-09 05:02:56 +08:00
|
|
|
if (*error)
|
|
|
|
return -1;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
IFDBG(3) g_debug ("Caption: %s", caption);
|
2007-12-20 19:12:05 +08:00
|
|
|
parasite = gimp_parasite_new (GIMP_PARASITE_COMMENT, GIMP_PARASITE_PERSISTENT,
|
|
|
|
write_len, caption);
|
2019-08-19 22:04:15 +08:00
|
|
|
gimp_image_attach_parasite (image, parasite);
|
2007-12-20 19:12:05 +08:00
|
|
|
gimp_parasite_free (parasite);
|
|
|
|
g_free (caption);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_1022 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2008-01-09 05:02:56 +08:00
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
/* Load quick mask info */
|
|
|
|
gboolean quick_mask_empty; /* Quick mask initially empty */
|
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process image resource block: 1022: Quick Mask");
|
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &img_a->quick_mask_id, 2, error) < 2 ||
|
|
|
|
psd_read (input, &quick_mask_empty, 1, error) < 1)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
img_a->quick_mask_id = GUINT16_FROM_BE (img_a->quick_mask_id);
|
|
|
|
|
|
|
|
IFDBG(3) g_debug ("Quick mask channel: %d, empty: %d",
|
2013-06-20 01:15:52 +08:00
|
|
|
img_a->quick_mask_id,
|
|
|
|
quick_mask_empty);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_1024 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2008-01-09 05:02:56 +08:00
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
/* Load image layer state - current active layer counting from bottom up */
|
|
|
|
IFDBG(2) g_debug ("Process image resource block: 1024: Layer State");
|
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &img_a->layer_state, 2, error) < 2)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
img_a->layer_state = GUINT16_FROM_BE (img_a->layer_state);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_1028 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
/* Load IPTC data block */
|
|
|
|
|
|
|
|
#ifdef HAVE_IPTCDATA
|
|
|
|
IptcData *iptc_data;
|
|
|
|
guchar *iptc_buf;
|
|
|
|
guint iptc_buf_len;
|
|
|
|
#else
|
|
|
|
gchar *name;
|
|
|
|
#endif /* HAVE_IPTCDATA */
|
|
|
|
|
|
|
|
GimpParasite *parasite;
|
|
|
|
gchar *res_data;
|
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process image resource block: 1028: IPTC data");
|
|
|
|
|
|
|
|
res_data = g_malloc (res_a->data_len);
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, res_data, res_a->data_len, error) < res_a->data_len)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2010-11-10 02:03:47 +08:00
|
|
|
g_free (res_data);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_IPTCDATA
|
|
|
|
/* Load IPTC data structure */
|
|
|
|
iptc_data = iptc_data_new_from_data (res_data, res_a->data_len);
|
|
|
|
IFDBG (3) iptc_data_dump (iptc_data, 0);
|
|
|
|
|
|
|
|
/* Store resource data as a GIMP IPTC parasite */
|
|
|
|
IFDBG (2) g_debug ("Processing IPTC data as GIMP IPTC parasite");
|
|
|
|
/* Serialize IPTC data */
|
|
|
|
iptc_data_save (iptc_data, &iptc_buf, &iptc_buf_len);
|
|
|
|
if (iptc_buf_len > 0)
|
|
|
|
{
|
|
|
|
parasite = gimp_parasite_new (GIMP_PARASITE_IPTC,
|
|
|
|
GIMP_PARASITE_PERSISTENT,
|
|
|
|
iptc_buf_len, iptc_buf);
|
2019-08-19 22:04:15 +08:00
|
|
|
gimp_image_attach_parasite (image, parasite);
|
2007-12-20 19:12:05 +08:00
|
|
|
gimp_parasite_free (parasite);
|
|
|
|
}
|
|
|
|
|
|
|
|
iptc_data_unref (iptc_data);
|
|
|
|
g_free (iptc_buf);
|
|
|
|
|
|
|
|
#else
|
|
|
|
/* Store resource data as a standard psd parasite */
|
|
|
|
IFDBG (2) g_debug ("Processing IPTC data as psd parasite");
|
|
|
|
name = g_strdup_printf ("psd-image-resource-%.4s-%.4x",
|
|
|
|
res_a->type, res_a->id);
|
2008-01-09 05:02:56 +08:00
|
|
|
IFDBG(3) g_debug ("Parasite name: %s", name);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
parasite = gimp_parasite_new (name, 0, res_a->data_len, res_data);
|
2019-08-19 22:04:15 +08:00
|
|
|
gimp_image_attach_parasite (image, parasite);
|
2007-12-20 19:12:05 +08:00
|
|
|
gimp_parasite_free (parasite);
|
|
|
|
g_free (name);
|
|
|
|
|
|
|
|
#endif /* HAVE_IPTCDATA */
|
|
|
|
|
|
|
|
g_free (res_data);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_1032 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
/* Load grid and guides */
|
|
|
|
|
|
|
|
/* Grid info is not used (CS2 or earlier) */
|
|
|
|
|
|
|
|
GuideHeader hdr;
|
|
|
|
GuideResource guide;
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process image resource block 1032: Grid and Guide Info");
|
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &hdr.fVersion, 4, error) < 4 ||
|
|
|
|
psd_read (input, &hdr.fGridCycleV, 4, error) < 4 ||
|
|
|
|
psd_read (input, &hdr.fGridCycleH, 4, error) < 4 ||
|
|
|
|
psd_read (input, &hdr.fGuideCount, 4, error) < 4)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
hdr.fVersion = GUINT32_FROM_BE (hdr.fVersion);
|
|
|
|
hdr.fGridCycleV = GUINT32_FROM_BE (hdr.fGridCycleV);
|
|
|
|
hdr.fGridCycleH = GUINT32_FROM_BE (hdr.fGridCycleH);
|
|
|
|
hdr.fGuideCount = GUINT32_FROM_BE (hdr.fGuideCount);
|
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
IFDBG(3) g_debug ("Grids & Guides: %d, %d, %d, %d",
|
2007-12-20 19:12:05 +08:00
|
|
|
hdr.fVersion,
|
|
|
|
hdr.fGridCycleV,
|
|
|
|
hdr.fGridCycleH,
|
|
|
|
hdr.fGuideCount);
|
|
|
|
|
|
|
|
for (i = 0; i < hdr.fGuideCount; ++i)
|
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &guide.fLocation, 4, error) < 4 ||
|
|
|
|
psd_read (input, &guide.fDirection, 1, error) < 1)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
guide.fLocation = GUINT32_FROM_BE (guide.fLocation);
|
|
|
|
guide.fLocation /= 32;
|
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
IFDBG(3) g_debug ("Guide: %d px, %d",
|
2007-12-20 19:12:05 +08:00
|
|
|
guide.fLocation,
|
|
|
|
guide.fDirection);
|
|
|
|
|
|
|
|
if (guide.fDirection == PSD_VERTICAL)
|
2019-08-19 22:04:15 +08:00
|
|
|
gimp_image_add_vguide (image, guide.fLocation);
|
2007-12-20 19:12:05 +08:00
|
|
|
else
|
2019-08-19 22:04:15 +08:00
|
|
|
gimp_image_add_hguide (image, guide.fLocation);
|
2007-12-20 19:12:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_1033 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GFile *file,
|
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
/* Load thumbnail image */
|
|
|
|
|
|
|
|
struct jpeg_decompress_struct cinfo;
|
|
|
|
struct jpeg_error_mgr jerr;
|
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
FILE *f;
|
2007-12-20 19:12:05 +08:00
|
|
|
ThumbnailInfo thumb_info;
|
2013-06-20 01:15:52 +08:00
|
|
|
GeglBuffer *buffer;
|
|
|
|
const Babl *format;
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpLayer *layer;
|
2008-01-09 05:02:56 +08:00
|
|
|
guchar *buf;
|
|
|
|
guchar *rgb_buf;
|
|
|
|
guchar **rowbuf;
|
2007-12-20 19:12:05 +08:00
|
|
|
gint i;
|
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process image resource block %d: Thumbnail Image", res_a->id);
|
|
|
|
|
|
|
|
/* Read thumbnail resource header info */
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &thumb_info.format, 4, error) < 4 ||
|
|
|
|
psd_read (input, &thumb_info.width, 4, error) < 4 ||
|
|
|
|
psd_read (input, &thumb_info.height, 4, error) < 4 ||
|
|
|
|
psd_read (input, &thumb_info.widthbytes, 4, error) < 4 ||
|
|
|
|
psd_read (input, &thumb_info.size, 4, error) < 4 ||
|
|
|
|
psd_read (input, &thumb_info.compressedsize, 4, error) < 4 ||
|
|
|
|
psd_read (input, &thumb_info.bitspixel, 2, error) < 2 ||
|
|
|
|
psd_read (input, &thumb_info.planes, 2, error) < 2)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
thumb_info.format = GINT32_FROM_BE (thumb_info.format);
|
|
|
|
thumb_info.width = GINT32_FROM_BE (thumb_info.width);
|
|
|
|
thumb_info.height = GINT32_FROM_BE (thumb_info.height);
|
|
|
|
thumb_info.widthbytes = GINT32_FROM_BE (thumb_info.widthbytes);
|
|
|
|
thumb_info.size = GINT32_FROM_BE (thumb_info.size);
|
|
|
|
thumb_info.compressedsize = GINT32_FROM_BE (thumb_info.compressedsize);
|
|
|
|
thumb_info.bitspixel = GINT16_FROM_BE (thumb_info.bitspixel);
|
|
|
|
thumb_info.planes = GINT16_FROM_BE (thumb_info.planes);
|
|
|
|
|
|
|
|
IFDBG(2) g_debug ("\nThumbnail:\n"
|
|
|
|
"\tFormat: %d\n"
|
|
|
|
"\tDimensions: %d x %d\n",
|
2013-06-20 01:15:52 +08:00
|
|
|
thumb_info.format,
|
|
|
|
thumb_info.width,
|
|
|
|
thumb_info.height);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
if (thumb_info.format != 1)
|
|
|
|
{
|
2008-01-09 05:02:56 +08:00
|
|
|
IFDBG(1) g_debug ("Unknown thumbnail format %d", thumb_info.format);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Load Jpeg RGB thumbnail info */
|
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
/* Open input also as a FILE. */
|
2021-10-02 04:58:14 +08:00
|
|
|
f = g_fopen (g_file_peek_path (file), "rb");
|
2021-05-10 11:21:02 +08:00
|
|
|
|
|
|
|
if (! f)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Now seek to the same position as we have in input. */
|
|
|
|
fseek(f, g_seekable_tell (G_SEEKABLE (input)), SEEK_SET);
|
|
|
|
|
2007-12-20 19:12:05 +08:00
|
|
|
/* Step 1: Allocate and initialize JPEG decompression object */
|
|
|
|
cinfo.err = jpeg_std_error (&jerr);
|
|
|
|
jpeg_create_decompress (&cinfo);
|
|
|
|
|
|
|
|
/* Step 2: specify data source (eg, a file) */
|
|
|
|
jpeg_stdio_src(&cinfo, f);
|
|
|
|
|
|
|
|
/* Step 3: read file parameters with jpeg_read_header() */
|
|
|
|
jpeg_read_header (&cinfo, TRUE);
|
|
|
|
|
|
|
|
/* Step 4: set parameters for decompression */
|
|
|
|
|
|
|
|
|
|
|
|
/* Step 5: Start decompressor */
|
|
|
|
jpeg_start_decompress (&cinfo);
|
|
|
|
|
|
|
|
/* temporary buffers */
|
|
|
|
buf = g_new (guchar, cinfo.output_height * cinfo.output_width
|
|
|
|
* cinfo.output_components);
|
|
|
|
if (res_a->id == PSD_THUMB_RES)
|
|
|
|
rgb_buf = g_new (guchar, cinfo.output_height * cinfo.output_width
|
|
|
|
* cinfo.output_components);
|
|
|
|
else
|
|
|
|
rgb_buf = NULL;
|
|
|
|
rowbuf = g_new (guchar *, cinfo.output_height);
|
|
|
|
|
|
|
|
for (i = 0; i < cinfo.output_height; ++i)
|
|
|
|
rowbuf[i] = buf + cinfo.output_width * cinfo.output_components * i;
|
|
|
|
|
|
|
|
/* Create image layer */
|
2019-08-19 22:04:15 +08:00
|
|
|
gimp_image_resize (image, cinfo.output_width, cinfo.output_height, 0, 0);
|
|
|
|
layer = gimp_layer_new (image, _("Background"),
|
|
|
|
cinfo.output_width,
|
|
|
|
cinfo.output_height,
|
|
|
|
GIMP_RGB_IMAGE,
|
|
|
|
100,
|
|
|
|
gimp_image_get_default_new_layer_mode (image));
|
|
|
|
buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer));
|
2015-04-27 01:31:01 +08:00
|
|
|
format = babl_format ("R'G'B' u8");
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
/* Step 6: while (scan lines remain to be read) */
|
|
|
|
/* jpeg_read_scanlines(...); */
|
|
|
|
while (cinfo.output_scanline < cinfo.output_height)
|
|
|
|
{
|
|
|
|
jpeg_read_scanlines (&cinfo,
|
|
|
|
(JSAMPARRAY) &rowbuf[cinfo.output_scanline], 1);
|
2015-04-27 01:31:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (res_a->id == PSD_THUMB_RES) /* Order is BGR for resource 1033 */
|
|
|
|
{
|
|
|
|
guchar *dst = rgb_buf;
|
|
|
|
guchar *src = buf;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
2015-04-27 01:31:01 +08:00
|
|
|
for (i = 0; i < gegl_buffer_get_width (buffer) * gegl_buffer_get_height (buffer); ++i)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2015-04-27 01:31:01 +08:00
|
|
|
guchar r, g, b;
|
|
|
|
|
|
|
|
r = *(src++);
|
|
|
|
g = *(src++);
|
|
|
|
b = *(src++);
|
|
|
|
*(dst++) = b;
|
|
|
|
*(dst++) = g;
|
|
|
|
*(dst++) = r;
|
2007-12-20 19:12:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-27 01:31:01 +08:00
|
|
|
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0,
|
|
|
|
gegl_buffer_get_width (buffer),
|
|
|
|
gegl_buffer_get_height (buffer)),
|
|
|
|
0, format, rgb_buf ? rgb_buf : buf, GEGL_AUTO_ROWSTRIDE);
|
|
|
|
|
2007-12-20 19:12:05 +08:00
|
|
|
/* Step 7: Finish decompression */
|
|
|
|
jpeg_finish_decompress (&cinfo);
|
|
|
|
/* We can ignore the return value since suspension is not possible
|
|
|
|
* with the stdio data source.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Step 8: Release JPEG decompression object */
|
|
|
|
jpeg_destroy_decompress (&cinfo);
|
|
|
|
|
|
|
|
/* free up the temporary buffers */
|
|
|
|
g_free (rowbuf);
|
|
|
|
g_free (buf);
|
|
|
|
g_free (rgb_buf);
|
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
/* Close FILE */
|
|
|
|
fclose (f);
|
|
|
|
|
2007-12-20 19:12:05 +08:00
|
|
|
/* At this point you may want to check to see whether any
|
|
|
|
* corrupt-data warnings occurred (test whether
|
|
|
|
* jerr.num_warnings is nonzero).
|
|
|
|
*/
|
2019-08-19 22:04:15 +08:00
|
|
|
gimp_image_insert_layer (image, layer, NULL, 0);
|
2013-06-20 01:15:52 +08:00
|
|
|
g_object_unref (buffer);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_1039 (const PSDimageres *res_a,
|
2020-02-21 19:08:19 +08:00
|
|
|
PSDimage *img_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
/* Load ICC profile */
|
2015-08-20 17:15:26 +08:00
|
|
|
GimpColorProfile *profile;
|
|
|
|
gchar *icc_profile;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process image resource block: 1039: ICC Profile");
|
|
|
|
|
|
|
|
icc_profile = g_malloc (res_a->data_len);
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, icc_profile, res_a->data_len, error) < res_a->data_len)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2010-11-10 02:03:47 +08:00
|
|
|
g_free (icc_profile);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-08-20 17:15:26 +08:00
|
|
|
profile = gimp_color_profile_new_from_icc_profile ((guint8 *) icc_profile,
|
|
|
|
res_a->data_len,
|
|
|
|
NULL);
|
|
|
|
if (profile)
|
|
|
|
{
|
2020-02-21 19:08:19 +08:00
|
|
|
if (img_a->color_mode == PSD_CMYK &&
|
|
|
|
gimp_color_profile_is_cmyk (profile))
|
|
|
|
{
|
|
|
|
img_a->cmyk_profile = profile;
|
2022-07-21 20:34:31 +08:00
|
|
|
/* Store CMYK profile in GimpImage if attached */
|
|
|
|
gimp_image_set_simulation_profile (image, img_a->cmyk_profile);
|
2020-02-21 19:08:19 +08:00
|
|
|
}
|
2021-11-03 10:40:32 +08:00
|
|
|
else if (img_a->color_mode == PSD_LAB)
|
|
|
|
{
|
|
|
|
g_debug ("LAB color profile ignored.");
|
|
|
|
g_object_unref (profile);
|
|
|
|
}
|
2020-02-21 19:08:19 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
gimp_image_set_color_profile (image, profile);
|
|
|
|
g_object_unref (profile);
|
|
|
|
}
|
2015-08-20 17:15:26 +08:00
|
|
|
}
|
|
|
|
|
2007-12-20 19:12:05 +08:00
|
|
|
g_free (icc_profile);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_1045 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2008-01-09 05:02:56 +08:00
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
/* Load alpha channel names stored as a series of unicode strings
|
|
|
|
in a GPtrArray */
|
|
|
|
|
|
|
|
gchar *str;
|
2008-01-09 05:02:56 +08:00
|
|
|
gint32 block_rem;
|
|
|
|
gint32 read_len;
|
|
|
|
gint32 write_len;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process image resource block 1045: Unicode Alpha Channel Names");
|
|
|
|
|
|
|
|
if (img_a->alpha_names)
|
|
|
|
{
|
2008-01-09 05:02:56 +08:00
|
|
|
gint i;
|
|
|
|
IFDBG(3) g_debug ("Deleting localised alpha channel names");
|
|
|
|
for (i = 0; i < img_a->alpha_names->len; ++i)
|
|
|
|
{
|
|
|
|
str = g_ptr_array_index (img_a->alpha_names, i);
|
|
|
|
g_free (str);
|
|
|
|
}
|
2007-12-20 19:12:05 +08:00
|
|
|
g_ptr_array_free (img_a->alpha_names, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
img_a->alpha_names = g_ptr_array_new ();
|
|
|
|
|
|
|
|
block_rem = res_a->data_len;
|
|
|
|
while (block_rem > 1)
|
|
|
|
{
|
2023-05-04 10:57:28 +08:00
|
|
|
str = fread_unicode_string (&read_len, &write_len, 1, FALSE, input,
|
|
|
|
error);
|
2008-01-09 05:02:56 +08:00
|
|
|
if (*error)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
IFDBG(3) g_debug ("String: %s, %d, %d", str, read_len, write_len);
|
2007-12-20 19:12:05 +08:00
|
|
|
if (write_len >= 0)
|
|
|
|
{
|
2008-01-09 05:02:56 +08:00
|
|
|
g_ptr_array_add (img_a->alpha_names, (gpointer) str);
|
2007-12-20 19:12:05 +08:00
|
|
|
}
|
|
|
|
block_rem -= read_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_1046 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
/* Load indexed color table count */
|
|
|
|
guchar *cmap;
|
|
|
|
gint32 cmap_count = 0;
|
|
|
|
gint16 index_count = 0;
|
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process image resource block: 1046: Indexed Color Table Count");
|
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &index_count, 2, error) < 2)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
index_count = GINT16_FROM_BE (index_count);
|
|
|
|
|
2008-01-09 05:02:56 +08:00
|
|
|
IFDBG(3) g_debug ("Indexed color table count: %d", index_count);
|
2007-12-20 19:12:05 +08:00
|
|
|
/* FIXME - check that we have indexed image */
|
|
|
|
if (index_count && index_count < 256)
|
|
|
|
{
|
2023-05-24 05:37:46 +08:00
|
|
|
cmap = gimp_image_get_colormap (image, NULL, &cmap_count);
|
2007-12-20 19:12:05 +08:00
|
|
|
if (cmap && index_count < cmap_count)
|
2019-08-19 22:04:15 +08:00
|
|
|
gimp_image_set_colormap (image, cmap, index_count);
|
2007-12-20 19:12:05 +08:00
|
|
|
g_free (cmap);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_1053 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2008-01-09 05:02:56 +08:00
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
/* Load image alpha channel ids (tattoos) */
|
2008-01-09 05:02:56 +08:00
|
|
|
gint16 tot_rec;
|
|
|
|
gint16 cidx;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process image resource block: 1053: Channel ID");
|
|
|
|
|
|
|
|
tot_rec = res_a->data_len / 4;
|
|
|
|
if (tot_rec ==0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
img_a->alpha_id = g_malloc (sizeof (img_a->alpha_id) * tot_rec);
|
|
|
|
img_a->alpha_id_count = tot_rec;
|
|
|
|
for (cidx = 0; cidx < tot_rec; ++cidx)
|
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &img_a->alpha_id[cidx], 4, error) < 4)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
img_a->alpha_id[cidx] = GUINT32_FROM_BE (img_a->alpha_id[cidx]);
|
|
|
|
|
|
|
|
IFDBG(3) g_debug ("Channel id: %d", img_a->alpha_id[cidx]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_1058 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
|
|
|
gchar *name;
|
|
|
|
|
|
|
|
GimpParasite *parasite;
|
|
|
|
gchar *res_data;
|
|
|
|
|
2013-10-30 05:48:46 +08:00
|
|
|
IFDBG(2) g_debug ("Process image resource block: 1058: Exif data");
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
res_data = g_malloc (res_a->data_len);
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, res_data, res_a->data_len, error) < res_a->data_len)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2010-11-10 02:03:47 +08:00
|
|
|
g_free (res_data);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Store resource data as a standard psd parasite */
|
|
|
|
IFDBG (2) g_debug ("Processing exif data as psd parasite");
|
|
|
|
name = g_strdup_printf ("psd-image-resource-%.4s-%.4x",
|
|
|
|
res_a->type, res_a->id);
|
2008-01-09 05:02:56 +08:00
|
|
|
IFDBG(3) g_debug ("Parasite name: %s", name);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
parasite = gimp_parasite_new (name, 0, res_a->data_len, res_data);
|
2019-08-19 22:04:15 +08:00
|
|
|
gimp_image_attach_parasite (image, parasite);
|
2007-12-20 19:12:05 +08:00
|
|
|
gimp_parasite_free (parasite);
|
|
|
|
g_free (name);
|
|
|
|
|
|
|
|
g_free (res_data);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-02-22 06:24:54 +08:00
|
|
|
static gint
|
|
|
|
load_resource_1069 (const PSDimageres *res_a,
|
|
|
|
GimpImage *image,
|
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2021-02-22 06:24:54 +08:00
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
guint16 layer_count;
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process image resource block: 1069: Layer Selection ID(s)");
|
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &layer_count, 2, error) < 2)
|
2021-02-22 06:24:54 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2021-02-22 06:24:54 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
layer_count = GUINT16_FROM_BE (layer_count);
|
|
|
|
|
|
|
|
/* This should probably not happen, but just in case the block is
|
|
|
|
* duplicated, let's just free the previous selection.
|
|
|
|
*/
|
|
|
|
g_list_free (img_a->layer_selection);
|
|
|
|
img_a->layer_selection = NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < layer_count; i++)
|
|
|
|
{
|
|
|
|
guint32 layer_id;
|
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &layer_id, 4, error) < 4)
|
2021-02-22 06:24:54 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2021-02-22 06:24:54 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
layer_id = GUINT32_FROM_BE (layer_id);
|
|
|
|
img_a->layer_selection = g_list_prepend (img_a->layer_selection, GINT_TO_POINTER (layer_id));
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-06-20 01:15:52 +08:00
|
|
|
static gint
|
|
|
|
load_resource_1077 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2013-06-20 01:15:52 +08:00
|
|
|
PSDimage *img_a,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2013-06-20 01:15:52 +08:00
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
/* Load alpha channel display info */
|
|
|
|
|
|
|
|
DisplayInfoNew dsp_info;
|
|
|
|
CMColor ps_color;
|
|
|
|
gint16 tot_rec;
|
|
|
|
gint cidx;
|
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process image resource block 1077: Display Info New");
|
|
|
|
|
|
|
|
/* For now, skip first 4 bytes since intention is unclear. Seems to be
|
|
|
|
a version number that is always one, but who knows. */
|
2021-05-10 11:21:02 +08:00
|
|
|
if (! psd_seek (input, 4, G_SEEK_CUR, error))
|
|
|
|
return -1;
|
2013-06-20 01:15:52 +08:00
|
|
|
|
|
|
|
tot_rec = res_a->data_len / 13;
|
|
|
|
if (tot_rec == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
img_a->alpha_display_info = g_new (PSDchanneldata *, tot_rec);
|
|
|
|
img_a->alpha_display_count = tot_rec;
|
|
|
|
for (cidx = 0; cidx < tot_rec; ++cidx)
|
|
|
|
{
|
2023-11-20 07:20:03 +08:00
|
|
|
GeglColor *color;
|
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &dsp_info.colorSpace, 2, error) < 2 ||
|
|
|
|
psd_read (input, &dsp_info.color, 8, error) < 8 ||
|
|
|
|
psd_read (input, &dsp_info.opacity, 2, error) < 2 ||
|
|
|
|
psd_read (input, &dsp_info.mode, 1, error) < 1)
|
2013-06-20 01:15:52 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2013-06-20 01:15:52 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
dsp_info.colorSpace = GINT16_FROM_BE (dsp_info.colorSpace);
|
|
|
|
ps_color.cmyk.cyan = GUINT16_FROM_BE (dsp_info.color[0]);
|
|
|
|
ps_color.cmyk.magenta = GUINT16_FROM_BE (dsp_info.color[1]);
|
|
|
|
ps_color.cmyk.yellow = GUINT16_FROM_BE (dsp_info.color[2]);
|
|
|
|
ps_color.cmyk.black = GUINT16_FROM_BE (dsp_info.color[3]);
|
|
|
|
dsp_info.opacity = GINT16_FROM_BE (dsp_info.opacity);
|
|
|
|
|
2023-11-20 07:20:03 +08:00
|
|
|
color = gegl_color_new ("red");
|
|
|
|
|
2013-06-20 01:15:52 +08:00
|
|
|
switch (dsp_info.colorSpace)
|
|
|
|
{
|
|
|
|
case PSD_CS_RGB:
|
2023-11-20 07:20:03 +08:00
|
|
|
/* TODO: which space? */
|
|
|
|
gegl_color_set_rgba_with_space (color,
|
|
|
|
ps_color.rgb.red / 65535.0,
|
|
|
|
ps_color.rgb.green / 65535.0,
|
|
|
|
ps_color.rgb.blue / 65535.0,
|
|
|
|
1.0, NULL);
|
2013-06-20 01:15:52 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PSD_CS_HSB:
|
2023-11-20 07:20:03 +08:00
|
|
|
{
|
2024-04-21 11:42:27 +08:00
|
|
|
gfloat hsv[3] =
|
2023-11-20 07:20:03 +08:00
|
|
|
{
|
2024-04-21 11:42:27 +08:00
|
|
|
ps_color.hsv.hue / 65535.0f,
|
|
|
|
ps_color.hsv.saturation / 65535.0f,
|
|
|
|
ps_color.hsv.value / 65535.0f
|
2023-11-20 07:20:03 +08:00
|
|
|
};
|
|
|
|
|
2024-04-21 11:42:27 +08:00
|
|
|
gegl_color_set_pixel (color, babl_format ("HSV float"), hsv);
|
2023-11-20 07:20:03 +08:00
|
|
|
}
|
2013-06-20 01:15:52 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PSD_CS_CMYK:
|
2023-11-20 07:20:03 +08:00
|
|
|
/* TODO: which space? */
|
|
|
|
gegl_color_set_cmyk (color,
|
|
|
|
1.0 - ps_color.cmyk.cyan / 65535.0,
|
|
|
|
1.0 - ps_color.cmyk.magenta / 65535.0,
|
|
|
|
1.0 - ps_color.cmyk.yellow / 65535.0,
|
|
|
|
1.0 - ps_color.cmyk.black / 65535.0,
|
|
|
|
1.0, NULL);
|
2013-06-20 01:15:52 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PSD_CS_GRAYSCALE:
|
2023-11-20 07:20:03 +08:00
|
|
|
{
|
|
|
|
gdouble gray = ps_color.gray.gray / 10000.0;
|
|
|
|
|
|
|
|
/* TODO: which space? */
|
|
|
|
gegl_color_set_pixel (color, babl_format_with_space ("Y' double", NULL), &gray);
|
|
|
|
}
|
2013-06-20 01:15:52 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PSD_CS_FOCOLTONE:
|
|
|
|
case PSD_CS_TRUMATCH:
|
|
|
|
case PSD_CS_HKS:
|
|
|
|
case PSD_CS_LAB:
|
|
|
|
case PSD_CS_PANTONE:
|
|
|
|
case PSD_CS_TOYO:
|
|
|
|
case PSD_CS_DIC:
|
|
|
|
case PSD_CS_ANPA:
|
|
|
|
default:
|
|
|
|
if (CONVERSION_WARNINGS)
|
|
|
|
g_message ("Unsupported color space: %d",
|
|
|
|
dsp_info.colorSpace);
|
|
|
|
}
|
|
|
|
|
2020-04-27 03:45:44 +08:00
|
|
|
IFDBG(2) g_debug ("PS cSpace: %d, col: %d %d %d %d, opacity: %d, mode: %d",
|
2013-06-20 01:15:52 +08:00
|
|
|
dsp_info.colorSpace, ps_color.cmyk.cyan, ps_color.cmyk.magenta,
|
|
|
|
ps_color.cmyk.yellow, ps_color.cmyk.black, dsp_info.opacity,
|
2020-04-27 03:45:44 +08:00
|
|
|
dsp_info.mode);
|
2013-06-20 01:15:52 +08:00
|
|
|
|
2023-11-20 07:20:03 +08:00
|
|
|
IFDBG(2) g_debug ("cSpace: %d, opacity: %d, mode: %d",
|
|
|
|
dsp_info.colorSpace, dsp_info.opacity, dsp_info.mode);
|
2013-06-20 01:15:52 +08:00
|
|
|
|
2020-04-27 03:45:44 +08:00
|
|
|
img_a->alpha_display_info[cidx] = g_malloc0 (sizeof (PSDchanneldata));
|
2023-11-20 07:20:03 +08:00
|
|
|
img_a->alpha_display_info[cidx]->gimp_color = color;
|
2013-06-20 01:15:52 +08:00
|
|
|
img_a->alpha_display_info[cidx]->opacity = dsp_info.opacity;
|
|
|
|
img_a->alpha_display_info[cidx]->ps_mode = dsp_info.mode;
|
|
|
|
img_a->alpha_display_info[cidx]->ps_cspace = dsp_info.colorSpace;
|
|
|
|
img_a->alpha_display_info[cidx]->ps_color = ps_color;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-12-20 19:12:05 +08:00
|
|
|
static gint
|
2008-01-09 05:02:56 +08:00
|
|
|
load_resource_2000 (const PSDimageres *res_a,
|
2019-08-19 22:04:15 +08:00
|
|
|
GimpImage *image,
|
2021-05-10 11:21:02 +08:00
|
|
|
GInputStream *input,
|
2008-01-09 05:02:56 +08:00
|
|
|
GError **error)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2024-07-12 14:16:25 +08:00
|
|
|
gdouble *controlpoints;
|
|
|
|
gint32 x[3];
|
|
|
|
gint32 y[3];
|
|
|
|
GimpPath *path = NULL;
|
|
|
|
gint16 type;
|
|
|
|
gint16 init_fill;
|
|
|
|
gint16 num_rec;
|
|
|
|
gint16 path_rec;
|
|
|
|
gint16 cntr;
|
|
|
|
gint image_width;
|
|
|
|
gint image_height;
|
|
|
|
gint i;
|
|
|
|
gboolean closed;
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
/* Load path data from image resources 2000-2998 */
|
|
|
|
|
|
|
|
IFDBG(2) g_debug ("Process image resource block: %d :Path data", res_a->id);
|
|
|
|
path_rec = res_a->data_len / 26;
|
|
|
|
if (path_rec ==0)
|
|
|
|
return 0;
|
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &type, 2, error) < 2)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
type = GINT16_FROM_BE (type);
|
|
|
|
if (type != PSD_PATH_FILL_RULE)
|
|
|
|
{
|
2008-01-09 05:02:56 +08:00
|
|
|
IFDBG(1) g_debug ("Unexpected path record type: %d", type);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
if (! psd_seek (input, 24, G_SEEK_CUR, error))
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
path_rec--;
|
|
|
|
if (path_rec ==0)
|
|
|
|
return 0;
|
|
|
|
|
2021-04-06 06:47:07 +08:00
|
|
|
image_width = gimp_image_get_width (image);
|
|
|
|
image_height = gimp_image_get_height (image);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
/* Create path */
|
2011-12-01 06:17:09 +08:00
|
|
|
if (res_a->id == PSD_WORKING_PATH)
|
|
|
|
{
|
|
|
|
/* use "Working Path" for the path name to match the Photoshop display */
|
2024-07-09 07:39:51 +08:00
|
|
|
path = gimp_path_new (image, "Working Path");
|
2011-12-01 06:17:09 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Use the name stored in the PSD to name the path */
|
2024-07-09 07:39:51 +08:00
|
|
|
path = gimp_path_new (image, res_a->name);
|
2011-12-01 06:17:09 +08:00
|
|
|
}
|
|
|
|
|
2024-07-09 07:39:51 +08:00
|
|
|
gimp_image_insert_path (image, path, NULL, -1);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
while (path_rec > 0)
|
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &type, 2, error) < 2)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
type = GINT16_FROM_BE (type);
|
2008-01-09 05:02:56 +08:00
|
|
|
IFDBG(3) g_debug ("Path record type %d", type);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
if (type == PSD_PATH_FILL_RULE)
|
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
if (! psd_seek (input, 24, G_SEEK_CUR, error))
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (type == PSD_PATH_FILL_INIT)
|
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &init_fill, 2, error) < 2)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-05-10 11:21:02 +08:00
|
|
|
if (! psd_seek (input, 22, G_SEEK_CUR, error))
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (type == PSD_PATH_CL_LEN
|
|
|
|
|| type == PSD_PATH_OP_LEN)
|
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &num_rec, 2, error) < 2)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
num_rec = GINT16_FROM_BE (num_rec);
|
2021-05-10 11:21:02 +08:00
|
|
|
IFDBG(3) g_debug ("Num path records %d", num_rec);
|
2007-12-20 19:12:05 +08:00
|
|
|
if (num_rec > path_rec)
|
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type == PSD_PATH_CL_LEN)
|
|
|
|
closed = TRUE;
|
|
|
|
else
|
|
|
|
closed = FALSE;
|
|
|
|
cntr = 0;
|
|
|
|
controlpoints = g_malloc (sizeof (gdouble) * num_rec * 6);
|
2021-05-10 11:21:02 +08:00
|
|
|
if (! psd_seek (input, 22, G_SEEK_CUR, error))
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2010-11-10 02:03:47 +08:00
|
|
|
g_free (controlpoints);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (num_rec > 0)
|
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &type, 2, error) < 2)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
type = GINT16_FROM_BE (type);
|
2008-01-09 05:02:56 +08:00
|
|
|
IFDBG(3) g_debug ("Path record type %d", type);
|
2007-12-20 19:12:05 +08:00
|
|
|
|
|
|
|
if (type == PSD_PATH_CL_LNK
|
|
|
|
|| type == PSD_PATH_CL_UNLNK
|
|
|
|
|| type == PSD_PATH_OP_LNK
|
|
|
|
|| type == PSD_PATH_OP_UNLNK)
|
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
if (psd_read (input, &y[0], 4, error) < 4 ||
|
|
|
|
psd_read (input, &x[0], 4, error) < 4 ||
|
|
|
|
psd_read (input, &y[1], 4, error) < 4 ||
|
|
|
|
psd_read (input, &x[1], 4, error) < 4 ||
|
|
|
|
psd_read (input, &y[2], 4, error) < 4 ||
|
|
|
|
psd_read (input, &x[2], 4, error) < 4)
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
for (i = 0; i < 3; ++i)
|
|
|
|
{
|
|
|
|
x[i] = GINT32_FROM_BE (x[i]);
|
|
|
|
controlpoints[cntr] = x[i] / 16777216.0 * image_width;
|
|
|
|
cntr++;
|
|
|
|
y[i] = GINT32_FROM_BE (y[i]);
|
|
|
|
controlpoints[cntr] = y[i] / 16777216.0 * image_height;
|
|
|
|
cntr++;
|
|
|
|
}
|
2008-01-09 05:02:56 +08:00
|
|
|
IFDBG(3) g_debug ("Path points (%d,%d), (%d,%d), (%d,%d)",
|
2007-12-20 19:12:05 +08:00
|
|
|
x[0], y[0], x[1], y[1], x[2], y[2]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-01-09 05:02:56 +08:00
|
|
|
IFDBG(1) g_debug ("Unexpected path type record %d", type);
|
2021-05-10 11:21:02 +08:00
|
|
|
if (! psd_seek (input, 24, G_SEEK_CUR, error))
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
path_rec--;
|
|
|
|
num_rec--;
|
|
|
|
}
|
|
|
|
/* Add sub-path */
|
2024-07-09 07:39:51 +08:00
|
|
|
gimp_path_stroke_new_from_points (path,
|
2024-07-19 23:07:43 +08:00
|
|
|
GIMP_PATH_STROKE_TYPE_BEZIER,
|
2024-07-09 07:39:51 +08:00
|
|
|
cntr, controlpoints, closed);
|
2007-12-20 19:12:05 +08:00
|
|
|
g_free (controlpoints);
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
if (! psd_seek (input, 24, G_SEEK_CUR, error))
|
2007-12-20 19:12:05 +08:00
|
|
|
{
|
2021-05-10 11:21:02 +08:00
|
|
|
psd_set_error (error);
|
2007-12-20 19:12:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
path_rec--;
|
|
|
|
}
|
|
|
|
|
2013-06-20 01:15:52 +08:00
|
|
|
return 0;
|
2007-12-20 19:12:05 +08:00
|
|
|
}
|
2022-10-29 02:01:48 +08:00
|
|
|
|
|
|
|
static gint
|
|
|
|
load_resource_2999 (const PSDimageres *res_a,
|
|
|
|
GimpImage *image,
|
|
|
|
GInputStream *input,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
gchar *path_name;
|
|
|
|
gint16 path_flatness_int;
|
|
|
|
gint16 path_flatness_fixed;
|
|
|
|
gfloat path_flatness;
|
|
|
|
GimpParasite *parasite;
|
|
|
|
gint32 read_len;
|
|
|
|
gint32 write_len;
|
|
|
|
|
|
|
|
path_name = fread_pascal_string (&read_len, &write_len, 2, input, error);
|
|
|
|
if (*error)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Convert from fixed to floating point */
|
2024-04-09 05:51:36 +08:00
|
|
|
if (psd_read (input, &path_flatness_int, 2, error) < 2 ||
|
|
|
|
psd_read (input, &path_flatness_fixed, 2, error) < 2)
|
2022-10-29 02:01:48 +08:00
|
|
|
{
|
|
|
|
psd_set_error (error);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
path_flatness_fixed = GINT16_FROM_BE (path_flatness_fixed);
|
2024-04-09 05:51:36 +08:00
|
|
|
path_flatness_int = GINT16_FROM_BE (path_flatness_int);
|
|
|
|
|
2022-10-29 02:01:48 +08:00
|
|
|
/* Converting from Adobe fixed point value to float */
|
|
|
|
path_flatness = (path_flatness_fixed - 0.5f) / 65536.0;
|
|
|
|
path_flatness += path_flatness_int;
|
|
|
|
|
|
|
|
/* Adobe path flatness range is 0.2 to 100.0 */
|
|
|
|
path_flatness = CLAMP (path_flatness, 0.2f, 100.0f);
|
|
|
|
|
|
|
|
/* Save to image parasite */
|
|
|
|
parasite = gimp_parasite_new (PSD_PARASITE_CLIPPING_PATH, 0,
|
|
|
|
read_len, path_name);
|
|
|
|
gimp_image_attach_parasite (image, parasite);
|
|
|
|
gimp_parasite_free (parasite);
|
|
|
|
|
|
|
|
parasite = gimp_parasite_new (PSD_PARASITE_PATH_FLATNESS, 0,
|
|
|
|
sizeof (gfloat), &path_flatness);
|
|
|
|
gimp_image_attach_parasite (image, parasite);
|
|
|
|
gimp_parasite_free (parasite);
|
|
|
|
|
|
|
|
/* Adobe says they ignore the last two bytes, the fill rule */
|
2024-04-09 05:51:36 +08:00
|
|
|
if (psd_read (input, &path_flatness_fixed, 2, error) < 2)
|
2022-10-29 02:01:48 +08:00
|
|
|
{
|
|
|
|
psd_set_error (error);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (path_name);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|