[gegl] buffer: samplers handling dynamic number of components



commit 365e53a5b8f1d75f7caa05c90faddb4ea3d2fa93
Author: Øyvind Kolås <pippin gimp org>
Date:   Tue Oct 30 22:03:57 2018 +0100

    buffer: samplers handling dynamic number of components
    
    All resampling for GeglBuffers used to happen in RaGaBaA float, now
    grayscale formats end up using YaA float instead, which will improve
    performance of scaling/rotating in GIMP as well as other tools using
    GeglBuffers resampling like the sculpt tool when in grayscale mode.
    
    buffer: add members for interpolation bpp/components
    
    buffer: make linear sampler component generic
    
    buffer: generalize cubic sampler
    
    buffer: generalize lohalo innerloop
    
    For now, assuming that input is still a premultiplied format and treat last component
    differently, should sniff whether the interpolation format has alpha and only do
    different treatment in that case.
    
    buffer: generalize nohalo for components
    
    buffer: nohalo slight simplification
    
    foo

 gegl/buffer/gegl-sampler-cubic.c  |  24 ++-
 gegl/buffer/gegl-sampler-linear.c |  84 +++------
 gegl/buffer/gegl-sampler-lohalo.c | 123 +++++-------
 gegl/buffer/gegl-sampler-nohalo.c | 386 ++++++++------------------------------
 gegl/buffer/gegl-sampler.c        |  51 ++++-
 gegl/buffer/gegl-sampler.h        |  24 +--
 6 files changed, 219 insertions(+), 473 deletions(-)
---
diff --git a/gegl/buffer/gegl-sampler-cubic.c b/gegl/buffer/gegl-sampler-cubic.c
index b67a625c8..4e1997ea9 100644
--- a/gegl/buffer/gegl-sampler-cubic.c
+++ b/gegl/buffer/gegl-sampler-cubic.c
@@ -15,6 +15,7 @@
  *
  * Copyright 2012 Nicolas Robidoux based on earlier code
  *           2012 Massimo Valentini
+ *           2018 Øyvind Kolås <pippin gimp org>
  */
 
 #include "config.h"
@@ -164,16 +165,18 @@ gegl_sampler_cubic_get (      GeglSampler       *self,
                                GEGL_SAMPLER_LINEAR, 5))
   {
     GeglSamplerCubic *cubic       = (GeglSamplerCubic*)(self);
+    gint              components = self->interpolate_components;
     const gint        offsets[16] = {
-                                      -4-GEGL_SAMPLER_MAXIMUM_WIDTH   *4, 4, 4, 4,
-                                        (GEGL_SAMPLER_MAXIMUM_WIDTH-3)*4, 4, 4, 4,
-                                        (GEGL_SAMPLER_MAXIMUM_WIDTH-3)*4, 4, 4, 4,
-                                        (GEGL_SAMPLER_MAXIMUM_WIDTH-3)*4, 4, 4, 4
+                                      -components-GEGL_SAMPLER_MAXIMUM_WIDTH   *components, components, 
components, components,
+                                        (GEGL_SAMPLER_MAXIMUM_WIDTH-3)*components, components, components, 
components,
+                                        (GEGL_SAMPLER_MAXIMUM_WIDTH-3)*components, components, components, 
components,
+                                        (GEGL_SAMPLER_MAXIMUM_WIDTH-3)*components, components, components, 
components
                                     };
     gfloat           *sampler_bptr;
     gfloat            factor;
-    gfloat            newval[4]   = {0, 0, 0, 0};
-    gint              i,
+    gfloat            newval[components];
+    gint              c,
+                      i,
                       j,
                       k           = 0;
 
@@ -204,6 +207,9 @@ gegl_sampler_cubic_get (      GeglSampler       *self,
 
     sampler_bptr = gegl_sampler_get_ptr (self, ix, iy, repeat_mode);
 
+    for (c = 0; c < components; c++)
+      newval[c] = 0.0f;
+
     for (j=-1; j<3; j++)
       for (i=-1; i<3; i++)
         {
@@ -212,10 +218,8 @@ gegl_sampler_cubic_get (      GeglSampler       *self,
           factor = cubicKernel (y - j, cubic->b, cubic->c) *
                    cubicKernel (x - i, cubic->b, cubic->c);
 
-          newval[0] += factor * sampler_bptr[0];
-          newval[1] += factor * sampler_bptr[1];
-          newval[2] += factor * sampler_bptr[2];
-          newval[3] += factor * sampler_bptr[3];
+          for (c = 0; c < components; c++)
+            newval[c] += factor * sampler_bptr[c];
         }
 
     babl_process (self->fish, newval, output, 1);
diff --git a/gegl/buffer/gegl-sampler-linear.c b/gegl/buffer/gegl-sampler-linear.c
index a96391bb1..911992637 100644
--- a/gegl/buffer/gegl-sampler-linear.c
+++ b/gegl/buffer/gegl-sampler-linear.c
@@ -77,15 +77,15 @@ gegl_sampler_linear_get (     GeglSampler       *self,
                         const gdouble            absolute_x,
                         const gdouble            absolute_y,
                               GeglBufferMatrix2 *scale,
-                              void            *output,
-                              GeglAbyssPolicy  repeat_mode)
+                              void              *output,
+                              GeglAbyssPolicy    repeat_mode)
 {
+  gint nc = self->interpolate_components;
   if (! _gegl_sampler_box_get (self, absolute_x, absolute_y, scale,
                                output, repeat_mode,
                                GEGL_SAMPLER_NEAREST, 4))
   {
     const gint pixels_per_buffer_row = GEGL_SAMPLER_MAXIMUM_WIDTH;
-    const gint channels = 4;
 
     /*
      * The "-1/2"s are there because we want the index of the pixel to
@@ -125,16 +125,16 @@ gegl_sampler_linear_get (     GeglSampler       *self,
     /*
      * Load top row:
      */
-    const gfloat top_left_0 = *in_bptr++;
-    const gfloat top_left_1 = *in_bptr++;
-    const gfloat top_left_2 = *in_bptr++;
-    const gfloat top_left_3 = *in_bptr++;
-    const gfloat top_rite_0 = *in_bptr++;
-    const gfloat top_rite_1 = *in_bptr++;
-    const gfloat top_rite_2 = *in_bptr++;
-    const gfloat top_rite_3 = *in_bptr;
+    gfloat top_left[nc];
+    gfloat top_rite[nc];
 
-    in_bptr += 1 + ( pixels_per_buffer_row - 2 ) * channels;
+    for (gint c = 0; c < nc; c++)
+      top_left[c] = *in_bptr++;
+
+    for (gint c = 0; c < nc; c++)
+      top_rite[c] = *in_bptr++;
+
+    in_bptr += ( pixels_per_buffer_row - 2 ) * nc;
 
     {
     /*
@@ -148,59 +148,33 @@ gegl_sampler_linear_get (     GeglSampler       *self,
     /*
      * Load bottom row:
      */
-    const gfloat bot_left_0 = *in_bptr++;
-    const gfloat bot_left_1 = *in_bptr++;
-    const gfloat bot_left_2 = *in_bptr++;
-    const gfloat bot_left_3 = *in_bptr++;
-    const gfloat bot_rite_0 = *in_bptr++;
-    const gfloat bot_rite_1 = *in_bptr++;
-    const gfloat bot_rite_2 = *in_bptr++;
-    const gfloat bot_rite_3 = *in_bptr;
+    gfloat bot_left[4];
+    gfloat bot_rite[4];
+    for (gint c = 0; c < nc; c++)
+      bot_left[c] = *in_bptr++;
+    for (gint c = 0; c < nc; c++)
+      bot_rite[c] = *in_bptr++;
 
     /*
      * Last bilinear weight:
      */
+    {
     const gfloat w_times_z = (gfloat) 1. - ( x + w_times_y );
 
     gfloat newval[4];
 
-    newval[0] =
-      x_times_y * bot_rite_0
-      +
-      w_times_y * bot_left_0
-      +
-      x_times_z * top_rite_0
-      +
-      w_times_z * top_left_0;
-
-    newval[1] =
-      x_times_y * bot_rite_1
-      +
-      w_times_y * bot_left_1
-      +
-      x_times_z * top_rite_1
-      +
-      w_times_z * top_left_1;
-
-    newval[2] =
-      x_times_y * bot_rite_2
-      +
-      w_times_y * bot_left_2
-      +
-      x_times_z * top_rite_2
-      +
-      w_times_z * top_left_2;
-
-    newval[3] =
-      x_times_y * bot_rite_3
-      +
-      w_times_y * bot_left_3
-      +
-      x_times_z * top_rite_3
-      +
-      w_times_z * top_left_3;
+      for (gint c = 0; c < nc; c++)
+        newval[c] =
+        x_times_y * bot_rite[c]
+        +
+        w_times_y * bot_left[c]
+        +
+        x_times_z * top_rite[c]
+        +
+        w_times_z * top_left[c];
 
       babl_process (self->fish, newval, output, 1);
     }
+    }
   }
 }
diff --git a/gegl/buffer/gegl-sampler-lohalo.c b/gegl/buffer/gegl-sampler-lohalo.c
index 8bb31f7f3..8fd35dfff 100644
--- a/gegl/buffer/gegl-sampler-lohalo.c
+++ b/gegl/buffer/gegl-sampler-lohalo.c
@@ -364,7 +364,7 @@ ewa_update (const gint              j,
                   gfloat*  restrict ewa_newval)
 {
   const gint skip = j * channels + i * row_skip;
-
+  gint c;
   const gfloat weight = robidoux (c_major_x,
                                   c_major_y,
                                   c_minor_x,
@@ -373,10 +373,8 @@ ewa_update (const gint              j,
                                   y_0 - (gfloat) i);
 
   *total_weight += weight;
-  ewa_newval[0] += weight * input_ptr[ skip     ];
-  ewa_newval[1] += weight * input_ptr[ skip + 1 ];
-  ewa_newval[2] += weight * input_ptr[ skip + 2 ];
-  ewa_newval[3] += weight * input_ptr[ skip + 3 ];
+  for (c = 0; c < channels; c++)
+    ewa_newval[c] += weight * input_ptr[ skip + c ];
 }
 
 static void
@@ -392,7 +390,7 @@ gegl_sampler_lohalo_get (      GeglSampler*    restrict  self,
    * provided by gegl_sampler_get_ptr (self, ix, iy). pixels_per_row
    * corresponds to fetch_rectangle.width in gegl_sampler_get_ptr.
    */
-  const gint channels       = 4;
+  const gint channels       = self->interpolate_components;
   const gint pixels_per_row = GEGL_SAMPLER_MAXIMUM_WIDTH;
   const gint row_skip       = channels * pixels_per_row;
 
@@ -501,86 +499,52 @@ gegl_sampler_lohalo_get (      GeglSampler*    restrict  self,
   const gfloat tre = ay - qua - yt3;
   const gfloat two = xt2 - one + xt3;
   const gfloat dos = yt2 - uno + yt3;
-
+  gint c;
   /*
    * The newval array will contain one computed resampled value per
    * channel:
    */
   gfloat newval[channels];
-  newval[0] =
-    extended_sigmoidal (
-      uno * ( one * inverse_sigmoidal (input_ptr[ uno_one_shift ]) +
-              two * inverse_sigmoidal (input_ptr[ uno_two_shift ]) +
-              thr * inverse_sigmoidal (input_ptr[ uno_thr_shift ]) +
-              fou * inverse_sigmoidal (input_ptr[ uno_fou_shift ]) ) +
-      dos * ( one * inverse_sigmoidal (input_ptr[ dos_one_shift ]) +
-              two * inverse_sigmoidal (input_ptr[ dos_two_shift ]) +
-              thr * inverse_sigmoidal (input_ptr[ dos_thr_shift ]) +
-              fou * inverse_sigmoidal (input_ptr[ dos_fou_shift ]) ) +
-      tre * ( one * inverse_sigmoidal (input_ptr[ tre_one_shift ]) +
-              two * inverse_sigmoidal (input_ptr[ tre_two_shift ]) +
-              thr * inverse_sigmoidal (input_ptr[ tre_thr_shift ]) +
-              fou * inverse_sigmoidal (input_ptr[ tre_fou_shift ]) ) +
-      qua * ( one * inverse_sigmoidal (input_ptr[ qua_one_shift ]) +
-              two * inverse_sigmoidal (input_ptr[ qua_two_shift ]) +
-              thr * inverse_sigmoidal (input_ptr[ qua_thr_shift ]) +
-              fou * inverse_sigmoidal (input_ptr[ qua_fou_shift ]) ) );
-  newval[1] =
-    extended_sigmoidal (
-      uno * ( one * inverse_sigmoidal (input_ptr[ uno_one_shift + 1 ]) +
-              two * inverse_sigmoidal (input_ptr[ uno_two_shift + 1 ]) +
-              thr * inverse_sigmoidal (input_ptr[ uno_thr_shift + 1 ]) +
-              fou * inverse_sigmoidal (input_ptr[ uno_fou_shift + 1 ]) ) +
-      dos * ( one * inverse_sigmoidal (input_ptr[ dos_one_shift + 1 ]) +
-              two * inverse_sigmoidal (input_ptr[ dos_two_shift + 1 ]) +
-              thr * inverse_sigmoidal (input_ptr[ dos_thr_shift + 1 ]) +
-              fou * inverse_sigmoidal (input_ptr[ dos_fou_shift + 1 ]) ) +
-      tre * ( one * inverse_sigmoidal (input_ptr[ tre_one_shift + 1 ]) +
-              two * inverse_sigmoidal (input_ptr[ tre_two_shift + 1 ]) +
-              thr * inverse_sigmoidal (input_ptr[ tre_thr_shift + 1 ]) +
-              fou * inverse_sigmoidal (input_ptr[ tre_fou_shift + 1 ]) ) +
-      qua * ( one * inverse_sigmoidal (input_ptr[ qua_one_shift + 1 ]) +
-              two * inverse_sigmoidal (input_ptr[ qua_two_shift + 1 ]) +
-              thr * inverse_sigmoidal (input_ptr[ qua_thr_shift + 1 ]) +
-              fou * inverse_sigmoidal (input_ptr[ qua_fou_shift + 1 ]) ) );
-  newval[2] =
+  for (c = 0; c < channels-1; c++)
+   newval[c] =
     extended_sigmoidal (
-      uno * ( one * inverse_sigmoidal (input_ptr[ uno_one_shift + 2 ]) +
-              two * inverse_sigmoidal (input_ptr[ uno_two_shift + 2 ]) +
-              thr * inverse_sigmoidal (input_ptr[ uno_thr_shift + 2 ]) +
-              fou * inverse_sigmoidal (input_ptr[ uno_fou_shift + 2 ]) ) +
-      dos * ( one * inverse_sigmoidal (input_ptr[ dos_one_shift + 2 ]) +
-              two * inverse_sigmoidal (input_ptr[ dos_two_shift + 2 ]) +
-              thr * inverse_sigmoidal (input_ptr[ dos_thr_shift + 2 ]) +
-              fou * inverse_sigmoidal (input_ptr[ dos_fou_shift + 2 ]) ) +
-      tre * ( one * inverse_sigmoidal (input_ptr[ tre_one_shift + 2 ]) +
-              two * inverse_sigmoidal (input_ptr[ tre_two_shift + 2 ]) +
-              thr * inverse_sigmoidal (input_ptr[ tre_thr_shift + 2 ]) +
-              fou * inverse_sigmoidal (input_ptr[ tre_fou_shift + 2 ]) ) +
-      qua * ( one * inverse_sigmoidal (input_ptr[ qua_one_shift + 2 ]) +
-              two * inverse_sigmoidal (input_ptr[ qua_two_shift + 2 ]) +
-              thr * inverse_sigmoidal (input_ptr[ qua_thr_shift + 2 ]) +
-              fou * inverse_sigmoidal (input_ptr[ qua_fou_shift + 2 ]) ) );
+      uno * ( one * inverse_sigmoidal (input_ptr[ uno_one_shift + c ]) +
+              two * inverse_sigmoidal (input_ptr[ uno_two_shift + c ]) +
+              thr * inverse_sigmoidal (input_ptr[ uno_thr_shift + c ]) +
+              fou * inverse_sigmoidal (input_ptr[ uno_fou_shift + c ]) ) +
+      dos * ( one * inverse_sigmoidal (input_ptr[ dos_one_shift + c ]) +
+              two * inverse_sigmoidal (input_ptr[ dos_two_shift + c ]) +
+              thr * inverse_sigmoidal (input_ptr[ dos_thr_shift + c ]) +
+              fou * inverse_sigmoidal (input_ptr[ dos_fou_shift + c ]) ) +
+      tre * ( one * inverse_sigmoidal (input_ptr[ tre_one_shift + c ]) +
+              two * inverse_sigmoidal (input_ptr[ tre_two_shift + c ]) +
+              thr * inverse_sigmoidal (input_ptr[ tre_thr_shift + c ]) +
+              fou * inverse_sigmoidal (input_ptr[ tre_fou_shift + c ]) ) +
+      qua * ( one * inverse_sigmoidal (input_ptr[ qua_one_shift + c ]) +
+              two * inverse_sigmoidal (input_ptr[ qua_two_shift + c ]) +
+              thr * inverse_sigmoidal (input_ptr[ qua_thr_shift + c ]) +
+              fou * inverse_sigmoidal (input_ptr[ qua_fou_shift + c ]) ) );
   /*
    * It appears that it is a bad idea to sigmoidize the transparency
    * channel (in RaGaBaA, at least). So don't.
    */
-  newval[3] = uno * ( one * input_ptr[ uno_one_shift + 3 ] +
-                      two * input_ptr[ uno_two_shift + 3 ] +
-                      thr * input_ptr[ uno_thr_shift + 3 ] +
-                      fou * input_ptr[ uno_fou_shift + 3 ] ) +
-              dos * ( one * input_ptr[ dos_one_shift + 3 ] +
-                      two * input_ptr[ dos_two_shift + 3 ] +
-                      thr * input_ptr[ dos_thr_shift + 3 ] +
-                      fou * input_ptr[ dos_fou_shift + 3 ] ) +
-              tre * ( one * input_ptr[ tre_one_shift + 3 ] +
-                      two * input_ptr[ tre_two_shift + 3 ] +
-                      thr * input_ptr[ tre_thr_shift + 3 ] +
-                      fou * input_ptr[ tre_fou_shift + 3 ] ) +
-              qua * ( one * input_ptr[ qua_one_shift + 3 ] +
-                      two * input_ptr[ qua_two_shift + 3 ] +
-                      thr * input_ptr[ qua_thr_shift + 3 ] +
-                      fou * input_ptr[ qua_fou_shift + 3 ] );
+  newval[channels-1] =
+              uno * ( one * input_ptr[ uno_one_shift + channels - 1 ] +
+                      two * input_ptr[ uno_two_shift + channels - 1 ] +
+                      thr * input_ptr[ uno_thr_shift + channels - 1 ] +
+                      fou * input_ptr[ uno_fou_shift + channels - 1 ] ) +
+              dos * ( one * input_ptr[ dos_one_shift + channels - 1 ] +
+                      two * input_ptr[ dos_two_shift + channels - 1 ] +
+                      thr * input_ptr[ dos_thr_shift + channels - 1 ] +
+                      fou * input_ptr[ dos_fou_shift + channels - 1 ] ) +
+              tre * ( one * input_ptr[ tre_one_shift + channels - 1 ] +
+                      two * input_ptr[ tre_two_shift + channels - 1 ] +
+                      thr * input_ptr[ tre_thr_shift + channels - 1 ] +
+                      fou * input_ptr[ tre_fou_shift + channels - 1 ] ) +
+              qua * ( one * input_ptr[ qua_one_shift + channels - 1 ] +
+                      two * input_ptr[ qua_two_shift + channels - 1 ] +
+                      thr * input_ptr[ qua_thr_shift + channels - 1 ] +
+                      fou * input_ptr[ qua_fou_shift + channels - 1 ] );
 
   {
     /*
@@ -1025,10 +989,9 @@ gegl_sampler_lohalo_get (      GeglSampler*    restrict  self,
            */
           const gfloat beta = twice_s1s1 > (gdouble) 2. ? (gfloat) ( ( (gdouble) 1.0 - theta ) / 
total_weight ) : (gfloat) 0.;
           const gfloat newtheta = twice_s1s1 > (gdouble) 2. ? theta : (gfloat) 1.;
-          newval[0] = newtheta * newval[0] + beta * ewa_newval[0];
-          newval[1] = newtheta * newval[1] + beta * ewa_newval[1];
-          newval[2] = newtheta * newval[2] + beta * ewa_newval[2];
-          newval[3] = newtheta * newval[3] + beta * ewa_newval[3];
+          gint c;
+          for (c = 0; c < channels; c++)
+            newval[c] = newtheta * newval[c] + beta * ewa_newval[c];
         }
       }
 
diff --git a/gegl/buffer/gegl-sampler-nohalo.c b/gegl/buffer/gegl-sampler-nohalo.c
index fda400318..8983bdced 100644
--- a/gegl/buffer/gegl-sampler-nohalo.c
+++ b/gegl/buffer/gegl-sampler-nohalo.c
@@ -17,6 +17,7 @@
  * 2012 (c) Nicolas Robidoux
  * 2009-2011 (c) Nicolas Robidoux, Adam Turcotte, Chantal Racette,
  * Anthony Thyssen, John Cupitt and Øyvind Kolås.
+ * 2018 Øyvind Kolås
  */
 
 /*
@@ -1205,12 +1206,11 @@ ewa_update (const gint              j,
                                 c_minor_y,
                                 x_0 - (gfloat) j,
                                 y_0 - (gfloat) i);
+  gint c;
 
   *total_weight += weight;
-  ewa_newval[0] += weight * input_ptr[ skip     ];
-  ewa_newval[1] += weight * input_ptr[ skip + 1 ];
-  ewa_newval[2] += weight * input_ptr[ skip + 2 ];
-  ewa_newval[3] += weight * input_ptr[ skip + 3 ];
+  for (c = 0; c < channels; c++)
+    ewa_newval[c] += weight * input_ptr[ skip + c ];
 }
 
 static void
@@ -1226,7 +1226,7 @@ gegl_sampler_nohalo_get (      GeglSampler*    restrict  self,
    * provided by gegl_sampler_get_ptr (self, ix, iy). pixels_per_row
    * corresponds to fetch_rectangle.width in gegl_sampler_get_ptr.
    */
-  const gint channels       = 4;
+  const gint channels       = self->interpolate_components;
   const gint pixels_per_row = GEGL_SAMPLER_MAXIMUM_WIDTH;
   const gint row_skip       = channels * pixels_per_row;
 
@@ -1311,28 +1311,6 @@ gegl_sampler_nohalo_get (      GeglSampler*    restrict  self,
   const gint cin_thr_shift =                    shift_forw_2_row;
   const gint cin_fou_shift = shift_forw_1_pix + shift_forw_2_row;
 
-  /*
-   * Channel by channel computation of the new pixel values:
-   */
-  gfloat uno_one_0, uno_two_0, uno_thr_0, uno_fou_0;
-  gfloat dos_one_0, dos_two_0, dos_thr_0, dos_fou_0;
-  gfloat tre_one_0, tre_two_0, tre_thr_0, tre_fou_0;
-  gfloat qua_one_0, qua_two_0, qua_thr_0, qua_fou_0;
-
-  gfloat uno_one_1, uno_two_1, uno_thr_1, uno_fou_1;
-  gfloat dos_one_1, dos_two_1, dos_thr_1, dos_fou_1;
-  gfloat tre_one_1, tre_two_1, tre_thr_1, tre_fou_1;
-  gfloat qua_one_1, qua_two_1, qua_thr_1, qua_fou_1;
-
-  gfloat uno_one_2, uno_two_2, uno_thr_2, uno_fou_2;
-  gfloat dos_one_2, dos_two_2, dos_thr_2, dos_fou_2;
-  gfloat tre_one_2, tre_two_2, tre_thr_2, tre_fou_2;
-  gfloat qua_one_2, qua_two_2, qua_thr_2, qua_fou_2;
-
-  gfloat uno_one_3, uno_two_3, uno_thr_3, uno_fou_3;
-  gfloat dos_one_3, dos_two_3, dos_thr_3, dos_fou_3;
-  gfloat tre_one_3, tre_two_3, tre_thr_3, tre_fou_3;
-  gfloat qua_one_3, qua_two_3, qua_thr_3, qua_fou_3;
 
   /*
    * The newval array will contain one computed resampled value per
@@ -1340,47 +1318,6 @@ gegl_sampler_nohalo_get (      GeglSampler*    restrict  self,
    */
   gfloat newval[channels];
 
-  /*
-   * First channel:
-   */
-  nohalo_subdivision (input_ptr[ uno_two_shift ],
-                      input_ptr[ uno_thr_shift ],
-                      input_ptr[ uno_fou_shift ],
-                      input_ptr[ dos_one_shift ],
-                      input_ptr[ dos_two_shift ],
-                      input_ptr[ dos_thr_shift ],
-                      input_ptr[ dos_fou_shift ],
-                      input_ptr[ dos_fiv_shift ],
-                      input_ptr[ tre_one_shift ],
-                      input_ptr[ tre_two_shift ],
-                      input_ptr[ tre_thr_shift ],
-                      input_ptr[ tre_fou_shift ],
-                      input_ptr[ tre_fiv_shift ],
-                      input_ptr[ qua_one_shift ],
-                      input_ptr[ qua_two_shift ],
-                      input_ptr[ qua_thr_shift ],
-                      input_ptr[ qua_fou_shift ],
-                      input_ptr[ qua_fiv_shift ],
-                      input_ptr[ cin_two_shift ],
-                      input_ptr[ cin_thr_shift ],
-                      input_ptr[ cin_fou_shift ],
-                      &uno_one_0,
-                      &uno_two_0,
-                      &uno_thr_0,
-                      &uno_fou_0,
-                      &dos_one_0,
-                      &dos_two_0,
-                      &dos_thr_0,
-                      &dos_fou_0,
-                      &tre_one_0,
-                      &tre_two_0,
-                      &tre_thr_0,
-                      &tre_fou_0,
-                      &qua_one_0,
-                      &qua_two_0,
-                      &qua_thr_0,
-                      &qua_fou_0);
-
   {
     /*
      * Computation of the needed weights (coefficients).
@@ -1466,223 +1403,54 @@ gegl_sampler_nohalo_get (      GeglSampler*    restrict  self,
     const gfloat c11dxdy =
       xm1over2_times_ym1over2 * xp1over2sq_times_yp1over2sq;
 
-    newval[0] = lbb (c00,
-                     c10,
-                     c01,
-                     c11,
-                     c00dx,
-                     c10dx,
-                     c01dx,
-                     c11dx,
-                     c00dy,
-                     c10dy,
-                     c01dy,
-                     c11dy,
-                     c00dxdy,
-                     c10dxdy,
-                     c01dxdy,
-                     c11dxdy,
-                     uno_one_0,
-                     uno_two_0,
-                     uno_thr_0,
-                     uno_fou_0,
-                     dos_one_0,
-                     dos_two_0,
-                     dos_thr_0,
-                     dos_fou_0,
-                     tre_one_0,
-                     tre_two_0,
-                     tre_thr_0,
-                     tre_fou_0,
-                     qua_one_0,
-                     qua_two_0,
-                     qua_thr_0,
-                     qua_fou_0);
-    /*
-     * Second channel:
-     */
-    nohalo_subdivision (input_ptr[ uno_two_shift + 1 ],
-                        input_ptr[ uno_thr_shift + 1 ],
-                        input_ptr[ uno_fou_shift + 1 ],
-                        input_ptr[ dos_one_shift + 1 ],
-                        input_ptr[ dos_two_shift + 1 ],
-                        input_ptr[ dos_thr_shift + 1 ],
-                        input_ptr[ dos_fou_shift + 1 ],
-                        input_ptr[ dos_fiv_shift + 1 ],
-                        input_ptr[ tre_one_shift + 1 ],
-                        input_ptr[ tre_two_shift + 1 ],
-                        input_ptr[ tre_thr_shift + 1 ],
-                        input_ptr[ tre_fou_shift + 1 ],
-                        input_ptr[ tre_fiv_shift + 1 ],
-                        input_ptr[ qua_one_shift + 1 ],
-                        input_ptr[ qua_two_shift + 1 ],
-                        input_ptr[ qua_thr_shift + 1 ],
-                        input_ptr[ qua_fou_shift + 1 ],
-                        input_ptr[ qua_fiv_shift + 1 ],
-                        input_ptr[ cin_two_shift + 1 ],
-                        input_ptr[ cin_thr_shift + 1 ],
-                        input_ptr[ cin_fou_shift + 1 ],
-                        &uno_one_1,
-                        &uno_two_1,
-                        &uno_thr_1,
-                        &uno_fou_1,
-                        &dos_one_1,
-                        &dos_two_1,
-                        &dos_thr_1,
-                        &dos_fou_1,
-                        &tre_one_1,
-                        &tre_two_1,
-                        &tre_thr_1,
-                        &tre_fou_1,
-                        &qua_one_1,
-                        &qua_two_1,
-                        &qua_thr_1,
-                        &qua_fou_1);
-    newval[1] = lbb (c00,
-                     c10,
-                     c01,
-                     c11,
-                     c00dx,
-                     c10dx,
-                     c01dx,
-                     c11dx,
-                     c00dy,
-                     c10dy,
-                     c01dy,
-                     c11dy,
-                     c00dxdy,
-                     c10dxdy,
-                     c01dxdy,
-                     c11dxdy,
-                     uno_one_1,
-                     uno_two_1,
-                     uno_thr_1,
-                     uno_fou_1,
-                     dos_one_1,
-                     dos_two_1,
-                     dos_thr_1,
-                     dos_fou_1,
-                     tre_one_1,
-                     tre_two_1,
-                     tre_thr_1,
-                     tre_fou_1,
-                     qua_one_1,
-                     qua_two_1,
-                     qua_thr_1,
-                     qua_fou_1);
-    /*
-     * Third channel:
-     */
-    nohalo_subdivision (input_ptr[ uno_two_shift + 2 ],
-                        input_ptr[ uno_thr_shift + 2 ],
-                        input_ptr[ uno_fou_shift + 2 ],
-                        input_ptr[ dos_one_shift + 2 ],
-                        input_ptr[ dos_two_shift + 2 ],
-                        input_ptr[ dos_thr_shift + 2 ],
-                        input_ptr[ dos_fou_shift + 2 ],
-                        input_ptr[ dos_fiv_shift + 2 ],
-                        input_ptr[ tre_one_shift + 2 ],
-                        input_ptr[ tre_two_shift + 2 ],
-                        input_ptr[ tre_thr_shift + 2 ],
-                        input_ptr[ tre_fou_shift + 2 ],
-                        input_ptr[ tre_fiv_shift + 2 ],
-                        input_ptr[ qua_one_shift + 2 ],
-                        input_ptr[ qua_two_shift + 2 ],
-                        input_ptr[ qua_thr_shift + 2 ],
-                        input_ptr[ qua_fou_shift + 2 ],
-                        input_ptr[ qua_fiv_shift + 2 ],
-                        input_ptr[ cin_two_shift + 2 ],
-                        input_ptr[ cin_thr_shift + 2 ],
-                        input_ptr[ cin_fou_shift + 2 ],
-                        &uno_one_2,
-                        &uno_two_2,
-                        &uno_thr_2,
-                        &uno_fou_2,
-                        &dos_one_2,
-                        &dos_two_2,
-                        &dos_thr_2,
-                        &dos_fou_2,
-                        &tre_one_2,
-                        &tre_two_2,
-                        &tre_thr_2,
-                        &tre_fou_2,
-                        &qua_one_2,
-                        &qua_two_2,
-                        &qua_thr_2,
-                        &qua_fou_2);
-    newval[2] = lbb (c00,
-                     c10,
-                     c01,
-                     c11,
-                     c00dx,
-                     c10dx,
-                     c01dx,
-                     c11dx,
-                     c00dy,
-                     c10dy,
-                     c01dy,
-                     c11dy,
-                     c00dxdy,
-                     c10dxdy,
-                     c01dxdy,
-                     c11dxdy,
-                     uno_one_2,
-                     uno_two_2,
-                     uno_thr_2,
-                     uno_fou_2,
-                     dos_one_2,
-                     dos_two_2,
-                     dos_thr_2,
-                     dos_fou_2,
-                     tre_one_2,
-                     tre_two_2,
-                     tre_thr_2,
-                     tre_fou_2,
-                     qua_one_2,
-                     qua_two_2,
-                     qua_thr_2,
-                     qua_fou_2);
-    /*
-     * Fourth channel:
-     */
-    nohalo_subdivision (input_ptr[ uno_two_shift + 3 ],
-                        input_ptr[ uno_thr_shift + 3 ],
-                        input_ptr[ uno_fou_shift + 3 ],
-                        input_ptr[ dos_one_shift + 3 ],
-                        input_ptr[ dos_two_shift + 3 ],
-                        input_ptr[ dos_thr_shift + 3 ],
-                        input_ptr[ dos_fou_shift + 3 ],
-                        input_ptr[ dos_fiv_shift + 3 ],
-                        input_ptr[ tre_one_shift + 3 ],
-                        input_ptr[ tre_two_shift + 3 ],
-                        input_ptr[ tre_thr_shift + 3 ],
-                        input_ptr[ tre_fou_shift + 3 ],
-                        input_ptr[ tre_fiv_shift + 3 ],
-                        input_ptr[ qua_one_shift + 3 ],
-                        input_ptr[ qua_two_shift + 3 ],
-                        input_ptr[ qua_thr_shift + 3 ],
-                        input_ptr[ qua_fou_shift + 3 ],
-                        input_ptr[ qua_fiv_shift + 3 ],
-                        input_ptr[ cin_two_shift + 3 ],
-                        input_ptr[ cin_thr_shift + 3 ],
-                        input_ptr[ cin_fou_shift + 3 ],
-                        &uno_one_3,
-                        &uno_two_3,
-                        &uno_thr_3,
-                        &uno_fou_3,
-                        &dos_one_3,
-                        &dos_two_3,
-                        &dos_thr_3,
-                        &dos_fou_3,
-                        &tre_one_3,
-                        &tre_two_3,
-                        &tre_thr_3,
-                        &tre_fou_3,
-                        &qua_one_3,
-                        &qua_two_3,
-                        &qua_thr_3,
-                        &qua_fou_3);
-    newval[3] = lbb (c00,
+  for (gint c = 0; c < channels; c++)
+  {
+  /*
+   * Channel by channel computation of the new pixel values:
+   */
+  gfloat uno_one, uno_two, uno_thr, uno_fou;
+  gfloat dos_one, dos_two, dos_thr, dos_fou;
+  gfloat tre_one, tre_two, tre_thr, tre_fou;
+  gfloat qua_one, qua_two, qua_thr, qua_fou;
+  nohalo_subdivision (input_ptr[ uno_two_shift + c],
+                      input_ptr[ uno_thr_shift + c],
+                      input_ptr[ uno_fou_shift + c],
+                      input_ptr[ dos_one_shift + c],
+                      input_ptr[ dos_two_shift + c],
+                      input_ptr[ dos_thr_shift + c],
+                      input_ptr[ dos_fou_shift + c],
+                      input_ptr[ dos_fiv_shift + c],
+                      input_ptr[ tre_one_shift + c],
+                      input_ptr[ tre_two_shift + c],
+                      input_ptr[ tre_thr_shift + c],
+                      input_ptr[ tre_fou_shift + c],
+                      input_ptr[ tre_fiv_shift + c],
+                      input_ptr[ qua_one_shift + c],
+                      input_ptr[ qua_two_shift + c],
+                      input_ptr[ qua_thr_shift + c],
+                      input_ptr[ qua_fou_shift + c],
+                      input_ptr[ qua_fiv_shift + c],
+                      input_ptr[ cin_two_shift + c],
+                      input_ptr[ cin_thr_shift + c],
+                      input_ptr[ cin_fou_shift + c],
+                      &uno_one,
+                      &uno_two,
+                      &uno_thr,
+                      &uno_fou,
+                      &dos_one,
+                      &dos_two,
+                      &dos_thr,
+                      &dos_fou,
+                      &tre_one,
+                      &tre_two,
+                      &tre_thr,
+                      &tre_fou,
+                      &qua_one,
+                      &qua_two,
+                      &qua_thr,
+                      &qua_fou);
+
+    newval[c] = lbb (c00,
                      c10,
                      c01,
                      c11,
@@ -1698,22 +1466,24 @@ gegl_sampler_nohalo_get (      GeglSampler*    restrict  self,
                      c10dxdy,
                      c01dxdy,
                      c11dxdy,
-                     uno_one_3,
-                     uno_two_3,
-                     uno_thr_3,
-                     uno_fou_3,
-                     dos_one_3,
-                     dos_two_3,
-                     dos_thr_3,
-                     dos_fou_3,
-                     tre_one_3,
-                     tre_two_3,
-                     tre_thr_3,
-                     tre_fou_3,
-                     qua_one_3,
-                     qua_two_3,
-                     qua_thr_3,
-                     qua_fou_3);
+                     uno_one,
+                     uno_two,
+                     uno_thr,
+                     uno_fou,
+                     dos_one,
+                     dos_two,
+                     dos_thr,
+                     dos_fou,
+                     tre_one,
+                     tre_two,
+                     tre_thr,
+                     tre_fou,
+                     qua_one,
+                     qua_two,
+                     qua_thr,
+                     qua_fou);
+  }
+
 
     {
       /*
@@ -1925,7 +1695,7 @@ gegl_sampler_nohalo_get (      GeglSampler*    restrict  self,
        * ImageMagick (now fixed, thanks to Cristy, the lead dev).
        */
       const double sqrt_discriminant =
-        sqrt (discriminant > 0. ? discriminant : 0.);
+        discriminant > 0. ? sqrt (discriminant) : 0.;
 
       /*
        * Initially, we only compute the squares of the singular
@@ -2109,10 +1879,8 @@ gegl_sampler_nohalo_get (      GeglSampler*    restrict  self,
            * Storage for the EWA contribution:
            */
           gfloat ewa_newval[channels];
-          ewa_newval[0] = (gfloat) 0;
-          ewa_newval[1] = (gfloat) 0;
-          ewa_newval[2] = (gfloat) 0;
-          ewa_newval[3] = (gfloat) 0;
+          for (gint c = 0; c < channels; c++)
+            ewa_newval[c] = (gfloat) 0;
 
           {
             gint i = out_top_0;
@@ -2143,10 +1911,8 @@ gegl_sampler_nohalo_get (      GeglSampler*    restrict  self,
                */
               const gfloat beta =
                 (gfloat) ( ( (gdouble) 1.0 - theta ) / total_weight );
-              newval[0] = theta * newval[0] + beta * ewa_newval[0];
-              newval[1] = theta * newval[1] + beta * ewa_newval[1];
-              newval[2] = theta * newval[2] + beta * ewa_newval[2];
-              newval[3] = theta * newval[3] + beta * ewa_newval[3];
+              for (gint c = 0; c < channels; c++)
+                newval[c] = theta * newval[c] + beta * ewa_newval[c];
             }
           }
         }
diff --git a/gegl/buffer/gegl-sampler.c b/gegl/buffer/gegl-sampler.c
index 89e7ddeb8..fd7d52b02 100644
--- a/gegl/buffer/gegl-sampler.c
+++ b/gegl/buffer/gegl-sampler.c
@@ -135,7 +135,7 @@ gegl_sampler_init (GeglSampler *sampler)
 
   sampler->level[0].sampler_buffer =
     g_malloc (GEGL_SAMPLER_MAXIMUM_WIDTH *
-              GEGL_SAMPLER_MAXIMUM_HEIGHT * GEGL_SAMPLER_BPP);
+              GEGL_SAMPLER_MAXIMUM_HEIGHT * 5 * 4); // XXX : maxes out at 5 components
 }
 
 static void
@@ -192,8 +192,46 @@ gegl_sampler_prepare (GeglSampler *self)
   if (klass->prepare)
     klass->prepare (self);
 
-  self->interpolate_format = babl_format_with_space ("RaGaBaA float",
-                                         gegl_buffer_get_format(self->buffer));
+  {
+    const Babl *model = babl_format_get_model (gegl_buffer_get_format (self->buffer));
+
+    if (babl_model_is (model, "Y")||
+        babl_model_is (model, "Y'")||
+        babl_model_is (model, "Y~")||
+        babl_model_is (model, "YA")||
+        babl_model_is (model, "YaA")||
+        babl_model_is (model, "Y'aA")||
+        babl_model_is (model, "Y'A")||
+        babl_model_is (model, "Y~A"))
+    {
+       self->interpolate_format = babl_format_with_space ("YaA float",
+                                     gegl_buffer_get_format(self->buffer));
+    }
+#if 0
+    else if (babl_model_is (model, "RGB")||
+        babl_model_is (model, "R'G'B'")||
+        babl_model_is (model, "R~G~B~") ||
+        babl_model_is (model, "RGBA")||
+        babl_model_is (model, "R'G'B'A")||
+        babl_model_is (model, "R~G~B~A")||
+        babl_model_is (model, "RaGaBaA")||
+        babl_model_is (model, "R'aG'aB'aA")||
+        babl_model_is (model, "R~aG~aB~aA"))
+    {
+       self->interpolate_format = babl_format_with_space ("RaGaBaA float",
+                                     gegl_buffer_get_format(self->buffer));
+    }
+#endif
+    else
+    {
+       self->interpolate_format = babl_format_with_space ("RaGaBaA float",
+                                     gegl_buffer_get_format(self->buffer));
+    }
+
+    self->interpolate_bpp = babl_format_get_bytes_per_pixel (self->interpolate_format);
+    self->interpolate_components = babl_format_get_n_components (self->interpolate_format);
+  }
+
   if (!self->fish)
     self->fish = babl_fish (self->interpolate_format, self->format);
 
@@ -203,7 +241,6 @@ gegl_sampler_prepare (GeglSampler *self)
    */
   self->level[0].sampler_rectangle.width = 0;
   self->level[0].sampler_rectangle.height = 0;
-
 }
 
 void
@@ -292,21 +329,21 @@ gegl_sampler_get_from_mipmap (GeglSampler    *sampler,
                                                                   level_no);
       if (!level->sampler_buffer)
         level->sampler_buffer =
-          g_malloc (GEGL_SAMPLER_ROWSTRIDE * GEGL_SAMPLER_MAXIMUM_HEIGHT);
+          g_malloc (GEGL_SAMPLER_MAXIMUM_WIDTH * sampler->interpolate_bpp * GEGL_SAMPLER_MAXIMUM_HEIGHT);
 
       gegl_buffer_get (sampler->buffer,
                        &level->sampler_rectangle,
                        scale,
                        sampler->interpolate_format,
                        level->sampler_buffer,
-                       GEGL_SAMPLER_ROWSTRIDE,
+                       GEGL_SAMPLER_MAXIMUM_WIDTH * sampler->interpolate_bpp,
                        repeat_mode);
     }
 
   dx         = x - level->sampler_rectangle.x;
   dy         = y - level->sampler_rectangle.y;
   buffer_ptr = (guchar *) level->sampler_buffer;
-  sof        = (dx + dy * GEGL_SAMPLER_MAXIMUM_WIDTH) * GEGL_SAMPLER_BPP;
+  sof        = (dx + dy * GEGL_SAMPLER_MAXIMUM_WIDTH) * sampler->interpolate_bpp;
 
   return (gfloat*) (buffer_ptr + sof);
 }
diff --git a/gegl/buffer/gegl-sampler.h b/gegl/buffer/gegl-sampler.h
index ea86eb5ee..a3f11bbe2 100644
--- a/gegl/buffer/gegl-sampler.h
+++ b/gegl/buffer/gegl-sampler.h
@@ -43,8 +43,6 @@ G_BEGIN_DECLS
 
 #define GEGL_SAMPLER_MAXIMUM_HEIGHT 64
 #define GEGL_SAMPLER_MAXIMUM_WIDTH (GEGL_SAMPLER_MAXIMUM_HEIGHT)
-#define GEGL_SAMPLER_BPP 16
-#define GEGL_SAMPLER_ROWSTRIDE (GEGL_SAMPLER_MAXIMUM_WIDTH * GEGL_SAMPLER_BPP)
 
 typedef struct _GeglSamplerClass GeglSamplerClass;
 
@@ -70,6 +68,8 @@ struct _GeglSampler
   const Babl        *format;
   const Babl        *interpolate_format;
   const Babl        *fish;
+  gint               interpolate_bpp;
+  gint               interpolate_components;
   GeglSampler       *point_sampler;
   GeglSamplerGetFun  point_sampler_get_fun;
 
@@ -196,7 +196,7 @@ gegl_sampler_get_ptr (GeglSampler    *sampler,
                        1.0,
                        sampler->interpolate_format,
                        level->sampler_buffer,
-                       GEGL_SAMPLER_MAXIMUM_WIDTH * GEGL_SAMPLER_BPP,
+                       GEGL_SAMPLER_MAXIMUM_WIDTH * sampler->interpolate_bpp,
                        repeat_mode);
       level->last_x = x;
       level->last_y = y;
@@ -206,7 +206,7 @@ gegl_sampler_get_ptr (GeglSampler    *sampler,
 
   dx         = x - level->sampler_rectangle.x;
   dy         = y - level->sampler_rectangle.y;
-  sof        = (dx + dy * GEGL_SAMPLER_MAXIMUM_WIDTH) * GEGL_SAMPLER_BPP;
+  sof        = (dx + dy * GEGL_SAMPLER_MAXIMUM_WIDTH) * sampler->interpolate_bpp;
   buffer_ptr = (guchar *) level->sampler_buffer;
 
   delta_x = level->last_x - x;
@@ -229,11 +229,15 @@ _gegl_sampler_box_get (GeglSampler*    restrict  self,
                        GeglSamplerType           point_sampler_type,
                        gint                      n_samples)
 {
+  gint channels = self->interpolate_components;
   if (scale && fabs (gegl_buffer_matrix2_determinant (scale)) >= 4.0)
     {
-      gfloat  result[4] = {0,0,0,0};
+      gfloat  result[channels];
       gdouble uv_samples_inv;
 
+      for (gint c = 0; c < channels; c++)
+        result[c] = 0.0f;
+
       if (! self->point_sampler)
         {
           self->point_sampler = gegl_buffer_sampler_new (self->buffer,
@@ -315,10 +319,10 @@ _gegl_sampler_box_get (GeglSampler*    restrict  self,
               for (u = 0; u < u_samples; u++)
                 {
                   int c;
-                  gfloat input[4];
+                  gfloat input[channels];
                   self->point_sampler_get_fun (self->point_sampler,
                                                x, y, NULL, input, repeat_mode);
-                  for (c = 0; c < 4; c++)
+                  for (c = 0; c < channels; c++)
                     result[c] += input[c];
 
                   x += u_dx;
@@ -330,10 +334,8 @@ _gegl_sampler_box_get (GeglSampler*    restrict  self,
             }
         }
 
-      result[0] *= uv_samples_inv;
-      result[1] *= uv_samples_inv;
-      result[2] *= uv_samples_inv;
-      result[3] *= uv_samples_inv;
+      for (gint c = 0; c < channels; c++)
+        result[c] *= uv_samples_inv;
 
       babl_process (self->fish, result, output, 1);
 



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