[gegl] operations: add gegl:color-enhance
- From: Thomas Manni <tmanni src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] operations: add gegl:color-enhance
- Date: Tue, 13 Jan 2015 19:15:17 +0000 (UTC)
commit 19f8868b50e336f0a3b8a05ee8c994f0a4eff18b
Author: Thomas Manni <thomas manni free fr>
Date: Tue Jan 13 20:00:00 2015 +0100
operations: add gegl:color-enhance
operations/common/Makefile.am | 1 +
operations/common/color-enhance.c | 242 ++++++++++++++++++++++++
po/POTFILES.in | 1 +
tests/compositions/Makefile.am | 1 +
tests/compositions/color-enhance.xml | 11 +
tests/compositions/reference/color-enhance.png | Bin 0 -> 140850 bytes
6 files changed, 256 insertions(+), 0 deletions(-)
---
diff --git a/operations/common/Makefile.am b/operations/common/Makefile.am
index 76839cb..2833161 100644
--- a/operations/common/Makefile.am
+++ b/operations/common/Makefile.am
@@ -24,6 +24,7 @@ op_LTLIBRARIES = \
cartoon.la \
channel-mixer.la \
checkerboard.la \
+ color-enhance.la \
color-exchange.la \
color-reduction.la \
color-rotate.la \
diff --git a/operations/common/color-enhance.c b/operations/common/color-enhance.c
new file mode 100644
index 0000000..ecd160f
--- /dev/null
+++ b/operations/common/color-enhance.c
@@ -0,0 +1,242 @@
+/* This file is an image processing operation for GEGL
+ *
+ * GEGL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * GEGL 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * This operation is inspired from the color enhance gimp plugin.
+ * It alters the chroma component to cover maximum possible range,
+ * keeping hue and lightness untouched.
+ *
+ * Thomas Manni <thomas manni free fr>
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+#include <math.h>
+
+#ifdef GEGL_PROPERTIES
+
+#else
+
+#define GEGL_OP_FILTER
+#define GEGL_OP_C_FILE "color-enhance.c"
+
+#include "gegl-op.h"
+
+static void
+buffer_get_min_max (GeglBuffer *buffer,
+ gdouble *min,
+ gdouble *max)
+{
+ GeglBufferIterator *gi;
+
+ gi = gegl_buffer_iterator_new (buffer, NULL, 0, babl_format ("CIE LCH(ab) float"),
+ GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
+
+ *min = G_MAXDOUBLE;
+ *max = -G_MAXDOUBLE;
+
+ while (gegl_buffer_iterator_next (gi))
+ {
+ gint o;
+ gfloat *buf = gi->data[0];
+
+ for (o = 0; o < gi->length; o++)
+ {
+ *min = MIN (buf[1], *min);
+ *max = MAX (buf[1], *max);
+ buf += 3;
+ }
+ }
+}
+
+static void prepare (GeglOperation *operation)
+{
+ const Babl *format;
+ const Babl *in_format = gegl_operation_get_source_format (operation, "input");
+
+ if (in_format)
+ {
+ if (babl_format_has_alpha (in_format))
+ format = babl_format ("CIE LCH(ab) alpha float");
+ else
+ format = babl_format ("CIE LCH(ab) float");
+ }
+ else
+ {
+ format = babl_format ("CIE LCH(ab) float");
+ }
+
+ gegl_operation_set_format (operation, "input", format);
+ gegl_operation_set_format (operation, "output", format);
+}
+
+static GeglRectangle
+get_required_for_output (GeglOperation *operation,
+ const gchar *input_pad,
+ const GeglRectangle *roi)
+{
+ GeglRectangle result = *gegl_operation_source_get_bounding_box (operation, "input");
+
+ /* Don't request an infinite plane */
+ if (gegl_rectangle_is_infinite_plane (&result))
+ return *roi;
+
+ return result;
+}
+
+static GeglRectangle
+get_cached_region (GeglOperation *operation,
+ const GeglRectangle *roi)
+{
+ GeglRectangle result = *gegl_operation_source_get_bounding_box (operation, "input");
+
+ if (gegl_rectangle_is_infinite_plane (&result))
+ return *roi;
+
+ return result;
+}
+
+
+static gboolean
+process (GeglOperation *operation,
+ GeglBuffer *input,
+ GeglBuffer *output,
+ const GeglRectangle *result,
+ gint level)
+{
+ const Babl *format = gegl_operation_get_format (operation, "output");
+ gboolean has_alpha = babl_format_has_alpha (format);
+ GeglBufferIterator *gi;
+ gdouble min;
+ gdouble max;
+ gdouble delta;
+
+ buffer_get_min_max (input, &min, &max);
+
+ gi = gegl_buffer_iterator_new (input, result, 0, format,
+ GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
+
+ gegl_buffer_iterator_add (gi, output, result, 0, format,
+ GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
+
+ delta = max - min;
+
+ if (! delta)
+ {
+ gegl_buffer_copy (input, NULL, output, NULL);
+ return TRUE;
+ }
+
+ if (has_alpha)
+ {
+ while (gegl_buffer_iterator_next (gi))
+ {
+ gfloat *in = gi->data[0];
+ gfloat *out = gi->data[1];
+
+ gint i;
+ for (i = 0; i < gi->length; i++)
+ {
+ out[0] = in[0];
+ out[1] = (in[1] - min) / delta * 100.0;
+ out[2] = in[2];
+ out[3] = in[3];
+
+ in += 4;
+ out += 4;
+ }
+ }
+ }
+ else
+ {
+ while (gegl_buffer_iterator_next (gi))
+ {
+ gfloat *in = gi->data[0];
+ gfloat *out = gi->data[1];
+
+ gint i;
+ for (i = 0; i < gi->length; i++)
+ {
+ out[0] = in[0];
+ out[1] = (in[1] - min) / delta * 100.0;
+ out[2] = in[2];
+
+ in += 3;
+ out += 3;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/* Pass-through when trying to perform a reduction on an infinite plane
+ */
+static gboolean
+operation_process (GeglOperation *operation,
+ GeglOperationContext *context,
+ const gchar *output_prop,
+ const GeglRectangle *result,
+ gint level)
+{
+ GeglOperationClass *operation_class;
+
+ const GeglRectangle *in_rect =
+ gegl_operation_source_get_bounding_box (operation, "input");
+
+ operation_class = GEGL_OPERATION_CLASS (gegl_op_parent_class);
+
+ if (in_rect && gegl_rectangle_is_infinite_plane (in_rect))
+ {
+ gpointer in = gegl_operation_context_get_object (context, "input");
+ gegl_operation_context_take_object (context, "output",
+ g_object_ref (G_OBJECT (in)));
+ return TRUE;
+ }
+
+ /* chain up, which will create the needed buffers for our actual
+ * process function
+ */
+ return operation_class->process (operation, context, output_prop, result,
+ gegl_operation_context_get_level (context));
+}
+
+static void
+gegl_op_class_init (GeglOpClass *klass)
+{
+ GeglOperationClass *operation_class;
+ GeglOperationFilterClass *filter_class;
+
+ operation_class = GEGL_OPERATION_CLASS (klass);
+ filter_class = GEGL_OPERATION_FILTER_CLASS (klass);
+
+ filter_class->process = process;
+
+ operation_class->prepare = prepare;
+ operation_class->process = operation_process;
+ operation_class->get_required_for_output = get_required_for_output;
+ operation_class->get_cached_region = get_cached_region;
+ operation_class->opencl_support = FALSE;
+
+ gegl_operation_class_set_keys (operation_class,
+ "name", "gegl:color-enhance",
+ "title", _("Color Enhance"),
+ "categories" , "color:enhance",
+ "description",
+ _("Stretch color chroma to cover maximum possible range, "
+ "keeping hue and lightness untouched."),
+ NULL);
+}
+
+#endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index bd011f6..3aa29ae 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -19,6 +19,7 @@ operations/common/cartoon.c
operations/common/channel-mixer.c
operations/common/checkerboard.c
operations/common/color.c
+operations/common/color-enhance.c
operations/common/color-exchange.c
operations/common/color-reduction.c
operations/common/color-rotate.c
diff --git a/tests/compositions/Makefile.am b/tests/compositions/Makefile.am
index cb21a1f..d7d65b9 100644
--- a/tests/compositions/Makefile.am
+++ b/tests/compositions/Makefile.am
@@ -21,6 +21,7 @@ TESTS = \
checkerboard.xml \
clones.xml \
colors.xml \
+ color-enhance.xml \
color-exchange.xml \
color-to-alpha.xml \
composite-transform.xml \
diff --git a/tests/compositions/color-enhance.xml b/tests/compositions/color-enhance.xml
new file mode 100644
index 0000000..76e79c7
--- /dev/null
+++ b/tests/compositions/color-enhance.xml
@@ -0,0 +1,11 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<gegl>
+ <node operation='gegl:color-enhance'>
+ </node>
+ <node operation='gegl:load'>
+ <params>
+ <param name='path'>data/parliament_0.png</param>
+ </params>
+ </node>
+</gegl>
+
diff --git a/tests/compositions/reference/color-enhance.png b/tests/compositions/reference/color-enhance.png
new file mode 100644
index 0000000..df0bc51
Binary files /dev/null and b/tests/compositions/reference/color-enhance.png differ
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]