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.
parent 0a23bc3a
......@@ -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)
......
......@@ -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;
......
......@@ -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);
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment