mirror of https://github.com/GNOME/gimp.git
Greatly reduced memory requirements for layered image loading - we now do
Sun Jan 10 20:13:13 GMT 1999 Adam D. Moss <adam@gimp.org> * plug-ins/psd/psd.c: Greatly reduced memory requirements for layered image loading - we now do just-in-time channel unpacking. Some little cleanups too.
This commit is contained in:
parent
f0558a7ea2
commit
1fa91b23aa
|
@ -1,3 +1,10 @@
|
||||||
|
Sun Jan 10 20:13:13 GMT 1999 Adam D. Moss <adam@gimp.org>
|
||||||
|
|
||||||
|
* plug-ins/psd/psd.c:
|
||||||
|
Greatly reduced memory requirements for layered image loading -
|
||||||
|
we now do just-in-time channel unpacking. Some little
|
||||||
|
cleanups too.
|
||||||
|
|
||||||
Sat Jan 9 21:24:20 PST 1999 Manish Singh <yosh@gimp.org>
|
Sat Jan 9 21:24:20 PST 1999 Manish Singh <yosh@gimp.org>
|
||||||
|
|
||||||
* autogen.sh: rework to do gcg by ourselves
|
* autogen.sh: rework to do gcg by ourselves
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* PSD Plugin version 2.0.0
|
* PSD Plugin version 2.0.1
|
||||||
* This GIMP plug-in is designed to load Adobe Photoshop(tm) files (.PSD)
|
* This GIMP plug-in is designed to load Adobe Photoshop(tm) files (.PSD)
|
||||||
*
|
*
|
||||||
* Adam D. Moss <adam@gimp.org> <adam@foxbox.org>
|
* Adam D. Moss <adam@gimp.org> <adam@foxbox.org>
|
||||||
|
@ -35,67 +35,68 @@
|
||||||
/*
|
/*
|
||||||
* Revision history:
|
* Revision history:
|
||||||
*
|
*
|
||||||
* 98.09.04 / v2.0.0 / Adam D. Moss
|
* 1999.01.10 / v2.0.1 / Adam D. Moss
|
||||||
|
* Greatly reduced memory requirements for layered image loading -
|
||||||
|
* we now do just-in-time channel unpacking. Some little
|
||||||
|
* cleanups too.
|
||||||
|
*
|
||||||
|
* 1998.09.04 / v2.0.0 / Adam D. Moss
|
||||||
* Now recognises and loads the new Guides extensions written
|
* Now recognises and loads the new Guides extensions written
|
||||||
* by Photoshop 4 and 5.
|
* by Photoshop 4 and 5.
|
||||||
*
|
*
|
||||||
* 98.07.31 / v1.9.9.9f / Adam D. Moss
|
* 1998.07.31 / v1.9.9.9f / Adam D. Moss
|
||||||
* Use OVERLAY_MODE if available.
|
* Use OVERLAY_MODE if available.
|
||||||
*
|
*
|
||||||
* 98.07.31 / v1.9.9.9e / Adam D. Moss
|
* 1998.07.31 / v1.9.9.9e / Adam D. Moss
|
||||||
* Worked around some buggy PSD savers (suspect PS4 on Mac) - ugh.
|
* Worked around some buggy PSD savers (suspect PS4 on Mac) - ugh.
|
||||||
* Fixed a bug when loading layer masks of certain dimensions.
|
* Fixed a bug when loading layer masks of certain dimensions.
|
||||||
*
|
*
|
||||||
* 98.05.04 / v1.9.9.9b / Adam D. Moss
|
* 1998.05.04 / v1.9.9.9b / Adam D. Moss
|
||||||
* Changed the Pascal-style string-reading stuff. That fixed
|
* Changed the Pascal-style string-reading stuff. That fixed
|
||||||
* some file-padding problems. Made all debugging output
|
* some file-padding problems. Made all debugging output
|
||||||
* compile-time optional (please leave it enabled for now).
|
* compile-time optional (please leave it enabled for now).
|
||||||
* Reduced memory requirements; still much room for improvement.
|
* Reduced memory requirements; still much room for improvement.
|
||||||
*
|
*
|
||||||
* 98.04.28 / v1.9.9.9 / Adam D. Moss
|
* 1998.04.28 / v1.9.9.9 / Adam D. Moss
|
||||||
* Fixed the correct channel interlacing of 'raw' flat images.
|
* Fixed the correct channel interlacing of 'raw' flat images.
|
||||||
* Thanks to Christian Kirsch and Jay Cox for spotting this.
|
* Thanks to Christian Kirsch and Jay Cox for spotting this.
|
||||||
* Changed some of the I/O routines.
|
* Changed some of the I/O routines.
|
||||||
*
|
*
|
||||||
* 98.04.26 / v1.9.9.8 / Adam D. Moss
|
* 1998.04.26 / v1.9.9.8 / Adam D. Moss
|
||||||
* Implemented Aux-channels for layered files. Got rid
|
* Implemented Aux-channels for layered files. Got rid
|
||||||
* of <endian.h> nonsense. Improved Layer Mask padding.
|
* of <endian.h> nonsense. Improved Layer Mask padding.
|
||||||
* Enforced num_layers/num_channels limit checks.
|
* Enforced num_layers/num_channels limit checks.
|
||||||
*
|
*
|
||||||
* 98.04.23 / v1.9.9.5 / Adam D. Moss
|
* 1998.04.23 / v1.9.9.5 / Adam D. Moss
|
||||||
* Got Layer Masks working, got Aux-channels working
|
* Got Layer Masks working, got Aux-channels working
|
||||||
* for unlayered files, fixed 'raw' channel loading, fixed
|
* for unlayered files, fixed 'raw' channel loading, fixed
|
||||||
* some other mini-bugs, slightly better progress meters.
|
* some other mini-bugs, slightly better progress meters.
|
||||||
* Thanks to everyone who is helping with the testing!
|
* Thanks to everyone who is helping with the testing!
|
||||||
*
|
*
|
||||||
* 98.04.21 / v1.9.9.1 / Adam D. Moss
|
* 1998.04.21 / v1.9.9.1 / Adam D. Moss
|
||||||
* A little cleanup. Implemented Layer Masks but disabled
|
* A little cleanup. Implemented Layer Masks but disabled
|
||||||
* them again - PS masks can be a different size to their
|
* them again - PS masks can be a different size to their
|
||||||
* owning layer, unlike those in GIMP.
|
* owning layer, unlike those in GIMP.
|
||||||
*
|
*
|
||||||
* 98.04.19 / v1.9.9.0 / Adam D. Moss
|
* 1998.04.19 / v1.9.9.0 / Adam D. Moss
|
||||||
* Much happier now.
|
* Much happier now.
|
||||||
*
|
*
|
||||||
* 97.03.13 / v1.9.0 / Adam D. Moss
|
* 1997.03.13 / v1.9.0 / Adam D. Moss
|
||||||
* Layers, channels and masks, oh my.
|
* Layers, channels and masks, oh my.
|
||||||
* + Bugfixes & rearchitecturing.
|
* + Bugfixes & rearchitecturing.
|
||||||
*
|
*
|
||||||
* 97.01.30 / v1.0.12 / Torsten Martinsen
|
* 1997.01.30 / v1.0.12 / Torsten Martinsen
|
||||||
* Flat PSD image loading.
|
* Flat PSD image loading.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO:
|
* TODO:
|
||||||
*
|
*
|
||||||
* Crush 16bpp channels
|
* Crush 16bpp channels (Wait until GIMP 2.0, probably)
|
||||||
* CMYK -> RGB
|
* CMYK -> RGB
|
||||||
* Load BITMAP mode
|
* Load BITMAP mode
|
||||||
*
|
*
|
||||||
* File saving. (I am unlikely to be able to do this for
|
* File saving
|
||||||
* practical reasons. Suggest someone works on it as a
|
|
||||||
* separate plugin - please let me know.)
|
|
||||||
*
|
|
||||||
* Reduce memory requirements!
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -106,7 +107,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* *** DEFINES *** */
|
/* *** USER DEFINES *** */
|
||||||
|
|
||||||
/* set to TRUE if you want debugging, FALSE otherwise */
|
/* set to TRUE if you want debugging, FALSE otherwise */
|
||||||
#define PSD_DEBUG TRUE
|
#define PSD_DEBUG TRUE
|
||||||
|
@ -120,7 +121,7 @@
|
||||||
/* the max number of guides that this plugin should let an image have */
|
/* the max number of guides that this plugin should let an image have */
|
||||||
#define MAX_GUIDES 200
|
#define MAX_GUIDES 200
|
||||||
|
|
||||||
/* *** END OF DEFINES *** */
|
/* *** END OF USER DEFINES *** */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,35 +150,6 @@ typedef enum
|
||||||
} psd_imagetype;
|
} psd_imagetype;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Declare some local functions.
|
|
||||||
*/
|
|
||||||
static void query (void);
|
|
||||||
static void run (char *name,
|
|
||||||
int nparams,
|
|
||||||
GParam *param,
|
|
||||||
int *nreturn_vals,
|
|
||||||
GParam **return_vals);
|
|
||||||
GDrawableType psd_type_to_gimp_type
|
|
||||||
(psd_imagetype psdtype);
|
|
||||||
GImageType psd_type_to_gimp_base_type
|
|
||||||
(psd_imagetype psdtype);
|
|
||||||
GLayerMode psd_lmode_to_gimp_lmode
|
|
||||||
(gchar modekey[4]);
|
|
||||||
static gint32 load_image (char *filename);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GPlugInInfo PLUG_IN_INFO =
|
|
||||||
{
|
|
||||||
NULL, /* init_proc */
|
|
||||||
NULL, /* quit_proc */
|
|
||||||
query, /* query_proc */
|
|
||||||
run, /* run_proc */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct PsdChannel
|
typedef struct PsdChannel
|
||||||
{
|
{
|
||||||
gchar *name;
|
gchar *name;
|
||||||
|
@ -186,8 +158,18 @@ typedef struct PsdChannel
|
||||||
|
|
||||||
guint32 compressedsize;
|
guint32 compressedsize;
|
||||||
|
|
||||||
} PSDchannel;
|
fpos_t fpos; /* Remember where the data is in the file, so we can
|
||||||
|
come back to it! */
|
||||||
|
|
||||||
|
/* We can't just assume that the channel's width and height are the
|
||||||
|
* same as those of the layer that owns the channel, since this
|
||||||
|
* channel may be a layer mask, which Photoshop allows to have a
|
||||||
|
* different size from the layer which it applies to.
|
||||||
|
*/
|
||||||
|
guint32 width;
|
||||||
|
guint32 height;
|
||||||
|
|
||||||
|
} PSDchannel;
|
||||||
|
|
||||||
|
|
||||||
typedef struct PsdGuide
|
typedef struct PsdGuide
|
||||||
|
@ -197,7 +179,6 @@ typedef struct PsdGuide
|
||||||
} PSDguide;
|
} PSDguide;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct PsdLayer
|
typedef struct PsdLayer
|
||||||
{
|
{
|
||||||
gint num_channels;
|
gint num_channels;
|
||||||
|
@ -225,7 +206,6 @@ typedef struct PsdLayer
|
||||||
} PSDlayer;
|
} PSDlayer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct PsdImage
|
typedef struct PsdImage
|
||||||
{
|
{
|
||||||
gint num_layers;
|
gint num_layers;
|
||||||
|
@ -247,15 +227,42 @@ typedef struct PsdImage
|
||||||
gchar *caption;
|
gchar *caption;
|
||||||
|
|
||||||
guint active_layer_num;
|
guint active_layer_num;
|
||||||
|
|
||||||
} PSDimage;
|
} PSDimage;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static PSDimage psd_image;
|
/* Declare some local functions.
|
||||||
|
*/
|
||||||
|
static void query (void);
|
||||||
|
static void run (char *name,
|
||||||
|
int nparams,
|
||||||
|
GParam *param,
|
||||||
|
int *nreturn_vals,
|
||||||
|
GParam **return_vals);
|
||||||
|
static GDrawableType psd_type_to_gimp_type
|
||||||
|
(psd_imagetype psdtype);
|
||||||
|
static GImageType psd_type_to_gimp_base_type
|
||||||
|
(psd_imagetype psdtype);
|
||||||
|
static GLayerMode psd_lmode_to_gimp_lmode
|
||||||
|
(gchar modekey[4]);
|
||||||
|
static gint32 load_image (char *filename);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Various local variables...
|
||||||
|
*/
|
||||||
|
GPlugInInfo PLUG_IN_INFO =
|
||||||
|
{
|
||||||
|
NULL, /* init_proc */
|
||||||
|
NULL, /* quit_proc */
|
||||||
|
query, /* query_proc */
|
||||||
|
run, /* run_proc */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static PSDimage psd_image;
|
||||||
|
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
gchar signature[4];
|
gchar signature[4];
|
||||||
gushort version;
|
gushort version;
|
||||||
|
@ -312,8 +319,9 @@ static void read_whole_file(FILE *fd);
|
||||||
static void reshuffle_cmap(guchar *map256);
|
static void reshuffle_cmap(guchar *map256);
|
||||||
static guchar* getpascalstring(FILE *fd, gchar *why);
|
static guchar* getpascalstring(FILE *fd, gchar *why);
|
||||||
static gchar* getstring(size_t n, FILE * fd, gchar *why);
|
static gchar* getstring(size_t n, FILE * fd, gchar *why);
|
||||||
void throwchunk(size_t n, FILE * fd, gchar *why);
|
static void throwchunk(size_t n, FILE * fd, gchar *why);
|
||||||
void dumpchunk(size_t n, FILE * fd, gchar *why);
|
static void dumpchunk(size_t n, FILE * fd, gchar *why);
|
||||||
|
static void seek_to_and_unpack_pixeldata(FILE* fd, gint layeri, gint channeli);
|
||||||
|
|
||||||
|
|
||||||
MAIN()
|
MAIN()
|
||||||
|
@ -390,7 +398,7 @@ run (char *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GDrawableType
|
static GDrawableType
|
||||||
psd_type_to_gimp_type (psd_imagetype psdtype)
|
psd_type_to_gimp_type (psd_imagetype psdtype)
|
||||||
{
|
{
|
||||||
switch(psdtype)
|
switch(psdtype)
|
||||||
|
@ -407,7 +415,7 @@ psd_type_to_gimp_type (psd_imagetype psdtype)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GLayerMode
|
static GLayerMode
|
||||||
psd_lmode_to_gimp_lmode (gchar modekey[4])
|
psd_lmode_to_gimp_lmode (gchar modekey[4])
|
||||||
{
|
{
|
||||||
if (strncmp(modekey, "norm", 4)==0) return(NORMAL_MODE);
|
if (strncmp(modekey, "norm", 4)==0) return(NORMAL_MODE);
|
||||||
|
@ -444,7 +452,7 @@ psd_lmode_to_gimp_lmode (gchar modekey[4])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GImageType
|
static GImageType
|
||||||
psd_type_to_gimp_base_type (psd_imagetype psdtype)
|
psd_type_to_gimp_base_type (psd_imagetype psdtype)
|
||||||
{
|
{
|
||||||
switch(psdtype)
|
switch(psdtype)
|
||||||
|
@ -787,7 +795,10 @@ dispatch_resID(guint ID, FILE *fd, guint32 *offset, guint32 Size)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
IFDBG printf ("\t\t<Undocumented field.>\n");
|
IFDBG printf ("\t\t<Undocumented field.>\n");
|
||||||
|
IFDBG
|
||||||
dumpchunk(Size, fd, "dispatch_res");
|
dumpchunk(Size, fd, "dispatch_res");
|
||||||
|
else
|
||||||
|
throwchunk(Size, fd, "dispatch_res");
|
||||||
(*offset) += Size;
|
(*offset) += Size;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1013,9 +1024,7 @@ do_layer_struct(FILE *fd, guint32 *offset)
|
||||||
static void
|
static void
|
||||||
do_layer_pixeldata(FILE *fd, guint32 *offset)
|
do_layer_pixeldata(FILE *fd, guint32 *offset)
|
||||||
{
|
{
|
||||||
guint16 compression;
|
|
||||||
gint layeri, channeli;
|
gint layeri, channeli;
|
||||||
guchar *tmpline;
|
|
||||||
|
|
||||||
for (layeri=0; layeri<psd_image.num_layers; layeri++)
|
for (layeri=0; layeri<psd_image.num_layers; layeri++)
|
||||||
{
|
{
|
||||||
|
@ -1036,10 +1045,34 @@ do_layer_pixeldata(FILE *fd, guint32 *offset)
|
||||||
height = psd_image.layer[layeri].height;
|
height = psd_image.layer[layeri].height;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpline = xmalloc(width + 1);
|
fgetpos(fd, &psd_image.layer[layeri].channel[channeli].fpos);
|
||||||
|
psd_image.layer[layeri].channel[channeli].width = width;
|
||||||
|
psd_image.layer[layeri].channel[channeli].height = height;
|
||||||
|
|
||||||
|
throwchunk(psd_image.layer[layeri].channel[channeli].compressedsize,
|
||||||
|
fd, "channel data skip");
|
||||||
|
(*offset) +=
|
||||||
|
psd_image.layer[layeri].channel[channeli].compressedsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
seek_to_and_unpack_pixeldata(FILE* fd, gint layeri, gint channeli)
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
guchar *tmpline;
|
||||||
|
gint compression;
|
||||||
|
guint32 offset = 0;
|
||||||
|
|
||||||
|
fsetpos(fd, &psd_image.layer[layeri].channel[channeli].fpos);
|
||||||
|
|
||||||
compression = getgshort(fd, "layer channel compression type");
|
compression = getgshort(fd, "layer channel compression type");
|
||||||
(*offset)+=2;
|
offset+=2;
|
||||||
|
|
||||||
|
width = psd_image.layer[layeri].channel[channeli].width;
|
||||||
|
height = psd_image.layer[layeri].channel[channeli].height;
|
||||||
|
|
||||||
IFDBG
|
IFDBG
|
||||||
{
|
{
|
||||||
|
@ -1048,41 +1081,38 @@ do_layer_pixeldata(FILE *fd, guint32 *offset)
|
||||||
channeli,
|
channeli,
|
||||||
psd_image.layer[layeri].channel[channeli].type,
|
psd_image.layer[layeri].channel[channeli].type,
|
||||||
compression,
|
compression,
|
||||||
compression==0?"raw":(compression==1?"RLE":"UNKNOWN!"));
|
compression==0?"raw":(compression==1?"RLE":"*UNKNOWN!*"));
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
IFDBG {printf("\t\t\t\tLoading channel data (%d bytes)...\n",
|
|
||||||
width*height);fflush(stdout);}
|
|
||||||
|
|
||||||
psd_image.layer[layeri].channel[channeli].data =
|
psd_image.layer[layeri].channel[channeli].data =
|
||||||
xmalloc (width * height);
|
xmalloc (width * height);
|
||||||
|
|
||||||
|
tmpline = xmalloc(width + 1);
|
||||||
|
|
||||||
switch (compression)
|
switch (compression)
|
||||||
{
|
{
|
||||||
case 0: /* raw data */
|
case 0: /* raw data */
|
||||||
{
|
{
|
||||||
gint linei;
|
gint linei;
|
||||||
|
|
||||||
for (linei=0;
|
for (linei=0; linei < height; linei++)
|
||||||
linei<height;
|
|
||||||
linei++)
|
|
||||||
{
|
{
|
||||||
xfread(fd,
|
xfread(fd,
|
||||||
(psd_image.layer[layeri].channel[channeli].data+
|
(psd_image.layer[layeri].channel[channeli].data+
|
||||||
linei * width),
|
linei * width),
|
||||||
width,
|
width,
|
||||||
"raw channel line");
|
"raw channel line");
|
||||||
(*offset) += width;
|
offset += width;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pad raw data to multiple of 2? */
|
|
||||||
#if 0
|
#if 0
|
||||||
if ((height *
|
/* Pad raw data to multiple of 2? */
|
||||||
width) & 1)
|
if ((height * width) & 1)
|
||||||
{
|
{
|
||||||
getguchar(fd, "raw channel padding");
|
getguchar(fd, "raw channel padding");
|
||||||
(*offset)++;
|
offset++;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1096,9 +1126,9 @@ do_layer_pixeldata(FILE *fd, guint32 *offset)
|
||||||
data to unpack to the right length... hmm... */
|
data to unpack to the right length... hmm... */
|
||||||
throwchunk(height * 2,
|
throwchunk(height * 2,
|
||||||
fd, "widthlist");
|
fd, "widthlist");
|
||||||
(*offset) += height * 2;
|
offset += height * 2;
|
||||||
|
|
||||||
blockread = (*offset);
|
blockread = offset;
|
||||||
|
|
||||||
/*IFDBG {printf("\nHere comes the guitar solo...\n");
|
/*IFDBG {printf("\nHere comes the guitar solo...\n");
|
||||||
fflush(stdout);}*/
|
fflush(stdout);}*/
|
||||||
|
@ -1111,7 +1141,7 @@ do_layer_pixeldata(FILE *fd, guint32 *offset)
|
||||||
unpack_pb_channel(fd, tmpline,
|
unpack_pb_channel(fd, tmpline,
|
||||||
width
|
width
|
||||||
/*+ (width&1)*/,
|
/*+ (width&1)*/,
|
||||||
offset);
|
&offset);
|
||||||
memcpy((psd_image.layer[layeri].channel[channeli].data+
|
memcpy((psd_image.layer[layeri].channel[channeli].data+
|
||||||
linei * width),
|
linei * width),
|
||||||
tmpline,
|
tmpline,
|
||||||
|
@ -1119,7 +1149,7 @@ do_layer_pixeldata(FILE *fd, guint32 *offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
IFDBG {printf("\t\t\t\t\tActual compressed size was %d bytes\n"
|
IFDBG {printf("\t\t\t\t\tActual compressed size was %d bytes\n"
|
||||||
, (*offset)-blockread);fflush(stdout);}
|
, offset-blockread);fflush(stdout);}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: /* *unknown* */
|
default: /* *unknown* */
|
||||||
|
@ -1134,11 +1164,6 @@ do_layer_pixeldata(FILE *fd, guint32 *offset)
|
||||||
else
|
else
|
||||||
IFDBG {printf("\nTRIED TO FREE NULL!");fflush(stdout);}
|
IFDBG {printf("\nTRIED TO FREE NULL!");fflush(stdout);}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* printf("\n[[%ld]]\n", getglong(fd, "uhhhh"));
|
|
||||||
(*offset)+=4;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1158,7 +1183,6 @@ do_layers(FILE *fd, guint32 *offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_layer_and_mask(FILE *fd)
|
do_layer_and_mask(FILE *fd)
|
||||||
{
|
{
|
||||||
|
@ -1203,12 +1227,11 @@ do_layer_and_mask(FILE *fd)
|
||||||
printf("PSD: Stern warning - no mask info.\n");
|
printf("PSD: Stern warning - no mask info.\n");
|
||||||
|
|
||||||
|
|
||||||
/* If 'offset' wasn't being buggily updated, we wouldn't need this. */
|
/* If 'offset' wasn't being buggily updated, we wouldn't need this. (!?) */
|
||||||
fseek(fd, Size+offset_now, SEEK_SET);
|
fseek(fd, Size+offset_now, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_image_resources(FILE *fd)
|
do_image_resources(FILE *fd)
|
||||||
{
|
{
|
||||||
|
@ -1574,6 +1597,7 @@ load_image(char *name)
|
||||||
GDrawable *drawable = NULL;
|
GDrawable *drawable = NULL;
|
||||||
GPixelRgn pixel_rgn;
|
GPixelRgn pixel_rgn;
|
||||||
gint32 iter;
|
gint32 iter;
|
||||||
|
fpos_t tmpfpos;
|
||||||
|
|
||||||
|
|
||||||
IFDBG printf("------- %s ---------------------------------\n",name);
|
IFDBG printf("------- %s ---------------------------------\n",name);
|
||||||
|
@ -1615,6 +1639,8 @@ load_image(char *name)
|
||||||
gimp_image_new (PSDheader.columns, PSDheader.rows, gimagetype);
|
gimp_image_new (PSDheader.columns, PSDheader.rows, gimagetype);
|
||||||
gimp_image_set_filename (image_ID, name);
|
gimp_image_set_filename (image_ID, name);
|
||||||
|
|
||||||
|
fgetpos (fd, &tmpfpos);
|
||||||
|
|
||||||
for (lnum=0; lnum<psd_image.num_layers; lnum++)
|
for (lnum=0; lnum<psd_image.num_layers; lnum++)
|
||||||
{
|
{
|
||||||
gint numc;
|
gint numc;
|
||||||
|
@ -1633,6 +1659,7 @@ load_image(char *name)
|
||||||
{
|
{
|
||||||
merged_data = xmalloc(psd_image.layer[lnum].width *
|
merged_data = xmalloc(psd_image.layer[lnum].width *
|
||||||
psd_image.layer[lnum].height);
|
psd_image.layer[lnum].height);
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 0);
|
||||||
memcpy(merged_data, psd_image.layer[lnum].channel[0].data,
|
memcpy(merged_data, psd_image.layer[lnum].channel[0].data,
|
||||||
psd_image.layer[lnum].width *
|
psd_image.layer[lnum].width *
|
||||||
psd_image.layer[lnum].height);
|
psd_image.layer[lnum].height);
|
||||||
|
@ -1642,6 +1669,8 @@ load_image(char *name)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 0);
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 1);
|
||||||
merged_data =
|
merged_data =
|
||||||
chans_to_GRAYA (psd_image.layer[lnum].channel[1].data,
|
chans_to_GRAYA (psd_image.layer[lnum].channel[1].data,
|
||||||
psd_image.layer[lnum].channel[0].data,
|
psd_image.layer[lnum].channel[0].data,
|
||||||
|
@ -1668,6 +1697,9 @@ load_image(char *name)
|
||||||
IFDBG printf("It's RGB.\n");
|
IFDBG printf("It's RGB.\n");
|
||||||
if (!psd_layer_has_alpha(&psd_image.layer[lnum]))
|
if (!psd_layer_has_alpha(&psd_image.layer[lnum]))
|
||||||
{
|
{
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 0);
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 1);
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 2);
|
||||||
merged_data =
|
merged_data =
|
||||||
chans_to_RGB (psd_image.layer[lnum].channel[0].data,
|
chans_to_RGB (psd_image.layer[lnum].channel[0].data,
|
||||||
psd_image.layer[lnum].channel[1].data,
|
psd_image.layer[lnum].channel[1].data,
|
||||||
|
@ -1684,6 +1716,10 @@ load_image(char *name)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 0);
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 1);
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 2);
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 3);
|
||||||
merged_data =
|
merged_data =
|
||||||
chans_to_RGBA (psd_image.layer[lnum].channel[1].data,
|
chans_to_RGBA (psd_image.layer[lnum].channel[1].data,
|
||||||
psd_image.layer[lnum].channel[2].data,
|
psd_image.layer[lnum].channel[2].data,
|
||||||
|
@ -1733,6 +1769,7 @@ load_image(char *name)
|
||||||
lm_data = xmalloc(psd_image.layer[lnum].width *
|
lm_data = xmalloc(psd_image.layer[lnum].width *
|
||||||
psd_image.layer[lnum].height);
|
psd_image.layer[lnum].height);
|
||||||
{
|
{
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, iter);
|
||||||
/* PS layer masks can be a different size to
|
/* PS layer masks can be a different size to
|
||||||
their owning layer, so we have to resize them. */
|
their owning layer, so we have to resize them. */
|
||||||
resize_mask(psd_image.layer[lnum].channel[iter].data,
|
resize_mask(psd_image.layer[lnum].channel[iter].data,
|
||||||
|
@ -1804,8 +1841,9 @@ load_image(char *name)
|
||||||
gimp_progress_update ((double)(lnum+1.0) /
|
gimp_progress_update ((double)(lnum+1.0) /
|
||||||
(double)psd_image.num_layers);
|
(double)psd_image.num_layers);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
fsetpos (fd, &tmpfpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((psd_image.num_aux_channels > 0) &&
|
if ((psd_image.num_aux_channels > 0) &&
|
||||||
|
@ -1821,7 +1859,7 @@ load_image(char *name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (want_aux || (psd_image.num_layers==0)) /* PS2-style - NO LAYERS. */
|
if (want_aux || (psd_image.num_layers==0)) /* Photoshop2-style: NO LAYERS. */
|
||||||
{
|
{
|
||||||
|
|
||||||
IFDBG printf("Image data %ld chars\n", PSDheader.imgdatalen);
|
IFDBG printf("Image data %ld chars\n", PSDheader.imgdatalen);
|
||||||
|
@ -1879,7 +1917,8 @@ load_image(char *name)
|
||||||
|
|
||||||
if (PSDheader.bpp != 8)
|
if (PSDheader.bpp != 8)
|
||||||
{
|
{
|
||||||
printf("%s: The GIMP only supports 8-bit deep PSD images\n",
|
printf("%s: The GIMP only supports 8-bit deep PSD images "
|
||||||
|
"at this time.\n",
|
||||||
prog_name);
|
prog_name);
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
@ -1963,9 +2002,6 @@ load_image(char *name)
|
||||||
dest = xmalloc( step * PSDheader.columns * PSDheader.rows );
|
dest = xmalloc( step * PSDheader.columns * PSDheader.rows );
|
||||||
|
|
||||||
|
|
||||||
gimp_progress_update ((double)0.0);
|
|
||||||
|
|
||||||
|
|
||||||
if (PSDheader.compression == 1)
|
if (PSDheader.compression == 1)
|
||||||
{
|
{
|
||||||
nguchars = PSDheader.columns * PSDheader.rows;
|
nguchars = PSDheader.columns * PSDheader.rows;
|
||||||
|
@ -1973,16 +2009,15 @@ load_image(char *name)
|
||||||
xfread(fd, temp, PSDheader.imgdatalen, "image data");
|
xfread(fd, temp, PSDheader.imgdatalen, "image data");
|
||||||
if (!cmyk)
|
if (!cmyk)
|
||||||
{
|
{
|
||||||
gimp_progress_update ((double)0.25);
|
gimp_progress_update ((double)1.00);
|
||||||
decode(PSDheader.imgdatalen, nguchars, temp, dest, step);
|
decode(PSDheader.imgdatalen, nguchars, temp, dest, step);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gimp_progress_update ((double)0.25);
|
gimp_progress_update ((double)1.00);
|
||||||
cmykbuf = xmalloc(step * nguchars);
|
cmykbuf = xmalloc(step * nguchars);
|
||||||
decode(PSDheader.imgdatalen, nguchars, temp, cmykbuf, step);
|
decode(PSDheader.imgdatalen, nguchars, temp, cmykbuf, step);
|
||||||
|
|
||||||
gimp_progress_update ((double)0.50);
|
|
||||||
cmyk2rgb(cmykbuf, dest, PSDheader.columns, PSDheader.rows,
|
cmyk2rgb(cmykbuf, dest, PSDheader.columns, PSDheader.rows,
|
||||||
step > 4);
|
step > 4);
|
||||||
g_free(cmykbuf);
|
g_free(cmykbuf);
|
||||||
|
@ -1993,18 +2028,17 @@ load_image(char *name)
|
||||||
{
|
{
|
||||||
if (!cmyk)
|
if (!cmyk)
|
||||||
{
|
{
|
||||||
gimp_progress_update ((double)0.50);
|
gimp_progress_update ((double)1.00);
|
||||||
xfread_interlaced(fd, dest, PSDheader.imgdatalen,
|
xfread_interlaced(fd, dest, PSDheader.imgdatalen,
|
||||||
"raw image data", step);
|
"raw image data", step);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gimp_progress_update ((double)0.25);
|
gimp_progress_update ((double)1.00);
|
||||||
cmykbuf = xmalloc(PSDheader.imgdatalen);
|
cmykbuf = xmalloc(PSDheader.imgdatalen);
|
||||||
xfread_interlaced(fd, cmykbuf, PSDheader.imgdatalen,
|
xfread_interlaced(fd, cmykbuf, PSDheader.imgdatalen,
|
||||||
"raw cmyk image data", step);
|
"raw cmyk image data", step);
|
||||||
|
|
||||||
gimp_progress_update ((double)0.50);
|
|
||||||
cmykp2rgb(cmykbuf, dest,
|
cmykp2rgb(cmykbuf, dest,
|
||||||
PSDheader.columns, PSDheader.rows, step > 4);
|
PSDheader.columns, PSDheader.rows, step > 4);
|
||||||
g_free(cmykbuf);
|
g_free(cmykbuf);
|
||||||
|
@ -2022,7 +2056,7 @@ load_image(char *name)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gimp_progress_update ((double)0.96);
|
gimp_progress_update ((double)1.00);
|
||||||
|
|
||||||
if (channels == step) /* gimp bpp == psd bpp */
|
if (channels == step) /* gimp bpp == psd bpp */
|
||||||
{
|
{
|
||||||
|
@ -2100,18 +2134,27 @@ decode(long clen, long uclen, char * src, char * dst, int step)
|
||||||
|
|
||||||
l = clen;
|
l = clen;
|
||||||
for (i = 0; i < PSDheader.rows*PSDheader.channels; ++i)
|
for (i = 0; i < PSDheader.rows*PSDheader.channels; ++i)
|
||||||
|
{
|
||||||
l -= PSDheader.rowlength[i];
|
l -= PSDheader.rowlength[i];
|
||||||
|
}
|
||||||
if (l)
|
if (l)
|
||||||
|
{
|
||||||
g_warning("decode: %ld should be zero\n", (long)l);
|
g_warning("decode: %ld should be zero\n", (long)l);
|
||||||
|
}
|
||||||
|
|
||||||
w = PSDheader.rowlength;
|
w = PSDheader.rowlength;
|
||||||
|
|
||||||
packbitsdecode(&clen, uclen, src, dst++, step);
|
packbitsdecode(&clen, uclen, src, dst++, step);
|
||||||
for (j = 0; j < step-1; ++j) {
|
|
||||||
|
for (j = 0; j < step-1; ++j)
|
||||||
|
{
|
||||||
for (i = 0; i < PSDheader.rows; ++i)
|
for (i = 0; i < PSDheader.rows; ++i)
|
||||||
|
{
|
||||||
src += *w++;
|
src += *w++;
|
||||||
|
}
|
||||||
packbitsdecode(&clen, uclen, src, dst++, step);
|
packbitsdecode(&clen, uclen, src, dst++, step);
|
||||||
}
|
}
|
||||||
|
|
||||||
IFDBG printf("clen %ld\n", clen);
|
IFDBG printf("clen %ld\n", clen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2308,7 +2351,7 @@ cmyk_to_rgb(gint *c, gint *m, gint *y, gint *k)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
dumpchunk(size_t n, FILE * fd, gchar *why)
|
dumpchunk(size_t n, FILE * fd, gchar *why)
|
||||||
{
|
{
|
||||||
guint32 i;
|
guint32 i;
|
||||||
|
@ -2324,9 +2367,10 @@ dumpchunk(size_t n, FILE * fd, gchar *why)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
throwchunk(size_t n, FILE * fd, gchar *why)
|
throwchunk(size_t n, FILE * fd, gchar *why)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
guchar *tmpchunk;
|
guchar *tmpchunk;
|
||||||
|
|
||||||
if (n==0)
|
if (n==0)
|
||||||
|
@ -2337,6 +2381,19 @@ throwchunk(size_t n, FILE * fd, gchar *why)
|
||||||
tmpchunk = xmalloc(n);
|
tmpchunk = xmalloc(n);
|
||||||
xfread(fd, tmpchunk, n, why);
|
xfread(fd, tmpchunk, n, why);
|
||||||
g_free(tmpchunk);
|
g_free(tmpchunk);
|
||||||
|
#else
|
||||||
|
if (n==0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fseek(fd, n, SEEK_CUR) != 0)
|
||||||
|
{
|
||||||
|
printf("%s: unable to seek forward while reading '%s' chunk\n",
|
||||||
|
prog_name, why);
|
||||||
|
gimp_quit();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* PSD Plugin version 2.0.0
|
* PSD Plugin version 2.0.1
|
||||||
* This GIMP plug-in is designed to load Adobe Photoshop(tm) files (.PSD)
|
* This GIMP plug-in is designed to load Adobe Photoshop(tm) files (.PSD)
|
||||||
*
|
*
|
||||||
* Adam D. Moss <adam@gimp.org> <adam@foxbox.org>
|
* Adam D. Moss <adam@gimp.org> <adam@foxbox.org>
|
||||||
|
@ -35,67 +35,68 @@
|
||||||
/*
|
/*
|
||||||
* Revision history:
|
* Revision history:
|
||||||
*
|
*
|
||||||
* 98.09.04 / v2.0.0 / Adam D. Moss
|
* 1999.01.10 / v2.0.1 / Adam D. Moss
|
||||||
|
* Greatly reduced memory requirements for layered image loading -
|
||||||
|
* we now do just-in-time channel unpacking. Some little
|
||||||
|
* cleanups too.
|
||||||
|
*
|
||||||
|
* 1998.09.04 / v2.0.0 / Adam D. Moss
|
||||||
* Now recognises and loads the new Guides extensions written
|
* Now recognises and loads the new Guides extensions written
|
||||||
* by Photoshop 4 and 5.
|
* by Photoshop 4 and 5.
|
||||||
*
|
*
|
||||||
* 98.07.31 / v1.9.9.9f / Adam D. Moss
|
* 1998.07.31 / v1.9.9.9f / Adam D. Moss
|
||||||
* Use OVERLAY_MODE if available.
|
* Use OVERLAY_MODE if available.
|
||||||
*
|
*
|
||||||
* 98.07.31 / v1.9.9.9e / Adam D. Moss
|
* 1998.07.31 / v1.9.9.9e / Adam D. Moss
|
||||||
* Worked around some buggy PSD savers (suspect PS4 on Mac) - ugh.
|
* Worked around some buggy PSD savers (suspect PS4 on Mac) - ugh.
|
||||||
* Fixed a bug when loading layer masks of certain dimensions.
|
* Fixed a bug when loading layer masks of certain dimensions.
|
||||||
*
|
*
|
||||||
* 98.05.04 / v1.9.9.9b / Adam D. Moss
|
* 1998.05.04 / v1.9.9.9b / Adam D. Moss
|
||||||
* Changed the Pascal-style string-reading stuff. That fixed
|
* Changed the Pascal-style string-reading stuff. That fixed
|
||||||
* some file-padding problems. Made all debugging output
|
* some file-padding problems. Made all debugging output
|
||||||
* compile-time optional (please leave it enabled for now).
|
* compile-time optional (please leave it enabled for now).
|
||||||
* Reduced memory requirements; still much room for improvement.
|
* Reduced memory requirements; still much room for improvement.
|
||||||
*
|
*
|
||||||
* 98.04.28 / v1.9.9.9 / Adam D. Moss
|
* 1998.04.28 / v1.9.9.9 / Adam D. Moss
|
||||||
* Fixed the correct channel interlacing of 'raw' flat images.
|
* Fixed the correct channel interlacing of 'raw' flat images.
|
||||||
* Thanks to Christian Kirsch and Jay Cox for spotting this.
|
* Thanks to Christian Kirsch and Jay Cox for spotting this.
|
||||||
* Changed some of the I/O routines.
|
* Changed some of the I/O routines.
|
||||||
*
|
*
|
||||||
* 98.04.26 / v1.9.9.8 / Adam D. Moss
|
* 1998.04.26 / v1.9.9.8 / Adam D. Moss
|
||||||
* Implemented Aux-channels for layered files. Got rid
|
* Implemented Aux-channels for layered files. Got rid
|
||||||
* of <endian.h> nonsense. Improved Layer Mask padding.
|
* of <endian.h> nonsense. Improved Layer Mask padding.
|
||||||
* Enforced num_layers/num_channels limit checks.
|
* Enforced num_layers/num_channels limit checks.
|
||||||
*
|
*
|
||||||
* 98.04.23 / v1.9.9.5 / Adam D. Moss
|
* 1998.04.23 / v1.9.9.5 / Adam D. Moss
|
||||||
* Got Layer Masks working, got Aux-channels working
|
* Got Layer Masks working, got Aux-channels working
|
||||||
* for unlayered files, fixed 'raw' channel loading, fixed
|
* for unlayered files, fixed 'raw' channel loading, fixed
|
||||||
* some other mini-bugs, slightly better progress meters.
|
* some other mini-bugs, slightly better progress meters.
|
||||||
* Thanks to everyone who is helping with the testing!
|
* Thanks to everyone who is helping with the testing!
|
||||||
*
|
*
|
||||||
* 98.04.21 / v1.9.9.1 / Adam D. Moss
|
* 1998.04.21 / v1.9.9.1 / Adam D. Moss
|
||||||
* A little cleanup. Implemented Layer Masks but disabled
|
* A little cleanup. Implemented Layer Masks but disabled
|
||||||
* them again - PS masks can be a different size to their
|
* them again - PS masks can be a different size to their
|
||||||
* owning layer, unlike those in GIMP.
|
* owning layer, unlike those in GIMP.
|
||||||
*
|
*
|
||||||
* 98.04.19 / v1.9.9.0 / Adam D. Moss
|
* 1998.04.19 / v1.9.9.0 / Adam D. Moss
|
||||||
* Much happier now.
|
* Much happier now.
|
||||||
*
|
*
|
||||||
* 97.03.13 / v1.9.0 / Adam D. Moss
|
* 1997.03.13 / v1.9.0 / Adam D. Moss
|
||||||
* Layers, channels and masks, oh my.
|
* Layers, channels and masks, oh my.
|
||||||
* + Bugfixes & rearchitecturing.
|
* + Bugfixes & rearchitecturing.
|
||||||
*
|
*
|
||||||
* 97.01.30 / v1.0.12 / Torsten Martinsen
|
* 1997.01.30 / v1.0.12 / Torsten Martinsen
|
||||||
* Flat PSD image loading.
|
* Flat PSD image loading.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO:
|
* TODO:
|
||||||
*
|
*
|
||||||
* Crush 16bpp channels
|
* Crush 16bpp channels (Wait until GIMP 2.0, probably)
|
||||||
* CMYK -> RGB
|
* CMYK -> RGB
|
||||||
* Load BITMAP mode
|
* Load BITMAP mode
|
||||||
*
|
*
|
||||||
* File saving. (I am unlikely to be able to do this for
|
* File saving
|
||||||
* practical reasons. Suggest someone works on it as a
|
|
||||||
* separate plugin - please let me know.)
|
|
||||||
*
|
|
||||||
* Reduce memory requirements!
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -106,7 +107,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* *** DEFINES *** */
|
/* *** USER DEFINES *** */
|
||||||
|
|
||||||
/* set to TRUE if you want debugging, FALSE otherwise */
|
/* set to TRUE if you want debugging, FALSE otherwise */
|
||||||
#define PSD_DEBUG TRUE
|
#define PSD_DEBUG TRUE
|
||||||
|
@ -120,7 +121,7 @@
|
||||||
/* the max number of guides that this plugin should let an image have */
|
/* the max number of guides that this plugin should let an image have */
|
||||||
#define MAX_GUIDES 200
|
#define MAX_GUIDES 200
|
||||||
|
|
||||||
/* *** END OF DEFINES *** */
|
/* *** END OF USER DEFINES *** */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,35 +150,6 @@ typedef enum
|
||||||
} psd_imagetype;
|
} psd_imagetype;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Declare some local functions.
|
|
||||||
*/
|
|
||||||
static void query (void);
|
|
||||||
static void run (char *name,
|
|
||||||
int nparams,
|
|
||||||
GParam *param,
|
|
||||||
int *nreturn_vals,
|
|
||||||
GParam **return_vals);
|
|
||||||
GDrawableType psd_type_to_gimp_type
|
|
||||||
(psd_imagetype psdtype);
|
|
||||||
GImageType psd_type_to_gimp_base_type
|
|
||||||
(psd_imagetype psdtype);
|
|
||||||
GLayerMode psd_lmode_to_gimp_lmode
|
|
||||||
(gchar modekey[4]);
|
|
||||||
static gint32 load_image (char *filename);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GPlugInInfo PLUG_IN_INFO =
|
|
||||||
{
|
|
||||||
NULL, /* init_proc */
|
|
||||||
NULL, /* quit_proc */
|
|
||||||
query, /* query_proc */
|
|
||||||
run, /* run_proc */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct PsdChannel
|
typedef struct PsdChannel
|
||||||
{
|
{
|
||||||
gchar *name;
|
gchar *name;
|
||||||
|
@ -186,8 +158,18 @@ typedef struct PsdChannel
|
||||||
|
|
||||||
guint32 compressedsize;
|
guint32 compressedsize;
|
||||||
|
|
||||||
} PSDchannel;
|
fpos_t fpos; /* Remember where the data is in the file, so we can
|
||||||
|
come back to it! */
|
||||||
|
|
||||||
|
/* We can't just assume that the channel's width and height are the
|
||||||
|
* same as those of the layer that owns the channel, since this
|
||||||
|
* channel may be a layer mask, which Photoshop allows to have a
|
||||||
|
* different size from the layer which it applies to.
|
||||||
|
*/
|
||||||
|
guint32 width;
|
||||||
|
guint32 height;
|
||||||
|
|
||||||
|
} PSDchannel;
|
||||||
|
|
||||||
|
|
||||||
typedef struct PsdGuide
|
typedef struct PsdGuide
|
||||||
|
@ -197,7 +179,6 @@ typedef struct PsdGuide
|
||||||
} PSDguide;
|
} PSDguide;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct PsdLayer
|
typedef struct PsdLayer
|
||||||
{
|
{
|
||||||
gint num_channels;
|
gint num_channels;
|
||||||
|
@ -225,7 +206,6 @@ typedef struct PsdLayer
|
||||||
} PSDlayer;
|
} PSDlayer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct PsdImage
|
typedef struct PsdImage
|
||||||
{
|
{
|
||||||
gint num_layers;
|
gint num_layers;
|
||||||
|
@ -247,15 +227,42 @@ typedef struct PsdImage
|
||||||
gchar *caption;
|
gchar *caption;
|
||||||
|
|
||||||
guint active_layer_num;
|
guint active_layer_num;
|
||||||
|
|
||||||
} PSDimage;
|
} PSDimage;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static PSDimage psd_image;
|
/* Declare some local functions.
|
||||||
|
*/
|
||||||
|
static void query (void);
|
||||||
|
static void run (char *name,
|
||||||
|
int nparams,
|
||||||
|
GParam *param,
|
||||||
|
int *nreturn_vals,
|
||||||
|
GParam **return_vals);
|
||||||
|
static GDrawableType psd_type_to_gimp_type
|
||||||
|
(psd_imagetype psdtype);
|
||||||
|
static GImageType psd_type_to_gimp_base_type
|
||||||
|
(psd_imagetype psdtype);
|
||||||
|
static GLayerMode psd_lmode_to_gimp_lmode
|
||||||
|
(gchar modekey[4]);
|
||||||
|
static gint32 load_image (char *filename);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Various local variables...
|
||||||
|
*/
|
||||||
|
GPlugInInfo PLUG_IN_INFO =
|
||||||
|
{
|
||||||
|
NULL, /* init_proc */
|
||||||
|
NULL, /* quit_proc */
|
||||||
|
query, /* query_proc */
|
||||||
|
run, /* run_proc */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static PSDimage psd_image;
|
||||||
|
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
gchar signature[4];
|
gchar signature[4];
|
||||||
gushort version;
|
gushort version;
|
||||||
|
@ -312,8 +319,9 @@ static void read_whole_file(FILE *fd);
|
||||||
static void reshuffle_cmap(guchar *map256);
|
static void reshuffle_cmap(guchar *map256);
|
||||||
static guchar* getpascalstring(FILE *fd, gchar *why);
|
static guchar* getpascalstring(FILE *fd, gchar *why);
|
||||||
static gchar* getstring(size_t n, FILE * fd, gchar *why);
|
static gchar* getstring(size_t n, FILE * fd, gchar *why);
|
||||||
void throwchunk(size_t n, FILE * fd, gchar *why);
|
static void throwchunk(size_t n, FILE * fd, gchar *why);
|
||||||
void dumpchunk(size_t n, FILE * fd, gchar *why);
|
static void dumpchunk(size_t n, FILE * fd, gchar *why);
|
||||||
|
static void seek_to_and_unpack_pixeldata(FILE* fd, gint layeri, gint channeli);
|
||||||
|
|
||||||
|
|
||||||
MAIN()
|
MAIN()
|
||||||
|
@ -390,7 +398,7 @@ run (char *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GDrawableType
|
static GDrawableType
|
||||||
psd_type_to_gimp_type (psd_imagetype psdtype)
|
psd_type_to_gimp_type (psd_imagetype psdtype)
|
||||||
{
|
{
|
||||||
switch(psdtype)
|
switch(psdtype)
|
||||||
|
@ -407,7 +415,7 @@ psd_type_to_gimp_type (psd_imagetype psdtype)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GLayerMode
|
static GLayerMode
|
||||||
psd_lmode_to_gimp_lmode (gchar modekey[4])
|
psd_lmode_to_gimp_lmode (gchar modekey[4])
|
||||||
{
|
{
|
||||||
if (strncmp(modekey, "norm", 4)==0) return(NORMAL_MODE);
|
if (strncmp(modekey, "norm", 4)==0) return(NORMAL_MODE);
|
||||||
|
@ -444,7 +452,7 @@ psd_lmode_to_gimp_lmode (gchar modekey[4])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GImageType
|
static GImageType
|
||||||
psd_type_to_gimp_base_type (psd_imagetype psdtype)
|
psd_type_to_gimp_base_type (psd_imagetype psdtype)
|
||||||
{
|
{
|
||||||
switch(psdtype)
|
switch(psdtype)
|
||||||
|
@ -787,7 +795,10 @@ dispatch_resID(guint ID, FILE *fd, guint32 *offset, guint32 Size)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
IFDBG printf ("\t\t<Undocumented field.>\n");
|
IFDBG printf ("\t\t<Undocumented field.>\n");
|
||||||
|
IFDBG
|
||||||
dumpchunk(Size, fd, "dispatch_res");
|
dumpchunk(Size, fd, "dispatch_res");
|
||||||
|
else
|
||||||
|
throwchunk(Size, fd, "dispatch_res");
|
||||||
(*offset) += Size;
|
(*offset) += Size;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1013,9 +1024,7 @@ do_layer_struct(FILE *fd, guint32 *offset)
|
||||||
static void
|
static void
|
||||||
do_layer_pixeldata(FILE *fd, guint32 *offset)
|
do_layer_pixeldata(FILE *fd, guint32 *offset)
|
||||||
{
|
{
|
||||||
guint16 compression;
|
|
||||||
gint layeri, channeli;
|
gint layeri, channeli;
|
||||||
guchar *tmpline;
|
|
||||||
|
|
||||||
for (layeri=0; layeri<psd_image.num_layers; layeri++)
|
for (layeri=0; layeri<psd_image.num_layers; layeri++)
|
||||||
{
|
{
|
||||||
|
@ -1036,10 +1045,34 @@ do_layer_pixeldata(FILE *fd, guint32 *offset)
|
||||||
height = psd_image.layer[layeri].height;
|
height = psd_image.layer[layeri].height;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpline = xmalloc(width + 1);
|
fgetpos(fd, &psd_image.layer[layeri].channel[channeli].fpos);
|
||||||
|
psd_image.layer[layeri].channel[channeli].width = width;
|
||||||
|
psd_image.layer[layeri].channel[channeli].height = height;
|
||||||
|
|
||||||
|
throwchunk(psd_image.layer[layeri].channel[channeli].compressedsize,
|
||||||
|
fd, "channel data skip");
|
||||||
|
(*offset) +=
|
||||||
|
psd_image.layer[layeri].channel[channeli].compressedsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
seek_to_and_unpack_pixeldata(FILE* fd, gint layeri, gint channeli)
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
guchar *tmpline;
|
||||||
|
gint compression;
|
||||||
|
guint32 offset = 0;
|
||||||
|
|
||||||
|
fsetpos(fd, &psd_image.layer[layeri].channel[channeli].fpos);
|
||||||
|
|
||||||
compression = getgshort(fd, "layer channel compression type");
|
compression = getgshort(fd, "layer channel compression type");
|
||||||
(*offset)+=2;
|
offset+=2;
|
||||||
|
|
||||||
|
width = psd_image.layer[layeri].channel[channeli].width;
|
||||||
|
height = psd_image.layer[layeri].channel[channeli].height;
|
||||||
|
|
||||||
IFDBG
|
IFDBG
|
||||||
{
|
{
|
||||||
|
@ -1048,41 +1081,38 @@ do_layer_pixeldata(FILE *fd, guint32 *offset)
|
||||||
channeli,
|
channeli,
|
||||||
psd_image.layer[layeri].channel[channeli].type,
|
psd_image.layer[layeri].channel[channeli].type,
|
||||||
compression,
|
compression,
|
||||||
compression==0?"raw":(compression==1?"RLE":"UNKNOWN!"));
|
compression==0?"raw":(compression==1?"RLE":"*UNKNOWN!*"));
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
IFDBG {printf("\t\t\t\tLoading channel data (%d bytes)...\n",
|
|
||||||
width*height);fflush(stdout);}
|
|
||||||
|
|
||||||
psd_image.layer[layeri].channel[channeli].data =
|
psd_image.layer[layeri].channel[channeli].data =
|
||||||
xmalloc (width * height);
|
xmalloc (width * height);
|
||||||
|
|
||||||
|
tmpline = xmalloc(width + 1);
|
||||||
|
|
||||||
switch (compression)
|
switch (compression)
|
||||||
{
|
{
|
||||||
case 0: /* raw data */
|
case 0: /* raw data */
|
||||||
{
|
{
|
||||||
gint linei;
|
gint linei;
|
||||||
|
|
||||||
for (linei=0;
|
for (linei=0; linei < height; linei++)
|
||||||
linei<height;
|
|
||||||
linei++)
|
|
||||||
{
|
{
|
||||||
xfread(fd,
|
xfread(fd,
|
||||||
(psd_image.layer[layeri].channel[channeli].data+
|
(psd_image.layer[layeri].channel[channeli].data+
|
||||||
linei * width),
|
linei * width),
|
||||||
width,
|
width,
|
||||||
"raw channel line");
|
"raw channel line");
|
||||||
(*offset) += width;
|
offset += width;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pad raw data to multiple of 2? */
|
|
||||||
#if 0
|
#if 0
|
||||||
if ((height *
|
/* Pad raw data to multiple of 2? */
|
||||||
width) & 1)
|
if ((height * width) & 1)
|
||||||
{
|
{
|
||||||
getguchar(fd, "raw channel padding");
|
getguchar(fd, "raw channel padding");
|
||||||
(*offset)++;
|
offset++;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1096,9 +1126,9 @@ do_layer_pixeldata(FILE *fd, guint32 *offset)
|
||||||
data to unpack to the right length... hmm... */
|
data to unpack to the right length... hmm... */
|
||||||
throwchunk(height * 2,
|
throwchunk(height * 2,
|
||||||
fd, "widthlist");
|
fd, "widthlist");
|
||||||
(*offset) += height * 2;
|
offset += height * 2;
|
||||||
|
|
||||||
blockread = (*offset);
|
blockread = offset;
|
||||||
|
|
||||||
/*IFDBG {printf("\nHere comes the guitar solo...\n");
|
/*IFDBG {printf("\nHere comes the guitar solo...\n");
|
||||||
fflush(stdout);}*/
|
fflush(stdout);}*/
|
||||||
|
@ -1111,7 +1141,7 @@ do_layer_pixeldata(FILE *fd, guint32 *offset)
|
||||||
unpack_pb_channel(fd, tmpline,
|
unpack_pb_channel(fd, tmpline,
|
||||||
width
|
width
|
||||||
/*+ (width&1)*/,
|
/*+ (width&1)*/,
|
||||||
offset);
|
&offset);
|
||||||
memcpy((psd_image.layer[layeri].channel[channeli].data+
|
memcpy((psd_image.layer[layeri].channel[channeli].data+
|
||||||
linei * width),
|
linei * width),
|
||||||
tmpline,
|
tmpline,
|
||||||
|
@ -1119,7 +1149,7 @@ do_layer_pixeldata(FILE *fd, guint32 *offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
IFDBG {printf("\t\t\t\t\tActual compressed size was %d bytes\n"
|
IFDBG {printf("\t\t\t\t\tActual compressed size was %d bytes\n"
|
||||||
, (*offset)-blockread);fflush(stdout);}
|
, offset-blockread);fflush(stdout);}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: /* *unknown* */
|
default: /* *unknown* */
|
||||||
|
@ -1134,11 +1164,6 @@ do_layer_pixeldata(FILE *fd, guint32 *offset)
|
||||||
else
|
else
|
||||||
IFDBG {printf("\nTRIED TO FREE NULL!");fflush(stdout);}
|
IFDBG {printf("\nTRIED TO FREE NULL!");fflush(stdout);}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* printf("\n[[%ld]]\n", getglong(fd, "uhhhh"));
|
|
||||||
(*offset)+=4;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1158,7 +1183,6 @@ do_layers(FILE *fd, guint32 *offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_layer_and_mask(FILE *fd)
|
do_layer_and_mask(FILE *fd)
|
||||||
{
|
{
|
||||||
|
@ -1203,12 +1227,11 @@ do_layer_and_mask(FILE *fd)
|
||||||
printf("PSD: Stern warning - no mask info.\n");
|
printf("PSD: Stern warning - no mask info.\n");
|
||||||
|
|
||||||
|
|
||||||
/* If 'offset' wasn't being buggily updated, we wouldn't need this. */
|
/* If 'offset' wasn't being buggily updated, we wouldn't need this. (!?) */
|
||||||
fseek(fd, Size+offset_now, SEEK_SET);
|
fseek(fd, Size+offset_now, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_image_resources(FILE *fd)
|
do_image_resources(FILE *fd)
|
||||||
{
|
{
|
||||||
|
@ -1574,6 +1597,7 @@ load_image(char *name)
|
||||||
GDrawable *drawable = NULL;
|
GDrawable *drawable = NULL;
|
||||||
GPixelRgn pixel_rgn;
|
GPixelRgn pixel_rgn;
|
||||||
gint32 iter;
|
gint32 iter;
|
||||||
|
fpos_t tmpfpos;
|
||||||
|
|
||||||
|
|
||||||
IFDBG printf("------- %s ---------------------------------\n",name);
|
IFDBG printf("------- %s ---------------------------------\n",name);
|
||||||
|
@ -1615,6 +1639,8 @@ load_image(char *name)
|
||||||
gimp_image_new (PSDheader.columns, PSDheader.rows, gimagetype);
|
gimp_image_new (PSDheader.columns, PSDheader.rows, gimagetype);
|
||||||
gimp_image_set_filename (image_ID, name);
|
gimp_image_set_filename (image_ID, name);
|
||||||
|
|
||||||
|
fgetpos (fd, &tmpfpos);
|
||||||
|
|
||||||
for (lnum=0; lnum<psd_image.num_layers; lnum++)
|
for (lnum=0; lnum<psd_image.num_layers; lnum++)
|
||||||
{
|
{
|
||||||
gint numc;
|
gint numc;
|
||||||
|
@ -1633,6 +1659,7 @@ load_image(char *name)
|
||||||
{
|
{
|
||||||
merged_data = xmalloc(psd_image.layer[lnum].width *
|
merged_data = xmalloc(psd_image.layer[lnum].width *
|
||||||
psd_image.layer[lnum].height);
|
psd_image.layer[lnum].height);
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 0);
|
||||||
memcpy(merged_data, psd_image.layer[lnum].channel[0].data,
|
memcpy(merged_data, psd_image.layer[lnum].channel[0].data,
|
||||||
psd_image.layer[lnum].width *
|
psd_image.layer[lnum].width *
|
||||||
psd_image.layer[lnum].height);
|
psd_image.layer[lnum].height);
|
||||||
|
@ -1642,6 +1669,8 @@ load_image(char *name)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 0);
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 1);
|
||||||
merged_data =
|
merged_data =
|
||||||
chans_to_GRAYA (psd_image.layer[lnum].channel[1].data,
|
chans_to_GRAYA (psd_image.layer[lnum].channel[1].data,
|
||||||
psd_image.layer[lnum].channel[0].data,
|
psd_image.layer[lnum].channel[0].data,
|
||||||
|
@ -1668,6 +1697,9 @@ load_image(char *name)
|
||||||
IFDBG printf("It's RGB.\n");
|
IFDBG printf("It's RGB.\n");
|
||||||
if (!psd_layer_has_alpha(&psd_image.layer[lnum]))
|
if (!psd_layer_has_alpha(&psd_image.layer[lnum]))
|
||||||
{
|
{
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 0);
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 1);
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 2);
|
||||||
merged_data =
|
merged_data =
|
||||||
chans_to_RGB (psd_image.layer[lnum].channel[0].data,
|
chans_to_RGB (psd_image.layer[lnum].channel[0].data,
|
||||||
psd_image.layer[lnum].channel[1].data,
|
psd_image.layer[lnum].channel[1].data,
|
||||||
|
@ -1684,6 +1716,10 @@ load_image(char *name)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 0);
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 1);
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 2);
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, 3);
|
||||||
merged_data =
|
merged_data =
|
||||||
chans_to_RGBA (psd_image.layer[lnum].channel[1].data,
|
chans_to_RGBA (psd_image.layer[lnum].channel[1].data,
|
||||||
psd_image.layer[lnum].channel[2].data,
|
psd_image.layer[lnum].channel[2].data,
|
||||||
|
@ -1733,6 +1769,7 @@ load_image(char *name)
|
||||||
lm_data = xmalloc(psd_image.layer[lnum].width *
|
lm_data = xmalloc(psd_image.layer[lnum].width *
|
||||||
psd_image.layer[lnum].height);
|
psd_image.layer[lnum].height);
|
||||||
{
|
{
|
||||||
|
seek_to_and_unpack_pixeldata(fd, lnum, iter);
|
||||||
/* PS layer masks can be a different size to
|
/* PS layer masks can be a different size to
|
||||||
their owning layer, so we have to resize them. */
|
their owning layer, so we have to resize them. */
|
||||||
resize_mask(psd_image.layer[lnum].channel[iter].data,
|
resize_mask(psd_image.layer[lnum].channel[iter].data,
|
||||||
|
@ -1804,8 +1841,9 @@ load_image(char *name)
|
||||||
gimp_progress_update ((double)(lnum+1.0) /
|
gimp_progress_update ((double)(lnum+1.0) /
|
||||||
(double)psd_image.num_layers);
|
(double)psd_image.num_layers);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
fsetpos (fd, &tmpfpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((psd_image.num_aux_channels > 0) &&
|
if ((psd_image.num_aux_channels > 0) &&
|
||||||
|
@ -1821,7 +1859,7 @@ load_image(char *name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (want_aux || (psd_image.num_layers==0)) /* PS2-style - NO LAYERS. */
|
if (want_aux || (psd_image.num_layers==0)) /* Photoshop2-style: NO LAYERS. */
|
||||||
{
|
{
|
||||||
|
|
||||||
IFDBG printf("Image data %ld chars\n", PSDheader.imgdatalen);
|
IFDBG printf("Image data %ld chars\n", PSDheader.imgdatalen);
|
||||||
|
@ -1879,7 +1917,8 @@ load_image(char *name)
|
||||||
|
|
||||||
if (PSDheader.bpp != 8)
|
if (PSDheader.bpp != 8)
|
||||||
{
|
{
|
||||||
printf("%s: The GIMP only supports 8-bit deep PSD images\n",
|
printf("%s: The GIMP only supports 8-bit deep PSD images "
|
||||||
|
"at this time.\n",
|
||||||
prog_name);
|
prog_name);
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
@ -1963,9 +2002,6 @@ load_image(char *name)
|
||||||
dest = xmalloc( step * PSDheader.columns * PSDheader.rows );
|
dest = xmalloc( step * PSDheader.columns * PSDheader.rows );
|
||||||
|
|
||||||
|
|
||||||
gimp_progress_update ((double)0.0);
|
|
||||||
|
|
||||||
|
|
||||||
if (PSDheader.compression == 1)
|
if (PSDheader.compression == 1)
|
||||||
{
|
{
|
||||||
nguchars = PSDheader.columns * PSDheader.rows;
|
nguchars = PSDheader.columns * PSDheader.rows;
|
||||||
|
@ -1973,16 +2009,15 @@ load_image(char *name)
|
||||||
xfread(fd, temp, PSDheader.imgdatalen, "image data");
|
xfread(fd, temp, PSDheader.imgdatalen, "image data");
|
||||||
if (!cmyk)
|
if (!cmyk)
|
||||||
{
|
{
|
||||||
gimp_progress_update ((double)0.25);
|
gimp_progress_update ((double)1.00);
|
||||||
decode(PSDheader.imgdatalen, nguchars, temp, dest, step);
|
decode(PSDheader.imgdatalen, nguchars, temp, dest, step);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gimp_progress_update ((double)0.25);
|
gimp_progress_update ((double)1.00);
|
||||||
cmykbuf = xmalloc(step * nguchars);
|
cmykbuf = xmalloc(step * nguchars);
|
||||||
decode(PSDheader.imgdatalen, nguchars, temp, cmykbuf, step);
|
decode(PSDheader.imgdatalen, nguchars, temp, cmykbuf, step);
|
||||||
|
|
||||||
gimp_progress_update ((double)0.50);
|
|
||||||
cmyk2rgb(cmykbuf, dest, PSDheader.columns, PSDheader.rows,
|
cmyk2rgb(cmykbuf, dest, PSDheader.columns, PSDheader.rows,
|
||||||
step > 4);
|
step > 4);
|
||||||
g_free(cmykbuf);
|
g_free(cmykbuf);
|
||||||
|
@ -1993,18 +2028,17 @@ load_image(char *name)
|
||||||
{
|
{
|
||||||
if (!cmyk)
|
if (!cmyk)
|
||||||
{
|
{
|
||||||
gimp_progress_update ((double)0.50);
|
gimp_progress_update ((double)1.00);
|
||||||
xfread_interlaced(fd, dest, PSDheader.imgdatalen,
|
xfread_interlaced(fd, dest, PSDheader.imgdatalen,
|
||||||
"raw image data", step);
|
"raw image data", step);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gimp_progress_update ((double)0.25);
|
gimp_progress_update ((double)1.00);
|
||||||
cmykbuf = xmalloc(PSDheader.imgdatalen);
|
cmykbuf = xmalloc(PSDheader.imgdatalen);
|
||||||
xfread_interlaced(fd, cmykbuf, PSDheader.imgdatalen,
|
xfread_interlaced(fd, cmykbuf, PSDheader.imgdatalen,
|
||||||
"raw cmyk image data", step);
|
"raw cmyk image data", step);
|
||||||
|
|
||||||
gimp_progress_update ((double)0.50);
|
|
||||||
cmykp2rgb(cmykbuf, dest,
|
cmykp2rgb(cmykbuf, dest,
|
||||||
PSDheader.columns, PSDheader.rows, step > 4);
|
PSDheader.columns, PSDheader.rows, step > 4);
|
||||||
g_free(cmykbuf);
|
g_free(cmykbuf);
|
||||||
|
@ -2022,7 +2056,7 @@ load_image(char *name)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gimp_progress_update ((double)0.96);
|
gimp_progress_update ((double)1.00);
|
||||||
|
|
||||||
if (channels == step) /* gimp bpp == psd bpp */
|
if (channels == step) /* gimp bpp == psd bpp */
|
||||||
{
|
{
|
||||||
|
@ -2100,18 +2134,27 @@ decode(long clen, long uclen, char * src, char * dst, int step)
|
||||||
|
|
||||||
l = clen;
|
l = clen;
|
||||||
for (i = 0; i < PSDheader.rows*PSDheader.channels; ++i)
|
for (i = 0; i < PSDheader.rows*PSDheader.channels; ++i)
|
||||||
|
{
|
||||||
l -= PSDheader.rowlength[i];
|
l -= PSDheader.rowlength[i];
|
||||||
|
}
|
||||||
if (l)
|
if (l)
|
||||||
|
{
|
||||||
g_warning("decode: %ld should be zero\n", (long)l);
|
g_warning("decode: %ld should be zero\n", (long)l);
|
||||||
|
}
|
||||||
|
|
||||||
w = PSDheader.rowlength;
|
w = PSDheader.rowlength;
|
||||||
|
|
||||||
packbitsdecode(&clen, uclen, src, dst++, step);
|
packbitsdecode(&clen, uclen, src, dst++, step);
|
||||||
for (j = 0; j < step-1; ++j) {
|
|
||||||
|
for (j = 0; j < step-1; ++j)
|
||||||
|
{
|
||||||
for (i = 0; i < PSDheader.rows; ++i)
|
for (i = 0; i < PSDheader.rows; ++i)
|
||||||
|
{
|
||||||
src += *w++;
|
src += *w++;
|
||||||
|
}
|
||||||
packbitsdecode(&clen, uclen, src, dst++, step);
|
packbitsdecode(&clen, uclen, src, dst++, step);
|
||||||
}
|
}
|
||||||
|
|
||||||
IFDBG printf("clen %ld\n", clen);
|
IFDBG printf("clen %ld\n", clen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2308,7 +2351,7 @@ cmyk_to_rgb(gint *c, gint *m, gint *y, gint *k)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
dumpchunk(size_t n, FILE * fd, gchar *why)
|
dumpchunk(size_t n, FILE * fd, gchar *why)
|
||||||
{
|
{
|
||||||
guint32 i;
|
guint32 i;
|
||||||
|
@ -2324,9 +2367,10 @@ dumpchunk(size_t n, FILE * fd, gchar *why)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
throwchunk(size_t n, FILE * fd, gchar *why)
|
throwchunk(size_t n, FILE * fd, gchar *why)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
guchar *tmpchunk;
|
guchar *tmpchunk;
|
||||||
|
|
||||||
if (n==0)
|
if (n==0)
|
||||||
|
@ -2337,6 +2381,19 @@ throwchunk(size_t n, FILE * fd, gchar *why)
|
||||||
tmpchunk = xmalloc(n);
|
tmpchunk = xmalloc(n);
|
||||||
xfread(fd, tmpchunk, n, why);
|
xfread(fd, tmpchunk, n, why);
|
||||||
g_free(tmpchunk);
|
g_free(tmpchunk);
|
||||||
|
#else
|
||||||
|
if (n==0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fseek(fd, n, SEEK_CUR) != 0)
|
||||||
|
{
|
||||||
|
printf("%s: unable to seek forward while reading '%s' chunk\n",
|
||||||
|
prog_name, why);
|
||||||
|
gimp_quit();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue