[gegl] workshop: add bayer-matrix operation



commit b21539c7b2d3889d71d92109663bcd332ac7c0de
Author: Ell <ell_se yahoo com>
Date:   Sat Feb 4 15:31:19 2017 -0500

    workshop: add bayer-matrix operation
    
    Renders a Bayer matrix pattern.  Useful for ordered dithering.

 operations/workshop/Makefile.am    |    1 +
 operations/workshop/bayer-matrix.c |  259 ++++++++++++++++++++++++++++++++++++
 po/POTFILES.in                     |    1 +
 3 files changed, 261 insertions(+), 0 deletions(-)
---
diff --git a/operations/workshop/Makefile.am b/operations/workshop/Makefile.am
index d9d4215..8715aeb 100644
--- a/operations/workshop/Makefile.am
+++ b/operations/workshop/Makefile.am
@@ -12,6 +12,7 @@ LIBS = $(op_libs)
 
 opdir = $(ext_dir)
 op_LTLIBRARIES =    \
+       bayer-matrix.la \
        bilateral-filter-fast.la \
        demosaic-bimedian.la \
        demosaic-simple.la \
diff --git a/operations/workshop/bayer-matrix.c b/operations/workshop/bayer-matrix.c
new file mode 100644
index 0000000..04c18d1
--- /dev/null
+++ b/operations/workshop/bayer-matrix.c
@@ -0,0 +1,259 @@
+/* This file is an image processing operation for GEGL
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2017 Ell
+ *
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+#include <math.h>
+
+#ifdef GEGL_PROPERTIES
+
+property_int (subdivisions, _("Subdivisions"), 1)
+  description(_("Number of subdivisions"))
+  value_range (0, 15)
+
+enum_start (gegl_bayer_matrix_rotation)
+   enum_value (GEGL_BAYER_MATRIX_ROTATION_0,   "0",   N_("0°"))
+   enum_value (GEGL_BAYER_MATRIX_ROTATION_90,  "90",  N_("90°"))
+   enum_value (GEGL_BAYER_MATRIX_ROTATION_180, "180", N_("180°"))
+   enum_value (GEGL_BAYER_MATRIX_ROTATION_270, "270", N_("270°"))
+enum_end (GeglBayerMatrixRotation)
+
+property_enum (rotation, _("Rotation"),
+               GeglBayerMatrixRotation, gegl_bayer_matrix_rotation,
+               GEGL_BAYER_MATRIX_ROTATION_0)
+  description (_("Pattern rotation angle"))
+
+property_boolean (reflect, _("Reflect"), FALSE)
+  description(_("Reflect the pattern horizontally"))
+
+property_double (amplitude, _("Amplitude"), 0.5)
+  description(_("Pattern amplitude"))
+  value_range (-G_MAXDOUBLE, G_MAXDOUBLE)
+  ui_range    (0.0, 1.0)
+
+property_double (offset, _("Offset"), 0.5)
+  description(_("Value offset"))
+  value_range (-G_MAXDOUBLE, G_MAXDOUBLE)
+  ui_range    (0.0, 1.0)
+
+property_double  (exponent, _("Exponent"), 1.0)
+  description(_("Value exponent"))
+  value_range (0.0, G_MAXDOUBLE)
+  ui_range    (0.0, 10.0)
+
+property_int (x_offset, _("X Offset"), 0)
+  description (_("Offset for X axis"))
+  value_range (G_MININT, G_MAXINT)
+  ui_range    (10000, 10000)
+  ui_meta     ("unit", "pixel-coordinate")
+  ui_meta     ("axis", "x")
+
+property_int (y_offset, _("Y Offset"), 0)
+  description (_("Offset for Y axis"))
+  value_range (G_MININT, G_MAXINT)
+  ui_range    (10000, 10000)
+  ui_meta     ("unit", "pixel-coordinate")
+  ui_meta     ("axis", "y")
+
+#else
+
+#define GEGL_OP_POINT_RENDER
+#define GEGL_OP_NAME     bayer_matrix
+#define GEGL_OP_C_SOURCE bayer-matrix.c
+
+#include "gegl-op.h"
+#include <math.h>
+
+#define GEGL_BAYER_MATRIX_MAX_LUT_SUBDIVISIONS 8
+
+static void
+finalize (GObject *object)
+{
+  GeglOperation  *op = (void*) object;
+  GeglProperties *o  = GEGL_PROPERTIES (op);
+
+  if (o->user_data)
+    {
+      g_free (o->user_data);
+      o->user_data = NULL;
+    }
+
+  G_OBJECT_CLASS (gegl_op_parent_class)->finalize (object);
+}
+
+static gfloat
+value_at (GeglProperties *o,
+          gint            x,
+          gint            y)
+{
+  guint value = 0;
+
+  static const gint subdivision_value_luts[2][4][2][2] =
+    {
+      {
+        {{0, 2},
+         {3, 1}},
+
+        {{2, 1},
+         {0, 3}},
+
+         {{1, 3},
+          {2, 0}},
+
+         {{3, 0},
+          {1, 2}}
+      },
+
+      {
+        {{2, 0},
+         {1, 3}},
+
+        {{1, 2},
+         {3, 0}},
+
+         {{3, 1},
+          {0, 2}},
+
+         {{0, 3},
+          {2, 1}}
+      }
+    };
+  const gint (* subdivision_values)[2];
+
+  subdivision_values = subdivision_value_luts[o->reflect][o->rotation];
+
+  for (gint i = 0; i < o->subdivisions; i++)
+    {
+      value <<= 2;
+      value  |= subdivision_values[y & 1][x & 1];
+      x     >>= 1;
+      y     >>= 1;
+    }
+
+  return powf (o->offset - .5f +
+               2.f * o->amplitude * (value + .5f) / (1u << (2 * o->subdivisions)),
+               o->exponent);
+}
+
+static void
+prepare (GeglOperation *operation)
+{
+  GeglProperties *o = GEGL_PROPERTIES (operation);
+
+  if (o->subdivisions <= GEGL_BAYER_MATRIX_MAX_LUT_SUBDIVISIONS)
+    {
+      gint    size;
+      gint    x, y;
+      gfloat *lut;
+
+      size = 1 << o->subdivisions;
+
+      o->user_data = lut = g_renew (gfloat, o->user_data, size * size);
+
+      for (y = 0; y < size; y++)
+        {
+          for (x = 0; x < size; x++)
+            {
+              *lut++ = value_at (o, x, y);
+            }
+        }
+    }
+
+  gegl_operation_set_format (operation, "output", babl_format ("Y' float"));
+}
+
+static GeglRectangle
+get_bounding_box (GeglOperation *operation)
+{
+  return gegl_rectangle_infinite_plane ();
+}
+
+static gboolean
+process (GeglOperation       *operation,
+         void                *out_buf,
+         glong                n_pixels,
+         const GeglRectangle *roi,
+         gint                 level)
+{
+  GeglProperties *o      = GEGL_PROPERTIES (operation);
+  gint            i, j;
+  gfloat         *result = out_buf;
+  const gfloat   *lut    = NULL;
+  gint            size;
+  gint            coord_mask;
+
+  if (o->subdivisions <= GEGL_BAYER_MATRIX_MAX_LUT_SUBDIVISIONS)
+    lut = o->user_data;
+
+  size       = 1 << o->subdivisions;
+  coord_mask = size - 1;
+
+  for (j = 0; j < roi->height; j++)
+    {
+      gint y                = (j + roi->y - o->y_offset) & coord_mask;
+      const gfloat *lut_row = lut;
+
+      if (lut_row)
+        lut_row += size * y;
+
+      for (i = 0; i < roi->width; i++)
+        {
+          gint x = (i + roi->x - o->x_offset) & coord_mask;
+
+          if (lut_row)
+            *result = lut_row[x];
+          else
+            *result = value_at (o, x, y);
+
+          result++;
+        }
+    }
+
+  return TRUE;
+}
+
+static void
+gegl_op_class_init (GeglOpClass *klass)
+{
+  GObjectClass                  *object_class;
+  GeglOperationClass            *operation_class;
+  GeglOperationPointRenderClass *point_render_class;
+
+  object_class       = G_OBJECT_CLASS (klass);
+  operation_class    = GEGL_OPERATION_CLASS (klass);
+  point_render_class = GEGL_OPERATION_POINT_RENDER_CLASS (klass);
+
+  object_class->finalize = finalize;
+
+  point_render_class->process = process;
+
+  operation_class->get_bounding_box = get_bounding_box;
+  operation_class->prepare          = prepare;
+
+  gegl_operation_class_set_keys (operation_class,
+    "name",               "gegl:bayer-matrix",
+    "title",              _("Bayer Matrix"),
+    "categories",         "render",
+    "position-dependent", "true",
+    "license",            "GPL3+",
+    "description",        _("Generate a bayer matrix pattern"),
+    NULL);
+}
+
+#endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 489bc73..56a8fb2 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -226,6 +226,7 @@ operations/transform/shear.c
 operations/transform/transform.c
 operations/transform/transform-core.c
 operations/transform/translate.c
+operations/workshop/bayer-matrix.c
 operations/workshop/bilateral-filter-fast.c
 operations/workshop/demosaic-bimedian.c
 operations/workshop/demosaic-simple.c


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