[gegl] buffer: make bilinear interpolation from mipmap be default for scaled get



commit 8dd0bef29abd4bbb48994de5c7421637dce5149f
Author: Øyvind Kolås <pippin gimp org>
Date:   Sun Jan 28 02:43:58 2018 +0100

    buffer: make bilinear interpolation from mipmap be default for scaled get
    
    gegl_buffer_get's last argument the repeat-mode is now a combined bit-field
    flags argument. In addition to choosing the edge repeat behavior for the fetch
    we can now also control the interpolation used when scaling from the nearest
    bigger mipmap level explicitly by oring one of the buffer scaling modes into
    the flags.
    
    The available values that can be | in with the repeat-mode, are, with the
    performance scaling factors relative to the default, GEGL_BUFFER_BILINEAR, note
    that for the range 0-2.0 the default is boxfilter - since it is a nicer
    transition to nearest neighbor.
    
    GEGL_BUFFER_NEAREST     8.0
    GEGL_BUFFER_BILINEAR    1.0
    GEGL_BUFFER_BOXFILTER   0.4
    
    nearest uses nearest neighbor sampling from the next bigger size, bilinear uses
    a bilinear interpolation of the values from the bigger available size, sampling
    2x2 pixels for each output pixel, while boxfilter uses a 3x3 neighbourhood -
    which is sufficient for accurate box-filtering from the next bigger power of
    two scale in a mip-map.
    
    The names for these flags, in particular the prefix, might change, if neither
    of them are passed in GEGL_BUFFER_BILINEAR is assumed, this is slightly lower
    quality than the previoux default boxfilter, but is 5-6 times faster - while
    still being much better than nearest neighbor - and as we are zooming out; the
    more correct mipmap scaling dominates.

 gegl/buffer/gegl-buffer-access.c |   23 +++++++++++++++++------
 gegl/gegl-enums.h                |    5 +++--
 2 files changed, 20 insertions(+), 8 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index 7400213..785c69c 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -1889,11 +1889,22 @@ _gegl_buffer_get_unlocked (GeglBuffer          *buffer,
                            const Babl          *format,
                            gpointer             dest_buf,
                            gint                 rowstride,
-                           GeglAbyssPolicy      repeat_mode)
+                           GeglAbyssPolicy      flags)
 {
-  gboolean do_nearest = (repeat_mode & GEGL_BUFFER_NEAREST) != 0;
-  gboolean do_bilinear = (repeat_mode & GEGL_BUFFER_BILINEAR) != 0;
-  repeat_mode &= 0x7;
+  GeglAbyssPolicy repeat_mode = flags & 0x7; /* mask off interpolation from repeat mode part of flags */
+  gint interpolation = (flags & GEGL_BUFFER_BOXFILTER); /* BOXFILTER is and of all interpols */
+
+  if (interpolation == 0)
+  {
+    /* with no specified interpolation we aim for a trade-off where
+       100-200% ends up using box-filter - which is a better transition
+       to nearest neighbor which happens beyond 200% further below.
+     */
+    if (scale > 1.0)
+      interpolation = GEGL_BUFFER_BOXFILTER;
+    else
+      interpolation = GEGL_BUFFER_BILINEAR; /*about 2x as fast as box filter*/
+  }
 
   if (gegl_cl_is_accelerated ())
     {
@@ -2007,9 +2018,9 @@ _gegl_buffer_get_unlocked (GeglBuffer          *buffer,
       buf_width  = x2 - x1;
       buf_height = y2 - y1;
 
-      if (!do_nearest && scale <= 1.99)
+      if ((interpolation != GEGL_BUFFER_NEAREST) && scale <= 1.99)
         {
-          if (do_bilinear)
+          if (interpolation == GEGL_BUFFER_BILINEAR)
             {
               buf_width  += 1;
               buf_height += 1;
diff --git a/gegl/gegl-enums.h b/gegl/gegl-enums.h
index 9fcee42..4d8aa81 100644
--- a/gegl/gegl-enums.h
+++ b/gegl/gegl-enums.h
@@ -42,8 +42,9 @@ typedef enum {
   GEGL_ABYSS_LOOP  = 2,
   GEGL_ABYSS_BLACK = 3,
   GEGL_ABYSS_WHITE = 4,
-  GEGL_BUFFER_NEAREST = 32,
-  GEGL_BUFFER_BILINEAR = 64
+  GEGL_BUFFER_BILINEAR  = 16,
+  GEGL_BUFFER_NEAREST   = 32,
+  GEGL_BUFFER_BOXFILTER = 48,
 } GeglAbyssPolicy;
 
 GType gegl_abyss_policy_get_type (void) G_GNUC_CONST;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]