[gegl] buffer: use calling sampler for sub-sampling during box filtering



commit 37a1f5774f01f142f3bddd620383975aca0e860a
Author: Ell <ell_se yahoo com>
Date:   Sat Nov 17 11:53:30 2018 -0500

    buffer: use calling sampler for sub-sampling during box filtering
    
    When performing box filtering, in the linear and cubic samplers,
    use the calling sampler to sub-sample the buffer, instead of using
    a separate sampler of a different type.  This allows us to perform
    box filtering even when downscaling only along one direction,
    without loss of quality or discontinuity, undoing
    commit 662b9c35f5e052f94268ea0aea59923ed23b10bb.
    
    Note that this can make box filtering slower, since we used to use
    a cheaper sampler for sub-sampling.  This is somewhat countered by
    reducing the number of sub-samples.

 gegl/buffer/gegl-sampler-cubic.c              |   3 +-
 gegl/buffer/gegl-sampler-linear.c             |   3 +-
 gegl/buffer/gegl-sampler.c                    |   2 --
 gegl/buffer/gegl-sampler.h                    |  43 +++++++++-----------------
 tests/compositions/reference/clones.png       | Bin 724878 -> 729480 bytes
 tests/compositions/reference/simple-scale.png | Bin 463 -> 758 bytes
 6 files changed, 16 insertions(+), 35 deletions(-)
---
diff --git a/gegl/buffer/gegl-sampler-cubic.c b/gegl/buffer/gegl-sampler-cubic.c
index 4e1997ea9..f9f9c6ad7 100644
--- a/gegl/buffer/gegl-sampler-cubic.c
+++ b/gegl/buffer/gegl-sampler-cubic.c
@@ -161,8 +161,7 @@ gegl_sampler_cubic_get (      GeglSampler       *self,
                               GeglAbyssPolicy    repeat_mode)
 {
   if (! _gegl_sampler_box_get (self, absolute_x, absolute_y, scale,
-                               output, repeat_mode,
-                               GEGL_SAMPLER_LINEAR, 5))
+                               output, repeat_mode, 5))
   {
     GeglSamplerCubic *cubic       = (GeglSamplerCubic*)(self);
     gint              components = self->interpolate_components;
diff --git a/gegl/buffer/gegl-sampler-linear.c b/gegl/buffer/gegl-sampler-linear.c
index 911992637..fa3b46701 100644
--- a/gegl/buffer/gegl-sampler-linear.c
+++ b/gegl/buffer/gegl-sampler-linear.c
@@ -82,8 +82,7 @@ gegl_sampler_linear_get (     GeglSampler       *self,
 {
   gint nc = self->interpolate_components;
   if (! _gegl_sampler_box_get (self, absolute_x, absolute_y, scale,
-                               output, repeat_mode,
-                               GEGL_SAMPLER_NEAREST, 4))
+                               output, repeat_mode, 4))
   {
     const gint pixels_per_buffer_row = GEGL_SAMPLER_MAXIMUM_WIDTH;
 
diff --git a/gegl/buffer/gegl-sampler.c b/gegl/buffer/gegl-sampler.c
index fd7d52b02..8d569a2a0 100644
--- a/gegl/buffer/gegl-sampler.c
+++ b/gegl/buffer/gegl-sampler.c
@@ -279,8 +279,6 @@ dispose (GObject *gobject)
   /* This call handles unreffing the buffer and disconnecting signals */
   set_buffer (sampler, NULL);
 
-  g_clear_object (&sampler->point_sampler);
-
   G_OBJECT_CLASS (gegl_sampler_parent_class)->dispose (gobject);
 }
 
diff --git a/gegl/buffer/gegl-sampler.h b/gegl/buffer/gegl-sampler.h
index 40091eae8..e2d399318 100644
--- a/gegl/buffer/gegl-sampler.h
+++ b/gegl/buffer/gegl-sampler.h
@@ -59,8 +59,8 @@ typedef struct GeglSamplerLevel
 
 struct _GeglSampler
 {
-  GObject           parent_instance;
-  GeglSamplerGetFun get;
+  GObject            parent_instance;
+  GeglSamplerGetFun  get;
 
   /*< private >*/
   GeglBuffer        *buffer;
@@ -70,8 +70,6 @@ struct _GeglSampler
   const Babl        *fish;
   gint               interpolate_bpp;
   gint               interpolate_components;
-  GeglSampler       *point_sampler;
-  GeglSamplerGetFun  point_sampler_get_fun;
 
   GeglSamplerLevel   level[GEGL_SAMPLER_MIPMAP_LEVELS];
 };
@@ -226,8 +224,7 @@ _gegl_sampler_box_get (GeglSampler*    restrict  self,
                        GeglBufferMatrix2        *scale,
                        void*           restrict  output,
                        GeglAbyssPolicy           repeat_mode,
-                       GeglSamplerType           point_sampler_type,
-                       gint                      n_samples)
+                       gint                      max_n_samples)
 {
   gint channels = self->interpolate_components;
   if (scale)
@@ -237,8 +234,7 @@ _gegl_sampler_box_get (GeglSampler*    restrict  self,
       const gdouble v_norm2 = scale->coeff[0][1] * scale->coeff[0][1] +
                               scale->coeff[1][1] * scale->coeff[1][1];
 
-      if ((u_norm2 >= 4.0 && v_norm2 >= 1.0) ||
-          (v_norm2 >= 4.0 && u_norm2 >= 1.0))
+      if (u_norm2 >= 4.0 || v_norm2 >= 4.0)
         {
           gfloat  result[channels];
           gdouble uv_samples_inv;
@@ -246,23 +242,14 @@ _gegl_sampler_box_get (GeglSampler*    restrict  self,
           for (gint c = 0; c < channels; c++)
             result[c] = 0.0f;
 
-          if (! self->point_sampler)
-            {
-              self->point_sampler = gegl_buffer_sampler_new (self->buffer,
-                                                             self->format,
-                                                             point_sampler_type);
-              self->point_sampler_get_fun =
-                gegl_sampler_get_fun (self->point_sampler);
-            }
-
           if (gegl_buffer_matrix2_is_scale (scale))
             {
               const gdouble u_norm         = fabs (scale->coeff[0][0]);
               const gdouble v_norm         = fabs (scale->coeff[1][1]);
-              const gint    u_norm_i       = ceil (u_norm);
-              const gint    v_norm_i       = ceil (v_norm);
-              const gint    u_samples      = MIN (u_norm_i, n_samples);
-              const gint    v_samples      = MIN (v_norm_i, n_samples);
+              const gint    u_norm_i       = floor (u_norm);
+              const gint    v_norm_i       = floor (v_norm);
+              const gint    u_samples      = CLAMP (u_norm_i, 1, max_n_samples);
+              const gint    v_samples      = CLAMP (v_norm_i, 1, max_n_samples);
               const gdouble u_samples_inv  = 1.0 / u_samples;
               const gdouble v_samples_inv  = 1.0 / v_samples;
               const gdouble u_dx           = scale->coeff[0][0] * u_samples_inv;
@@ -285,8 +272,7 @@ _gegl_sampler_box_get (GeglSampler*    restrict  self,
                     {
                       int c;
                       gfloat input[4];
-                      self->point_sampler_get_fun (self->point_sampler,
-                                                   x, y, NULL, input, repeat_mode);
+                      self->get (self, x, y, NULL, input, repeat_mode);
                       for (c = 0; c < 4; c++)
                         result[c] += input[c];
 
@@ -300,10 +286,10 @@ _gegl_sampler_box_get (GeglSampler*    restrict  self,
             {
               const gdouble u_norm         = sqrt (u_norm2);
               const gdouble v_norm         = sqrt (v_norm2);
-              const gint    u_norm_i       = ceil (u_norm);
-              const gint    v_norm_i       = ceil (v_norm);
-              const gint    u_samples      = MIN (u_norm_i, n_samples);
-              const gint    v_samples      = MIN (v_norm_i, n_samples);
+              const gint    u_norm_i       = floor (u_norm);
+              const gint    v_norm_i       = floor (v_norm);
+              const gint    u_samples      = CLAMP (u_norm_i, 1, max_n_samples);
+              const gint    v_samples      = CLAMP (v_norm_i, 1, max_n_samples);
               const gdouble u_samples_inv  = 1.0 / u_samples;
               const gdouble v_samples_inv  = 1.0 / v_samples;
               const gdouble u_dx           = scale->coeff[0][0] * u_samples_inv;
@@ -330,8 +316,7 @@ _gegl_sampler_box_get (GeglSampler*    restrict  self,
                     {
                       int c;
                       gfloat input[channels];
-                      self->point_sampler_get_fun (self->point_sampler,
-                                                   x, y, NULL, input, repeat_mode);
+                      self->get (self, x, y, NULL, input, repeat_mode);
                       for (c = 0; c < channels; c++)
                         result[c] += input[c];
 
diff --git a/tests/compositions/reference/clones.png b/tests/compositions/reference/clones.png
index 67c8f7dc0..1d82808d0 100644
Binary files a/tests/compositions/reference/clones.png and b/tests/compositions/reference/clones.png differ
diff --git a/tests/compositions/reference/simple-scale.png b/tests/compositions/reference/simple-scale.png
index 0da98a527..f0243e88b 100644
Binary files a/tests/compositions/reference/simple-scale.png and 
b/tests/compositions/reference/simple-scale.png differ


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