[gegl] operations: some love to gegl:color-reduction



commit 89f61ba63a7a9e8e7e2fdde17124e824e47a0df5
Author: Téo Mazars <teomazars gmail com>
Date:   Wed Dec 4 10:42:06 2013 +0100

    operations: some love to gegl:color-reduction
    
    - use GeglRandom instead of a custom random number generator
    - use GeglBufferIterator where possible instead of buffer_get/set
    - allow the input to be precessed by chunk when possible
    - try to avoid code duplication (still not perfect)
    - tons of indentation and format fixes (sorry for the diff :/)
    
    the behavior is unchanged (minus the use of GeglRandom)

 operations/common/color-reduction.c |  614 +++++++++++++++--------------------
 1 files changed, 267 insertions(+), 347 deletions(-)
---
diff --git a/operations/common/color-reduction.c b/operations/common/color-reduction.c
index 7d3aefb..7975e4a 100644
--- a/operations/common/color-reduction.c
+++ b/operations/common/color-reduction.c
@@ -24,7 +24,7 @@
 #ifdef GEGL_CHANT_PROPERTIES
 
 gegl_chant_register_enum (gegl_dither_strategy)
-  enum_value (GEGL_DITHER_NONE,   "None")
+  enum_value (GEGL_DITHER_NONE, "None")
   enum_value (GEGL_DITHER_RANDOM, "Random")
   enum_value (GEGL_DITHER_RESILIENT, "Resilient")
   enum_value (GEGL_DITHER_RANDOM_COVARIANT, "Random Covariant")
@@ -52,13 +52,18 @@ gegl_chant_enum (dither_strategy, _("Dithering Strategy"),
                  GeglDitherStrategy, gegl_dither_strategy, GEGL_DITHER_RESILIENT,
                  _("The dithering strategy to use"))
 
+gegl_chant_seed (seed, rand, _("Seed"),
+                 _("Random seed"))
+
 #else
 
 #define GEGL_CHANT_TYPE_FILTER
-#define GEGL_CHANT_C_FILE       "color-reduction.c"
+#define GEGL_CHANT_C_FILE "color-reduction.c"
 
 #include "gegl-chant.h"
 
+#define REDUCE_16B(value) (((value) & ((1 << 17) - 1)) - 65536)
+
 static void
 prepare (GeglOperation *operation)
 {
@@ -67,7 +72,8 @@ prepare (GeglOperation *operation)
 }
 
 static void
-generate_channel_masks (guint *channel_bits, guint *channel_mask)
+generate_channel_masks (guint *channel_bits,
+                        guint *channel_mask)
 {
   gint i;
 
@@ -76,7 +82,9 @@ generate_channel_masks (guint *channel_bits, guint *channel_mask)
 }
 
 static guint
-quantize_value (guint value, guint n_bits, guint mask)
+quantize_value (guint value,
+                guint n_bits,
+                guint mask)
 {
   gint i;
 
@@ -88,42 +96,17 @@ quantize_value (guint value, guint n_bits, guint mask)
   return value;
 }
 
-static gint
-fast_random_int (void)
-{
-  #define PRIME1 2713
-  #define PRIME2 1913
-  static gboolean inited = 0;
-  static int rand1[PRIME1];
-  static int rand2[PRIME2];
-  static int r1, r2;
-  int ret;
-  if (G_UNLIKELY (!inited))
-    {
-       for (r1 = 0; r1 < PRIME1; r1++)
-         rand1[r1] = g_random_int ();
-       for (r2 = 0; r2 < PRIME2; r2++)
-         rand2[r2] = g_random_int ();
-       inited = TRUE;
-    }
-  ret = ((rand1[(r1++) % PRIME1] + rand2[(r2++) % PRIME2]));
-  ret &= ((1 << 17)-1);
-  ret -= 65536;
-  return ret;
-}
-
-
 static void
-process_floyd_steinberg (GeglBuffer *input,
-                         GeglBuffer *output,
+process_floyd_steinberg (GeglBuffer          *input,
+                         GeglBuffer          *output,
                          const GeglRectangle *result,
-                         guint *channel_bits)
+                         guint               *channel_bits)
 {
-  GeglRectangle        line_rect;
-  guint16             *line_buf;
-  gdouble             *error_buf [2];
-  guint                channel_mask [4];
-  gint                 y;
+  GeglRectangle  line_rect;
+  guint16       *line_buf;
+  gdouble       *error_buf [2];
+  guint          channel_mask [4];
+  gint           y;
 
   line_rect.x      = result->x;
   line_rect.y      = result->y;
@@ -137,86 +120,86 @@ process_floyd_steinberg (GeglBuffer *input,
   generate_channel_masks (channel_bits, channel_mask);
 
   for (y = 0; y < result->height; y++)
-  {
-    gdouble  *error_buf_swap;
-    gint      step;
-    gint      start_x;
-    gint      end_x;
-    gint      x;
-
-    /* Serpentine scanning; reverse direction every row */
-
-    if (y & 1)
-    {
-      start_x = result->width - 1;
-      end_x   = -1;
-      step    = -1;
-    }
-    else
-    {
-      start_x = 0;
-      end_x   = result->width;
-      step    = 1;
-    }
-
-    /* Pull input row */
-
-    gegl_buffer_get (input, &line_rect, 1.0, babl_format ("R'G'B'A u16"), line_buf,
-                     GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-
-    /* Process the row */
-
-    for (x = start_x; x != end_x; x += step)
     {
-      guint16  *pixel = &line_buf [x * 4];
-      guint     ch;
+      gdouble  *error_buf_swap;
+      gint      step;
+      gint      start_x;
+      gint      end_x;
+      gint      x;
 
-      for (ch = 0; ch < 4; ch++)
-      {
-        gdouble value;
-        gdouble value_clamped;
-        gdouble quantized;
-        gdouble qerror;
-
-        value         = pixel [ch] + error_buf [0] [x * 4 + ch];
-        value_clamped = CLAMP (value, 0.0, 65535.0);
-        quantized     = quantize_value ((guint) (value_clamped + 0.5), channel_bits [ch], channel_mask [ch]);
-        qerror        = value - quantized;
+      /* Serpentine scanning; reverse direction every row */
 
-        pixel [ch] = (guint16) quantized;
+      if (y & 1)
+        {
+          start_x = result->width - 1;
+          end_x   = -1;
+          step    = -1;
+        }
+      else
+        {
+          start_x = 0;
+          end_x   = result->width;
+          step    = 1;
+        }
 
-        /* Distribute the error */
+      /* Pull input row */
 
-        error_buf [1] [x * 4 + ch] += qerror * 5.0 / 16.0;  /* Down */
+      gegl_buffer_get (input, &line_rect, 1.0, babl_format ("R'G'B'A u16"), line_buf,
+                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
 
-        if (x + step >= 0 && x + step < result->width)
-        {
-          error_buf [0] [(x + step) * 4 + ch] += qerror * 6.0 / 16.0;  /* Ahead */
-          error_buf [1] [(x + step) * 4 + ch] += qerror * 1.0 / 16.0;  /* Down, ahead */
-        }
+      /* Process the row */
 
-        if (x - step >= 0 && x - step < result->width)
+      for (x = start_x; x != end_x; x += step)
         {
-          error_buf [1] [(x - step) * 4 + ch] += qerror * 3.0 / 16.0;  /* Down, behind */
+          guint16  *pixel = &line_buf [x * 4];
+          guint     ch;
+
+          for (ch = 0; ch < 4; ch++)
+            {
+              gdouble value;
+              gdouble value_clamped;
+              gdouble quantized;
+              gdouble qerror;
+
+              value         = pixel [ch] + error_buf [0] [x * 4 + ch];
+              value_clamped = CLAMP (value, 0.0, 65535.0);
+              quantized     = quantize_value ((guint) (value_clamped + 0.5), channel_bits [ch], channel_mask 
[ch]);
+              qerror        = value - quantized;
+
+              pixel [ch] = (guint16) quantized;
+
+              /* Distribute the error */
+
+              error_buf [1] [x * 4 + ch] += qerror * 5.0 / 16.0;  /* Down */
+
+              if (x + step >= 0 && x + step < result->width)
+                {
+                  error_buf [0] [(x + step) * 4 + ch] += qerror * 6.0 / 16.0;  /* Ahead */
+                  error_buf [1] [(x + step) * 4 + ch] += qerror * 1.0 / 16.0;  /* Down, ahead */
+                }
+
+              if (x - step >= 0 && x - step < result->width)
+                {
+                  error_buf [1] [(x - step) * 4 + ch] += qerror * 3.0 / 16.0;  /* Down, behind */
+                }
+            }
         }
-      }
-    }
 
-    /* Swap error accumulation rows */
+      /* Swap error accumulation rows */
 
-    error_buf_swap = error_buf [0];
-    error_buf [0]  = error_buf [1];
-    error_buf [1]  = error_buf_swap;
+      error_buf_swap = error_buf [0];
+      error_buf [0]  = error_buf [1];
+      error_buf [1]  = error_buf_swap;
 
-    /* Clear error buffer for next-plus-one line */
+      /* Clear error buffer for next-plus-one line */
 
-    memset (error_buf [1], 0, line_rect.width * 4 * sizeof (gdouble));
+      memset (error_buf [1], 0, line_rect.width * 4 * sizeof (gdouble));
 
-    /* Push output row */
+      /* Push output row */
 
-    gegl_buffer_set (output, &line_rect, 0, babl_format ("R'G'B'A u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
-    line_rect.y++;
-  }
+      gegl_buffer_set (output, &line_rect, 0, babl_format ("R'G'B'A u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
+      line_rect.y++;
+    }
 
   g_free (line_buf);
   g_free (error_buf [0]);
@@ -236,278 +219,235 @@ static const gdouble bayer_matrix_8x8 [] =
 };
 
 static void
-process_bayer (GeglBuffer *input,
-               GeglBuffer *output,
-               const GeglRectangle *result,
-               guint *channel_bits)
+process_row_bayer (GeglBufferIterator *gi,
+                   guint               channel_mask [4],
+                   guint               channel_bits [4],
+                   gint                y)
 {
-  GeglRectangle        line_rect;
-  guint16             *line_buf;
-  guint                channel_mask [4];
-  guint                y;
-
-  line_rect.x = result->x;
-  line_rect.y = result->y;
-  line_rect.width = result->width;
-  line_rect.height = 1;
-
-  line_buf = g_new (guint16, line_rect.width * 4);
-
-  generate_channel_masks (channel_bits, channel_mask);
-
-  for (y = 0; y < result->height; y++)
-  {
-    guint x;
-
-    gegl_buffer_get (input, &line_rect, 1.0, babl_format ("R'G'B'A u16"), line_buf,
-                     GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-
-    for (x = 0; x < result->width; x++)
+  guint16 *data_in  = (guint16*) gi->data [0];
+  guint16 *data_out = (guint16*) gi->data [1];
+  guint x;
+  for (x = 0; x < gi->roi->width; x++)
     {
-      guint16 *pixel = &line_buf [x * 4];
-      guint    ch;
+      guint pixel = 4 * (gi->roi->width * y + x);
+      guint ch;
 
       for (ch = 0; ch < 4; ch++)
-      {
-        gdouble value;
-        gdouble value_clamped;
-        gdouble quantized;
-
-        value         = pixel [ch] + ((bayer_matrix_8x8 [(y % 8) * 8 + (x % 8)] - 32) * 65536.0 / 65.0) / (1 
<< (channel_bits [ch] - 1));
-        value_clamped = CLAMP (value, 0.0, 65535.0);
-        quantized     = quantize_value ((guint) (value_clamped + 0.5), channel_bits [ch], channel_mask [ch]);
-
-        pixel [ch] = (guint16) quantized;
-      }
+        {
+          gdouble bayer;
+          gdouble value;
+          gdouble value_clamped;
+          gdouble quantized;
+
+          bayer         = bayer_matrix_8x8 [((gi->roi->y + y) % 8) * 8 + ((gi->roi->x + x) % 8)];
+          bayer         = ((bayer - 32) * 65536.0 / 65.0) / (1 << (channel_bits [ch] - 1));
+          value         = data_in [pixel + ch] + bayer;
+          value_clamped = CLAMP (value, 0.0, 65535.0);
+          quantized     = quantize_value ((guint) (value_clamped + 0.5),
+                                          channel_bits [ch],
+                                          channel_mask [ch]);
+
+          data_out [pixel + ch] = (guint16) quantized;
+        }
     }
-
-    gegl_buffer_set (output, &line_rect, 0, babl_format ("R'G'B'A u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
-    line_rect.y++;
-  }
-
-  g_free (line_buf);
 }
 
 static void
-process_random_covariant (GeglBuffer *input,
-                          GeglBuffer *output,
-                          const GeglRectangle *result,
-                          guint *channel_bits)
+process_row_random_covariant (GeglBufferIterator *gi,
+                              guint               channel_mask [4],
+                              guint               channel_bits [4],
+                              gint                y,
+                              GeglRandom         *rand)
 {
-  GeglRectangle        line_rect;
-  guint16             *line_buf;
-  guint                channel_mask [4];
-  guint                y;
-
-  line_rect.x = result->x;
-  line_rect.y = result->y;
-  line_rect.width = result->width;
-  line_rect.height = 1;
-
-  line_buf = g_new (guint16, line_rect.width * 4);
-
-  generate_channel_masks (channel_bits, channel_mask);
-
-  for (y = 0; y < result->height; y++)
-  {
-    guint x;
-
-    gegl_buffer_get (input, &line_rect, 1.0, babl_format ("R'G'B'A u16"), line_buf,
-                     GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-
-    for (x = 0; x < result->width; x++)
+  guint16 *data_in  = (guint16*) gi->data [0];
+  guint16 *data_out = (guint16*) gi->data [1];
+  guint x;
+  for (x = 0; x < gi->roi->width; x++)
     {
-      guint16 *pixel = &line_buf [x * 4];
-      guint    ch;
-      gint     r = fast_random_int ();
-
+      guint pixel = 4 * (gi->roi->width * y + x);
+      guint ch;
+      gint  r = REDUCE_16B (gegl_random_int (rand, gi->roi->x + x,
+                                             gi->roi->y + y, 0, 0));
       for (ch = 0; ch < 4; ch++)
-      {
-        gdouble value;
-        gdouble value_clamped;
-        gdouble quantized;
+        {
+          gdouble value;
+          gdouble value_clamped;
+          gdouble quantized;
 
-        value         = pixel [ch] + (r / (1 << channel_bits [ch]));
-        value_clamped = CLAMP (value, 0.0, 65535.0);
-        quantized     = quantize_value ((guint) (value_clamped + 0.5), channel_bits [ch], channel_mask [ch]);
+          value         = data_in [pixel + ch] + (r / (1 << channel_bits [ch]));
+          value_clamped = CLAMP (value, 0.0, 65535.0);
+          quantized     = quantize_value ((guint) (value_clamped + 0.5),
+                                          channel_bits [ch],
+                                          channel_mask [ch]);
 
-        pixel [ch] = (guint16) quantized;
-      }
+          data_out [pixel + ch] = (guint16) quantized;
+        }
     }
-
-    gegl_buffer_set (output, &line_rect, 0, babl_format ("R'G'B'A u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
-    line_rect.y++;
-  }
-
-  g_free (line_buf);
 }
 
 static void
-process_random (GeglBuffer *input,
-                GeglBuffer *output,
-                const GeglRectangle *result,
-                guint *channel_bits)
+process_row_random (GeglBufferIterator *gi,
+                    guint               channel_mask [4],
+                    guint               channel_bits [4],
+                    gint                y,
+                    GeglRandom         *rand)
 {
-  GeglRectangle        line_rect;
-  guint16             *line_buf;
-  guint                channel_mask [4];
-  guint                y;
-
-  line_rect.x = result->x;
-  line_rect.y = result->y;
-  line_rect.width = result->width;
-  line_rect.height = 1;
-
-  line_buf = g_new (guint16, line_rect.width * 4);
-
-  generate_channel_masks (channel_bits, channel_mask);
-
-  for (y = 0; y < result->height; y++)
-  {
-    guint x;
-
-    gegl_buffer_get (input, &line_rect, 1.0, babl_format ("R'G'B'A u16"), line_buf,
-                     GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-
-    for (x = 0; x < result->width; x++)
+  guint16 *data_in  = (guint16*) gi->data [0];
+  guint16 *data_out = (guint16*) gi->data [1];
+  guint x;
+  for (x = 0; x < gi->roi->width; x++)
     {
-      guint16 *pixel = &line_buf [x * 4];
-      guint    ch;
-
+      guint pixel = 4 * (gi->roi->width * y + x);
+      guint ch;
       for (ch = 0; ch < 4; ch++)
-      {
-        gdouble value;
-        gdouble value_clamped;
-        gdouble quantized;
-
-        value         = pixel [ch] + (fast_random_int () / (1 << channel_bits [ch]));
-        value_clamped = CLAMP (value, 0.0, 65535.0);
-        quantized     = quantize_value ((guint) (value_clamped + 0.5), channel_bits [ch], channel_mask [ch]);
-
-        pixel [ch] = (guint16) quantized;
-      }
+        {
+          gdouble value;
+          gdouble value_clamped;
+          gdouble quantized;
+          gint    r = REDUCE_16B (gegl_random_int (rand, gi->roi->x + x,
+                                                   gi->roi->y + y, 0, ch));
+
+          value         = data_in [pixel + ch] + (r / (1 << channel_bits [ch]));
+          value_clamped = CLAMP (value, 0.0, 65535.0);
+          quantized     = quantize_value ((guint) (value_clamped + 0.5),
+                                          channel_bits [ch],
+                                          channel_mask [ch]);
+
+          data_out [pixel + ch] = (guint16) quantized;
+        }
     }
-
-    gegl_buffer_set (output, &line_rect, 0, babl_format ("R'G'B'A u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
-    line_rect.y++;
-  }
-
-  g_free (line_buf);
 }
 
 static void
-process_resilient (GeglBuffer *input,
-                   GeglBuffer *output,
-                   const GeglRectangle *result,
-                   guint *channel_bits)
+process_row_resilient (GeglBufferIterator *gi,
+                       guint               channel_mask [4],
+                       guint               channel_bits [4],
+                       gint                y,
+                       GeglRandom         *rand)
 {
-  GeglRectangle        line_rect;
-  guint16             *line_buf;
-  guint                channel_mask [4];
-  guint                y;
-
-  line_rect.x = result->x;
-  line_rect.y = result->y;
-  line_rect.width = result->width;
-  line_rect.height = 1;
-
-  line_buf = g_new (guint16, line_rect.width * 4);
-
-  generate_channel_masks (channel_bits, channel_mask);
-
-  for (y = 0; y < result->height; y++)
-  {
-    guint x;
-
-    gegl_buffer_get (input, &line_rect, 1.0, babl_format ("R'G'B'A u16"), line_buf,
-                     GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-
-    for (x = 0; x < result->width; x++)
+  guint16 *data_in  = (guint16*) gi->data [0];
+  guint16 *data_out = (guint16*) gi->data [1];
+  guint    x;
+  for (x = 0; x < gi->roi->width; x++)
     {
-      guint16 *pixel = &line_buf [x * 4];
-      guint    ch;
-
+      guint pixel = 4 * (gi->roi->width * y + x);
+      guint ch;
       for (ch = 0; ch < 4; ch++)
-      {
-        gdouble value;
-        gdouble value_clamped;
-        gdouble quantized;
-
-        value         = pixel [ch] + 
-        (1.0/(((pixel[ch]+6*65535)/65535.0))/8 + 1.2) *(fast_random_int () / (1 << channel_bits [ch]));
-
-        value_clamped = CLAMP (value, 0.0, 65535.0);
-        quantized     = quantize_value ((guint) (value_clamped + 0.5), channel_bits [ch], channel_mask [ch]);
-
-        pixel [ch] = (guint16) quantized;
-      }
+        {
+          gdouble value;
+          gdouble value_clamped;
+          gdouble quantized;
+          gint    r = REDUCE_16B (gegl_random_int (rand, gi->roi->x + x,
+                                                   gi->roi->y + y, 0, ch));
+          value         = data_in [pixel + ch];
+          value         = value + ((65535.0 / (8 * value + 48 * 65535)) + 1.2) *
+                                  (r / (1 << channel_bits [ch]));
+          value_clamped = CLAMP (value, 0.0, 65535.0);
+          quantized     = quantize_value ((guint) (value_clamped + 0.5),
+                                          channel_bits [ch],
+                                          channel_mask [ch]);
+
+          data_out [pixel + ch] = (guint16) quantized;
+        }
     }
-
-    gegl_buffer_set (output, &line_rect, 0, babl_format ("R'G'B'A u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
-    line_rect.y++;
-  }
-
-  g_free (line_buf);
 }
 
 static void
-process_no_dither (GeglBuffer *input,
-                   GeglBuffer *output,
-                   const GeglRectangle *result,
-                   guint *channel_bits)
+process_row_no_dither (GeglBufferIterator *gi,
+                       guint               channel_mask [4],
+                       guint               channel_bits [4],
+                       guint               y)
 {
-  GeglRectangle        line_rect;
-  guint16             *line_buf;
-  guint                channel_mask [4];
-  guint                y;
-
-  line_rect.x = result->x;
-  line_rect.y = result->y;
-  line_rect.width = result->width;
-  line_rect.height = 1;
+  guint16 *data_in  = (guint16*) gi->data [0];
+  guint16 *data_out = (guint16*) gi->data [1];
+  guint x;
+  for (x = 0; x < gi->roi->width; x++)
+    {
+      guint pixel = 4 * (gi->roi->width * y + x);
+      guint ch;
+      for (ch = 0; ch < 4; ch++)
+        {
+          data_out [pixel + ch] = (guint16) quantize_value (data_in [pixel + ch],
+                                                            channel_bits [ch],
+                                                            channel_mask [ch]);
+        }
+    }
+}
 
-  line_buf = g_new (guint16, line_rect.width * 4);
+static void
+process_standard (GeglBuffer          *input,
+                  GeglBuffer          *output,
+                  const GeglRectangle *result,
+                  guint               *channel_bits,
+                  GeglRandom          *rand,
+                  GeglDitherStrategy   dither_strategy)
+{
+  GeglBufferIterator *gi;
+  guint               channel_mask [4];
 
   generate_channel_masks (channel_bits, channel_mask);
 
-  for (y = 0; y < result->height; y++)
-  {
-    guint x;
+  gi = gegl_buffer_iterator_new (input, result, 0, babl_format ("R'G'B'A u16"),
+                                 GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
 
-    gegl_buffer_get (input, &line_rect, 1.0, babl_format ("R'G'B'A u16"), line_buf,
-                     GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+  gegl_buffer_iterator_add (gi, output, result, 0, babl_format ("R'G'B'A u16"),
+                            GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);
 
-    for (x = 0; x < result->width; x++)
+  while (gegl_buffer_iterator_next (gi))
     {
-      guint16 *pixel = &line_buf [x * 4];
-      guint    ch;
-
-      for (ch = 0; ch < 4; ch++)
-      {
-        pixel [ch] = quantize_value (pixel [ch], channel_bits [ch], channel_mask [ch]);
-      }
+      guint    y;
+      for (y = 0; y < gi->roi->height; y++)
+        {
+          switch (dither_strategy)
+            {
+            case GEGL_DITHER_NONE:
+              process_row_no_dither (gi, channel_mask, channel_bits, y);
+              break;
+            case GEGL_DITHER_RANDOM:
+              process_row_random (gi, channel_mask, channel_bits, y, rand);
+              break;
+            case GEGL_DITHER_RESILIENT:
+              process_row_resilient (gi, channel_mask, channel_bits, y, rand);
+              break;
+            case GEGL_DITHER_RANDOM_COVARIANT:
+              process_row_random_covariant (gi, channel_mask, channel_bits, y, rand);
+              break;
+            case GEGL_DITHER_BAYER:
+              process_row_bayer (gi, channel_mask, channel_bits, y);
+              break;
+            case GEGL_DITHER_FLOYD_STEINBERG:
+              /* Done separately */
+              break;
+            default:
+              process_row_no_dither (gi, channel_mask, channel_bits, y);
+            }
+        }
     }
-
-    gegl_buffer_set (output, &line_rect, 0, babl_format ("R'G'B'A u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
-    line_rect.y++;
-  }
-
-  g_free (line_buf);
 }
 
 static GeglRectangle
-get_required_for_output (GeglOperation        *self,
+get_required_for_output (GeglOperation       *self,
                          const gchar         *input_pad,
                          const GeglRectangle *roi)
 {
-  return *gegl_operation_source_get_bounding_box (self, "input");
+  GeglChantO *o = GEGL_CHANT_PROPERTIES (self);
+
+  if (o->dither_strategy == GEGL_DITHER_FLOYD_STEINBERG)
+    return *gegl_operation_source_get_bounding_box (self, "input");
+  else
+    return *roi;
 }
 
 static GeglRectangle
 get_cached_region (GeglOperation       *self,
                    const GeglRectangle *roi)
 {
-  return *gegl_operation_source_get_bounding_box (self, "input");
+  GeglChantO *o = GEGL_CHANT_PROPERTIES (self);
+
+  if (o->dither_strategy == GEGL_DITHER_FLOYD_STEINBERG)
+    return *gegl_operation_source_get_bounding_box (self, "input");
+  else
+    return *roi;
 }
 
 static gboolean
@@ -525,31 +465,11 @@ process (GeglOperation       *operation,
   channel_bits [2] = o->blue_bits;
   channel_bits [3] = o->alpha_bits;
 
-  switch (o->dither_strategy)
-    {
-      case GEGL_DITHER_NONE:
-        process_no_dither (input, output, result, channel_bits);
-        break;
-      case GEGL_DITHER_RANDOM:
-        process_random (input, output, result, channel_bits);
-        break;
-      case GEGL_DITHER_RESILIENT:
-        process_resilient (input, output, result, channel_bits);
-        break;
-      case GEGL_DITHER_RANDOM_COVARIANT:
-        process_random_covariant (input, output, result,
-                                  channel_bits);
-        break;
-      case GEGL_DITHER_FLOYD_STEINBERG:
-        process_floyd_steinberg (input, output, result,
-                                 channel_bits);
-        break;
-      case GEGL_DITHER_BAYER:
-        process_bayer (input, output, result, channel_bits);
-        break;
-      default:
-        process_no_dither (input, output, result, channel_bits);
-    }
+  if (o->dither_strategy != GEGL_DITHER_FLOYD_STEINBERG)
+    process_standard (input, output, result, channel_bits,
+                      o->rand, o->dither_strategy);
+  else
+    process_floyd_steinberg (input, output, result, channel_bits);
 
   return TRUE;
 }


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