[gimp/wip/wormnest/psp-mask: 2/4] plug-ins: add support for reading of psp layer masks from older versions of psp.
- From: Jacob Boerema <jboerema src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/wip/wormnest/psp-mask: 2/4] plug-ins: add support for reading of psp layer masks from older versions of psp.
- Date: Tue, 6 Oct 2020 19:54:26 +0000 (UTC)
commit bda8e68f12631f808517e2df386be37c413bb6cf
Author: Jacob Boerema <jgboerema gmail com>
Date: Tue Sep 29 18:28:09 2020 -0400
plug-ins: add support for reading of psp layer masks from older versions of psp.
This only adds support for psp layer masks as found in older versions
of the psp file format. Newer versions use mask layers instead of
layer masks which are more complicated to convert.
plug-ins/common/file-psp.c | 127 +++++++++++++++++++++++++++++++++++++++------
1 file changed, 111 insertions(+), 16 deletions(-)
---
diff --git a/plug-ins/common/file-psp.c b/plug-ins/common/file-psp.c
index 47212145da..f1237f22b3 100644
--- a/plug-ins/common/file-psp.c
+++ b/plug-ins/common/file-psp.c
@@ -1806,19 +1806,16 @@ read_lz77_channel (FILE *f,
}
static int
-read_channel_data (FILE *f,
- PSPimage *ia,
- guchar **pixels,
- guint bytespp,
- guint offset,
- GeglBuffer *buffer,
- guint32 compressed_len,
- GError **error)
+read_channel_data (FILE *f,
+ PSPimage *ia,
+ guchar **pixels,
+ gint width, /* width of layer or mask channel */
+ gint height, /* height of layer or mask channel */
+ guint bytespp,
+ guint offset,
+ guint32 compressed_len,
+ GError **error)
{
- /* width, height below are the layer/channel dimensions,
- not necessarily the same as the image dimensions. */
- gint width = gegl_buffer_get_width (buffer);
- gint height = gegl_buffer_get_height (buffer);
gint decompress_result = 0;
gint line_width;
@@ -1939,6 +1936,89 @@ read_raster_layer_info (FILE *f,
return TRUE;
}
+static const Babl*
+get_mask_format (PSPimage *ia)
+{
+ const Babl *format = NULL;
+
+ switch (ia->depth)
+ {
+ case 48:
+ format = babl_format ("Y u16");
+ break;
+
+ case 8:
+ case 24:
+ format = babl_format ("Y u8");
+ break;
+
+ default:
+ break;
+ }
+
+ return format;
+}
+
+static gboolean
+read_layer_mask (FILE *f,
+ GimpLayer *layer,
+ GeglRectangle *mask_rect, /* dimensions of mask data */
+ GeglRectangle *layer_mask_rect, /* part of mask inside the layer boundaries */
+ PSPimage *ia,
+ gboolean mask_disabled,
+ guint32 compressed_len,
+ GError **error)
+{
+ GimpLayerMask *mask;
+ GeglBuffer *buffer;
+ guchar **pixels, *pixel;
+ gint i;
+
+ if (! (ia->base_type == GIMP_RGB || ia->base_type == GIMP_GRAY))
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ _("Invalid image base type for layer mask."));
+ return FALSE;
+ }
+
+ if (layer_mask_rect->height > 0 && layer_mask_rect->width > 0)
+ {
+ pixel = g_malloc0 (mask_rect->height * mask_rect->width * ia->bytes_per_sample);
+ pixels = g_new (guchar *, mask_rect->height);
+
+ for (i = 0; i < mask_rect->height; i++)
+ pixels[i] = pixel + mask_rect->width * ia->bytes_per_sample * i;
+
+ /* Mask is a grayscale layer which means bytes per sample is the same
+ as bytes per pixel. */
+ if (read_channel_data (f, ia, pixels, mask_rect->width, mask_rect->height,
+ ia->bytes_per_sample, 0,
+ compressed_len, error) == -1)
+ {
+ g_free (pixels);
+ g_free (pixel);
+ return FALSE;
+ }
+
+ mask = gimp_layer_create_mask (layer, GIMP_ADD_MASK_WHITE);
+ gimp_layer_add_mask (layer, mask);
+ buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));
+ gegl_buffer_set (buffer, mask_rect,
+ 0, get_mask_format (ia),
+ pixel +
+ ((layer_mask_rect->y - mask_rect->y) * mask_rect->width +
+ (layer_mask_rect->x - mask_rect->x)) * ia->bytes_per_sample,
+ mask_rect->width * ia->bytes_per_sample);
+ gimp_layer_set_apply_mask (layer, ! mask_disabled);
+
+ g_object_unref (buffer);
+ g_free (pixels);
+ g_free (pixel);
+ }
+
+ return TRUE;
+}
+
static GimpLayer *
read_layer_block (FILE *f,
GimpImage *image,
@@ -1969,6 +2049,7 @@ read_layer_block (FILE *f,
gint width, height, bytespp, offset;
guchar **pixels, *pixel;
GeglBuffer *buffer;
+ GeglRectangle mask_data_rect, layer_mask_rect;
block_start = ftell (f);
@@ -2252,8 +2333,22 @@ read_layer_block (FILE *f,
}
else if (bitmap_type == PSP_DIB_USER_MASK)
{
- /* FIXME: Add as layer mask */
- g_message ("Conversion of layer mask is not supported");
+ /* Set dimensions of layer mask. */
+ mask_data_rect.x = mask_rect[0] + saved_mask_rect[0];
+ mask_data_rect.y = mask_rect[1] + saved_mask_rect[1];
+ mask_data_rect.width = saved_mask_rect[2] - saved_mask_rect[0];
+ mask_data_rect.height = saved_mask_rect[3] - saved_mask_rect[1];
+ /* Crop mask to layer boundaries. */
+ if (gegl_rectangle_intersect (&layer_mask_rect,
+ GEGL_RECTANGLE (0, 0, width, height),
+ &mask_data_rect))
+ {
+ if (! read_layer_mask (f, layer, &mask_data_rect, &layer_mask_rect, ia,
+ mask_disabled, compressed_len, error))
+ {
+ g_message ("Reading layer mask failed.");
+ }
+ }
}
else
{
@@ -2283,8 +2378,8 @@ read_layer_block (FILE *f,
return NULL;
}
- if (read_channel_data (f, ia, pixels, bytespp, offset,
- buffer, compressed_len, error) == -1)
+ if (read_channel_data (f, ia, pixels, width, height, bytespp,
+ offset, compressed_len, error) == -1)
{
return NULL;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]