[gegl] color-reduction: add arithmetic dithers



commit e6fd6177a0d0c3ede8c96141fbb3066e2e32ddd6
Author: Øyvind Kolås <pippin gimp org>
Date:   Tue Sep 27 16:51:27 2016 +0200

    color-reduction: add arithmetic dithers
    
    Adds addition and xor based, with covariant variant implementations of the
    dithering methods described at http://pippin.gimp.org/a_dither/

 gegl/gegl-enums.c                   |    5 +
 gegl/gegl-enums.h                   |    6 +-
 operations/common/color-reduction.c |  159 ++++++++++++++++++++++++++++++++++-
 3 files changed, 165 insertions(+), 5 deletions(-)
---
diff --git a/gegl/gegl-enums.c b/gegl/gegl-enums.c
index 7dd4631..7e55c6f 100644
--- a/gegl/gegl-enums.c
+++ b/gegl/gegl-enums.c
@@ -90,6 +90,11 @@ gegl_dither_method_get_type (void)
         { GEGL_DITHER_RANDOM_COVARIANT, N_("Random Covariant"), "random-covariant" },
         { GEGL_DITHER_BAYER,            N_("Bayer"),            "bayer"            },
         { GEGL_DITHER_FLOYD_STEINBERG,  N_("Floyd-Steinberg"),  "floyd-steinberg"  },
+        { GEGL_DITHER_ARITHMETIC_ADD,   N_("Arithmetic-add"),  "add"  },
+        { GEGL_DITHER_ARITHMETIC_ADD_COVARIANT,   N_("Arithmetic-add-covariant"),  "add"  },
+        { GEGL_DITHER_ARITHMETIC_XOR,   N_("Arithmetic-xor"),  "xor"  },
+        { GEGL_DITHER_ARITHMETIC_XOR_COVARIANT,   N_("Arithmetic-xor-covariant"),  "xor"  },
+
         { 0, NULL, NULL }
       };
       gint i;
diff --git a/gegl/gegl-enums.h b/gegl/gegl-enums.h
index 3c08716..b669994 100644
--- a/gegl/gegl-enums.h
+++ b/gegl/gegl-enums.h
@@ -66,7 +66,11 @@ typedef enum {
   GEGL_DITHER_RESILIENT,
   GEGL_DITHER_RANDOM_COVARIANT,
   GEGL_DITHER_BAYER,
-  GEGL_DITHER_FLOYD_STEINBERG
+  GEGL_DITHER_FLOYD_STEINBERG,
+  GEGL_DITHER_ARITHMETIC_ADD,
+  GEGL_DITHER_ARITHMETIC_ADD_COVARIANT,
+  GEGL_DITHER_ARITHMETIC_XOR,
+  GEGL_DITHER_ARITHMETIC_XOR_COVARIANT,
 } GeglDitherMethod;
 
 GType gegl_dither_method_get_type (void) G_GNUC_CONST;
diff --git a/operations/common/color-reduction.c b/operations/common/color-reduction.c
index 8cd8109..f493efa 100644
--- a/operations/common/color-reduction.c
+++ b/operations/common/color-reduction.c
@@ -72,7 +72,7 @@ generate_channel_masks (guint *channel_bits,
     channel_mask [i] = ~((1 << (16 - channel_bits [i])) - 1);
 }
 
-static guint
+static inline guint
 quantize_value (guint value,
                 guint n_bits,
                 guint mask)
@@ -244,6 +244,145 @@ process_row_bayer (GeglBufferIterator *gi,
 }
 
 static void
+process_row_arithmetic_add (GeglBufferIterator *gi,
+                            guint               channel_mask [4],
+                            guint               channel_bits [4],
+                            gint                y)
+{
+  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++)
+        {
+          gint u = gi->roi->x + x;
+          gint v = gi->roi->y + y;
+          gfloat mask;
+          gfloat value;
+          gfloat value_clamped;
+          gfloat quantized;
+          mask         = (((u+ch * 67) + v * 236) * 119) & 255;
+          mask         = ((mask - 128) * 65536.0 / 256.0) / (1 << (channel_bits [ch] - 1));
+          value         = data_in [pixel + ch] + mask;
+          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;
+        }
+    }
+}
+
+static void
+process_row_arithmetic_xor (GeglBufferIterator *gi,
+                            guint               channel_mask [4],
+                            guint               channel_bits [4],
+                            gint                y)
+{
+  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++)
+        {
+          gint u = gi->roi->x + x;
+          gint v = gi->roi->y + y;
+          gfloat mask;
+          gfloat value;
+          gfloat value_clamped;
+          gfloat quantized;
+          mask         = (((u+ch * 17) ^ v * 149) * 1234) & 511;
+          mask         = ((mask - 257) * 65536.0 / 512.0) / (1 << (channel_bits [ch] - 1));
+          value         = data_in [pixel + ch] + mask;
+          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;
+        }
+    }
+}
+
+static void
+process_row_arithmetic_add_covariant (GeglBufferIterator *gi,
+                                      guint               channel_mask [4],
+                                      guint               channel_bits [4],
+                                      gint                y)
+{
+  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++)
+        {
+          gint u = gi->roi->x + x;
+          gint v = gi->roi->y + y;
+          gfloat mask;
+          gfloat value;
+          gfloat value_clamped;
+          gfloat quantized;
+          mask         = ((u+ v * 236) * 119) & 255;
+          mask         = ((mask - 128) * 65536.0 / 256.0) / (1 << (channel_bits [ch] - 1));
+          value         = data_in [pixel + ch] + mask;
+          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;
+        }
+    }
+}
+
+static void
+process_row_arithmetic_xor_covariant (GeglBufferIterator *gi,
+                                      guint               channel_mask [4],
+                                      guint               channel_bits [4],
+                                      gint                y)
+{
+  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++)
+        {
+          gint u = gi->roi->x + x;
+          gint v = gi->roi->y + y;
+          gfloat mask;
+          gfloat value;
+          gfloat value_clamped;
+          gfloat quantized;
+          mask         = ((u ^ v * 149) * 1234) & 511;
+          mask         = ((mask - 257) * 65536.0 / 512.0) / (1 << (channel_bits [ch] - 1));
+          value         = data_in [pixel + ch] + mask;
+          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;
+        }
+    }
+}
+static void
 process_row_random_covariant (GeglBufferIterator *gi,
                               guint               channel_mask [4],
                               guint               channel_bits [4],
@@ -261,9 +400,9 @@ process_row_random_covariant (GeglBufferIterator *gi,
                                              gi->roi->y + y, 0, 0));
       for (ch = 0; ch < 4; ch++)
         {
-          gdouble value;
-          gdouble value_clamped;
-          gdouble quantized;
+          gfloat value;
+          gfloat value_clamped;
+          gfloat quantized;
 
           value         = data_in [pixel + ch] + (r / (1 << channel_bits [ch]));
           value_clamped = CLAMP (value, 0.0, 65535.0);
@@ -409,6 +548,18 @@ process_standard (GeglBuffer          *input,
             case GEGL_DITHER_FLOYD_STEINBERG:
               /* Done separately */
               break;
+            case GEGL_DITHER_ARITHMETIC_ADD:
+              process_row_arithmetic_add (gi, channel_mask, channel_bits, y);
+              break;
+            case GEGL_DITHER_ARITHMETIC_XOR:
+              process_row_arithmetic_xor (gi, channel_mask, channel_bits, y);
+              break;
+            case GEGL_DITHER_ARITHMETIC_ADD_COVARIANT:
+              process_row_arithmetic_add_covariant (gi, channel_mask, channel_bits, y);
+              break;
+            case GEGL_DITHER_ARITHMETIC_XOR_COVARIANT:
+              process_row_arithmetic_xor_covariant (gi, channel_mask, channel_bits, y);
+              break;
             default:
               process_row_no_dither (gi, channel_mask, channel_bits, y);
             }


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