configure.in plug-ins/Makefile.am added new PSD load plug-in written by

2007-12-20  Sven Neumann  <sven@gimp.org>

	* configure.in
	* plug-ins/Makefile.am
	* plug-ins/psd: added new PSD load plug-in written by John Marshall.
	This plug-in adds a couple of features. See bug #448181 for details.

	* plug-ins/common/Makefile.am
	* plug-ins/common/plugin-defs.pl
	* plug-ins/common/psd-load.c: removed old psd-load plug-in.

svn path=/trunk/; revision=24408
This commit is contained in:
Sven Neumann 2007-12-20 11:12:05 +00:00 committed by Sven Neumann
parent 318bcd396d
commit 4e8df6af94
21 changed files with 6073 additions and 3392 deletions

View file

@ -1,3 +1,14 @@
2007-12-20 Sven Neumann <sven@gimp.org>
* configure.in
* plug-ins/Makefile.am
* plug-ins/psd: added new PSD load plug-in written by John Marshall.
This plug-in adds a couple of features. See bug #448181 for details.
* plug-ins/common/Makefile.am
* plug-ins/common/plugin-defs.pl
* plug-ins/common/psd-load.c: removed old psd-load plug-in.
2007-12-20 Sven Neumann <sven@gimp.org>
* app/widgets/gimpprofilechooserdialog.c: added code for adding a

View file

@ -66,6 +66,7 @@ SUBDIRS = \
pagecurl \
$(print) \
$(pygimp) \
psd \
rcm \
sgi \
sel2path \

View file

@ -133,7 +133,6 @@ libexec_PROGRAMS = \
$(POPPLER) \
postscript \
procedure-browser \
psd-load \
psd-save \
$(PSP) \
randomize \
@ -1730,22 +1729,6 @@ procedure_browser_LDADD = \
$(RT_LIBS) \
$(INTLLIBS)
psd_load_SOURCES = \
psd-load.c
psd_load_LDADD = \
$(libgimpui) \
$(libgimpwidgets) \
$(libgimpmodule) \
$(libgimp) \
$(libgimpmath) \
$(libgimpconfig) \
$(libgimpcolor) \
$(libgimpbase) \
$(GTK_LIBS) \
$(RT_LIBS) \
$(INTLLIBS)
psd_save_SOURCES = \
psd-save.c

View file

@ -96,7 +96,6 @@
'poppler' => { ui => 1, optional => 1, cflags => 1 },
'postscript' => { ui => 1 },
'procedure-browser' => { ui => 1 },
'psd-load' => { ui => 1 },
'psd-save' => { ui => 1 },
'psp' => { ui => 1, optional => 1, libopt => 'z' },
'randomize' => { ui => 1 },

File diff suppressed because it is too large Load diff

57
plug-ins/psd/Makefile.am Normal file
View file

@ -0,0 +1,57 @@
## Process this file with automake to produce Makefile.in
libgimpui = $(top_builddir)/libgimp/libgimpui-$(GIMP_API_VERSION).la
libgimpconfig = $(top_builddir)/libgimpconfig/libgimpconfig-$(GIMP_API_VERSION).la
libgimpwidgets = $(top_builddir)/libgimpwidgets/libgimpwidgets-$(GIMP_API_VERSION).la
libgimp = $(top_builddir)/libgimp/libgimp-$(GIMP_API_VERSION).la
libgimpcolor = $(top_builddir)/libgimpcolor/libgimpcolor-$(GIMP_API_VERSION).la
libgimpbase = $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la
libgimpmath = $(top_builddir)/libgimpmath/libgimpmath-$(GIMP_API_VERSION).la
if OS_WIN32
mwindows = -mwindows
endif
AM_LDFLAGS = $(mwindows)
libexecdir = $(gimpplugindir)/plug-ins
libexec_PROGRAMS = psd
psd_SOURCES = \
psd.c \
psd.h \
psd-util.c \
psd-util.h \
psd-load.c \
psd-load.h \
psd-thumb-load.c \
psd-thumb-load.h \
psd-image-res-load.c \
psd-image-res-load.h \
psd-layer-res-load.c \
psd-layer-res-load.h
EXTRA_DIST = \
TODO.txt \
new-resource-ids.txt
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(libgimpui) \
$(libgimpwidgets) \
$(libgimpconfig) \
$(libgimp) \
$(libgimpcolor) \
$(libgimpmath) \
$(libgimpbase) \
$(LIBJPEG) \
$(GTK_LIBS) \
$(EXIF_LIBS) \
$(IPTCDATA_LIBS) \
$(RT_LIBS) \
$(INTLLIBS)

54
plug-ins/psd/TODO.txt Normal file
View file

@ -0,0 +1,54 @@
Load
====
Photoshop 2.0 and lower files are not supported due to lack of
file specs and test files.
Add text names for colour modes
Parasite for layer blending ranges per channel?
Read & use global mask data
Check for block over-run in read_channel_data
Process errors from readers in read_channel_data
Invert layer mask - channel_set_show_masked or invert mask + parasite
decode more image resources
Read in layer resources and process adjustment layers etc.
add parasites as required - should be similar to image resources
add layer support for:
Text layers
vector masks
Image resources:
================
1005 - resolution
width and height units dropped.
1007 - Display info
save colour space & colour as parasite if unable to display.
1008 - caption - Add to XMP data block.
1025 - Working path (not saved) - Load
1026 - Layers Group Info - ?Load
1033 1036
Better error handling for Jpeg decompression. Check for JPEG being included
Custom error function.
1041 - Honour ICC untagged option
2000-2998 - Paths
Add initial fill rule and clipboard parasites.
2999 - Clipping path
Add as parasite to path record.

View file

@ -0,0 +1,23 @@
Unknown resource ID's seen in PSD files but not yet identified.
8BIM 1061 (0x0425)
8BIM 1062 (0x0426)
8BIM 1064 (0x0428)
8BIM 1069 (0x042d)
8BIM 1072 (0x0430)
8BIM 1077 (0x0435)
MeSa 7002 (0x165a)
MeSa 7003 (0x165b)
8BIM 4000 (0x0fa0)
8BIM 4001 (0x0fa1)
8BIM 4002 (0x0fa2)
8BIM 4003 (0x0fa3)
8BIM 4004 (0x0fa4)
8BIM 4005 (0x0fa5)
8BIM 4006 (0x0fa6)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,39 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* GIMP PSD Plug-in
* Copyright 2007 by John Marshall
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __PSD_IMAGE_RES_LOAD_H__
#define __PSD_IMAGE_RES_LOAD_H__
gint get_image_resource_header (PSDimageres *res_a,
FILE *f);
gint load_image_resource (PSDimageres *res_a,
const gint32 image_id,
PSDimage *img_a,
FILE *f);
gint load_thumbnail_resource (PSDimageres *res_a,
const gint32 image_id,
FILE *f);
#endif /* __PSD_IMAGE_RES_LOAD_H__ */

View file

@ -0,0 +1,473 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* GIMP PSD Plug-in
* Copyright 2007 by John Marshall
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* ----- Known Layer Resource Block Types -----
All layer resources not otherwise handled, including unknown types
are dropped with a warning.
* Adjustment layer IDs *
PSD_LADJ_LEVEL "levl" Drop Layer * Adjustment layer - levels (PS4) *
PSD_LADJ_CURVE "curv" Drop Layer * Adjustment layer - curves (PS4) *
PSD_LADJ_BRIGHTNESS "brit" Drop Layer * Adjustment layer - brightness contrast (PS4) *
PSD_LADJ_BALANCE "blnc" Drop Layer * Adjustment layer - color balance (PS4) *
PSD_LADJ_BLACK_WHITE "blwh" Drop Layer * Adjustment layer - black & white (PS10) *
PSD_LADJ_HUE "hue " Drop Layer * Adjustment layer - old hue saturation (PS4) *
PSD_LADJ_HUE2 "hue2" Drop Layer * Adjustment layer - hue saturation (PS5) *
PSD_LADJ_SELECTIVE "selc" Drop Layer * Adjustment layer - selective color (PS4) *
PSD_LADJ_MIXER "mixr" Drop Layer * Adjustment layer - channel mixer (PS9) *
PSD_LADJ_GRAD_MAP "grdm" Drop Layer * Adjustment layer - gradient map (PS9) *
PSD_LADJ_PHOTO_FILT "phfl" Drop Layer * Adjustment layer - photo filter (PS9) *
PSD_LADJ_EXPOSURE "expA" Drop Layer * Adjustment layer - exposure (PS10) *
PSD_LADJ_INVERT "nvrt" Drop Layer * Adjustment layer - invert (PS4) *
PSD_LADJ_THRESHOLD "thrs" Drop Layer * Adjustment layer - threshold (PS4) *
PSD_LADJ_POSTERIZE "post" Drop Layer * Adjustment layer - posterize (PS4) *
* Fill Layer IDs *
PSD_LFIL_SOLID "SoCo" - * Solid color sheet setting (PS6) *
PSD_LFIL_PATTERN "PtFl" - * Pattern fill setting (PS6) *
PSD_LFIL_GRADIENT "GdFl" - * Gradient fill setting (PS6) *
* Effects Layer IDs *
PSD_LFX_FX "lrFX" - * Effects layer info (PS5) *
PSD_LFX_FX2 "lfx2" - * Object based effects layer info (PS6) *
* Type Tool Layers *
PSD_LTYP_TYPE "tySh" - * Type tool layer (PS5) *
PSD_LTYP_TYPE2 "TySh" - * Type tool object setting (PS6) *
* Layer Properties *
PSD_LPRP_UNICODE "luni" Loaded * Unicode layer name (PS5) *
PSD_LPRP_SOURCE "lnsr" Loaded * Layer name source setting (PS6) *
PSD_LPRP_ID "lyid" Loaded * Layer ID (PS5) *
PSD_LPRP_BLEND_CLIP "clbl" - * Blend clipping elements (PS6) *
PSD_LPRP_BLEND_INT "infx" - * Blend interior elements (PS6) *
PSD_LPRP_KNOCKOUT "knko" - * Knockout setting (PS6) *
PSD_LPRP_PROTECT "lspf" - * Protected setting (PS6) *
PSD_LPRP_COLOR "lclr" - * Sheet color setting (PS6) *
PSD_LPRP_REF_POINT "fxrp" - * Reference point (PS6) *
* Vector mask *
PSD_LMSK_VMASK "vmsk" - * Vector mask setting (PS6) *
* Parasites *
PSD_LPAR_ANNOTATE "Anno" - * Annotation (PS6) *
* Other *
PSD_LOTH_PATTERN "Patt" - * Patterns (PS6) *
PSD_LOTH_GRADIENT "grdm" - * Gradient settings (PS6) *
PSD_LOTH_SECTION "lsct" Drop Layer * Section divider setting (PS6) (Layer Groups) *
PSD_LOTH_RESTRICT "brst" - * Channel blending restirction setting (PS6) *
PSD_LOTH_FOREIGN_FX "ffxi" - * Foreign effect ID (PS6) *
PSD_LOTH_PATT_DATA "shpa" - * Pattern data (PS6) *
PSD_LOTH_META_DATA "shmd" - * Meta data setting (PS6) *
PSD_LOTH_LAYER_DATA "layr" - * Layer data (PS6) *
* Effects layer resource IDs *
PSD_LFX_COMMON "cmnS" - * Effects layer - common state (PS5) *
PSD_LFX_DROP_SDW "dsdw" - * Effects layer - drop shadow (PS5) *
PSD_LFX_INNER_SDW "isdw" - * Effects layer - inner shadow (PS5) *
PSD_LFX_OUTER_GLW "oglw" - * Effects layer - outer glow (PS5) *
PSD_LFX_INNER_GLW "iglw" - * Effects layer - inner glow (PS5) *
PSD_LFX_BEVEL "bevl" - * Effects layer - bevel (PS5) *
*/
#include "config.h"
#include <string.h>
#include <glib/gstdio.h>
#include <libgimp/gimp.h>
#include "psd.h"
#include "psd-util.h"
#include "psd-layer-res-load.h"
#include "libgimp/stdplugins-intl.h"
/* Local function prototypes */
static gint load_resource_unknown (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f);
static gint load_resource_ladj (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f);
static gint load_resource_lfil (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f);
static gint load_resource_lfx (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f);
static gint load_resource_ltyp (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f);
static gint load_resource_luni (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f);
static gint load_resource_lyid (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f);
static gint load_resource_lsct (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f);
/* Public Functions */
gint
get_layer_resource_header (PSDlayerres *res_a,
FILE *f)
{
if (fread (res_a->sig, 4, 1, f) < 1
|| fread (res_a->key, 4, 1, f) < 1
|| fread (&res_a->data_len, 4, 1, f) < 1)
{
g_message (_("Error reading layer resource block header"));
return -1;
}
res_a->data_len = GUINT32_FROM_BE (res_a->data_len);
res_a->data_start = ftell (f);
IFDBG(2) g_debug ("Sig: %.4s, key: %.4s, start: %d, len: %d",
res_a->sig, res_a->key, res_a->data_start, res_a->data_len);
return 0;
}
gint
load_layer_resource (PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f)
{
gint pad;
/* Set file position to start of layer resource data block */
if (fseek (f, res_a->data_start, SEEK_SET) < 0)
{
g_message (_("Error setting file position"));
return -1;
}
/* Process layer resource blocks */
if (memcmp (res_a->sig, "8BIM", 4) != 0)
g_message (_("Unknown layer resource signature %.4s"), res_a->sig);
if (memcmp (res_a->key, PSD_LADJ_LEVEL, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_CURVE, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_BRIGHTNESS, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_BALANCE, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_BLACK_WHITE, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_HUE, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_HUE2, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_SELECTIVE, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_MIXER, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_GRAD_MAP, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_PHOTO_FILT, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_EXPOSURE, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_THRESHOLD, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_INVERT, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_POSTERIZE, 4) == 0)
load_resource_ladj (res_a, lyr_a, f);
else if (memcmp (res_a->key, PSD_LFIL_SOLID, 4) == 0
|| memcmp (res_a->key, PSD_LFIL_PATTERN, 4) == 0
|| memcmp (res_a->key, PSD_LFIL_GRADIENT, 4) == 0)
load_resource_lfil (res_a, lyr_a, f);
else if (memcmp (res_a->key, PSD_LFX_FX, 4) == 0
|| memcmp (res_a->key, PSD_LFX_FX2, 4) == 0)
load_resource_lfx (res_a, lyr_a, f);
else if (memcmp (res_a->key, PSD_LTYP_TYPE, 4) == 0
|| memcmp (res_a->key, PSD_LTYP_TYPE2, 4) == 0)
load_resource_ltyp (res_a, lyr_a, f);
else if (memcmp (res_a->key, PSD_LPRP_UNICODE, 4) == 0)
load_resource_luni (res_a, lyr_a, f);
else if (memcmp (res_a->key, PSD_LPRP_ID, 4) == 0)
load_resource_lyid (res_a, lyr_a, f);
else if (memcmp (res_a->key, PSD_LOTH_SECTION, 4) == 0)
load_resource_lsct (res_a, lyr_a, f);
else
load_resource_unknown (res_a, lyr_a, f);
/* Layer 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 layer resource block */
if (fseek (f, res_a->data_start + res_a->data_len + pad, SEEK_SET) < 0)
{
g_message (_("Error setting file position"));
return -1;
}
return 0;
}
/* Private Functions */
static gint
load_resource_unknown (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f)
{
IFDBG(2) g_debug ("Process unknown layer resource block: %.4s", res_a->key);
return 0;
}
static gint
load_resource_ladj (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f)
{
/* Load adjustment layer */
static gboolean msg_flag = FALSE;
IFDBG(2) g_debug ("Process layer resource block %.4s: Adjustment layer", res_a->key);
lyr_a->drop = TRUE;
if (! msg_flag && CONVERSION_WARNINGS)
{
g_message (_("Warning:\n"
"The image file contains adjustment layers. "
"These are not supported by the GIMP and will "
"be dropped."));
msg_flag = TRUE;
}
return 0;
}
static gint
load_resource_lfil (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f)
{
/* Load fill layer */
static gboolean msg_flag = FALSE;
IFDBG(2) g_debug ("Process layer resource block %.4s: Fill layer", res_a->key);
if (! msg_flag && CONVERSION_WARNINGS)
{
g_message (_("Warning:\n"
"The image file contains fill layers. "
"These are not supported by the GIMP and will "
"be rasterized."));
msg_flag = TRUE;
}
return 0;
}
static gint
load_resource_lfx (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f)
{
/* Load layer effects */
static gboolean msg_flag = FALSE;
IFDBG(2) g_debug ("Process layer resource block %.4s: Layer effects", res_a->key);
if (! msg_flag && CONVERSION_WARNINGS)
{
g_message (_("Warning:\n"
"The image file contains layer effects. "
"These are not supported by the GIMP and will "
"be dropped."));
msg_flag = TRUE;
}
return 0;
}
static gint
load_resource_ltyp (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f)
{
/* Load type tool layer */
gint16 version,
text_desc_vers;
gint32 desc_version;
guint64 t_xx,
t_xy,
t_yx,
t_yy,
t_tx,
t_ty;
gdouble transform_xx,
transform_xy,
transform_yx,
transform_yy,
transform_tx,
transform_ty;
static gboolean msg_flag = FALSE;
IFDBG(2) g_debug ("Process layer resource block %.4s: Type tool layer", res_a->key);
if (! msg_flag && CONVERSION_WARNINGS)
{
g_message (_("Warning:\n"
"The image file contains type tool layers. "
"These are not supported by the GIMP and will "
"be dropped."));
msg_flag = TRUE;
}
/* New style type tool layers (ps6) */
if (memcmp (res_a->key, PSD_LTYP_TYPE2, 4) == 0)
{
if (fread (&version, 2, 1, f) < 1
|| fread (&t_xx, 8, 1, f) < 1
|| fread (&t_xy, 8, 1, f) < 1
|| fread (&t_yx, 8, 1, f) < 1
|| fread (&t_yy, 8, 1, f) < 1
|| fread (&t_tx, 8, 1, f) < 1
|| fread (&t_ty, 8, 1, f) < 1
|| fread (&text_desc_vers, 2, 1, f) < 1
|| fread (&desc_version, 4, 1, f) < 1)
{
g_message (_("Error reading text descriptor info"));
return -1;
}
version = GINT16_FROM_BE (version);
text_desc_vers = GINT16_FROM_BE (text_desc_vers);
desc_version = GINT32_FROM_BE (desc_version);
// t_xx = GUINT64_FROM_BE (t_xx);
// t_xy = GUINT64_FROM_BE (t_xy);
// t_yx = GUINT64_FROM_BE (t_yx);
// t_yy = GUINT64_FROM_BE (t_yy);
// t_tx = GUINT64_FROM_BE (t_tx);
// t_ty = GUINT64_FROM_BE (t_ty);
transform_xx = t_xx >> 11;
transform_xy = t_xy >> 11;
transform_yx = t_yx >> 11;
transform_yy = t_yy >> 11;
transform_tx = t_tx >> 11;
transform_ty = t_ty >> 11;
IFDBG(2) g_debug ("Version: %d, Text desc. vers.: %d, Desc. vers.: %d",
version, text_desc_vers, desc_version);
IFDBG(2) g_debug ("Transform\n\txx: %f\n\txy: %f\n\tyx: %f"
"\n\tyy: %f\n\ttx: %f\n\tty: %f",
transform_xx, transform_xy, transform_yx,
transform_yy, transform_tx, transform_ty);
// classID = fread_unicode_string (&read_len, &write_len, 4, f);
// IFDBG(2) g_debug ("Unicode name: %s", classID);
}
return 0;
}
static gint
load_resource_luni (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f)
{
/* Load layer name in unicode (length padded to multiple of 4 bytes) */
gint32 read_len,
write_len;
IFDBG(2) g_debug ("Process layer resource block luni: Unicode Name");
if (lyr_a->name)
g_free (lyr_a->name);
lyr_a->name = fread_unicode_string (&read_len, &write_len, 4, f);
IFDBG(2) g_debug ("Unicode name: %s", lyr_a->name);
return 0;
}
static gint
load_resource_lyid (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f)
{
/* Load layer id (tattoo) */
IFDBG(2) g_debug ("Process layer resource block lyid: Layer ID");
if (fread (&lyr_a->id, 4, 1, f) < 1)
{
g_message (_("Error reading layer ID"));
return -1;
}
lyr_a->id = GUINT32_FROM_BE (lyr_a->id);
IFDBG(2) g_debug ("Layer id: %i", lyr_a->id);
return 0;
}
static gint
load_resource_lsct (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f)
{
/* Load adjustment layer */
static gboolean msg_flag = FALSE;
guint32 type;
IFDBG(2) g_debug ("Process layer resource block %.4s: Section divider", res_a->key);
if (fread (&type, 4, 1, f) < 1)
{
g_message (_("Error reading Section divider record"));
return -1;
}
type = GUINT32_FROM_BE (type);
IFDBG(2) g_debug ("Section divider type: %i", type);
if (type == 1 || /* Layer group start - open folder */
type == 2) /* Layer group start - closed folder */
{
lyr_a->drop = TRUE;
if (! msg_flag && CONVERSION_WARNINGS)
{
g_message (_("Warning:\n"
"The image file contains layer groups. "
"These are not supported by the GIMP and will "
"be dropped."));
msg_flag = TRUE;
}
}
if (type == 3) /* End of layer group - hidden in UI */
lyr_a->drop = TRUE;
return 0;
}

View file

@ -0,0 +1,34 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* GIMP PSD Plug-in
* Copyright 2007 by John Marshall
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __PSD_LAYER_RES_LOAD_H__
#define __PSD_LAYER_RES_LOAD_H__
gint get_layer_resource_header (PSDlayerres *res_a,
FILE *f);
gint load_layer_resource (PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f);
#endif /* __PSD_LAYER_RES_LOAD_H__ */

1801
plug-ins/psd/psd-load.c Normal file

File diff suppressed because it is too large Load diff

29
plug-ins/psd/psd-load.h Normal file
View file

@ -0,0 +1,29 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* GIMP PSD Plug-in
* Copyright 2007 by John Marshall
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __PSD_LOAD_H__
#define __PSD_LOAD_H__
gint32 load_image (const gchar *filename);
#endif /* __PSD_LOAD_H__ */

View file

@ -0,0 +1,317 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* GIMP PSD Plug-in
* Copyright 2007 by John Marshall
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <errno.h>
#include <glib/gstdio.h>
#include <libgimp/gimp.h>
#include "psd.h"
#include "psd-image-res-load.h"
#include "psd-thumb-load.h"
#include "libgimp/stdplugins-intl.h"
/* Local function prototypes */
static gint read_header_block (PSDimage *img_a,
FILE *f);
static gint read_color_mode_block (PSDimage *img_a,
FILE *f);
static gint read_image_resource_block (PSDimage *img_a,
FILE *f);
static gint32 create_gimp_image (PSDimage *img_a,
const gchar *filename);
static gint add_image_resources (const gint32 image_id,
PSDimage *img_a,
FILE *f);
/* Main file load function */
gint32
load_thumbnail_image (const gchar *filename,
gint *width,
gint *height)
{
FILE *f;
struct stat st;
PSDimage img_a;
gint32 image_id = -1;
/* ----- Open PSD file ----- */
if (g_stat (filename, &st) == -1)
return -1;
IFDBG(1) g_debug ("Open file %s", gimp_filename_to_utf8 (filename));
f = g_fopen (filename, "rb");
if (f == NULL)
{
g_message (_("Could not open '%s' for reading: %s"),
gimp_filename_to_utf8 (filename), g_strerror (errno));
return -1;
}
gimp_progress_init_printf (_("Loading thumbnail for '%s'"),
gimp_filename_to_utf8 (filename));
IFDBG(2) g_debug ("Read header block");
/* ----- Read the PSD file Header block ----- */
if (read_header_block (&img_a, f) < 0)
{
fclose(f);
return -1;
}
gimp_progress_update (0.2);
IFDBG(2) g_debug ("Read colour mode block");
/* ----- Read the PSD file Colour Mode block ----- */
if (read_color_mode_block (&img_a, f) < 0)
{
fclose(f);
return -1;
}
gimp_progress_update (0.4);
IFDBG(2) g_debug ("Read image resource block");
/* ----- Read the PSD file Image Resource block ----- */
if (read_image_resource_block (&img_a, f) < 0)
{
fclose(f);
return -1;
}
gimp_progress_update (0.6);
IFDBG(2) g_debug ("Create GIMP image");
/* ----- Create GIMP image ----- */
image_id = create_gimp_image (&img_a, filename);
if (image_id == -1)
{
fclose(f);
return -1;
}
gimp_progress_update (0.8);
IFDBG(2) g_debug ("Add image resources");
/* ----- Add image resources ----- */
if (add_image_resources (image_id, &img_a, f) < 1)
{
gimp_image_delete (image_id);
fclose(f);
return -1;
}
gimp_progress_update (1.0);
gimp_image_clean_all (image_id);
gimp_image_undo_enable (image_id);
fclose (f);
*width = img_a.columns;
*height = img_a.rows;
return image_id;
}
/* Local functions */
static gint
read_header_block (PSDimage *img_a,
FILE *f)
{
guint16 version;
gchar sig[4];
gchar buf[6];
if (fread (sig, 4, 1, f) < 1
|| fread (&version, 2, 1, f) < 1
|| fread (buf, 6, 1, f) < 1
|| fread (&img_a->channels, 2, 1, f) < 1
|| fread (&img_a->rows, 4, 1, f) < 1
|| fread (&img_a->columns, 4, 1, f) < 1
|| fread (&img_a->bps, 2, 1, f) < 1
|| fread (&img_a->color_mode, 2, 1, f) < 1)
{
g_message (_("Error reading file header"));
return -1;
}
version = GUINT16_FROM_BE (version);
img_a->channels = GUINT16_FROM_BE (img_a->channels);
img_a->rows = GUINT32_FROM_BE (img_a->rows);
img_a->columns = GUINT32_FROM_BE (img_a->columns);
img_a->bps = GUINT16_FROM_BE (img_a->bps);
img_a->color_mode = GUINT16_FROM_BE (img_a->color_mode);
IFDBG(1) g_debug ("\n\n\tSig: %.4s\n\tVer: %d\n\tChannels: "
"%d\n\tSize: %dx%d\n\tBPS: %d\n\tMode: %d\n",
sig, version, img_a->channels,
img_a->columns, img_a->rows,
img_a->bps, img_a->color_mode);
if (memcmp (sig, "8BPS", 4) != 0)
{
g_message (_("Incorrect file signature"));
return -1;
}
if (version != 1)
{
g_message (_("Unsupported PSD file format version %d"), version);
return -1;
}
if (img_a->channels > MAX_CHANNELS)
{
g_message (_("Too many channels in file (%d)"), img_a->channels);
return -1;
}
if (img_a->rows == 0 || img_a->columns == 0)
{
g_message (_("Unsupported PSD file version (< 2.5)")); /* FIXME - image size */
/* in resource block 1000 */
return -1; /* don't have PS2 file spec */
}
return 0;
}
static gint
read_color_mode_block (PSDimage *img_a,
FILE *f)
{
guint32 block_len;
guint32 block_start;
guint32 block_end;
if (fread (&block_len, 4, 1, f) < 1)
{
g_message (_("Error reading color block"));
return -1;
}
block_len = GUINT32_FROM_BE (block_len);
IFDBG(1) g_debug ("Color map block size = %d", block_len);
block_start = ftell (f);
block_end = block_start + block_len;
if (fseek (f, block_end, SEEK_SET) < 0)
{
g_message (_("Error setting file position"));
return -1;
}
return 0;
}
static gint
read_image_resource_block (PSDimage *img_a,
FILE *f)
{
guint32 block_len;
guint32 block_end;
if (fread (&block_len, 4, 1, f) < 1)
{
g_message (_("Error reading image resource block"));
return -1;
}
img_a->image_res_len = GUINT32_FROM_BE (block_len);
IFDBG(1) g_debug ("Image resource block size = %d", (int)img_a->image_res_len);
img_a->image_res_start = ftell (f);
block_end = img_a->image_res_start + img_a->image_res_len;
if (fseek (f, block_end, SEEK_SET) < 0)
{
g_message (_("Error setting file position"));
return -1;
}
return 0;
}
static gint32
create_gimp_image (PSDimage *img_a,
const gchar *filename)
{
gint32 image_id = -1;
img_a->base_type = GIMP_RGB;
/* Create gimp image */
IFDBG(2) g_debug ("Create image");
if ((image_id = gimp_image_new (img_a->columns, img_a->rows,
img_a->base_type)) == -1)
{
g_message (_("Could not create a new image"));
return -1;
}
gimp_image_undo_disable (image_id);
gimp_image_set_filename (image_id, filename);
return image_id;
}
static gint
add_image_resources (const gint32 image_id,
PSDimage *img_a,
FILE *f)
{
PSDimageres res_a;
gint status;
if (fseek (f, img_a->image_res_start, SEEK_SET) < 0)
{
g_message (_("Error setting file position"));
return -1;
}
while (ftell (f) < img_a->image_res_start + img_a->image_res_len)
{
if (get_image_resource_header (&res_a, f) < 0)
return -1;
if (res_a.data_start + res_a.data_len >
img_a->image_res_start + img_a->image_res_len)
{
g_message ("Unexpected end of image resource data");
return 0;
}
status = load_thumbnail_resource (&res_a, image_id, f);
/* Error */
if (status < 0)
return -1;
/* Thumbnail Loaded */
if (status > 0)
return 1;
}
return 0;
}

View file

@ -0,0 +1,31 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* GIMP PSD Plug-in
* Copyright 2007 by John Marshall
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __PSD_THUMB_LOAD_H__
#define __PSD_THUMB_LOAD_H__
gint32 load_thumbnail_image (const gchar *filename,
gint *width,
gint *height);
#endif /* __PSD_THUMB_LOAD_H__ */

791
plug-ins/psd/psd-util.c Normal file
View file

@ -0,0 +1,791 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* GIMP PSD Plug-in
* Copyright 2007 by John Marshall
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <glib/gstdio.h>
#include <libgimp/gimp.h>
#include "psd.h"
#include "psd-util.h"
#include "libgimp/stdplugins-intl.h"
/* Local constants */
#define MIN_RUN 3
/* Local function prototypes */
/* Utility function */
gchar *
fread_pascal_string (gint32 *bytes_read,
gint32 *bytes_written,
const guint16 pad_len,
FILE *f)
{
/* Reads a pascal string padded to a multiple of pad_len and converts to utf-8 */
gchar *str,
*utf8_str;
guchar len;
gint32 padded_len;
*bytes_read = 0;
*bytes_written = -1;
if (fread (&len, 1, 1, f) < 1)
{
g_message (_("Error reading pascal string length"));
return NULL;
}
(*bytes_read)++;
IFDBG(3) g_debug ("Pascal string length %d", len);
if (len == 0)
{
if (fseek (f, pad_len - 1, SEEK_CUR) < 0)
{
g_message (_("Error setting file position"));
return NULL;
}
*bytes_read += (pad_len - 1);
*bytes_written = 0;
return NULL;
}
str = g_malloc (len);
if (fread (str, len, 1, f) < 1)
{
g_message (_("Error reading pascal string"));
return NULL;
}
*bytes_read += len;
if (pad_len > 0)
{
padded_len = len + 1;
while (padded_len % pad_len != 0)
{
if (fseek (f, 1, SEEK_CUR) < 0)
{
g_message (_("Error setting file position"));
return NULL;
}
(*bytes_read)++;
padded_len++;
}
}
utf8_str = gimp_any_to_utf8 (str, len, _("Invalid UTF-8 string in PSD file"));
*bytes_written = strlen (utf8_str);
g_free (str);
IFDBG(2) g_debug ("Pascal string: %s, bytes_read: %d, bytes_written: %d",
utf8_str, *bytes_read, *bytes_written);
return utf8_str;
}
gint32
fwrite_pascal_string (const gchar *src,
const guint16 pad_len,
FILE *f)
{
/* Converts utf-8 string to current locale and writes as pascal string with
padding to pad width */
gchar *str,
*pascal_str,
null_str = 0x0;
guchar pascal_len;
gint32 bytes_written = 0;
gsize len;
if (src == NULL)
{
/* Write null string as two null bytes (0x0) */
if (fwrite (&null_str, 1, 1, f) < 1
|| fwrite (&null_str, 1, 1, f) < 1)
{
g_message (_("Error writing pascal string"));
return -1;
}
bytes_written += 2;
}
else
{
str = g_locale_from_utf8 (src, -1, NULL, &len, NULL);
if (len > 255)
pascal_len = 255;
else
pascal_len = len;
pascal_str = g_strndup (str, pascal_len);
g_free (str);
if (fwrite (&pascal_len, 1, 1, f) < 1
|| fwrite (pascal_str, pascal_len, 1, f) < 1)
{
g_message (_("Error writing pascal string"));
return -1;
}
bytes_written++;
bytes_written += pascal_len;
IFDBG(2) g_debug ("Pascal string: %s, bytes_written: %d",
pascal_str, bytes_written);
}
/* Pad with nulls */
if (pad_len > 0)
{
while (bytes_written % pad_len != 0)
{
if (fwrite (&null_str, 1, 1, f) < 1)
{
g_message (_("Error writing pascal string"));
return -1;
}
bytes_written++;
}
}
return bytes_written;
}
gchar *
fread_unicode_string (gint32 *bytes_read,
gint32 *bytes_written,
const guint16 pad_len,
FILE *f)
{
/* Reads a utf-16 string padded to a multiple of pad_len and converts to utf-8 */
gchar *utf8_str;
gunichar2 *utf16_str;
gint32 len,
i,
padded_len;
glong utf8_str_len;
*bytes_read = 0;
*bytes_written = -1;
if (fread (&len, 4, 1, f) < 1)
{
g_message (_("Error reading unicode string length"));
return NULL;
}
*bytes_read += 4;
len = GINT32_FROM_BE (len);
IFDBG(3) g_debug ("Unicode string length %d", len);
if (len == 0)
{
if (fseek (f, pad_len - 1, SEEK_CUR) < 0)
{
g_message (_("Error setting file position"));
return NULL;
}
*bytes_read += (pad_len - 1);
*bytes_written = 0;
return NULL;
}
utf16_str = g_malloc (len * 2);
for (i = 0; i < len; ++i)
{
if (fread (&utf16_str[i], 2, 1, f) < 1)
{
g_message (_("Error reading unicode string"));
return NULL;
}
*bytes_read += 2;
utf16_str[i] = GINT16_FROM_BE (utf16_str[i]);
}
if (pad_len > 0)
{
padded_len = len + 1;
while (padded_len % pad_len != 0)
{
if (fseek (f, 1, SEEK_CUR) < 0)
{
g_message (_("Error setting file position"));
return NULL;
}
(*bytes_read)++;
padded_len++;
}
}
utf8_str = g_utf16_to_utf8 (utf16_str, len, NULL, &utf8_str_len, NULL);
*bytes_written = utf8_str_len;
g_free (utf16_str);
IFDBG(3) g_debug ("Unicode string: %s, bytes_read: %d, bytes_written: %d",
utf8_str, *bytes_read, *bytes_written);
return utf8_str;
}
gint32
fwrite_unicode_string (const gchar *src,
const guint16 pad_len,
FILE *f)
{
/* Converts utf-8 string to utf-16 and writes 4 byte length then string
padding to pad width */
gunichar2 *utf16_str;
gchar null_str = 0x0;
gint32 utf16_len = 0,
bytes_written = 0;
gint i;
glong len;
if (src == NULL)
{
/* Write null string as four byte 0 int32 */
if (fwrite (&utf16_len, 4, 1, f) < 1)
{
g_message (_("Error writing unicode string"));
return -1;
}
bytes_written += 4;
}
else
{
utf16_str = g_utf8_to_utf16 (src, -1, NULL, &len, NULL);
/* Byte swap as required */
utf16_len = len;
for (i = 0; i < utf16_len; ++i)
utf16_str[i] = GINT16_TO_BE (utf16_str[i]);
utf16_len = GINT32_TO_BE (utf16_len);
if (fwrite (&utf16_len, 4, 1, f) < 1
|| fwrite (utf16_str, 2, utf16_len + 1, f) < utf16_len + 1)
{
g_message (_("Error writing unicode string"));
return -1;
}
bytes_written += (4 + 2 * utf16_len + 2);
IFDBG(2) g_debug ("Unicode string: %s, bytes_written: %d",
src, bytes_written);
}
/* Pad with nulls */
if (pad_len > 0)
{
while (bytes_written % pad_len != 0)
{
if (fwrite (&null_str, 1, 1, f) < 1)
{
g_message (_("Error writing unicode string"));
return -1;
}
bytes_written++;
}
}
return bytes_written;
}
gint
decode_packbits (const gchar *src,
gchar *dst,
guint16 packed_len,
guint32 unpacked_len)
{
/*
* Decode a PackBits chunk.
*/
int n;
gchar dat;
gint32 unpack_left = unpacked_len,
pack_left = packed_len,
error_code = 0,
return_val = 0;
IFDBG(3) g_debug ("Decode packbits");
IFDBG(3) g_debug ("Packed len %d, unpacked %d",packed_len, unpacked_len);
while (unpack_left > 0 && pack_left > 0)
{
n = *src;
src++;
pack_left--;
if (n == 128) /* nop */
continue;
else if (n > 128)
n -= 256;
if (n < 0) /* replicate next gchar |n|+ 1 times */
{
n = 1 - n;
if (! pack_left)
{
IFDBG(2) g_debug ("Input buffer exhausted in replicate");
error_code = 1;
break;
}
if (n > unpack_left)
{
IFDBG(2) g_debug ("Overrun in packbits replicate of %d chars", n - unpack_left);
error_code = 2;
}
dat = *src;
for (; n > 0; --n)
{
if (! unpack_left)
break;
*dst = dat;
dst++;
unpack_left--;
}
if (unpack_left)
{
src++;
pack_left--;
}
}
else /* copy next n+1 gchars literally */
{
n++;
for (; n > 0; --n)
{
if (! pack_left)
{
IFDBG(2) g_debug ("Input buffer exhausted in copy");
error_code = 3;
break;
}
if (! unpack_left)
{
IFDBG(2) g_debug ("Output buffer exhausted in copy");
error_code = 4;
break;
}
*dst = *src;
dst++;
unpack_left--;
src++;
pack_left--;
}
}
}
if (unpack_left > 0)
{
/* Pad with zeros to end of output buffer */
for (n = 0; n < pack_left; ++n)
{
*dst = 0;
dst++;
}
}
IFDBG(3) g_debug ("Pack left %d, unpack left %d", pack_left, unpack_left);
if (unpack_left)
{
IFDBG(2) g_debug ("Packbits decode - unpack left %d", unpack_left);
return_val -= unpack_left;
}
if (pack_left)
{
/* Some images seem to have a pad byte at the end of the packed data */
if (error_code || pack_left != 1)
{
IFDBG(2) g_debug ("Packbits decode - pack left %d", pack_left);
return_val = pack_left;
}
}
IFDBG(2)
if (error_code)
g_debug ("Error code %d", error_code);
return return_val;
}
gchar *
encode_packbits (const gchar *src,
const guint32 unpacked_len,
guint16 *packed_len)
{
/*
* Encode a PackBits chunk.
*/
GString *dst_str; /* destination string */
gint curr_char; /* current character */
gchar char_buff[128]; /* buffer of already read characters */
guchar run_len; /* number of characters in a run */
gint32 unpack_left = unpacked_len;
IFDBG(2) g_debug ("Encode packbits");
/* Initialise destination string */
dst_str = g_string_sized_new (unpacked_len);
/* prime the read loop */
curr_char = *src;
src++;
run_len = 0;
/* read input until there's nothing left */
while (unpack_left > 0)
{
char_buff[run_len] = (gchar) curr_char;
IFDBG(2) g_debug ("buff %x, run len %d, curr char %x",
char_buff[run_len], run_len, (gchar) curr_char);
run_len++;
if (run_len >= MIN_RUN)
{
gint i;
/* check for run */
for (i = 2; i <= MIN_RUN; ++i)
{
if (curr_char != char_buff[run_len - i])
{
/* no run */
i = 0;
break;
}
}
if (i != 0)
{
/* we have a run write out buffer before run*/
gint next_char;
if (run_len > MIN_RUN)
{
/* block size - 1 followed by contents */
g_string_append_c (dst_str, (run_len - MIN_RUN - 1));
g_string_append_len (dst_str, char_buff, (run_len - MIN_RUN));
IFDBG(2) g_debug ("(1) Number of chars: %d, run length tag: %d",
run_len - MIN_RUN, run_len - MIN_RUN - 1);
}
/* determine run length (MIN_RUN so far) */
run_len = MIN_RUN;
/* get next character */
next_char = *src;
src++;
unpack_left--;
while (next_char == curr_char)
{
run_len++;
if (run_len == 128)
{
/* run is at max length */
break;
}
next_char = *src;
src++;
unpack_left--;
}
/* write out encoded run length and run symbol */
g_string_append_c (dst_str, (gchar)(1 - (gint)(run_len)));
g_string_append_c (dst_str, curr_char);
IFDBG(2) g_debug ("(2) Number of chars: %d, run length tag: %d",
run_len, (1 - (gint)(run_len)));
if (unpack_left > 0)
{
/* make run breaker start of next buffer */
char_buff[0] = next_char;
run_len = 1;
}
else
{
/* file ends in a run */
run_len = 0;
}
}
}
if (run_len == 128)
{
/* write out buffer */
g_string_append_c (dst_str, 127);
g_string_append_len (dst_str, char_buff, 128);
IFDBG(2) g_debug ("(3) Number of chars: 128, run length tag: 127");
/* start a new buffer */
run_len = 0;
}
curr_char = *src;
src++;
unpack_left--;
}
/* write out last buffer */
if (run_len != 0)
{
if (run_len <= 128)
{
/* write out entire copy buffer */
g_string_append_c (dst_str, run_len - 1);
g_string_append_len (dst_str, char_buff, run_len);
IFDBG(2) g_debug ("(4) Number of chars: %d, run length tag: %d",
run_len, run_len - 1);
}
else
{
IFDBG(2) g_debug ("(5) Very bad - should not be here");
}
}
*packed_len = dst_str->len;
IFDBG(2) g_debug ("Packed len %d, unpacked %d", *packed_len, unpacked_len);
return g_string_free (dst_str, FALSE);
}
GimpLayerModeEffects
psd_to_gimp_blend_mode (const gchar *psd_mode)
{
if (g_ascii_strncasecmp (psd_mode, "norm", 4) == 0) /* Normal (ps3) */
return GIMP_NORMAL_MODE;
if (g_ascii_strncasecmp (psd_mode, "dark", 4) == 0) /* Darken (ps3) */
return GIMP_DARKEN_ONLY_MODE;
if (g_ascii_strncasecmp (psd_mode, "lite", 4) == 0) /* Lighten (ps3) */
return GIMP_LIGHTEN_ONLY_MODE;
if (g_ascii_strncasecmp (psd_mode, "hue ", 4) == 0) /* Hue (ps3) */
return GIMP_HUE_MODE;
if (g_ascii_strncasecmp (psd_mode, "sat ", 4) == 0) /* Saturation (ps3) */
{
if (CONVERSION_WARNINGS)
g_message (_("Gimp uses a different equation to photoshop for the "
"saturation blend mode. Results will differ."));
return GIMP_SATURATION_MODE;
}
if (g_ascii_strncasecmp (psd_mode, "colr", 4) == 0) /* Color (ps3) */
return GIMP_COLOR_MODE;
if (g_ascii_strncasecmp (psd_mode, "lum ", 4) == 0) /* Luminosity (ps3) */
{
if (CONVERSION_WARNINGS)
g_message (_("Gimp uses a different equation to photoshop for the "
"value (luminosity) blend mode. Results will differ."));
return GIMP_VALUE_MODE;
}
if (g_ascii_strncasecmp (psd_mode, "mul ", 4) == 0) /* Multiply (ps3) */
return GIMP_MULTIPLY_MODE;
if (g_ascii_strncasecmp (psd_mode, "scrn", 4) == 0) /* Screen (ps3) */
return GIMP_SCREEN_MODE;
if (g_ascii_strncasecmp (psd_mode, "diss", 4) == 0) /* Dissolve (ps3) */
return GIMP_DISSOLVE_MODE;
if (g_ascii_strncasecmp (psd_mode, "over", 4) == 0) /* Overlay (ps3) */
{
if (CONVERSION_WARNINGS)
g_message (_("Gimp uses a different equation to photoshop for the "
"overlay blend mode. Results will differ."));
return GIMP_OVERLAY_MODE;
}
if (g_ascii_strncasecmp (psd_mode, "hLit", 4) == 0) /* Hard light (ps3) */
return GIMP_HARDLIGHT_MODE;
if (g_ascii_strncasecmp (psd_mode, "sLit", 4) == 0) /* Soft light (ps3) */
{
if (CONVERSION_WARNINGS)
g_message (_("Gimp uses a different equation to photoshop for the "
"soft light blend mode. Results will differ."));
return GIMP_SOFTLIGHT_MODE;
}
if (g_ascii_strncasecmp (psd_mode, "diff", 4) == 0) /* Difference (ps3) */
return GIMP_DIFFERENCE_MODE;
if (g_ascii_strncasecmp (psd_mode, "smud", 4) == 0) /* Exclusion (ps6) */
{
if (CONVERSION_WARNINGS)
g_message (_("Exclusion blend mode not supported by GIMP. "
"Blend mode reverts to normal."));
return GIMP_NORMAL_MODE;
}
if (g_ascii_strncasecmp (psd_mode, "div ", 4) == 0) /* Color dodge (ps6) */
return GIMP_DODGE_MODE;
if (g_ascii_strncasecmp (psd_mode, "idiv", 4) == 0) /* Color burn (ps6) */
return GIMP_BURN_MODE;
if (g_ascii_strncasecmp (psd_mode, "lbrn", 4) == 0) /* Linear burn (ps7)*/
{
if (CONVERSION_WARNINGS)
g_message (_("Linear burn blend mode not supported by GIMP. "
"Blend mode reverts to normal."));
return GIMP_NORMAL_MODE;
}
if (g_ascii_strncasecmp (psd_mode, "lddg", 4) == 0) /* Linear dodge (ps7)*/
return GIMP_ADDITION_MODE;
if (g_ascii_strncasecmp (psd_mode, "lLit", 4) == 0) /* Linear light (ps7)*/
{
if (CONVERSION_WARNINGS)
g_message (_("Linear light blend mode not supported by GIMP. "
"Blend mode reverts to normal."));
return GIMP_NORMAL_MODE;
}
if (g_ascii_strncasecmp (psd_mode, "pLit", 4) == 0) /* Pin light (ps7)*/
{
if (CONVERSION_WARNINGS)
g_message (_("Pin light blend mode not supported by GIMP. "
"Blend mode reverts to normal."));
return GIMP_NORMAL_MODE;
}
if (g_ascii_strncasecmp (psd_mode, "vLit", 4) == 0) /* Vivid light (ps7)*/
{
if (CONVERSION_WARNINGS)
g_message (_("Vivid light blend mode not supported by GIMP. "
"Blend mode reverts to normal."));
return GIMP_NORMAL_MODE;
}
if (g_ascii_strncasecmp (psd_mode, "hMix", 4) == 0) /* Hard Mix (CS)*/
{
if (CONVERSION_WARNINGS)
g_message (_("Hard mix blend mode not supported by GIMP. "
"Blend mode reverts to normal."));
return GIMP_NORMAL_MODE;
}
if (CONVERSION_WARNINGS)
g_message (_("Unknown blend mode %.4s. Blend mode reverts to normal."), psd_mode);
return GIMP_NORMAL_MODE;
}
gchar *
gimp_to_psd_blend_mode (const GimpLayerModeEffects gimp_layer_mode)
{
gchar *psd_mode;
switch (gimp_layer_mode)
{
case GIMP_NORMAL_MODE:
psd_mode = g_strndup ("norm", 4); /* Normal (ps3) */
break;
case GIMP_DISSOLVE_MODE:
psd_mode = g_strndup ("diss", 4); /* Dissolve (ps3) */
break;
case GIMP_BEHIND_MODE:
if (CONVERSION_WARNINGS)
g_message (_("Behind blend mode not supported in PSD file. "
"Blend mode reverts to normal."));
psd_mode = g_strndup ("norm", 4);
break;
case GIMP_MULTIPLY_MODE:
psd_mode = g_strndup ("mul ", 4); /* Multiply (ps3) */
break;
case GIMP_SCREEN_MODE:
psd_mode = g_strndup ("scrn", 4); /* Screen (ps3) */
break;
case GIMP_OVERLAY_MODE:
if (CONVERSION_WARNINGS)
g_message (_("Gimp uses a different equation to photoshop for the "
"overlay blend mode. Results will differ."));
psd_mode = g_strndup ("over", 4); /* Overlay (ps3) */
break;
case GIMP_DIFFERENCE_MODE:
psd_mode = g_strndup ("diff", 4); /* Difference (ps3) */
break;
case GIMP_ADDITION_MODE:
psd_mode = g_strndup ("lddg", 4); /* Linear dodge (ps7)*/
break;
case GIMP_SUBTRACT_MODE:
if (CONVERSION_WARNINGS)
g_message (_("Photoshop does not support the subtract "
"blend mode. Layer mode reverts to normal."));
psd_mode = g_strndup ("norm", 4);
break;
case GIMP_DARKEN_ONLY_MODE:
psd_mode = g_strndup ("dark", 4); /* Darken (ps3) */
break;
case GIMP_LIGHTEN_ONLY_MODE:
psd_mode = g_strndup ("lite", 4); /* Lighten (ps3) */
break;
case GIMP_HUE_MODE:
psd_mode = g_strndup ("hue ", 4); /* Hue (ps3) */
break;
case GIMP_SATURATION_MODE:
if (CONVERSION_WARNINGS)
g_message (_("Gimp uses a different equation to photoshop for the "
"saturation blend mode. Results will differ."));
psd_mode = g_strndup ("sat ", 4); /* Saturation (ps3) */
break;
case GIMP_COLOR_MODE:
psd_mode = g_strndup ("colr", 4); /* Color (ps3) */
break;
case GIMP_VALUE_MODE:
if (CONVERSION_WARNINGS)
g_message (_("Gimp uses a different equation to photoshop for the "
"value (luminosity) blend mode. Results will differ."));
psd_mode = g_strndup ("lum ", 4); /* Luminosity (ps3) */
break;
case GIMP_DIVIDE_MODE:
if (CONVERSION_WARNINGS)
g_message (_("Photoshop does not support the divide "
"blend mode. Layer mode reverts to normal."));
psd_mode = g_strndup ("norm", 4);
break;
case GIMP_DODGE_MODE:
psd_mode = g_strndup ("div ", 4); /* Color Dodge (ps6) */
break;
case GIMP_BURN_MODE:
psd_mode = g_strndup ("idiv", 4); /* Color Burn (ps6) */
break;
case GIMP_HARDLIGHT_MODE:
psd_mode = g_strndup ("hLit", 4); /* Hard Light (ps3) */
break;
case GIMP_SOFTLIGHT_MODE:
if (CONVERSION_WARNINGS)
g_message (_("Gimp uses a different equation to photoshop for the "
"soft light blend mode. Results will differ."));
psd_mode = g_strndup ("sLit", 4); /* Soft Light (ps3) */
break;
case GIMP_GRAIN_EXTRACT_MODE:
if (CONVERSION_WARNINGS)
g_message (_("Photoshop does not support the grain extract "
"blend mode. Layer mode reverts to normal."));
psd_mode = g_strndup ("norm", 4);
break;
case GIMP_GRAIN_MERGE_MODE:
if (CONVERSION_WARNINGS)
g_message (_("Photoshop does not support the grain merge "
"blend mode. Layer mode reverts to normal."));
psd_mode = g_strndup ("norm", 4);
break;
case GIMP_COLOR_ERASE_MODE:
if (CONVERSION_WARNINGS)
g_message (_("Photoshop does not support the color erase "
"blend mode. Layer mode reverts to normal."));
psd_mode = g_strndup ("norm", 4);
break;
default:
if (CONVERSION_WARNINGS)
g_message (_("Blend mode %d not supported. Blend mode reverts to normal.")
, gimp_layer_mode);
psd_mode = g_strndup ("norm", 4);
}
return psd_mode;
}

57
plug-ins/psd/psd-util.h Normal file
View file

@ -0,0 +1,57 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* GIMP PSD Plug-in
* Copyright 2007 by John Marshall
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __PSD_UTIL_H__
#define __PSD_UTIL_H__
gchar * fread_pascal_string (gint32 *bytes_read,
gint32 *bytes_written,
const guint16 pad_len,
FILE *f);
gint32 fwrite_pascal_string (const gchar *src,
const guint16 pad_len,
FILE *f);
gchar * fread_unicode_string (gint32 *bytes_read,
gint32 *bytes_written,
const guint16 pad_len,
FILE *f);
gint32 fwrite_unicode_string (const gchar *src,
const guint16 pad_len,
FILE *f);
gint decode_packbits (const gchar *src,
gchar *dst,
guint16 packed_len,
guint32 unpacked_len);
gchar * encode_packbits (const gchar *src,
const guint32 unpacked_len,
guint16 *packed_len);
GimpLayerModeEffects psd_to_gimp_blend_mode (const gchar *psd_mode);
gchar * gimp_to_psd_blend_mode (const GimpLayerModeEffects gimp_layer_mode);
#endif /* __PSD_UTIL_H__ */

293
plug-ins/psd/psd.c Normal file
View file

@ -0,0 +1,293 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* GIMP PSD Plug-in
* Copyright 2007 by John Marshall
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <libgimp/gimp.h>
#include "psd.h"
#include "psd-load.h"
#include "psd-thumb-load.h"
#ifdef PSD_SAVE
#include "psd-save.h"
#endif
#include "libgimp/stdplugins-intl.h"
/* Local function prototypes */
static void query (void);
static void run (const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals);
/* Local variables */
GimpPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
MAIN ()
static void
query (void)
{
/* Register parameters */
/* File Load */
static const GimpParamDef load_args[] =
{
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
{ 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" }
};
/* Thumbnail Load */
static const GimpParamDef thumb_args[] =
{
{ GIMP_PDB_STRING, "filename", "The name of the file to load" },
{ GIMP_PDB_INT32, "thumb-size", "Preferred thumbnail size" }
};
static const GimpParamDef thumb_return_vals[] =
{
{ GIMP_PDB_IMAGE, "image", "Thumbnail image" },
{ GIMP_PDB_INT32, "image-width", "Width of full-sized image" },
{ GIMP_PDB_INT32, "image-height", "Height of full-sized image" }
};
#ifdef PSD_SAVE
/* File save */
static const GimpParamDef save_args[] =
{
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
{ 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" }
};
#endif /* PSD_SAVE */
/* Register procedures */
/* File load */
gimp_install_procedure (LOAD_PROC,
"Loads images from the Photoshop PSD file format",
"This plug-in loads images in Adobe "
"Photoshop (TM) native PSD format.",
"John Marshall",
"John Marshall",
"2007",
N_("Photoshop 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-psd");
gimp_register_magic_load_handler (LOAD_PROC,
"psd",
"",
"0,string,8BPS");
/* Thumbnail load */
gimp_install_procedure (LOAD_THUMB_PROC,
"Loads thumbnails from the Photoshop PSD file format",
"This plug-in loads thumnail images from Adobe "
"Photoshop (TM) native PSD format files.",
"John Marshall",
"John Marshall",
"2007",
NULL,
NULL,
GIMP_PLUGIN,
G_N_ELEMENTS (thumb_args),
G_N_ELEMENTS (thumb_return_vals),
thumb_args, thumb_return_vals);
gimp_register_thumbnail_loader (LOAD_PROC, LOAD_THUMB_PROC);
#ifdef PSD_SAVE
/* File save*/
gimp_install_procedure (SAVE_PROC,
"Saves images to the Photoshop PSD file format",
"This plug-in saves images in Adobe "
"Photoshop (TM) native PSD format.",
"John Marshall",
"John Marshall",
"2007",
N_("Photoshop image"),
"RGB*, GRAY*, INDEXED*",
GIMP_PLUGIN,
G_N_ELEMENTS (save_args), 0,
save_args, NULL);
gimp_register_save_handler (SAVE_PROC, "psd", "");
gimp_register_file_handler_mime (SAVE_PROC, "image/psd");
#endif /* PSD_SAVE */
}
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;
#ifdef PSD_SAVE
gint32 drawable_ID;
GimpExportReturn export = GIMP_EXPORT_CANCEL;
#endif /* PSD_SAVE */
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;
/* File load */
if (strcmp (name, LOAD_PROC) == 0)
{
image_ID = load_image (param[1].data.d_string);
if (image_ID != -1)
{
*nreturn_vals = 2;
values[1].type = GIMP_PDB_IMAGE;
values[1].data.d_image = image_ID;
}
else
{
g_message (_("Could not open '%s' for reading"),
gimp_filename_to_utf8 (param[1].data.d_string));
status = GIMP_PDB_EXECUTION_ERROR;
}
}
/* Thumbnail load */
else if (strcmp (name, LOAD_THUMB_PROC) == 0)
{
if (nparams < 2)
{
status = GIMP_PDB_CALLING_ERROR;
}
else
{
const gchar *filename = param[0].data.d_string;
gint width = 0;
gint height = 0;
image_ID = load_thumbnail_image (filename, &width, &height);
if (image_ID != -1)
{
*nreturn_vals = 4;
values[1].type = GIMP_PDB_IMAGE;
values[1].data.d_image = image_ID;
values[2].type = GIMP_PDB_INT32;
values[2].data.d_int32 = width;
values[3].type = GIMP_PDB_INT32;
values[3].data.d_int32 = height;
}
else
{
status = GIMP_PDB_EXECUTION_ERROR;
}
}
}
#ifdef PSD_SAVE
/* File save */
else if (strcmp (name, SAVE_PROC) == 0)
{
image_ID = param[1].data.d_int32;
drawable_ID = param[2].data.d_int32;
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, "PSD",
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 |
GIMP_EXPORT_CAN_HANDLE_LAYER_MASKS);
if (export == GIMP_EXPORT_CANCEL)
{
values[0].data.d_status = GIMP_PDB_CANCEL;
return;
}
break;
default:
break;
}
if (status == GIMP_PDB_SUCCESS)
{
if (save_image (param[3].data.d_string, image_ID, drawable_ID))
{
}
else
{
status = GIMP_PDB_EXECUTION_ERROR;
}
}
if (export == GIMP_EXPORT_EXPORT)
gimp_image_delete (image_ID);
}
#endif /* PSD_SAVE */
/* Unknown procedure */
else
{
status = GIMP_PDB_CALLING_ERROR;
}
values[0].data.d_status = status;
}

572
plug-ins/psd/psd.h Normal file
View file

@ -0,0 +1,572 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* GIMP PSD Plug-in
* Copyright 2007 by John Marshall
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __PSD_H__
#define __PSD_H__
/* Temporary disable of save functionality */
#ifdef PSD_SAVE
#undef PSD_SAVE
#else
/* #define PSD_SAVE */
#endif
/* Set to the level of debugging output you want, 0 for none.
* Setting higher than 2 will result in a very large amount of debug
* output being produced. */
#define PSD_DEBUG 0
#define IFDBG(level) if (PSD_DEBUG >= level)
/* Set to FALSE to supress pop-up warnings about lossy file conversions */
#define CONVERSION_WARNINGS FALSE
#define LOAD_PROC "file-psd-load"
#define LOAD_THUMB_PROC "file-psd-load-thumb"
#define SAVE_PROC "file-psd-save"
#define PLUG_IN_BINARY "psd"
#define DECODE_XMP_PROC "plug-in-metadata-decode-xmp"
#define GIMP_PARASITE_COMMENT "gimp-comment"
#define GIMP_PARASITE_ICC_PROFILE "icc-profile"
#define GIMP_PARASITE_EXIF "exif-data"
#define GIMP_PARASITE_IPTC "iptc-data"
#define METADATA_PARASITE "gimp-metadata"
#define METADATA_MARKER "GIMP_XMP_1"
#define PSD_PARASITE_DUOTONE_DATA "psd-duotone-data"
/* Copied from app/base/gimpimage-quick-mask.h - internal identifier for quick mask channel */
#define GIMP_IMAGE_QUICK_MASK_NAME "Qmask"
#define MAX_RAW_SIZE 0 /* FIXME all images are raw if 0 */
/* PSD spec defines */
#define MAX_CHANNELS 56 /* Photoshop CS to CS3 support 56 channels */
/* PSD spec constants */
/* Layer resource IDs */
/* Adjustment layer IDs */
#define PSD_LADJ_LEVEL "levl" /* Adjustment layer - levels (PS4) */
#define PSD_LADJ_CURVE "curv" /* Adjustment layer - curves (PS4) */
#define PSD_LADJ_BRIGHTNESS "brit" /* Adjustment layer - brightness/contrast (PS4) */
#define PSD_LADJ_BALANCE "blnc" /* Adjustment layer - color balance (PS4) */
#define PSD_LADJ_BLACK_WHITE "blwh" /* Adjustment layer - black & white (PS10) */
#define PSD_LADJ_HUE "hue " /* Adjustment layer - old hue/saturation (PS4) */
#define PSD_LADJ_HUE2 "hue2" /* Adjustment layer - hue/saturation (PS5) */
#define PSD_LADJ_SELECTIVE "selc" /* Adjustment layer - selective color (PS4) */
#define PSD_LADJ_MIXER "mixr" /* Adjustment layer - channel mixer (PS9) */
#define PSD_LADJ_GRAD_MAP "grdm" /* Adjustment layer - gradient map (PS9) */
#define PSD_LADJ_PHOTO_FILT "phfl" /* Adjustment layer - photo filter (PS9) */
#define PSD_LADJ_EXPOSURE "expA" /* Adjustment layer - exposure (PS10) */
#define PSD_LADJ_INVERT "nvrt" /* Adjustment layer - invert (PS4) */
#define PSD_LADJ_THRESHOLD "thrs" /* Adjustment layer - threshold (PS4) */
#define PSD_LADJ_POSTERIZE "post" /* Adjustment layer - posterize (PS4) */
/* Fill Layer IDs */
#define PSD_LFIL_SOLID "SoCo" /* Solid color sheet setting (PS6) */
#define PSD_LFIL_PATTERN "PtFl" /* Pattern fill setting (PS6) */
#define PSD_LFIL_GRADIENT "GdFl" /* Gradient fill setting (PS6) */
/* Effects Layer IDs */
#define PSD_LFX_FX "lrFX" /* Effects layer info (PS5) */
#define PSD_LFX_FX2 "lfx2" /* Object based effects layer info (PS6) */
/* Type Tool Layers */
#define PSD_LTYP_TYPE "tySh" /* Type tool layer (PS5) */
#define PSD_LTYP_TYPE2 "TySh" /* Type tool object setting (PS6) */
/* Layer Properties */
#define PSD_LPRP_UNICODE "luni" /* Unicode layer name (PS5) */
#define PSD_LPRP_SOURCE "lnsr" /* Layer name source setting (PS6) */
#define PSD_LPRP_ID "lyid" /* Layer ID (PS5) */
#define PSD_LPRP_BLEND_CLIP "clbl" /* Blend clipping elements (PS6) */
#define PSD_LPRP_BLEND_INT "infx" /* Blend interior elements (PS6) */
#define PSD_LPRP_KNOCKOUT "knko" /* Knockout setting (PS6) */
#define PSD_LPRP_PROTECT "lspf" /* Protected setting (PS6) */
#define PSD_LPRP_COLOR "lclr" /* Sheet color setting (PS6) */
#define PSD_LPRP_REF_POINT "fxrp" /* Reference point (PS6) */
/* Vector mask */
#define PSD_LMSK_VMASK "vmsk" /* Vector mask setting (PS6) */
/* Parasites */
#define PSD_LPAR_ANNOTATE "Anno" /* Annotation (PS6) */
/* Other */
#define PSD_LOTH_SECTION "lsct" /* Section divider setting - Layer goups (PS6) */
#define PSD_LOTH_PATTERN "Patt" /* Patterns (PS6) */
#define PSD_LOTH_GRADIENT "grdm" /* Gradient settings (PS6) */
#define PSD_LOTH_RESTRICT "brst" /* Channel blending restirction setting (PS6) */
#define PSD_LOTH_FOREIGN_FX "ffxi" /* Foreign effect ID (PS6) */
#define PSD_LOTH_PATT_DATA "shpa" /* Pattern data (PS6) */
#define PSD_LOTH_META_DATA "shmd" /* Meta data setting (PS6) */
#define PSD_LOTH_LAYER_DATA "layr" /* Layer data (PS6) */
/* Effects layer resource IDs */
#define PSD_LFX_COMMON "cmnS" /* Effects layer - common state (PS5) */
#define PSD_LFX_DROP_SDW "dsdw" /* Effects layer - drop shadow (PS5) */
#define PSD_LFX_INNER_SDW "isdw" /* Effects layer - inner shadow (PS5) */
#define PSD_LFX_OUTER_GLW "oglw" /* Effects layer - outer glow (PS5) */
#define PSD_LFX_INNER_GLW "iglw" /* Effects layer - inner glow (PS5) */
#define PSD_LFX_BEVEL "bevl" /* Effects layer - bevel (PS5) */
/* PSD spec enums */
/* Image colour modes */
typedef enum {
PSD_BITMAP = 0, /* Bitmap image */
PSD_GRAYSCALE = 1, /* Greyscale image */
PSD_INDEXED = 2, /* Indexed image */
PSD_RGB = 3, /* RGB image */
PSD_CMYK = 4, /* CMYK */
PSD_MULTICHANNEL = 7, /* Multichannel image*/
PSD_DUOTONE = 8, /* Duotone image*/
PSD_LAB = 9 /* L*a*b image */
} PSDColorMode;
/* Image colour spaces */
typedef enum {
PSD_CS_RGB = 0, /* RGB */
PSD_CS_HSB = 1, /* Hue, Saturation, Brightness */
PSD_CS_CMYK = 2, /* CMYK */
PSD_CS_PANTONE = 3, /* Pantone matching system (Lab)*/
PSD_CS_FOCOLTONE = 4, /* Focoltone colour system (CMYK)*/
PSD_CS_TRUMATCH = 5, /* Trumatch color (CMYK)*/
PSD_CS_TOYO = 6, /* Toyo 88 colorfinder 1050 (Lab)*/
PSD_CS_LAB = 7, /* L*a*b*/
PSD_CS_GRAYSCALE = 8, /* Grey scale */
PSD_CS_HKS = 10, /* HKS colors (CMYK)*/
PSD_CS_DIC = 11, /* DIC color guide (Lab)*/
PSD_CS_ANPA = 3000, /* Anpa color (Lab)*/
} PSDColorSpace;
/* Image Resource IDs */
typedef enum {
PSD_PS2_IMAGE_INFO = 1000, /* 0x03e8 - Obsolete - ps 2.0 image info */
PSD_MAC_PRINT_INFO = 1001, /* 0x03e9 - Optional - Mac print manager print info record */
PSD_PS2_COLOR_TAB = 1003, /* 0x03eb - Obsolete - ps 2.0 indexed colour table */
PSD_RESN_INFO = 1005, /* 0x03ed - ResolutionInfo structure */
PSD_ALPHA_NAMES = 1006, /* 0x03ee - Alpha channel names */
PSD_DISPLAY_INFO = 1007, /* 0x03ef - DisplayInfo structure */
PSD_CAPTION = 1008, /* 0x03f0 - Optional - Caption string */
PSD_BORDER_INFO = 1009, /* 0x03f1 - Border info */
PSD_BACKGROUND_COL = 1010, /* 0x03f2 - Background colour */
PSD_PRINT_FLAGS = 1011, /* 0x03f3 - Print flags */
PSD_GREY_HALFTONE = 1012, /* 0x03f4 - Greyscale and multichannel halftoning info */
PSD_COLOR_HALFTONE = 1013, /* 0x03f5 - Colour halftoning info */
PSD_DUOTONE_HALFTONE = 1014, /* 0x03f6 - Duotone halftoning info */
PSD_GREY_XFER = 1015, /* 0x03f7 - Greyscale and multichannel transfer functions */
PSD_COLOR_XFER = 1016, /* 0x03f8 - Colour transfer functions */
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, /* 0x03fc - Obsolete */
PSD_EPS_OPT = 1021, /* 0x03fd - EPS options */
PSD_QUICK_MASK = 1022, /* 0x03fe - Quick mask info */
PSD_OBSOLETE_02 = 1023, /* 0x03ff - Obsolete */
PSD_LAYER_STATE = 1024, /* 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, /* 0x0403 - Obsolete */
PSD_IPTC_NAA_DATA = 1028, /* 0x0404 - IPTC-NAA record (IMV4.pdf) */
PSD_IMAGE_MODE_RAW = 1029, /* 0x0405 - Image mode for raw format files */
PSD_JPEG_QUAL = 1030, /* 0x0406 - JPEG quality */
PSD_GRID_GUIDE = 1032, /* 0x0408 - Grid & guide info */
PSD_THUMB_RES = 1033, /* 0x0409 - Thumbnail resource */
PSD_COPYRIGHT_FLG = 1034, /* 0x040a - Copyright flag */
PSD_URL = 1035, /* 0x040b - URL string */
PSD_THUMB_RES2 = 1036, /* 0x040c - Thumbnail resource */
PSD_GLOBAL_ANGLE = 1037, /* 0x040d - Global angle */
PSD_COLOR_SAMPLER = 1038, /* 0x040e - Colour samplers resource */
PSD_ICC_PROFILE = 1039, /* 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, /* 0x0415 - Unicode alpha names */
PSD_IDX_COL_TAB_CNT = 1046, /* 0x0416 - Indexed colour table count */
PSD_IDX_TRANSPARENT = 1047, /* 0x0417 - Index of transparent colour (if any) */
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, /* 0x041d - Alpha IDs */
PSD_URL_LIST_UNI = 1054, /* 0x041e - URL list - unicode */
PSD_VERSION_INFO = 1057, /* 0x0421 - Version info */
PSD_EXIF_DATA = 1058, /* 0x0422 - Exif data block */
PSD_XMP_DATA = 1060, /* 0x0424 - XMP data block */
PSD_PATH_INFO_FIRST = 2000, /* 0x07d0 - First path info block */
PSD_PATH_INFO_LAST = 2998, /* 0x0bb6 - Last path info block */
PSD_CLIPPING_PATH = 2999, /* 0x0bb7 - Name of clipping path */
PSD_PRINT_FLAGS_2 = 10000 /* 0x2710 - Print flags */
} PSDImageResID;
/* Display resolution units */
typedef enum {
PSD_RES_INCH = 1, /* Pixels / inch */
PSD_RES_CM = 2, /* Pixels / cm */
} PSDDisplayResUnit;
/* Width and height units */
typedef enum {
PSD_UNIT_INCH = 1, /* inches */
PSD_UNIT_CM = 2, /* cm */
PSD_UNIT_POINT = 3, /* points (72 points = 1 inch) */
PSD_UNIT_PICA = 4, /* pica ( 6 pica = 1 inch) */
PSD_UNIT_COLUMN = 5, /* columns ( column defined in ps prefs, default = 2.5 inches) */
} PSDUnit;
/* Thumbnail image data encoding */
typedef enum {
kRawRGB = 0, /* RAW data format (never used?) */
kJpegRGB = 1 /* JPEG compression */
} PSDThumbFormat;
/* Path record types */
typedef enum {
PSD_PATH_CL_LEN = 0, /* Closed sub-path length record */
PSD_PATH_CL_LNK = 1, /* Closed sub-path Bezier knot, linked */
PSD_PATH_CL_UNLNK = 2, /* Closed sub-path Bezier knot, unlinked */
PSD_PATH_OP_LEN = 3, /* Open sub-path length record */
PSD_PATH_OP_LNK = 4, /* Open sub-path Bezier knot, linked */
PSD_PATH_OP_UNLNK = 5, /* Open sub-path Bezier knot, unlinked */
PSD_PATH_FILL_RULE = 6, /* Path fill rule record */
PSD_PATH_CLIPBOARD = 7, /* Path clipboard record */
PSD_PATH_FILL_INIT = 8 /* Path initial fill record */
} PSDpathtype;
/* Channel ID */
typedef enum {
PSD_CHANNEL_MASK = -2, /* User supplied layer mask */
PSD_CHANNEL_ALPHA = -1, /* Transparency mask */
PSD_CHANNEL_RED = 0, /* Red channel data */
PSD_CHANNEL_GREEN = 1, /* Green channel data */
PSD_CHANNEL_BLUE = 2 /* Blue channel data */
} PSDChannelID;
/* Clipping */
typedef enum {
PSD_CLIPPING_BASE = 0, /* Base clipping */
PSD_CLIPPING_NON_BASE = 1 /* Non-base clipping */
} PSDClipping;
/* Image compression mode */
typedef enum {
PSD_COMP_RAW = 0, /* Raw data */
PSD_COMP_RLE, /* RLE compressed */
PSD_COMP_ZIP, /* ZIP without prediction */
PSD_COMP_ZIP_PRED /* ZIP with prediction */
} PSDCompressMode;
/* Vertical - horizontal selection */
typedef enum {
PSD_VERTICAL = 0, /* Vertical */
PSD_HORIZONTAL = 1 /* Horizontal */
} VHSelect;
/* PSD spec data structures */
/* PSD field types */
typedef gint32 Fixed; /* Represents a fixed point implied decimal */
/* Apple colour space data structures */
/* RGB Color Value
A color value expressed in the RGB color space is composed of red, green,
and blue component values. Each color component is expressed as a numeric
value within the range of 0 to 65535.
*/
typedef struct
{
guint16 red;
guint16 green;
guint16 blue;
}CMRGBColor;
/* HSV Color Value
A color value expressed in the HSV color space is composed of hue,
saturation, and value component values. Each color component is
expressed as a numeric value within the range of 0 to 65535 inclusive.
The hue value represents a fraction of a circle in which red is
positioned at 0.
*/
typedef struct
{
guint16 hue;
guint16 saturation;
guint16 value;
}CMHSVColor;
/* CMYK Color Value
A color value expressed in the CMYK color space is composed of cyan, magenta,
yellow, and black component values. Each color component is expressed as a
numeric value within the range of 0 to 65535 inclusive, with 0 representing
100% ink (e.g. pure cyan = 0, 65535, 65535, 65535).
*/
typedef struct
{
guint16 cyan;
guint16 magenta;
guint16 yellow;
guint16 black;
}CMCMYKColor;
/* L*a*b* Color Value
The first three values in the color data are, respectively, the colors
lightness, a chrominance, and b chrominance components. The lightness
component is a 16bit value ranging from 0 to 10000. The chrominance
components are each 16bit values ranging from 12800 to 12700. Gray
values are represented by chrominance components of 0 (e.g. pure white
is defined as 10000, 0, 0).
*/
typedef struct
{
guint16 L;
gint16 a;
gint16 b;
} CMLabColor;
/* Gray Color Value
A color value expressed in the Gray color space is composed of a single component,
gray, represented as a numeric value within the range of 0 to 10000.
*/
typedef struct
{
guint16 gray;
} CMGrayColor ;
/* The color union is defined by the CMColor type definition.
*/
typedef union
{
CMRGBColor rgb;
CMHSVColor hsv;
CMLabColor Lab;
CMCMYKColor cmyk;
CMGrayColor gray;
} CMColor;
/* Image resolution data */
typedef struct {
Fixed hRes; /* Horizontal resolution pixels/inch */
gint16 hResUnit; /* Horizontal display resolution unit */
gint16 widthUnit; /* Width unit ?? */
Fixed vRes; /* Vertical resolution pixels/inch */
gint16 vResUnit; /* Vertical display resolution unit */
gint16 heightUnit; /* Height unit ?? */
} ResolutionInfo;
/* Grid & guide header */
typedef struct {
guint32 fVersion; /* Version - always 1 for PS */
guint32 fGridCycleV; /* Vertical grid size */
guint32 fGridCycleH; /* Horizontal grid size */
guint32 fGuideCount; /* Number of guides */
} GuideHeader;
/* Guide resource block */
typedef struct {
guint32 fLocation; /* Guide position in Pixels * 100 */
gchar fDirection; /* Guide orientation */
} GuideResource;
/* Thumbnail data */
typedef struct {
gint32 format; /* Thumbnail image data format (1 = JPEG) */
gint32 width; /* Thumbnail width in pixels */
gint32 height; /* Thumbnail height in pixels */
gint32 widthbytes; /* Padded row bytes ((width * bitspixel + 31) / 32 * 4) */
gint32 size; /* Total size (widthbytes * height * planes */
gint32 compressedsize; /* Size after compression for consistency */
gint16 bitspixel; /* Bits per pixel (always 24) */
gint16 planes; /* Number of planes (always 1) */
} ThumbnailInfo;
/* Channel display info data */
typedef struct {
gint16 colorSpace; /* Colour space from PSDColorSpace */
guint16 color[4]; /* 4 * 16 bit color components */
gint16 opacity; /* Opacity 0 to 100 */
gchar kind; /* Selected = 0, Protected = 1 */
gchar padding; /* Padding */
} DisplayInfo;
/* PSD Channel length info data structure */
typedef struct
{
gint16 channel_id; /* Channel ID */
guint32 data_len; /* Layer left */
} ChannelLengthInfo;
/* PSD Layer flags */
typedef struct
{
gboolean trans_prot; /* Transparency protected */
gboolean visible; /* Visible */
gboolean obsolete; /* Obsolete */
gboolean bit4; /* Bit 4 in use */
gboolean irrelevant; /* Pixel data irrelevant to image appearance */
} LayerFlags;
/* PSD Layer mask flags */
typedef struct
{
gboolean relative_pos; /* Mask position recorded relative to layer */
gboolean disabled; /* Mask disabled */
gboolean invert; /* Invert mask on blending */
} MaskFlags;
/* PSD Layer mask data (length 20) */
typedef struct
{
guint32 top; /* Layer top */
guint32 left; /* Layer left */
guint32 bottom; /* Layer bottom */
guint32 right; /* Layer right */
guchar def_color; /* Default background colour */
guchar flags; /* Layer flags */
guchar extra_def_color; /* Real default background colour */
guchar extra_flags; /* Real layer flags */
MaskFlags mask_flags; /* Flags */
} LayerMask;
/* PSD Layer mask data (length 36) */
typedef struct
{
guint32 top; /* Layer top */
guint32 left; /* Layer left */
guint32 bottom; /* Layer bottom */
guint32 right; /* Layer right */
} LayerMaskExtra;
/* PSD Layer data structure */
typedef struct
{
gboolean drop; /* Do not add layer to GIMP image */
guint32 top; /* Layer top */
guint32 left; /* Layer left */
guint32 bottom; /* Layer bottom */
guint32 right; /* Layer right */
guint16 num_channels; /* Number of channels */
ChannelLengthInfo *chn_info; /* Channel length info */
gchar mode_key[4]; /* Blend mode key */
gchar blend_mode[4]; /* Blend mode */
guchar opacity; /* Opacity - 0 = transparent ... 255 = opaque */
guchar clipping; /* Clipping */
guchar flags; /* Layer flags */
guchar filler; /* Filler */
guint32 extra_len; /* Extra data length */
gchar *name; /* Layer name */
guint32 mask_len; /* Layer mask data length */
LayerMask layer_mask; /* Layer mask data */
LayerMaskExtra layer_mask_extra; /* Layer mask extra data */
LayerFlags layer_flags; /* Layer flags */
guint32 id; /* Layer ID (Tattoo) */
} PSDlayer;
/* PSD Channel data structure */
typedef struct
{
gint16 id; /* Channel ID */
gchar *name; /* Channel name */
gchar *data; /* Channel image data */
guint32 rows; /* Channel rows */
guint32 columns; /* Channel columns */
} PSDchannel;
/* PSD Channel data structure */
typedef struct
{
GimpRGB gimp_color; /* Gimp RGB color */
gint16 opacity; /* Opacity */
guchar ps_kind; /* PS type flag */
gint16 ps_cspace; /* PS colour space */
CMColor ps_color; /* PS colour */
} PSDchanneldata;
/* PSD Image Resource data structure */
typedef struct
{
gchar type[4]; /* Image resource type */
gint16 id; /* Image resource ID */
gchar name[256]; /* Image resource name (pascal string) */
gint32 data_start; /* Image resource data start */
gint32 data_len; /* Image resource data length */
} PSDimageres;
/* PSD Layer Resource data structure */
typedef struct
{
gchar sig[4]; /* Layer resource signature */
gchar key[4]; /* Layer resource key */
gint32 data_start; /* Layer resource data start */
gint32 data_len; /* Layer resource data length */
} PSDlayerres;
/* PSD File data structures */
typedef struct
{
guint16 channels; /* Number of channels: 1- 56 */
gboolean transparency; /* Image has merged transparency alpha channel */
guint32 rows; /* Number of rows: 1 - 30000 */
guint32 columns; /* Number of columns: 1 - 30000 */
guint16 bps; /* Bits per channel: 1, 8 or 16 */
guint16 color_mode; /* Image colour mode: {PSDColorMode} */
GimpImageBaseType base_type; /* Image base colour mode: (GIMP) */
guint16 comp_mode; /* Merged image compression mode */
guchar *color_map; /* Colour map data */
guint32 color_map_len; /* Colour map data length */
guint32 color_map_entries; /* Colour map number of entries */
guint32 image_res_start; /* Image resource block start address */
guint32 image_res_len; /* Image resource block length */
guint32 mask_layer_start; /* Mask & layer block start address */
guint32 mask_layer_len; /* Mask & layer block length */
gint16 num_layers; /* Number of layers */
guint32 layer_data_start; /* Layer pixel data start */
guint32 layer_data_len; /* Layer pixel data length */
guint32 merged_image_start; /* Merged image pixel data block start address */
guint32 merged_image_len; /* Merged image pixel data block length */
gboolean no_icc; /* Do not use ICC profile */
guint16 layer_state; /* Active layer number counting from bottom up */
GPtrArray *alpha_names; /* Alpha channel names */
PSDchanneldata **alpha_display_info; /* Alpha channel display info */
guint16 alpha_display_count; /* Number of alpha channel display info recs */
guint32 *alpha_id; /* Alpha channel ids (tattoos) */
guint16 alpha_id_count; /* Number of alpha channel id items */
guint16 quick_mask_id; /* Channel number containing quick mask */
} PSDimage;
/* Public functions */
#endif /* __PSD_H__ */

View file

@ -111,7 +111,6 @@ plug-ins/common/polar.c
plug-ins/common/poppler.c
plug-ins/common/postscript.c
plug-ins/common/procedure-browser.c
plug-ins/common/psd-load.c
plug-ins/common/psd-save.c
plug-ins/common/psp.c
plug-ins/common/randomize.c