[gegl] buffer: implement bilinear dispatch along nearest
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] buffer: implement bilinear dispatch along nearest
- Date: Sun, 28 Jan 2018 20:58:56 +0000 (UTC)
commit 2bb890d4a220808b9678762d710bef05df68e6f7
Author: Øyvind Kolås <pippin gimp org>
Date: Sat Jan 27 01:36:54 2018 +0100
buffer: implement bilinear dispatch along nearest
The default remains boxfilter dispatch which is our highest quality, for the
time being, bilienar dispatch for 8bit nonlinear runs at only 17% of the
performance of the much higher quality boxfilter due to lack of fast paths.
With fast paths it might be a tolerable loss of quality at some speed gain.
gegl/buffer/gegl-buffer-access.c | 80 +++++++++++++++++++++++++------------
gegl/gegl-enums.h | 3 +-
gegl/graph/gegl-node.c | 8 ++--
3 files changed, 60 insertions(+), 31 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index 4ef98a2..7400213 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -1892,6 +1892,7 @@ _gegl_buffer_get_unlocked (GeglBuffer *buffer,
GeglAbyssPolicy repeat_mode)
{
gboolean do_nearest = (repeat_mode & GEGL_BUFFER_NEAREST) != 0;
+ gboolean do_bilinear = (repeat_mode & GEGL_BUFFER_BILINEAR) != 0;
repeat_mode &= 0x7;
if (gegl_cl_is_accelerated ())
@@ -2008,33 +2009,60 @@ _gegl_buffer_get_unlocked (GeglBuffer *buffer,
if (!do_nearest && scale <= 1.99)
{
- buf_width += 2;
- buf_height += 2;
- offset = (buf_width + 1) * bpp;
- sample_buf = g_malloc0 (buf_height * buf_width * bpp);
- /* NOTE: this iterate read dispatch could perhaps with advantage
- be done in the buffers format - or in a well suited for
- scaling format - rather than the target format?, right now
- requesting 8bit from floating point causes more conversions
- than desired */
- gegl_buffer_iterate_read_dispatch (buffer, &sample_rect,
+ if (do_bilinear)
+ {
+ buf_width += 1;
+ buf_height += 1;
+ sample_rect.width += factor;
+ sample_rect.height += factor;
+
+ sample_buf = g_malloc (buf_height * buf_width * bpp);
+ gegl_buffer_iterate_read_dispatch (buffer, &sample_rect,
+ (guchar*)sample_buf,
+ buf_width * bpp,
+ format, level, repeat_mode);
+
+ sample_rect.x = x1;
+ sample_rect.y = y1;
+ sample_rect.width = x2 - x1 + 1;
+ sample_rect.height = y2 - y1 + 1;
+
+ gegl_resample_bilinear (dest_buf,
+ sample_buf,
+ rect,
+ &sample_rect,
+ buf_width * bpp,
+ scale,
+ format,
+ rowstride);
+ }
+ else /* boxfilter */
+ {
+ buf_width += 2;
+ buf_height += 2;
+ offset = (buf_width + 1) * bpp;
+
+ sample_buf = g_malloc (buf_height * buf_width * bpp);
+ gegl_buffer_iterate_read_dispatch (buffer, &sample_rect,
(guchar*)sample_buf + offset,
- buf_width * bpp,
- format, level, repeat_mode);
+ buf_width * bpp,
+ format, level, repeat_mode);
+
+ sample_rect.x = x1 - 1;
+ sample_rect.y = y1 - 1;
+ sample_rect.width = x2 - x1 + 2;
+ sample_rect.height = y2 - y1 + 2;
+
+ gegl_resample_boxfilter (dest_buf,
+ sample_buf,
+ rect,
+ &sample_rect,
+ buf_width * bpp,
+ scale,
+ format,
+ rowstride);
+ }
- sample_rect.x = x1 - 1;
- sample_rect.y = y1 - 1;
- sample_rect.width = x2 - x1 + 2;
- sample_rect.height = y2 - y1 + 2;
-
- gegl_resample_boxfilter (dest_buf,
- sample_buf,
- rect,
- &sample_rect,
- buf_width * bpp,
- scale,
- format,
- rowstride);
g_free (sample_buf);
}
else if (buf_height && buf_width)
diff --git a/gegl/gegl-enums.h b/gegl/gegl-enums.h
index d333627..9fcee42 100644
--- a/gegl/gegl-enums.h
+++ b/gegl/gegl-enums.h
@@ -42,7 +42,8 @@ typedef enum {
GEGL_ABYSS_LOOP = 2,
GEGL_ABYSS_BLACK = 3,
GEGL_ABYSS_WHITE = 4,
- GEGL_BUFFER_NEAREST = 32
+ GEGL_BUFFER_NEAREST = 32,
+ GEGL_BUFFER_BILINEAR = 64
} GeglAbyssPolicy;
GType gegl_abyss_policy_get_type (void) G_GNUC_CONST;
diff --git a/gegl/graph/gegl-node.c b/gegl/graph/gegl-node.c
index 0b6bb2b..20dab0f 100644
--- a/gegl/graph/gegl-node.c
+++ b/gegl/graph/gegl-node.c
@@ -1136,7 +1136,7 @@ gegl_node_blit (GeglNode *self,
gint rowstride,
GeglBlitFlags flags)
{
- gboolean do_nearest = (flags & GEGL_BUFFER_NEAREST) != 0;
+ gint interpolation = flags & (GEGL_BUFFER_NEAREST | GEGL_BUFFER_BILINEAR);
flags &= 0xf;
g_return_if_fail (GEGL_IS_NODE (self));
@@ -1145,7 +1145,7 @@ gegl_node_blit (GeglNode *self,
if (rowstride == GEGL_AUTO_ROWSTRIDE && format)
rowstride = babl_format_get_bytes_per_pixel (format) * roi->width;
- if (!flags)
+ if (flags == 0) // DEFAULT, just render, caching only if graph is explicitly caching itself
{
GeglBuffer *buffer;
@@ -1161,7 +1161,7 @@ gegl_node_blit (GeglNode *self,
buffer = gegl_node_apply_roi (self, roi, 0);
}
if (buffer && destination_buf)
- gegl_buffer_get (buffer, roi, scale, format, destination_buf, rowstride, GEGL_ABYSS_NONE |
(do_nearest?GEGL_BUFFER_NEAREST:0));
+ gegl_buffer_get (buffer, roi, scale, format, destination_buf, rowstride, GEGL_ABYSS_NONE |
interpolation);
g_clear_object (&buffer);
}
@@ -1197,7 +1197,7 @@ gegl_node_blit (GeglNode *self,
{
gegl_buffer_get (buffer, roi, scale,
format, destination_buf, rowstride,
- GEGL_ABYSS_NONE|(do_nearest?GEGL_BUFFER_NEAREST:0));
+ GEGL_ABYSS_NONE|interpolation);
}
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]