[gegl] newsprint: new GEGL operation
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] newsprint: new GEGL operation
- Date: Thu, 23 Mar 2017 12:09:11 +0000 (UTC)
commit 30ca02a7ac35251643840bd594fd3467ba4bc47a
Author: Øyvind Kolås <pippin gimp org>
Date: Thu Mar 23 13:04:30 2017 +0100
newsprint: new GEGL operation
Reimplementation of scratch of most of the functionality of GIMPs newsprint
plug-in with additional color based modulation of halftoned results. More
documentation/exampels of this op will appear at
https://pippin.gimp.org/spachrotyzer/
operations/common/Makefile.am | 1 +
operations/common/newsprint.c | 347 +++++++++++++++++++++++++++++++++++++++++
po/POTFILES.in | 1 +
3 files changed, 349 insertions(+), 0 deletions(-)
---
diff --git a/operations/common/Makefile.am b/operations/common/Makefile.am
index bb8a312..1a661b6 100644
--- a/operations/common/Makefile.am
+++ b/operations/common/Makefile.am
@@ -94,6 +94,7 @@ gegl_common_la_SOURCES =\
motion-blur-circular.c \
motion-blur-linear.c \
motion-blur-zoom.c \
+ newsprint.c \
noise-cie-lch.c \
noise-hsv.c \
noise-hurl.c \
diff --git a/operations/common/newsprint.c b/operations/common/newsprint.c
new file mode 100644
index 0000000..99f5a45
--- /dev/null
+++ b/operations/common/newsprint.c
@@ -0,0 +1,347 @@
+/* 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/>.
+ *
+ * Copyright 2017 Øyvind Kolås <pippin gimp org>
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#ifdef GEGL_PROPERTIES
+
+property_int (inks, _("inks"), 1)
+ value_range (1, 4)
+ description (_("How many inks to use just black, rg, rgb(additive) or cmyk"))
+property_int (pattern, _("pattern"), 0)
+ value_range (0, 16)
+ description (_("halftoning pattern"))
+
+property_double (wavelength, _("wavelength"), 12.0)
+ value_range (0.0, 200.0) // rename to period?
+
+property_double (turbulence, _("turbulence"), 0.0)
+ value_range (0.0, 1.0) // rename to wave-pinch or period-pinch?
+
+property_double (blocksize, _("blocksize"), -1.0)
+ value_range (-1.0, 64.0)
+ description (_("number of wavelengths per local period"))
+
+property_double (angleboost, _("angleboost"), 0.0)
+ value_range (0.0, 4.0)
+ description (_("angle offset for patterns"))
+
+property_double (twist, _("black and green angle"), 0.5)
+ value_range (-2.0, 2.0)
+ description (_("angle offset for patterns"))
+
+property_double (twist2, _("red and cyan angle"), 0.166766661)
+ value_range (-2.0, 2.0)
+property_double (twist3, _("blue and magenta angle"), 0.84351)
+ value_range (-2.0, 2.0)
+property_double (twist4, _("yellow angle"), 0.0)
+ value_range (-2.0, 2.0)
+
+
+#else
+
+#define GEGL_OP_POINT_FILTER
+#define GEGL_OP_NAME newsprint
+#define GEGL_OP_C_SOURCE newsprint.c
+
+#include "gegl-op.h"
+
+static void
+prepare (GeglOperation *operation)
+{
+ gegl_operation_set_format (operation, "input", babl_format ("RGBA float"));
+ gegl_operation_set_format (operation, "output", babl_format ("RGBA float"));
+}
+
+#include <math.h>
+
+static inline float dmodf(float x, float y)
+{
+ return x - y * floorf(x/y);
+}
+
+#define fmodf dmodf
+
+/* for details and more liberal licensing of the following function, see
+ https://pippin.gimp.org/spachrotyzer/ */
+
+static
+float spachrotyze (
+ float x,
+ float y,
+ float part_white,
+ float offset,
+ float hue,
+ int pattern,
+ float wavelength,
+ float turbulence,
+ float blocksize,
+ float angleboost,
+ float twist)
+{
+ float aa = 2.0;
+ float acc = 0.0;
+
+ float angle = (1.0-(hue * angleboost) + twist);
+
+ float width = (wavelength * (1.0 - turbulence) +
+ (wavelength * offset) * turbulence);
+
+ float vec0 = cosf (-angle * 3.14151 / 2.0);
+ float vec1 = sinf (-angle * 3.14151 / 2.0);
+ float aa_sq = aa * aa;
+
+ for (float xi = 0.0; xi < aa; xi += 1.0)
+ {
+ float u = fmodf (x + xi/aa + 0.5 * width, blocksize * width);
+ for (float yi = 0.0; yi < aa; yi += 1.0)
+ {
+ float v = fmodf (y + yi/aa + 0.5 * width, blocksize * width);
+ float w = vec0 * u + vec1 * v;
+ float q = vec1 * u - vec0 * v;
+
+ float wperiod = fmodf (w, width);
+ float wphase = (wperiod / width) * 2.0 - 1.0;
+
+ float qperiod = fmodf (q, width);
+ float qphase = (qperiod / width) * 2.0 - 1.0;
+
+ if (pattern == 0) { /* line */
+ if (fabsf (wphase) < part_white)
+ acc += 1.0 / aa_sq;
+ }
+ else if (pattern == 1) { /* dot */
+ if (qphase * qphase + wphase * wphase <
+ part_white * part_white * 2.0)
+ acc += 1.0 / aa_sq;
+ }
+ else if (pattern == 2) { /* diamond */
+ if (fabsf(wphase) + fabsf(qphase) < (part_white * 2) )
+ acc += 1.0 / aa_sq;
+ }
+ else if (pattern == 3) { /* dot-to-diamond-to-dot */
+ float ax = fabsf (wphase ) ;
+ float ay = fabsf (qphase ) ;
+ float v = 0.0;
+
+ if (ax + ay > 1.0)
+ {
+ v = 2.0-(((ay - 1.0) * (ay - 1.0) + (ax - 1.0) * (ax - 1.0)));
+ }
+ else
+ {
+ v = (ay * ay + ax * ax);
+ }
+ v/=2.0;
+ if (v < part_white)
+ acc = acc + 1.0 / aa_sq;
+ } else if (pattern == 4)
+ {
+ if (fabsf (wphase) < part_white)
+ acc += 1.0 / aa_sq;
+ else if (fabsf (qphase) < part_white)
+ acc += 1.0 / aa_sq;
+ }
+ }
+ }
+ return acc;
+}
+static gboolean
+process (GeglOperation *operation,
+ void *in_buf,
+ void *out_buf,
+ glong n_pixels,
+ const GeglRectangle *roi,
+ gint level)
+{
+ GeglProperties *o = GEGL_PROPERTIES (operation);
+ gfloat *in_pixel = in_buf;
+ gfloat *out_pixel = out_buf;
+
+ gint x = roi->x; /* initial x */
+ gint y = roi->y; /* and y coordinates */
+ gfloat blocksize = o->blocksize;
+ if (blocksize < 0.0)
+ blocksize = 819200.0;
+
+ switch (o->inks)
+ {
+ case 0:
+ case 1:
+ case 2:
+ while (n_pixels--)
+ {
+ float luminance = in_pixel[1];
+ float chroma = fabs(in_pixel[0]-in_pixel[1]);
+ float angle = fabs(in_pixel[2]-in_pixel[1]);
+ float acc = spachrotyze(x, y,
+ luminance, chroma, angle,
+ o->pattern,
+ o->wavelength / (1.0*(1<<level)),
+ o->turbulence,
+ blocksize,
+ o->angleboost,
+ o->twist);
+ for (int c = 0; c < 3; c++)
+ out_pixel[c] = acc;
+
+ out_pixel[3] = 1.0;
+ out_pixel += 4;
+ in_pixel += 4;
+
+ /* update x and y coordinates */
+ x++; if (x>=roi->x + roi->width) { x=roi->x; y++; }
+ }
+ break;
+ case 3:
+ while (n_pixels--)
+ {
+ float pinch = fabs(in_pixel[0]-in_pixel[1]);
+ float angle = fabs(in_pixel[2]-in_pixel[1]);
+
+ out_pixel[0] = spachrotyze(x, y,
+ in_pixel[0], pinch, angle,
+ o->pattern,
+ o->wavelength / (1.0*(1<<level)),
+ o->turbulence,
+ blocksize,
+ o->angleboost,
+ o->twist2);
+ out_pixel[1] = spachrotyze(x, y,
+ in_pixel[1], pinch, angle,
+ o->pattern,
+ o->wavelength / (1.0*(1<<level)),
+ o->turbulence,
+ blocksize,
+ o->angleboost,
+ o->twist);
+ out_pixel[2] = spachrotyze(x, y,
+ in_pixel[2], pinch, angle,
+ o->pattern,
+ o->wavelength / (1.0*(1<<level)),
+ o->turbulence,
+ blocksize,
+ o->angleboost,
+ o->twist3);
+ out_pixel[3] = 1.0;
+ out_pixel += 4;
+ in_pixel += 4;
+
+ /* update x and y coordinates */
+ x++; if (x>=roi->x + roi->width) { x=roi->x; y++; }
+ }
+ break;
+ }
+
+
+ return TRUE;
+}
+
+#if 0
+#include "opencl/gegl-cl.h"
+#include "opencl/spachrotyze.cl.h"
+
+static GeglClRunData *cl_data = NULL;
+
+/* OpenCL processing function */
+static gboolean
+cl_process (GeglOperation *op,
+ cl_mem in_tex,
+ cl_mem out_tex,
+ size_t global_worksize,
+ const GeglRectangle *roi,
+ int level)
+{
+ const size_t gbl_size[2] = {roi->width, roi->height};
+ const size_t gbl_offs[2] = {roi->x, roi->y};
+
+ GeglProperties *o = GEGL_PROPERTIES (op);
+ cl_int cl_err = 0;
+
+ if (!cl_data)
+ {
+ const char *kernel_name[] = {"gegl_spachrotyzer", NULL};
+ cl_data = gegl_cl_compile_and_build (spachrotyzer_cl_source, kernel_name);
+ }
+
+ if (!cl_data)
+ {
+ g_warning ("cl fail\n");
+ CL_CHECK;
+ return 1;
+ }
+
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 0, sizeof(cl_mem), (void*)&in_tex);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 1, sizeof(cl_mem), (void*)&out_tex);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 2, sizeof(cl_int), (void*)&o->pattern);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 3, sizeof(cl_float), (void*)&o->wavelength);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 4, sizeof(cl_float), (void*)&o->turbulence);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 5, sizeof(cl_float), (void*)&o->blocksize);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 6, sizeof(cl_float), (void*)&o->angleboost);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 7, sizeof(cl_float), (void*)&o->twist);
+ CL_CHECK;
+
+ cl_err = gegl_clEnqueueNDRangeKernel(gegl_cl_get_command_queue (),
+ cl_data->kernel[0], 2,
+ gbl_offs, gbl_size, NULL,
+ 0, NULL, NULL);
+ CL_CHECK;
+
+ return FALSE;
+
+error:
+ return TRUE;
+}
+#endif
+
+static void
+gegl_op_class_init (GeglOpClass *klass)
+{
+ GeglOperationClass *operation_class;
+ GeglOperationPointFilterClass *point_filter_class;
+
+ operation_class = GEGL_OPERATION_CLASS (klass);
+ point_filter_class = GEGL_OPERATION_POINT_FILTER_CLASS (klass);
+
+ point_filter_class->process = process;
+ operation_class->prepare = prepare;
+#if 0
+ point_filter_class->cl_process = cl_process;
+ operation_class->opencl_support = TRUE;
+#endif
+
+ gegl_operation_class_set_keys (operation_class,
+ "name", "gegl:newsprint",
+ "title", _("newsprint"),
+ "position-dependent", "true",
+ "categories" , "render",
+ "reference-hash", "cc9c401d7c8bcea7147499ecbeda9986",
+ "description", _("Simulation of digital/analog AM halftoning with optional modulations. "),
+ "position-dependent", "true",
+ NULL);
+}
+
+#endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 1127ddb..f392295 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -83,6 +83,7 @@ operations/common/mosaic.c
operations/common/motion-blur-circular.c
operations/common/motion-blur-linear.c
operations/common/motion-blur-zoom.c
+operations/common/newsprint.c
operations/common/noise-cell.c
operations/common/noise-cie-lch.c
operations/common/noise-hsv.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]