mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-22 20:41:43 +00:00
applied patch from Dennis Ranke as attached to bug #551231. Changes the
2008-09-08 Sven Neumann <sven@gimp.org> * plug-ins/file-psd/psd-save.c: applied patch from Dennis Ranke as attached to bug #551231. Changes the PSD save plug-in to store transparency data in the image data section. Also fixes bug #551232 (saving an indexed image with multiple layers as PSD modifies the image). svn path=/trunk/; revision=26902
This commit is contained in:
parent
bdce2966d6
commit
8e29280319
|
@ -1,3 +1,11 @@
|
|||
2008-09-08 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* plug-ins/file-psd/psd-save.c: applied patch from Dennis Ranke as
|
||||
attached to bug #551231. Changes the PSD save plug-in to store
|
||||
transparency data in the image data section. Also fixes bug #551232
|
||||
(saving an indexed image with multiple layers as PSD modifies the
|
||||
image).
|
||||
|
||||
2008-09-08 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/paint/gimpbrushcore.c: based on a patch from David Gowers
|
||||
|
|
|
@ -120,6 +120,9 @@ typedef struct PsdImageData
|
|||
|
||||
GimpImageBaseType baseType;
|
||||
|
||||
gint32 merged_layer;/* Merged image,
|
||||
to be used for the image data section */
|
||||
|
||||
gint nChannels; /* Number of user channels in the image */
|
||||
gint32 *lChannels; /* User channels in the image */
|
||||
|
||||
|
@ -187,6 +190,8 @@ static void write_pixel_data (FILE *fd,
|
|||
glong *ChanLenPosition,
|
||||
gint32 rowlenOffset);
|
||||
|
||||
static gint32 create_merged_image (gint32 imageID);
|
||||
|
||||
|
||||
const GimpPlugInInfo PLUG_IN_INFO =
|
||||
{
|
||||
|
@ -692,7 +697,8 @@ save_header (FILE *fd,
|
|||
write_gint32 (fd, 0, "reserved 1"); /* 6 for the 'reserved' field + 4 bytes for a long */
|
||||
write_gint16 (fd, 0, "reserved 1"); /* and 2 bytes for a short */
|
||||
write_gint16 (fd, (PSDImageData.nChannels +
|
||||
nChansLayer (PSDImageData.baseType, 0, 0)),
|
||||
nChansLayer (PSDImageData.baseType,
|
||||
gimp_drawable_has_alpha (PSDImageData.merged_layer), 0)),
|
||||
"channels");
|
||||
write_gint32 (fd, PSDImageData.image_height, "rows");
|
||||
write_gint32 (fd, PSDImageData.image_width, "columns");
|
||||
|
@ -820,7 +826,8 @@ save_resources (FILE *fd,
|
|||
|
||||
/* --------------- Write Channel names --------------- */
|
||||
|
||||
if (PSDImageData.nChannels > 0)
|
||||
if (PSDImageData.nChannels > 0 ||
|
||||
gimp_drawable_has_alpha (PSDImageData.merged_layer))
|
||||
{
|
||||
xfwrite (fd, "8BIM", 4, "imageresources signature");
|
||||
write_gint16 (fd, 0x03EE, "0x03EE Id"); /* 1006 */
|
||||
|
@ -834,6 +841,10 @@ save_resources (FILE *fd,
|
|||
|
||||
/* Write all strings */
|
||||
|
||||
/* if the merged_image contains transparency, write a name for it first */
|
||||
if (gimp_drawable_has_alpha (PSDImageData.merged_layer))
|
||||
write_string (fd, "Transparency", "channel name");
|
||||
|
||||
for (i = PSDImageData.nChannels - 1; i >= 0; i--)
|
||||
{
|
||||
char *chName = gimp_drawable_get_name (PSDImageData.lChannels[i]);
|
||||
|
@ -1047,7 +1058,10 @@ save_layer_and_mask (FILE *fd,
|
|||
|
||||
/* Layer structure section */
|
||||
|
||||
write_gint16 (fd, PSDImageData.nLayers, "Layer structure count");
|
||||
if (gimp_drawable_has_alpha (PSDImageData.merged_layer))
|
||||
write_gint16 (fd, -PSDImageData.nLayers, "Layer structure count");
|
||||
else
|
||||
write_gint16 (fd, PSDImageData.nLayers, "Layer structure count");
|
||||
|
||||
/* Layer records section */
|
||||
/* GIMP layers must be written in reverse order */
|
||||
|
@ -1254,6 +1268,7 @@ write_pixel_data (FILE *fd,
|
|||
if ( gimp_drawable_has_alpha (drawableID) &&
|
||||
!gimp_drawable_is_indexed (drawableID))
|
||||
colors -= 1;
|
||||
|
||||
gimp_tile_cache_ntiles (2* (drawable->width / gimp_tile_width () + 1));
|
||||
|
||||
LengthsTable = g_new (gint16, height);
|
||||
|
@ -1267,21 +1282,26 @@ write_pixel_data (FILE *fd,
|
|||
|
||||
for (i = 0; i < bytes; i++)
|
||||
{
|
||||
int chan;
|
||||
gint chan;
|
||||
|
||||
len = 0;
|
||||
if (bytes != colors) /* Need to write alpha channel first */
|
||||
|
||||
if (bytes != colors && ltable_offset == 0) /* Need to write alpha channel first, except in image data section */
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
if (ltable_offset > 0)
|
||||
continue;
|
||||
chan = bytes - 1;
|
||||
}
|
||||
else
|
||||
chan = i - 1;
|
||||
{
|
||||
chan = i - 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
chan = i;
|
||||
{
|
||||
chan = i;
|
||||
}
|
||||
|
||||
if (ChanLenPosition)
|
||||
{
|
||||
write_gint16 (fd, 1, "Compression type (RLE)");
|
||||
|
@ -1423,25 +1443,18 @@ save_data (FILE *fd,
|
|||
{
|
||||
gint ChanCount;
|
||||
gint i, j;
|
||||
gint nChannel;
|
||||
gint32 imageHeight; /* Height of image */
|
||||
glong offset; /* offset in file of rle lengths */
|
||||
gint chan;
|
||||
gint32 bottom_layer;
|
||||
|
||||
IFDBG printf (" Function: save_data\n");
|
||||
|
||||
ChanCount = (PSDImageData.nChannels +
|
||||
nChansLayer (PSDImageData.baseType, 0, 0));
|
||||
|
||||
i = PSDImageData.nLayers - 1; /* Layers to be written */
|
||||
IFDBG printf ("\tProcessing %d layers\n", i);
|
||||
nChansLayer (PSDImageData.baseType,
|
||||
gimp_drawable_has_alpha (PSDImageData.merged_layer), 0));
|
||||
|
||||
imageHeight = gimp_image_height (image_id);
|
||||
|
||||
nChannel = 0;
|
||||
|
||||
|
||||
write_gint16 (fd, 1, "RLE compression");
|
||||
|
||||
/* All line lengths go before the rle pixel data */
|
||||
|
@ -1452,37 +1465,12 @@ save_data (FILE *fd,
|
|||
for (j = 0; j < imageHeight; j++)
|
||||
write_gint16 (fd, 0, "junk line lengths");
|
||||
|
||||
bottom_layer = PSDImageData.lLayers[PSDImageData.nLayers - 1];
|
||||
IFDBG printf ("\t\tWriting compressed image data\n");
|
||||
write_pixel_data (fd, PSDImageData.merged_layer,
|
||||
NULL, offset);
|
||||
|
||||
if (PSDImageData.nLayers != 1 ||
|
||||
gimp_drawable_width (bottom_layer) != gimp_image_width (image_id) ||
|
||||
gimp_drawable_height (bottom_layer) != gimp_image_height (image_id))
|
||||
{
|
||||
gint32 flat_image;
|
||||
gint32 flat_drawable;
|
||||
|
||||
IFDBG printf ("\t\tCreating flattened image\n");
|
||||
flat_image = gimp_image_duplicate (image_id);
|
||||
gimp_image_undo_disable (flat_image);
|
||||
flat_drawable = gimp_image_flatten (flat_image);
|
||||
|
||||
/* gimp_image_flatten() may fail if there are no visible layers */
|
||||
if (flat_drawable != -1)
|
||||
{
|
||||
IFDBG printf ("\t\tWriting compressed flattened image data\n");
|
||||
write_pixel_data (fd, flat_drawable, NULL, offset);
|
||||
}
|
||||
|
||||
gimp_image_delete (flat_image);
|
||||
}
|
||||
else
|
||||
{
|
||||
IFDBG printf ("\t\tWriting compressed image data\n");
|
||||
write_pixel_data (fd, PSDImageData.lLayers[PSDImageData.nLayers - 1],
|
||||
NULL, offset);
|
||||
}
|
||||
|
||||
chan = nChansLayer (PSDImageData.baseType, 0, 0);
|
||||
chan = nChansLayer (PSDImageData.baseType,
|
||||
gimp_drawable_has_alpha(PSDImageData.merged_layer), 0);
|
||||
|
||||
for (i = PSDImageData.nChannels - 1; i >= 0; i--)
|
||||
{
|
||||
|
@ -1494,7 +1482,66 @@ save_data (FILE *fd,
|
|||
}
|
||||
}
|
||||
|
||||
static gint32
|
||||
create_merged_image (gint32 image_id)
|
||||
{
|
||||
gint32 merged_layer;
|
||||
|
||||
merged_layer = gimp_layer_new_from_visible (image_id, image_id, SAVE_PROC);
|
||||
|
||||
if (gimp_image_base_type (image_id) != GIMP_INDEXED)
|
||||
{
|
||||
GimpPixelRgn region;
|
||||
gboolean transparency_found = FALSE;
|
||||
gpointer pr;
|
||||
|
||||
gimp_pixel_rgn_init (®ion,
|
||||
gimp_drawable_get (merged_layer),
|
||||
0, 0,
|
||||
gimp_image_width (image_id),
|
||||
gimp_image_height (image_id),
|
||||
TRUE, FALSE);
|
||||
|
||||
for (pr = gimp_pixel_rgns_register (1, ®ion);
|
||||
pr != NULL;
|
||||
pr = gimp_pixel_rgns_process (pr))
|
||||
{
|
||||
guchar *data = region.data;
|
||||
gint y;
|
||||
|
||||
for (y = 0; y < region.h; y++)
|
||||
{
|
||||
guchar *d = data;
|
||||
gint x;
|
||||
|
||||
for (x = 0; x < region.w; x++)
|
||||
{
|
||||
guint32 alpha = d[region.bpp - 1];
|
||||
|
||||
if (alpha < 255)
|
||||
{
|
||||
gint i;
|
||||
|
||||
transparency_found = TRUE;
|
||||
|
||||
/* blend against white, photoshop does this. */
|
||||
for (i = 0; i < region.bpp - 1; i++)
|
||||
d[i] = ((guint32) d[i] * alpha) / 255 + 255 - alpha;
|
||||
}
|
||||
|
||||
d += region.bpp;
|
||||
}
|
||||
|
||||
data += region.rowstride;
|
||||
}
|
||||
}
|
||||
|
||||
if (! transparency_found)
|
||||
gimp_layer_flatten (merged_layer);
|
||||
}
|
||||
|
||||
return merged_layer;
|
||||
}
|
||||
|
||||
static void
|
||||
get_image_data (FILE *fd,
|
||||
|
@ -1513,18 +1560,14 @@ get_image_data (FILE *fd,
|
|||
PSDImageData.baseType = gimp_image_base_type (image_id);
|
||||
IFDBG printf ("\tGot base type: %d\n", PSDImageData.baseType);
|
||||
|
||||
/* PSD format does not support indexed layered images */
|
||||
PSDImageData.merged_layer = create_merged_image (image_id);
|
||||
|
||||
if (PSDImageData.baseType == GIMP_INDEXED)
|
||||
{
|
||||
IFDBG printf ("\tFlattening indexed image\n");
|
||||
gimp_image_flatten (image_id);
|
||||
}
|
||||
|
||||
PSDImageData.lChannels = gimp_image_get_channels (image_id, &PSDImageData.nChannels);
|
||||
PSDImageData.lChannels = gimp_image_get_channels (image_id,
|
||||
&PSDImageData.nChannels);
|
||||
IFDBG printf ("\tGot number of channels: %d\n", PSDImageData.nChannels);
|
||||
|
||||
PSDImageData.lLayers = gimp_image_get_layers (image_id, &PSDImageData.nLayers);
|
||||
PSDImageData.lLayers = gimp_image_get_layers (image_id,
|
||||
&PSDImageData.nLayers);
|
||||
IFDBG printf ("\tGot number of layers: %d\n", PSDImageData.nLayers);
|
||||
|
||||
PSDImageData.layersDim = g_new (PSD_Layer_Dimension, PSDImageData.nLayers);
|
||||
|
@ -1606,6 +1649,10 @@ save_image (const gchar *filename,
|
|||
|
||||
save_data (fd, image_id);
|
||||
|
||||
/* Delete merged image now */
|
||||
|
||||
gimp_drawable_delete (PSDImageData.merged_layer);
|
||||
|
||||
IFDBG printf ("----- Closing PSD file, done -----\n\n");
|
||||
|
||||
fclose (fd);
|
||||
|
|
Loading…
Reference in a new issue