[gimp/gimp-2-10] plug-ins: improve PSD loading speed
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/gimp-2-10] plug-ins: improve PSD loading speed
- Date: Tue, 18 Feb 2020 17:21:43 +0000 (UTC)
commit 10bbdb323a8f66cf5e13e14c00efdbf16850b2ae
Author: Ell <ell_se yahoo com>
Date: Tue Feb 18 18:39:49 2020 +0200
plug-ins: improve PSD loading speed
In file-psd, improve loading speed, mostly by eliminating excessive
copies.
(cherry picked from commit 52f5a9f65453f78b3f1e0e3b31962178f5aa4bfb)
plug-ins/file-psd/psd-load.c | 190 +++++++++++++++++++++----------------------
plug-ins/file-psd/psd-util.c | 65 ++++++---------
2 files changed, 116 insertions(+), 139 deletions(-)
---
diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c
index 46a0c76d9f..cc1487c05e 100644
--- a/plug-ins/file-psd/psd-load.c
+++ b/plug-ins/file-psd/psd-load.c
@@ -1122,7 +1122,6 @@ add_layers (gint32 image_id,
PSDchannel **lyr_chn;
GArray *parent_group_stack;
gint32 parent_group_id = -1;
- guchar *pixels;
guint16 alpha_chn;
guint16 user_mask_chn;
guint16 layer_channels;
@@ -1137,15 +1136,12 @@ add_layers (gint32 image_id,
gint32 lm_y; /* Layer mask y */
gint32 lm_w; /* Layer mask width */
gint32 lm_h; /* Layer mask height */
- gint32 layer_size;
gint32 layer_id = -1;
gint32 mask_id = -1;
gint32 active_layer_id = -1;
gint lidx; /* Layer index */
gint cidx; /* Channel index */
gint rowi; /* Row index */
- gint coli; /* Column index */
- gint i;
gboolean alpha;
gboolean user_mask;
gboolean empty;
@@ -1530,29 +1526,66 @@ add_layers (gint32 image_id,
}
else
{
- layer_size = l_w * l_h;
+ GeglBufferIterator *iter;
+
bps = img_a->bps / 8;
if (bps == 0)
bps++;
- pixels = g_malloc (layer_size * layer_channels * bps);
- for (cidx = 0; cidx < layer_channels; ++cidx)
+
+ buffer = gimp_drawable_get_buffer (layer_id);
+
+ iter = gegl_buffer_iterator_new (
+ buffer, NULL, 0, get_layer_format (img_a, alpha),
+ GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE, 1);
+
+ while (gegl_buffer_iterator_next (iter))
{
- IFDBG(3) g_debug ("Start channel %d", channel_idx[cidx]);
- for (i = 0; i < layer_size; ++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);
+ const GeglRectangle *roi = &iter->items[0].roi;
+ guint8 *dst0 = iter->items[0].data;
+ gint src_step = bps;
+ gint dst_step = bps * layer_channels;
+
+ for (cidx = 0; cidx < layer_channels; ++cidx)
+ {
+ gint b;
+
+ if (roi->x == 0 && roi->y == 0)
+ IFDBG(3) g_debug ("Start channel %d", channel_idx[cidx]);
+
+ for (b = 0; b < bps; ++b)
+ {
+ guint8 *dst;
+ gint y;
+
+ dst = &dst0[cidx * bps + b];
+
+ for (y = 0; y < roi->height; y++)
+ {
+ const guint8 *src;
+ gint x;
+
+ src = (const guint8 *)
+ &lyr_chn[channel_idx[cidx]]->data[
+ ((roi->y + y) * l_w +
+ roi->x) * bps +
+ b];
+
+ for (x = 0; x < roi->width; ++x)
+ {
+ *dst = *src;
+
+ src += src_step;
+ dst += dst_step;
+ }
+ }
+ }
+ }
}
- 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_layer_format (img_a, alpha),
- pixels, GEGL_AUTO_ROWSTRIDE);
+ for (cidx = 0; cidx < layer_channels; ++cidx)
+ g_free (lyr_chn[channel_idx[cidx]]->data);
+
g_object_unref (buffer);
- g_free (pixels);
}
}
@@ -1574,69 +1607,27 @@ add_layers (gint32 image_id,
}
else
{
+ GeglRectangle mask_rect;
+
/* Load layer mask data */
lm_x = lyr_a[lidx]->layer_mask.left - l_x;
lm_y = lyr_a[lidx]->layer_mask.top - l_y;
lm_w = lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left;
lm_h = lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top;
IFDBG(3) g_debug ("Mask channel index %d", user_mask_chn);
- bps = (img_a->bps + 1) / 8;
- layer_size = lm_w * lm_h * bps;
- pixels = g_malloc (layer_size);
- IFDBG(3) g_debug ("Allocate Pixels %d", layer_size);
- /* Crop mask at layer boundary */
IFDBG(3) g_debug ("Original Mask %d %d %d %d", lm_x, lm_y, lm_w, lm_h);
- if (lm_x < 0
- || lm_y < 0
- || lm_w + lm_x > l_w
- || lm_h + lm_y > l_h)
- {
- if (CONVERSION_WARNINGS)
- g_message ("Warning\n"
- "The layer mask is partly outside the "
- "layer boundary. The mask will be "
- "cropped which may result in data loss.");
- i = 0;
- for (rowi = 0; rowi < lm_h; ++rowi)
- {
- if (rowi + lm_y >= 0 && rowi + lm_y < l_h)
- {
- for (coli = 0; coli < lm_w; ++coli)
- {
- if (coli + lm_x >= 0 && coli + lm_x < l_w)
- {
- memcpy (&pixels[i * bps], &lyr_chn[user_mask_chn]->data[(rowi *
lm_w + coli) * bps], bps);
- i++;
- }
- }
- }
- }
- if (lm_x < 0)
- {
- lm_w += lm_x;
- lm_x = 0;
- }
- if (lm_y < 0)
- {
- lm_h += lm_y;
- lm_y = 0;
- }
- if (lm_w + lm_x > l_w)
- lm_w = l_w - lm_x;
- if (lm_h + lm_y > l_h)
- lm_h = l_h - lm_y;
- }
- else
- {
- memcpy (pixels, lyr_chn[user_mask_chn]->data, layer_size);
- i = layer_size;
- }
- g_free (lyr_chn[user_mask_chn]->data);
- /* Draw layer mask data, if any */
- if (i > 0)
+ /* Crop mask at layer boundary, and draw layer mask data,
+ * if any
+ */
+ if (gegl_rectangle_intersect (
+ &mask_rect,
+ GEGL_RECTANGLE (0, 0, l_w, l_h),
+ GEGL_RECTANGLE (lm_x, lm_y, lm_w, lm_h)))
{
IFDBG(3) g_debug ("Layer %d %d %d %d", l_x, l_y, l_w, l_h);
- IFDBG(3) g_debug ("Mask %d %d %d %d", lm_x, lm_y, lm_w, lm_h);
+ IFDBG(3) g_debug ("Mask %d %d %d %d",
+ mask_rect.x, mask_rect.y,
+ mask_rect.width, mask_rect.height);
if (lyr_a[lidx]->layer_mask.def_color == 255)
mask_id = gimp_layer_create_mask (layer_id,
@@ -1645,18 +1636,25 @@ add_layers (gint32 image_id,
mask_id = gimp_layer_create_mask (layer_id,
GIMP_ADD_MASK_BLACK);
+ bps = img_a->bps / 8;
+ if (bps == 0)
+ bps++;
+
IFDBG(3) g_debug ("New layer mask %d", mask_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),
+ &mask_rect,
0, get_mask_format (img_a),
- pixels, GEGL_AUTO_ROWSTRIDE);
+ lyr_chn[user_mask_chn]->data + (
+ (mask_rect.y - lm_y) * lm_w +
+ (mask_rect.x - lm_x)) * bps,
+ lm_w * bps);
g_object_unref (buffer);
gimp_layer_set_apply_mask (layer_id,
! lyr_a[lidx]->layer_mask.mask_flags.disabled);
}
- g_free (pixels);
+ g_free (lyr_chn[user_mask_chn]->data);
}
}
@@ -2122,7 +2120,6 @@ read_channel_data (PSDchannel *channel,
{
gchar *raw_data;
gchar *src;
- gchar *dst;
guint32 readline_len;
gint i, j;
@@ -2157,8 +2154,7 @@ read_channel_data (PSDchannel *channel,
case PSD_COMP_RLE:
for (i = 0; i < channel->rows; ++i)
{
- src = g_malloc (rle_pack_len[i]);
- dst = g_malloc (readline_len);
+ src = gegl_scratch_alloc (rle_pack_len[i]);
/* FIXME check for over-run
if (ftell (f) + rle_pack_len[i] > block_end)
{
@@ -2169,15 +2165,13 @@ read_channel_data (PSDchannel *channel,
if (fread (src, rle_pack_len[i], 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
- g_free (src);
- g_free (dst);
+ gegl_scratch_free (src);
return -1;
}
/* FIXME check for errors returned from decode packbits */
- decode_packbits (src, dst, rle_pack_len[i], readline_len);
- g_free (src);
- memcpy (raw_data + i * readline_len, dst, readline_len);
- g_free (dst);
+ decode_packbits (src, raw_data + i * readline_len,
+ rle_pack_len[i], readline_len);
+ gegl_scratch_free (src);
}
break;
case PSD_COMP_ZIP:
@@ -2223,45 +2217,45 @@ read_channel_data (PSDchannel *channel,
{
case 32:
{
- guint32 *src = (guint32*) raw_data;
- guint32 *dst = g_malloc (channel->rows * channel->columns * 4);
+ guint32 *data = (guint32*) raw_data;
- channel->data = (gchar*) dst;
+ channel->data = raw_data;
+ raw_data = NULL;
for (i = 0; i < channel->rows * channel->columns; ++i)
- dst[i] = GUINT32_FROM_BE (src[i]);
+ data[i] = GUINT32_FROM_BE (data[i]);
if (compression == PSD_COMP_ZIP_PRED)
{
for (i = 0; i < channel->rows; ++i)
for (j = 1; j < channel->columns; ++j)
- dst[i * channel->columns + j] += dst[i * channel->columns + j - 1];
+ data[i * channel->columns + j] += data[i * channel->columns + j - 1];
}
break;
}
case 16:
{
- guint16 *src = (guint16*) raw_data;
- guint16 *dst = g_malloc (channel->rows * channel->columns * 2);
+ guint16 *data = (guint16*) raw_data;
- channel->data = (gchar*) dst;
+ channel->data = raw_data;
+ raw_data = NULL;
for (i = 0; i < channel->rows * channel->columns; ++i)
- dst[i] = GUINT16_FROM_BE (src[i]);
+ data[i] = GUINT16_FROM_BE (data[i]);
if (compression == PSD_COMP_ZIP_PRED)
{
for (i = 0; i < channel->rows; ++i)
for (j = 1; j < channel->columns; ++j)
- dst[i * channel->columns + j] += dst[i * channel->columns + j - 1];
+ data[i * channel->columns + j] += data[i * channel->columns + j - 1];
}
break;
}
case 8:
- channel->data = g_malloc (channel->rows * channel->columns * bps / 8 );
- memcpy (channel->data, raw_data, (channel->rows * channel->columns * bps / 8));
+ channel->data = raw_data;
+ raw_data = NULL;
if (compression == PSD_COMP_ZIP_PRED)
{
diff --git a/plug-ins/file-psd/psd-util.c b/plug-ins/file-psd/psd-util.c
index f71a57bdd6..5686bb7970 100644
--- a/plug-ins/file-psd/psd-util.c
+++ b/plug-ins/file-psd/psd-util.c
@@ -489,7 +489,6 @@ decode_packbits (const gchar *src,
*/
gint n;
- gchar dat;
gint32 unpack_left = unpacked_len;
gint32 pack_left = packed_len;
gint32 error_code = 0;
@@ -508,67 +507,51 @@ decode_packbits (const gchar *src,
if (n < 0) /* replicate next gchar |n|+ 1 times */
{
- n = 1 - n;
- if (! pack_left)
+ n = 1 - n;
+ if (pack_left < 1)
{
IFDBG(2) g_debug ("Input buffer exhausted in replicate");
error_code = 1;
break;
}
- if (n > unpack_left)
+ if (unpack_left < n)
{
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--;
- }
+ memset (dst, *src, n);
+ src++;
+ pack_left--;
+ dst += n;
+ unpack_left -= n;
}
else /* copy next n+1 gchars literally */
{
n++;
- for (; n > 0; --n)
+ if (pack_left < n)
+ {
+ IFDBG(2) g_debug ("Input buffer exhausted in copy");
+ error_code = 3;
+ break;
+ }
+ if (unpack_left < 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--;
+ IFDBG(2) g_debug ("Output buffer exhausted in copy");
+ error_code = 4;
+ break;
}
+ memcpy (dst, src, n);
+ src += n;
+ pack_left -= n;
+ dst += n;
+ unpack_left -= n;
}
}
if (unpack_left > 0)
{
/* Pad with zeros to end of output buffer */
- for (n = 0; n < pack_left; ++n)
- {
- *dst = 0;
- dst++;
- }
+ memset (dst, 0, unpack_left);
}
if (unpack_left)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]