[gimp/soc-2013-psd: 8/11] plug-ins: Support > 8 bit psd files properly.
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/soc-2013-psd: 8/11] plug-ins: Support > 8 bit psd files properly.
- Date: Wed, 30 Oct 2013 23:22:35 +0000 (UTC)
commit feee5bd75ae7685f0c8a2b7c825dfde9524c9618
Author: Simon Lui <simonlui src gnome org>
Date: Tue Sep 17 23:24:01 2013 -0400
plug-ins: Support > 8 bit psd files properly.
plug-ins/file-psd/psd-load.c | 141 +++++++++++++++++++++++++++++++-----------
plug-ins/file-psd/psd.h | 2 +-
2 files changed, 106 insertions(+), 37 deletions(-)
---
diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c
index 84da797..cb337a7 100644
--- a/plug-ins/file-psd/psd-load.c
+++ b/plug-ins/file-psd/psd-load.c
@@ -102,7 +102,7 @@ static void convert_1_bit (const gchar *src,
guint32 rows,
guint32 columns);
-static const Babl* get_psd_pixel_format (PSDimage *img_a);
+static const Babl* get_pixel_format (PSDimage *img_a);
/* Main file load function */
@@ -324,7 +324,7 @@ read_header_block (PSDimage *img_a,
return -1;
}
- /* Warnings for format conversions */
+ /* Warning for unsupported bit depth */
switch (img_a->bps)
{
case 32:
@@ -333,6 +333,11 @@ read_header_block (PSDimage *img_a,
case 16:
IFDBG(3) g_debug ("16 Bit Data");
+ if (CONVERSION_WARNINGS)
+ g_message (_("Warning:\n"
+ "The image you are loading has 16 bits per channel. GIMP "
+ "can only handle 8 bit, so it will be converted for you. "
+ "Information will be lost because of this conversion."));
break;
case 8:
@@ -481,6 +486,7 @@ read_layer_block (PSDimage *img_a,
img_a->num_layers = -1;
return NULL;
}
+
img_a->mask_layer_len = GUINT32_FROM_BE (block_len);
IFDBG(1) g_debug ("Layer and mask block size = %d", img_a->mask_layer_len);
@@ -522,6 +528,7 @@ read_layer_block (PSDimage *img_a,
/* Create pointer array for the layer records */
lyr_a = g_new (PSDlayer *, img_a->num_layers);
+
for (lidx = 0; lidx < img_a->num_layers; ++lidx)
{
/* Allocate layer record */
@@ -541,6 +548,7 @@ read_layer_block (PSDimage *img_a,
psd_set_error (feof (f), errno, error);
return NULL;
}
+
lyr_a[lidx]->top = GINT32_FROM_BE (lyr_a[lidx]->top);
lyr_a[lidx]->left = GINT32_FROM_BE (lyr_a[lidx]->left);
lyr_a[lidx]->bottom = GINT32_FROM_BE (lyr_a[lidx]->bottom);
@@ -587,6 +595,7 @@ read_layer_block (PSDimage *img_a,
lyr_a[lidx]->num_channels);
lyr_a[lidx]->chn_info = g_new (ChannelLengthInfo, lyr_a[lidx]->num_channels);
+
for (cidx = 0; cidx < lyr_a[lidx]->num_channels; ++cidx)
{
if (fread (&lyr_a[lidx]->chn_info[cidx].channel_id, 2, 1, f) < 1
@@ -627,6 +636,7 @@ read_layer_block (PSDimage *img_a,
lyr_a[lidx]->layer_flags.trans_prot = lyr_a[lidx]->flags & 1 ? TRUE : FALSE;
lyr_a[lidx]->layer_flags.visible = lyr_a[lidx]->flags & 2 ? FALSE : TRUE;
+
if (lyr_a[lidx]->flags & 8)
lyr_a[lidx]->layer_flags.irrelevant = lyr_a[lidx]->flags & 16 ? TRUE : FALSE;
else
@@ -799,9 +809,11 @@ read_layer_block (PSDimage *img_a,
psd_set_error (feof (f), errno, error);
return NULL;
}
+
block_len = GUINT32_FROM_BE (block_len);
block_rem -= (block_len + 4);
IFDBG(3) g_debug ("Remaining length %d", block_rem);
+
if (block_len > 0)
{
if (fseek (f, block_len, SEEK_CUR) < 0)
@@ -815,6 +827,7 @@ read_layer_block (PSDimage *img_a,
4, f, error);
if (*error)
return NULL;
+
block_rem -= read_len;
IFDBG(3) g_debug ("Remaining length %d", block_rem);
@@ -824,8 +837,13 @@ read_layer_block (PSDimage *img_a,
{
if (get_layer_resource_header (&res_a, f, error) < 0)
return NULL;
+
block_rem -= 12;
+ //Round up to the nearest even byte
+ while (res_a.data_len % 4 != 0)
+ res_a.data_len++;
+
if (res_a.data_len > block_rem)
{
IFDBG(1) g_debug ("Unexpected end of layer resource data");
@@ -899,6 +917,7 @@ create_gimp_image (PSDimage *img_a,
const gchar *filename)
{
gint32 image_id = -1;
+ GimpPrecision precision;
switch (img_a->color_mode)
{
@@ -923,10 +942,32 @@ create_gimp_image (PSDimage *img_a,
break;
}
+ switch (img_a->bps)
+ {
+ case 32:
+ precision = GIMP_PRECISION_U32_LINEAR;
+ break;
+
+ case 16:
+ precision = GIMP_PRECISION_U16_LINEAR;
+ break;
+
+ case 8:
+ case 1:
+ precision = GIMP_PRECISION_U8_LINEAR;
+ break;
+
+ default:
+ /* Precision not supported */
+ g_warning ("Invalid precision");
+ return -1;
+ break;
+ }
+
/* Create gimp image */
IFDBG(2) g_debug ("Create image");
- image_id = gimp_image_new (img_a->columns, img_a->rows, img_a->base_type);
-
+ image_id = gimp_image_new_with_precision (img_a->columns, img_a->rows,
+ img_a->base_type, precision);
gimp_image_set_filename (image_id, filename);
gimp_image_undo_disable (image_id);
@@ -1022,6 +1063,7 @@ add_layers (const gint32 image_id,
guint16 layer_channels;
guint16 channel_idx[MAX_CHANNELS];
guint16 *rle_pack_len;
+ guint16 bps;
gint32 l_x; /* Layer x */
gint32 l_y; /* Layer y */
gint32 l_w; /* Layer width */
@@ -1326,12 +1368,16 @@ add_layers (const gint32 image_id,
image_type = get_gimp_image_type (img_a->base_type, alpha);
IFDBG(3) g_debug ("Layer type %d", image_type);
layer_size = l_w * l_h;
- pixels = g_malloc (layer_size * layer_channels);
+ bps = img_a->bps / 8;
+ if (bps == 0)
+ bps++;
+ pixels = g_malloc (layer_size * layer_channels * bps);
for (cidx = 0; cidx < layer_channels; ++cidx)
{
IFDBG(3) g_debug ("Start channel %d", channel_idx[cidx]);
for (i = 0; i < layer_size; ++i)
- pixels[(i * layer_channels) + cidx] = lyr_chn[channel_idx[cidx]]->data[i];
+ memcpy (&pixels[((i * layer_channels) + cidx) * bps],
+ &lyr_chn[channel_idx[cidx]]->data[i * bps], bps);
g_free (lyr_chn[channel_idx[cidx]]->data);
}
@@ -1346,7 +1392,7 @@ add_layers (const gint32 image_id,
gimp_layer_set_lock_alpha (layer_id, lyr_a[lidx]->layer_flags.trans_prot);
buffer = gimp_drawable_get_buffer (layer_id);
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, gegl_buffer_get_width (buffer),
gegl_buffer_get_height (buffer)),
- 0, get_psd_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
+ 0, get_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
gimp_item_set_visible (layer_id, lyr_a[lidx]->layer_flags.visible);
if (lyr_a[lidx]->id)
gimp_item_set_tattoo (layer_id, lyr_a[lidx]->id);
@@ -1450,7 +1496,7 @@ add_layers (const gint32 image_id,
gimp_layer_add_mask (layer_id, mask_id);
buffer = gimp_drawable_get_buffer (mask_id);
gegl_buffer_set (buffer, GEGL_RECTANGLE (lm_x, lm_y, lm_w, lm_h), 0,
- get_psd_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
+ get_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
g_object_unref (buffer);
gimp_layer_set_apply_mask (layer_id,
! lyr_a[lidx]->layer_mask.mask_flags.disabled);
@@ -1483,6 +1529,7 @@ add_merged_image (const gint32 image_id,
guint16 base_channels;
guint16 extra_channels;
guint16 total_channels;
+ guint16 bps;
guint16 *rle_pack_len[MAX_CHANNELS];
guint32 alpha_id;
gint32 layer_size;
@@ -1503,6 +1550,9 @@ add_merged_image (const gint32 image_id,
total_channels = img_a->channels;
extra_channels = 0;
+ bps = img_a->bps / 8;
+ if (bps == 0)
+ bps++;
if ((img_a->color_mode == PSD_BITMAP ||
img_a->color_mode == PSD_GRAYSCALE ||
@@ -1608,12 +1658,13 @@ add_merged_image (const gint32 image_id,
image_type = get_gimp_image_type (img_a->base_type, img_a->transparency);
layer_size = img_a->columns * img_a->rows;
- pixels = g_malloc (layer_size * base_channels);
+ pixels = g_malloc (layer_size * base_channels * bps);
for (cidx = 0; cidx < base_channels; ++cidx)
{
for (i = 0; i < layer_size; ++i)
{
- pixels[(i * base_channels) + cidx] = chn_a[cidx].data[i];
+ memcpy (&pixels[((i * base_channels) + cidx) * bps],
+ &chn_a[cidx].data[i * bps], bps);
}
g_free (chn_a[cidx].data);
}
@@ -1627,7 +1678,7 @@ add_merged_image (const gint32 image_id,
gimp_image_insert_layer (image_id, layer_id, -1, 0);
buffer = gimp_drawable_get_buffer (layer_id);
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, gegl_buffer_get_width (buffer), gegl_buffer_get_height
(buffer)),
- 0, get_psd_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
+ 0, get_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
g_object_unref (buffer);
g_free (pixels);
}
@@ -1719,7 +1770,7 @@ add_merged_image (const gint32 image_id,
gimp_item_set_visible (channel_id, alpha_visible);
gegl_buffer_set (buffer,
GEGL_RECTANGLE (0, 0, gegl_buffer_get_width (buffer), gegl_buffer_get_height
(buffer)),
- 0, get_psd_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
+ 0, get_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
g_object_unref (buffer);
g_free (chn_a[cidx].data);
}
@@ -1903,14 +1954,20 @@ read_channel_data (PSDchannel *channel,
/* Convert channel data to GIMP format */
switch (bps)
{
+ case 32:
+ case 16:
+ case 8:
+ channel->data = (gchar *) g_malloc (channel->rows * channel->columns * bps / 8 );
+ memcpy (channel->data, raw_data, (channel->rows * channel->columns * bps / 8));
+ break;
+
case 1:
channel->data = (gchar *) g_malloc (channel->rows * channel->columns);
convert_1_bit (raw_data, channel->data, channel->rows, channel->columns);
break;
default:
- channel->data = (gchar *) g_malloc (channel->rows * channel->columns);
- memcpy (channel->data, raw_data, (channel->rows * channel->columns));
+ return -1;
break;
}
@@ -1953,7 +2010,7 @@ convert_1_bit (const gchar *src,
}
static const Babl*
-get_psd_pixel_format(PSDimage *img_a)
+get_pixel_format (PSDimage *img_a)
{
const Babl *format;
@@ -1962,18 +2019,21 @@ get_psd_pixel_format(PSDimage *img_a)
case GIMP_GRAY_IMAGE:
switch (img_a->bps)
{
- case 32:
- format = babl_format ("Y' float");
+ case 32:
+ format = babl_format ("Y u32");
break;
+
case 16:
- format = babl_format ("Y' u16");
+ format = babl_format ("Y u16");
break;
+
case 8:
case 1:
- format = babl_format ("Y' u8");
+ format = babl_format ("Y u8");
break;
+
default:
- return NULL;
+ return NULL;
break;
}
break;
@@ -1981,16 +2041,19 @@ get_psd_pixel_format(PSDimage *img_a)
case GIMP_GRAYA_IMAGE:
switch (img_a->bps)
{
- case 32:
- format = babl_format ("Y'A float");
- break;
+ case 32:
+ format = babl_format ("YA u32");
+ break;
+
case 16:
- format = babl_format ("Y'A u16");
+ format = babl_format ("YA u16");
break;
+
case 8:
case 1:
- format = babl_format ("Y'A u8");
+ format = babl_format ("YA u8");
break;
+
default:
return NULL;
break;
@@ -2001,16 +2064,19 @@ get_psd_pixel_format(PSDimage *img_a)
case GIMP_INDEXED_IMAGE:
switch (img_a->bps)
{
- case 32:
- format = babl_format ("R'G'B' float");
- break;
+ case 32:
+ format = babl_format ("RGB u32");
+ break;
+
case 16:
- format = babl_format ("R'G'B' u16");
+ format = babl_format ("RGB u16");
break;
+
case 8:
case 1:
- format = babl_format ("R'G'B' u8");
+ format = babl_format ("RGB u8");
break;
+
default:
return NULL;
break;
@@ -2021,16 +2087,19 @@ get_psd_pixel_format(PSDimage *img_a)
case GIMP_INDEXEDA_IMAGE:
switch (img_a->bps)
{
- case 32:
- format = babl_format ("R'G'B'A float");
- break;
+ case 32:
+ format = babl_format ("RGBA u32");
+ break;
+
case 16:
- format = babl_format ("R'G'B'A u16");
- break;
+ format = babl_format ("RGBA u16");
+ break;
+
case 8:
case 1:
- format = babl_format ("R'G'B'A u8");
+ format = babl_format ("RGBA u8");
break;
+
default:
return NULL;
break;
diff --git a/plug-ins/file-psd/psd.h b/plug-ins/file-psd/psd.h
index 794c742..f9a6a65 100644
--- a/plug-ins/file-psd/psd.h
+++ b/plug-ins/file-psd/psd.h
@@ -647,7 +647,7 @@ typedef struct
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, 16, or 32 */
+ guint16 bps; /* Bits per sample: 1, 8, 16, or 32 */
guint16 color_mode; /* Image color mode: {PSDColorMode} */
GimpImageBaseType base_type; /* Image base color mode: (GIMP) */
guint16 comp_mode; /* Merged image compression mode */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]