[gegl] workshop: complete rewrite of shadows-highlights operation
- From: Thomas Manni <tmanni src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] workshop: complete rewrite of shadows-highlights operation
- Date: Fri, 30 Jun 2017 20:37:46 +0000 (UTC)
commit 59cbe20b204c84e13d94c2900b7aa8d1197a193f
Author: Thomas Manni <thomas manni free fr>
Date: Tue Jun 27 16:47:02 2017 +0200
workshop: complete rewrite of shadows-highlights operation
A partial port of the darktable shadows-highlights filter.
Opencl support still in wip state.
opencl/shadows-highlights-correction.cl | 81 +++++
opencl/shadows-highlights-correction.cl.h | 83 +++++
.../workshop/shadows-highlights-correction.c | 358 ++++++++++++--------
operations/workshop/shadows-highlights.c | 90 +++---
4 files changed, 424 insertions(+), 188 deletions(-)
---
diff --git a/opencl/shadows-highlights-correction.cl b/opencl/shadows-highlights-correction.cl
new file mode 100644
index 0000000..88f35f0
--- /dev/null
+++ b/opencl/shadows-highlights-correction.cl
@@ -0,0 +1,81 @@
+float3 overlay(const float3 in_a,
+ const float3 in_b,
+ const float opacity,
+ const float transform,
+ const float ccorrect,
+ const float low_approximation)
+{
+ /* a contains underlying image; b contains mask */
+
+ const float3 scale = (float3)(100.0f, 128.0f, 128.0f);
+ const float lmin = 0.0f;
+ const float lmax = 1.0f;
+ const float halfmax = 0.5f;
+ const float doublemax = 2.0f;
+
+ float3 a = in_a / scale;
+ float3 b = in_b / scale;
+
+
+ float opacity2 = opacity*opacity;
+
+ while(opacity2 > 0.0f)
+ {
+ float la = a.x;
+ float lb = (b.x - halfmax) * sign(opacity)*sign(lmax - la) + halfmax;
+ float lref = copysign(fabs(la) > low_approximation ? 1.0f/fabs(la) : 1.0f/low_approximation, la);
+ float href = copysign(fabs(1.0f - la) > low_approximation ? 1.0f/fabs(1.0f - la) :
1.0f/low_approximation, 1.0f - la);
+
+ float chunk = opacity2 > 1.0f ? 1.0f : opacity2;
+ float optrans = chunk * transform;
+ opacity2 -= 1.0f;
+
+ a.x = la * (1.0f - optrans) + (la > halfmax ? lmax - (lmax - doublemax * (la - halfmax)) * (lmax-lb) :
doublemax * la * lb) * optrans;
+ a.y = a.y * (1.0f - optrans) + (a.y + b.y) * (a.x*lref * ccorrect + (1.0f - a.x)*href * (1.0f -
ccorrect)) * optrans;
+ a.z = a.z * (1.0f - optrans) + (a.z + b.z) * (a.x*lref * ccorrect + (1.0f - a.x)*href * (1.0f -
ccorrect)) * optrans;
+ }
+ /* output scaled back pixel */
+ return a * scale;
+}
+
+
+__kernel void shadows_highlights(__global const float4 *in,
+ __global const float3 *aux,
+ __global float4 *out,
+ const float shadows,
+ const float highlights,
+ const float compress,
+ const float shadows_ccorrect,
+ const float highlights_ccorrect,
+ const float whitepoint)
+{
+ int gid = get_global_id(0);
+ const float low_approximation = 0.01f;
+
+ float4 io = in[gid];
+ float3 m = (float3)0.0f;
+ float xform;
+
+ if (! aux)
+ {
+ out[gid] = io;
+ return;
+ }
+
+ /* blurred, inverted and desaturaed mask in m */
+ m.x = 100.0f - aux[gid].x;
+
+ /* white point adjustment */
+ io.x = io.x > 0.0f ? io.x/whitepoint : io.x;
+ m.x = m.x > 0.0f ? m.x/whitepoint : m.x;
+
+ /* overlay highlights */
+ xform = clamp(1.0f - 0.01f * m.x/(1.0f-compress), 0.0f, 1.0f);
+ io.xyz = overlay(io.xyz, m, -highlights, xform, 1.0f - highlights_ccorrect, low_approximation);
+
+ /* overlay shadows */
+ xform = clamp(0.01f * m.x/(1.0f-compress) - compress/(1.0f-compress), 0.0f, 1.0f);
+ io.xyz = overlay(io.xyz, m, shadows, xform, shadows_ccorrect, low_approximation);
+
+ out[gid] = io;
+}
\ No newline at end of file
diff --git a/opencl/shadows-highlights-correction.cl.h b/opencl/shadows-highlights-correction.cl.h
new file mode 100644
index 0000000..11cf477
--- /dev/null
+++ b/opencl/shadows-highlights-correction.cl.h
@@ -0,0 +1,83 @@
+static const char* shadows_highlights_correction_cl_source =
+"float3 overlay(const float3 in_a, \n"
+" const float3 in_b, \n"
+" const float opacity, \n"
+" const float transform, \n"
+" const float ccorrect, \n"
+" const float low_approximation) \n"
+"{ \n"
+" /* a contains underlying image; b contains mask */ \n"
+" \n"
+" const float3 scale = (float3)(100.0f, 128.0f, 128.0f); \n"
+" const float lmin = 0.0f; \n"
+" const float lmax = 1.0f; \n"
+" const float halfmax = 0.5f; \n"
+" const float doublemax = 2.0f; \n"
+" \n"
+" float3 a = in_a / scale; \n"
+" float3 b = in_b / scale; \n"
+" \n"
+" \n"
+" float opacity2 = opacity*opacity; \n"
+" \n"
+" while(opacity2 > 0.0f) \n"
+" { \n"
+" float la = a.x; \n"
+" float lb = (b.x - halfmax) * sign(opacity)*sign(lmax - la) + halfmax; \n"
+" float lref = copysign(fabs(la) > low_approximation ? 1.0f/fabs(la) : 1.0f/low_approximation, la);\n"
+" float href = copysign(fabs(1.0f - la) > low_approximation ? 1.0f/fabs(1.0f - la) :
1.0f/low_approximation, 1.0f - la);\n"
+" \n"
+" float chunk = opacity2 > 1.0f ? 1.0f : opacity2; \n"
+" float optrans = chunk * transform; \n"
+" opacity2 -= 1.0f; \n"
+" \n"
+" a.x = la * (1.0f - optrans) + (la > halfmax ? lmax - (lmax - doublemax * (la - halfmax)) * (lmax-lb) :
doublemax * la * lb) * optrans;\n"
+" a.y = a.y * (1.0f - optrans) + (a.y + b.y) * (a.x*lref * ccorrect + (1.0f - a.x)*href * (1.0f -
ccorrect)) * optrans;\n"
+" a.z = a.z * (1.0f - optrans) + (a.z + b.z) * (a.x*lref * ccorrect + (1.0f - a.x)*href * (1.0f -
ccorrect)) * optrans;\n"
+" } \n"
+" /* output scaled back pixel */ \n"
+" return a * scale; \n"
+"} \n"
+" \n"
+" \n"
+"__kernel void shadows_highlights(__global const float4 *in, \n"
+" __global const float3 *aux, \n"
+" __global float4 *out, \n"
+" const float shadows, \n"
+" const float highlights, \n"
+" const float compress, \n"
+" const float shadows_ccorrect, \n"
+" const float highlights_ccorrect, \n"
+" const float whitepoint) \n"
+"{ \n"
+" int gid = get_global_id(0); \n"
+" const float low_approximation = 0.01f; \n"
+" \n"
+" float4 io = in[gid]; \n"
+" float3 m = (float3)0.0f; \n"
+" float xform; \n"
+" \n"
+" if (! aux) \n"
+" { \n"
+" out[gid] = io; \n"
+" return; \n"
+" } \n"
+" \n"
+" /* blurred, inverted and desaturaed mask in m */ \n"
+" m.x = 100.0f - aux[gid].x; \n"
+" \n"
+" /* white point adjustment */ \n"
+" io.x = io.x > 0.0f ? io.x/whitepoint : io.x; \n"
+" m.x = m.x > 0.0f ? m.x/whitepoint : m.x; \n"
+" \n"
+" /* overlay highlights */ \n"
+" xform = clamp(1.0f - 0.01f * m.x/(1.0f-compress), 0.0f, 1.0f); \n"
+" io.xyz = overlay(io.xyz, m, -highlights, xform, 1.0f - highlights_ccorrect, low_approximation);\n"
+" \n"
+" /* overlay shadows */ \n"
+" xform = clamp(0.01f * m.x/(1.0f-compress) - compress/(1.0f-compress), 0.0f, 1.0f);\n"
+" io.xyz = overlay(io.xyz, m, shadows, xform, shadows_ccorrect, low_approximation);\n"
+" \n"
+" out[gid] = io; \n"
+"} \n"
+;
diff --git a/operations/workshop/shadows-highlights-correction.c
b/operations/workshop/shadows-highlights-correction.c
index 0690380..b5295e6 100644
--- a/operations/workshop/shadows-highlights-correction.c
+++ b/operations/workshop/shadows-highlights-correction.c
@@ -1,16 +1,22 @@
/* 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,
+ * 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
- * Lesser General Public License for more details.
+ * 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/>.
*
- * 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 a port of the Darktable Shadows Highlights filter
+ * copyright (c) 2012--2015 Ulrich Pegelow.
+ *
+ * GEGL port: Thomas Manni <thomas manni free fr>
*
*/
@@ -20,118 +26,82 @@
#ifdef GEGL_PROPERTIES
-property_double (s_amount, _("Shadows amount"), 0.2)
- value_range (0.0, 1.0)
+property_double (shadows, _("Shadows"), 50.0)
+ value_range (-100.0, 100.0)
+
+property_double (highlights, _("Highlights"), -50.0)
+ value_range (-100.0, 100.0)
-property_double (s_tonalwidth, _("Shadows tonal width"), 0.1)
- value_range (0.001, 1.0)
+property_double (whitepoint, _("White point adjustment"), 0.0)
+ value_range (-10.0, 10.0)
-property_double (h_amount, _("Highlights amount"), 0.2)
- value_range (0.0, 1.0)
+property_double (compress, _("Compress"), 50.0)
+ value_range (0.0, 100.0)
-property_double (h_tonalwidth, _("Highlights tonal width"), 0.1)
- value_range (0.001, 1.0)
+property_double (shadows_ccorrect, _("Shadows color adjustment"), 100.0)
+ value_range (0.0, 100.0)
+
+property_double (highlights_ccorrect, _("Highlights color adjustment"), 50.0)
+ value_range (0.0, 100.0)
#else
-#define GEGL_OP_POINT_COMPOSER3
+#define GEGL_OP_POINT_COMPOSER
#define GEGL_OP_NAME shadows_highlights_correction
#define GEGL_OP_C_SOURCE shadows-highlights-correction.c
#include "gegl-op.h"
+#include "gegl-debug.h"
#include <math.h>
-#define LUT_SIZE 2048
-
-typedef struct
-{
- gdouble shadows[LUT_SIZE];
- gdouble highlights[LUT_SIZE];
-} Luts;
-
-static void
-initialize_luts (GeglProperties *o)
-{
- gint i, scale = LUT_SIZE - 1;
- Luts *luts = (Luts *) o->user_data;
- gdouble s_scaled = o->s_tonalwidth * scale;
- gdouble h_scaled = (1.0 - o->h_tonalwidth) * scale;
-
- for (i = 0; i < LUT_SIZE; i++)
- {
- /* shadows */
- if (i < s_scaled)
- {
- luts->shadows[i] = 1.0 - pow((i / s_scaled), 2.0);
- }
- else
- {
- luts->shadows[i] = 0.0;
- }
-
- /* highlights */
- if (i > h_scaled)
- {
- luts->highlights[i] = 1.0 - pow((scale - i) / (scale - h_scaled), 2.0);
- }
- else
- {
- luts->highlights[i] = 0.0;
- }
- }
-}
+#define SIGN(x) (((x) < 0) ? -1.f : 1.f)
static void
prepare (GeglOperation *operation)
{
- GeglProperties *o = GEGL_PROPERTIES (operation);
- const Babl *rgba_f = babl_format ("R'G'B'A float");
- const Babl *y_f = babl_format ("Y' float");
-
- if (o->user_data == NULL)
- o->user_data = g_slice_new0 (Luts);
+ const Babl *laba = babl_format ("CIE Lab alpha float");
+ const Babl *lab = babl_format ("CIE Lab float");
- initialize_luts (o);
-
- gegl_operation_set_format (operation, "input", rgba_f);
- gegl_operation_set_format (operation, "aux", y_f);
- gegl_operation_set_format (operation, "aux2", y_f);
- gegl_operation_set_format (operation, "output", rgba_f);
-}
-
-static void
-finalize (GObject *object)
-{
- GeglProperties *o = GEGL_PROPERTIES (object);
-
- if (o->user_data)
- {
- g_slice_free (Luts, o->user_data);
- o->user_data = NULL;
- }
-
- G_OBJECT_CLASS (gegl_op_parent_class)->finalize (object);
+ gegl_operation_set_format (operation, "input", laba);
+ gegl_operation_set_format (operation, "aux", lab);
+ gegl_operation_set_format (operation, "output", laba);
}
static gboolean
process (GeglOperation *operation,
void *in_buf,
void *aux_buf,
- void *aux2_buf,
void *out_buf,
glong n_pixels,
const GeglRectangle *roi,
gint level)
{
GeglProperties *o = GEGL_PROPERTIES (operation);
- Luts *luts = (Luts *) o->user_data;
gfloat *src = in_buf;
gfloat *dst = out_buf;
gfloat *aux = aux_buf;
- gfloat *aux2 = aux2_buf;
- if (!aux || !aux2)
+ gfloat shadows = 2.f * fminf (fmaxf (-1.0, (o->shadows / 100.f)), 1.f);
+ gfloat highlights = 2.f * fminf (fmaxf (-1.0, (o->highlights / 100.f)), 1.f);
+ gfloat whitepoint = fmaxf (1.f - o->whitepoint / 100.f, 0.01f);
+ gfloat compress = fminf (fmaxf (0, (o->compress / 100.f)), 0.99f);
+
+ gfloat shadows_ccorrect = (fminf (fmaxf (0.0f, (o->shadows_ccorrect / 100.f)), 1.f) - 0.5f)
+ * SIGN(shadows) + 0.5f;
+
+ gfloat highlights_ccorrect = (fminf (fmaxf (0.0f, (o->highlights_ccorrect / 100.f)), 1.f) - 0.5f)
+ * SIGN(-highlights) + 0.5f;
+
+ gfloat max[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ gfloat min[4] = { 0.0f, -1.0f, -1.0f, 0.0f };
+ gfloat lmin = 0.0f;
+ gfloat lmax = max[0] + fabs(min[0]);
+ gfloat halfmax = lmax / 2.0;
+ gfloat doublemax = lmax * 2.0;
+ gfloat low_approximation = 0.01f;
+
+ if (!aux)
{
memcpy (out_buf, in_buf, sizeof (gfloat) * 4 * n_pixels);
return TRUE;
@@ -139,76 +109,172 @@ process (GeglOperation *operation,
while (n_pixels--)
{
- gfloat *src_pix = src;
- gfloat shadows_estimation = *aux;
- gfloat highlights_estimation = *aux2;
-
- gdouble correction;
- gdouble lut_value;
- gint b;
+ gfloat ta[3];
+ gfloat tb[3];
+ gfloat highlights2;
+ gfloat highlights_xform;
+ gfloat shadows2;
+ gfloat shadows_xform;
- /* shadows correction */
-
- if (o->s_amount)
- {
- lut_value = luts->shadows[(gint) (shadows_estimation * (LUT_SIZE - 1))];
+ ta[0] = src[0] / 100.f;
+ ta[1] = src[1] / 128.f;
+ ta[2] = src[2] / 128.f;
- if (lut_value > 0.0)
- {
- correction = o->s_amount * lut_value;
+ tb[0] = (100.f - aux[0]) / 100.f;
+ tb[1] = 0.f;
+ tb[2] = 0.f;
- for (b = 0; b < 3; b++)
- {
- gfloat new_shadow = 1.0 - shadows_estimation;
+ ta[0] = ta[0] > 0.0f ? ta[0] / whitepoint : ta[0];
+ tb[0] = tb[0] > 0.0f ? tb[0] / whitepoint : tb[0];
- if (src_pix[b] < 0.5)
- new_shadow = 2.0 * src_pix[b] * new_shadow;
- else
- new_shadow = 1.0 - 2.0 * (1.0 - src_pix[b]) * (1.0 - new_shadow);
+ highlights2 = highlights * highlights;
+ highlights_xform = CLAMP(1.0f - tb[0] / (1.0f - compress), 0.0f, 1.0f);
- src_pix[b] = correction * new_shadow + (1.0 - correction) * src_pix[b];
- }
- }
+ while (highlights2 > 0.0f)
+ {
+ gfloat lref, href;
+ gfloat chunk, optrans;
+
+ gfloat la = ta[0];
+ gfloat lb = (tb[0] - halfmax) * SIGN(-highlights) * SIGN(lmax - la) + halfmax;
+ lb = CLAMP(lb, lmin, lmax);
+ lref = copysignf(fabs(la) > low_approximation ? 1.0f / fabs(la) : 1.0f / low_approximation, la);
+ href = copysignf(
+ fabs(1.0f - la) > low_approximation ? 1.0f / fabs(1.0f - la) : 1.0f / low_approximation, 1.0f
- la);
+
+ chunk = highlights2 > 1.0f ? 1.0f : highlights2;
+ optrans = chunk * highlights_xform;
+ highlights2 -= 1.0f;
+
+ ta[0] = la * (1.0 - optrans)
+ + (la > halfmax ? lmax - (lmax - doublemax * (la - halfmax)) * (lmax - lb) : doublemax * la
+ * lb) *
optrans;
+
+ ta[1] = ta[1] * (1.0f - optrans)
+ + (ta[1] + tb[1]) * (ta[0] * lref * (1.0f - highlights_ccorrect)
+ + (1.0f - ta[0]) * href * highlights_ccorrect) * optrans;
+
+ ta[2] = ta[2] * (1.0f - optrans)
+ + (ta[2] + tb[2]) * (ta[0] * lref * (1.0f - highlights_ccorrect)
+ + (1.0f - ta[0]) * href * highlights_ccorrect) * optrans;
}
- /* highlights correction */
+ shadows2 = shadows * shadows;
+ shadows_xform = CLAMP(tb[0] / (1.0f - compress) - compress / (1.0f - compress), 0.0f, 1.0f);
- if (o->h_amount)
- {
- lut_value = luts->highlights[(gint) (highlights_estimation * (LUT_SIZE - 1))];
+ while (shadows2 > 0.0f)
+ {
+ gfloat lref, href;
+ gfloat chunk, optrans;
- if (lut_value > 0.0)
- {
- correction = o->h_amount * lut_value;
+ gfloat la = ta[0];
+ gfloat lb = (tb[0] - halfmax) * SIGN(shadows) * SIGN(lmax - la) + halfmax;
+ lref = copysignf(fabs(la) > low_approximation ? 1.0f / fabs(la) : 1.0f / low_approximation, la);
+ href = copysignf(
+ fabs(1.0f - la) > low_approximation ? 1.0f / fabs(1.0f - la) : 1.0f / low_approximation, 1.0f -
la);
- for (b = 0; b < 3; b++)
- {
- gfloat new_highlight = 1.0 - highlights_estimation;
+ chunk = shadows2 > 1.0f ? 1.0f : shadows2;
+ optrans = chunk * shadows_xform;
+ shadows2 -= 1.0f;
- if (src_pix[b] < 0.5)
- new_highlight = 2.0 * src_pix[b] * new_highlight;
- else
- new_highlight = 1.0 - 2.0 * (1.0 - src_pix[b]) * (1.0 - new_highlight);
+ ta[0] = la * (1.0 - optrans)
+ + (la > halfmax ? lmax - (lmax - doublemax * (la - halfmax)) * (lmax - lb) : doublemax * la
+ * lb) * optrans;
- src_pix[b] = correction * new_highlight + (1.0 - correction) * src_pix[b];
- }
- }
- }
+ ta[1] = ta[1] * (1.0f - optrans)
+ + (ta[1] + tb[1]) * (ta[0] * lref * shadows_ccorrect
+ + (1.0f - ta[0]) * href * (1.0f - shadows_ccorrect)) * optrans;
+
+ ta[2] = ta[2] * (1.0f - optrans)
+ + (ta[2] + tb[2]) * (ta[0] * lref * shadows_ccorrect
+ + (1.0f - ta[0]) * href * (1.0f - shadows_ccorrect)) * optrans;
+ }
- dst[0] = src_pix[0];
- dst[1] = src_pix[1];
- dst[2] = src_pix[2];
+ dst[0] = ta[0] * 100.f;
+ dst[1] = ta[1] * 128.f;
+ dst[2] = ta[2] * 128.f;
dst[3] = src[3];
src += 4;
dst += 4;
- aux += 1;
- aux2 += 1;
+ aux += 3;
}
return TRUE;
}
+/*
+
+#include "opencl/gegl-cl.h"
+
+#include "opencl/shadows-highlights-correction.cl.h"
+
+static GeglClRunData *cl_data = NULL;
+
+static gboolean
+cl_process (GeglOperation *op,
+ cl_mem in_tex,
+ cl_mem aux_tex,
+ cl_mem out_tex,
+ size_t global_worksize,
+ const GeglRectangle *roi,
+ gint level)
+{
+ GeglProperties *o = GEGL_PROPERTIES (op);
+
+ cl_int cl_err = 0;
+
+ gfloat shadows = 2.f * fminf (fmaxf (-1.0, (o->shadows / 100.f)), 1.f);
+ gfloat highlights = 2.f * fminf (fmaxf (-1.0, (o->highlights / 100.f)), 1.f);
+ gfloat whitepoint = fmaxf (1.f - o->whitepoint / 100.f, 0.01f);
+ gfloat compress = fminf (fmaxf (0, (o->compress / 100.f)), 0.99f);
+
+ gfloat shadows_ccorrect = (fminf (fmaxf (0.0f, (o->shadows_ccorrect / 100.f)), 1.f) - 0.5f)
+ * SIGN(shadows) + 0.5f;
+
+ gfloat highlights_ccorrect = (fminf (fmaxf (0.0f, (o->highlights_ccorrect / 100.f)), 1.f) - 0.5f)
+ * SIGN(-highlights) + 0.5f;
+
+ if (!cl_data)
+ {
+ const char *kernel_name[] = {"shadows_highlights", NULL};
+ cl_data = gegl_cl_compile_and_build (shadows_highlights_correction_cl_source, kernel_name);
+ }
+ if (!cl_data) return TRUE;
+
+ 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), (aux_tex)? (void*)&aux_tex : NULL);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 2, sizeof(cl_mem), (void*)&out_tex);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 3, sizeof(cl_float), (void*)&shadows);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 4, sizeof(cl_float), (void*)&highlights);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 5, sizeof(cl_float), (void*)&compress);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 6, sizeof(cl_float), (void*)&shadows_ccorrect);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 7, sizeof(cl_float), (void*)&highlights_ccorrect);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 8, sizeof(cl_float), (void*)&whitepoint);
+ CL_CHECK;
+
+ cl_err = gegl_clEnqueueNDRangeKernel(gegl_cl_get_command_queue (),
+ cl_data->kernel[0], 1,
+ NULL, &global_worksize, NULL,
+ 0, NULL, NULL);
+ CL_CHECK;
+
+ return FALSE;
+
+error:
+ return TRUE;
+}
+
+*/
+
static GeglRectangle
get_bounding_box (GeglOperation *self)
{
@@ -224,25 +290,27 @@ get_bounding_box (GeglOperation *self)
static void
gegl_op_class_init (GeglOpClass *klass)
{
- GObjectClass *object_class;
- GeglOperationClass *operation_class;
- GeglOperationPointComposer3Class *point_composer3_class;
-
- object_class = G_OBJECT_CLASS (klass);
- operation_class = GEGL_OPERATION_CLASS (klass);
- point_composer3_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass);
+ GeglOperationClass *operation_class;
+ GeglOperationPointComposerClass *point_composer_class;
- object_class->finalize = finalize;
+ operation_class = GEGL_OPERATION_CLASS (klass);
+ point_composer_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass);
operation_class->prepare = prepare;
operation_class->get_bounding_box = get_bounding_box;
- operation_class->opencl_support = FALSE;
+
+
+ point_composer_class->process = process;
- point_composer3_class->process = process;
+ /*
+ point_composer_class->cl_process = cl_process;
+ operation_class->opencl_support = TRUE;
+ */
gegl_operation_class_set_keys (operation_class,
"name", "gegl:shadows-highlights-correction",
"categories", "hidden",
+ "license", "GPL3+",
"description", _("Lighten shadows and darken highlights"),
NULL);
}
diff --git a/operations/workshop/shadows-highlights.c b/operations/workshop/shadows-highlights.c
index 9793374..67e2b48 100644
--- a/operations/workshop/shadows-highlights.c
+++ b/operations/workshop/shadows-highlights.c
@@ -1,16 +1,22 @@
/* 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,
+ * 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
- * Lesser General Public License for more details.
+ * 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/>.
*
- * 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 a port of the Darktable Shadows Highlights filter
+ * copyright (c) 2012--2015 Ulrich Pegelow.
+ *
+ * GEGL port: Thomas Manni <thomas manni free fr>
*
*/
@@ -19,22 +25,26 @@
#ifdef GEGL_PROPERTIES
-property_double (s_amount, _("Shadows amount"), 0.2)
- value_range (0.0, 1.0)
+property_double (shadows, _("Shadows"), 50.0)
+ value_range (-100.0, 100.0)
-property_double (s_tonalwidth, _("Shadows tonal width"), 0.1)
- value_range (0.001, 1.0)
+property_double (highlights, _("Highlights"), -50.0)
+ value_range (-100.0, 100.0)
-property_double (s_radius, _("Shadows radius"), 5.0)
- value_range (0.0, 100.0)
+property_double (whitepoint, _("White point adjustment"), 0.0)
+ value_range (-10.0, 10.0)
-property_double (h_amount, _("Highlights amount"), 0.2)
- value_range (0.0, 1.0)
+property_double (radius, _("Radius"), 100.0)
+ value_range (0.1, G_MAXDOUBLE)
+ ui_range (0.1, 200.0)
-property_double (h_tonalwidth, _("Highlights tonal width"), 0.1)
- value_range (0.001, 1.0)
+property_double (compress, _("Compress"), 50.0)
+ value_range (0.0, 100.0)
+
+property_double (shadows_ccorrect, _("Shadows color adjustment"), 100.0)
+ value_range (0.0, 100.0)
-property_double (h_radius, _("Highlights radius"), 5.0)
+property_double (highlights_ccorrect, _("Highlights color adjustment"), 50.0)
value_range (0.0, 100.0)
#else
@@ -51,45 +61,38 @@ attach (GeglOperation *operation)
GeglNode *gegl;
GeglNode *input;
GeglNode *output;
- GeglNode *s_blur;
- GeglNode *h_blur;
+ GeglNode *blur;
GeglNode *shprocess;
gegl = operation->node;
input = gegl_node_get_input_proxy (gegl, "input");
output = gegl_node_get_output_proxy (gegl, "output");
- s_blur = gegl_node_new_child (gegl,
- "operation", "gegl:gaussian-blur",
- "abyss-policy", 1,
- NULL);
+ blur = gegl_node_new_child (gegl,
+ "operation", "gegl:gaussian-blur",
+ "abyss-policy", 1,
+ NULL);
- h_blur = gegl_node_new_child (gegl,
- "operation", "gegl:gaussian-blur",
- "abyss-policy", 1,
- NULL);
shprocess = gegl_node_new_child (gegl,
"operation", "gegl:shadows-highlights-correction",
NULL);
- gegl_node_link (input, s_blur);
- gegl_node_link (input, h_blur);
+ gegl_node_link (input, blur);
gegl_node_link_many (input, shprocess, output, NULL);
- gegl_node_connect_to (s_blur, "output", shprocess, "aux");
- gegl_node_connect_to (h_blur, "output", shprocess, "aux2");
+ gegl_node_connect_to (blur, "output", shprocess, "aux");
- gegl_operation_meta_redirect (operation, "s-amount", shprocess, "s-amount");
- gegl_operation_meta_redirect (operation, "s-tonalwidth", shprocess, "s-tonalwidth");
- gegl_operation_meta_redirect (operation, "s-radius", s_blur, "std-dev-x");
- gegl_operation_meta_redirect (operation, "s-radius", s_blur, "std-dev-y");
- gegl_operation_meta_redirect (operation, "h-amount", shprocess, "h-amount");
- gegl_operation_meta_redirect (operation, "h-tonalwidth", shprocess, "h-tonalwidth");
- gegl_operation_meta_redirect (operation, "h-radius", h_blur, "std-dev-x");
- gegl_operation_meta_redirect (operation, "h-radius", h_blur, "std-dev-y");
+ gegl_operation_meta_redirect (operation, "radius", blur, "std-dev-x");
+ gegl_operation_meta_redirect (operation, "radius", blur, "std-dev-y");
+ gegl_operation_meta_redirect (operation, "shadows", shprocess, "shadows");
+ gegl_operation_meta_redirect (operation, "highlights", shprocess, "highlights");
+ gegl_operation_meta_redirect (operation, "whitepoint", shprocess, "whitepoint");
+ gegl_operation_meta_redirect (operation, "compress", shprocess, "compress");
+ gegl_operation_meta_redirect (operation, "shadows-ccorrect", shprocess, "shadows-ccorrect");
+ gegl_operation_meta_redirect (operation, "highlights-ccorrect", shprocess, "highlights-ccorrect");
- gegl_operation_meta_watch_nodes (operation, s_blur, h_blur, shprocess, NULL);
+ gegl_operation_meta_watch_nodes (operation, blur, shprocess, NULL);
}
static void
@@ -105,6 +108,7 @@ gegl_op_class_init (GeglOpClass *klass)
"name", "gegl:shadows-highlights",
"title", _("Shadows-Highlights"),
"categories", "light",
+ "license", "GPL3+",
"description", _("Perform shadows and highlights correction"),
NULL);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]