[gnome-photos] Absorb gegl:shadows-highlights
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-photos] Absorb gegl:shadows-highlights
- Date: Mon, 11 Dec 2017 17:13:47 +0000 (UTC)
commit 1fa3d66965355b4f41a0a168ab1db638bb3e6dd6
Author: Debarshi Ray <debarshir gnome org>
Date: Sat Dec 9 12:25:44 2017 +0100
Absorb gegl:shadows-highlights
This is a GEGL port of Darktable's shadhi operation. It is being
carried in-tree until gegl:shadows-highlights is considered stable
enough to be moved out of the workshop.
https://bugzilla.gnome.org/show_bug.cgi?id=788201
src/Makefile.am | 8 +
src/photos-gegl.c | 6 +
...hotos-operation-shadows-highlights-correction.c | 457 ++++++++++++++++++++
...hotos-operation-shadows-highlights-correction.h | 42 ++
src/photos-operation-shadows-highlights.c | 380 ++++++++++++++++
src/photos-operation-shadows-highlights.h | 42 ++
6 files changed, 935 insertions(+), 0 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 543f1c9..b91f6e6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -170,6 +170,10 @@ gnome_photos_SOURCES = \
photos-operation-png-guess-sizes.h \
photos-operation-saturation.c \
photos-operation-saturation.h \
+ photos-operation-shadows-highlights.c \
+ photos-operation-shadows-highlights.h \
+ photos-operation-shadows-highlights-correction.c \
+ photos-operation-shadows-highlights-correction.h \
photos-operation-svg-multiply.c \
photos-operation-svg-multiply.h \
photos-organize-collection-dialog.c \
@@ -340,6 +344,10 @@ gnome_photos_thumbnailer_SOURCES = \
photos-operation-png-guess-sizes.h \
photos-operation-saturation.c \
photos-operation-saturation.h \
+ photos-operation-shadows-highlights.c \
+ photos-operation-shadows-highlights.h \
+ photos-operation-shadows-highlights-correction.c \
+ photos-operation-shadows-highlights-correction.h \
photos-operation-svg-multiply.c \
photos-operation-svg-multiply.h \
photos-pipeline.c \
diff --git a/src/photos-gegl.c b/src/photos-gegl.c
index 8e80028..766c4e6 100644
--- a/src/photos-gegl.c
+++ b/src/photos-gegl.c
@@ -35,6 +35,8 @@
#include "photos-operation-jpg-guess-sizes.h"
#include "photos-operation-png-guess-sizes.h"
#include "photos-operation-saturation.h"
+#include "photos-operation-shadows-highlights.h"
+#include "photos-operation-shadows-highlights-correction.h"
#include "photos-operation-svg-multiply.h"
#include "photos-quarks.h"
@@ -53,8 +55,10 @@ static const gchar *REQUIRED_GEGL_OPS[] =
{
"gegl:buffer-sink",
"gegl:buffer-source",
+ "gegl:convert-format",
"gegl:crop",
"gegl:exposure",
+ "gegl:gaussian-blur",
"gegl:gray",
"gegl:load",
"gegl:noise-reduction",
@@ -564,6 +568,8 @@ photos_gegl_ensure_builtins (void)
g_type_ensure (PHOTOS_TYPE_OPERATION_JPG_GUESS_SIZES);
g_type_ensure (PHOTOS_TYPE_OPERATION_PNG_GUESS_SIZES);
g_type_ensure (PHOTOS_TYPE_OPERATION_SATURATION);
+ g_type_ensure (PHOTOS_TYPE_OPERATION_SHADOWS_HIGHLIGHTS);
+ g_type_ensure (PHOTOS_TYPE_OPERATION_SHADOWS_HIGHLIGHTS_CORRECTION);
g_type_ensure (PHOTOS_TYPE_OPERATION_SVG_MULTIPLY);
g_once_init_leave (&once_init_value, 1);
diff --git a/src/photos-operation-shadows-highlights-correction.c
b/src/photos-operation-shadows-highlights-correction.c
new file mode 100644
index 0000000..d04172e
--- /dev/null
+++ b/src/photos-operation-shadows-highlights-correction.c
@@ -0,0 +1,457 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2017 Red Hat, Inc.
+ * Copyright © 2017 Thomas Manni
+ * Copyright © 2012 – 2015 Ulrich Pegelow
+ *
+ * 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/>.
+ */
+
+/* Based on code from:
+ * + Darktable
+ * + GEGL
+ */
+
+
+#include "config.h"
+
+#include <math.h>
+
+#include <babl/babl.h>
+#include <gegl.h>
+
+#include "photos-operation-shadows-highlights-correction.h"
+
+
+struct _PhotosOperationShadowsHighlightsCorrection
+{
+ GeglOperationPointComposer parent_instance;
+ gdouble compress;
+ gdouble highlights;
+ gdouble highlights_color_correct;
+ gdouble shadows;
+ gdouble shadows_color_correct;
+ gdouble whitepoint;
+};
+
+enum
+{
+ PROP_0,
+ PROP_COMPRESS,
+ PROP_HIGHLIGHTS,
+ PROP_HIGHLIGHTS_COLOR_CORRECT,
+ PROP_SHADOWS,
+ PROP_SHADOWS_COLOR_CORRECT,
+ PROP_WHITEPOINT
+};
+
+
+G_DEFINE_TYPE (PhotosOperationShadowsHighlightsCorrection,
+ photos_operation_shadows_highlights_correction,
+ GEGL_TYPE_OPERATION_POINT_COMPOSER);
+
+
+static GeglRectangle
+photos_operation_shadows_highlights_correction_get_bounding_box (GeglOperation *operation)
+{
+ GeglRectangle *in_bbox;
+ GeglRectangle bbox;
+
+ gegl_rectangle_set (&bbox, 0, 0, 0, 0);
+
+ in_bbox = gegl_operation_source_get_bounding_box (operation, "input");
+ if (in_bbox == NULL)
+ goto out;
+
+ bbox = *in_bbox;
+
+ out:
+ return bbox;
+}
+
+
+static void
+photos_operation_shadows_highlights_correction_prepare (GeglOperation *operation)
+{
+ const Babl *format_cie_l;
+ const Babl *format_cie_laba;
+
+ format_cie_l = babl_format ("CIE L float");
+ format_cie_laba = babl_format ("CIE Lab alpha float");
+
+ gegl_operation_set_format (operation, "aux", format_cie_l);
+ gegl_operation_set_format (operation, "input", format_cie_laba);
+ gegl_operation_set_format (operation, "output", format_cie_laba);
+}
+
+
+static gboolean
+photos_operation_shadows_highlights_correction_process (GeglOperation *operation,
+ void *in_buf,
+ void *aux_buf,
+ void *out_buf,
+ glong n_pixels,
+ const GeglRectangle *roi,
+ gint level)
+{
+ PhotosOperationShadowsHighlightsCorrection *self = PHOTOS_OPERATION_SHADOWS_HIGHLIGHTS_CORRECTION
(operation);
+ gfloat *aux = aux_buf;
+ gfloat *in = in_buf;
+ gfloat *out = out_buf;
+ gfloat compress;
+ gfloat compress_100 = (gfloat) self->compress / 100.0f;
+ gfloat compress_inverted;
+ gfloat doublemax;
+ gfloat halfmax;
+ gfloat highlights;
+ gfloat highlights_100 = (gfloat) self->highlights / 100.0f;
+ gfloat highlights_color_correct;
+ gfloat highlights_color_correct_100 = (gfloat) self->highlights_color_correct / 100.0f;
+ gfloat highlights_color_correct_inverted;
+ gfloat highlights_sign_negated;
+ gfloat lmax = 1.0f;
+ gfloat low_approximation = 0.01f;
+ gfloat shadows;
+ gfloat shadows_100 = (gfloat) self->shadows / 100.0f;
+ gfloat shadows_color_correct;
+ gfloat shadows_color_correct_100 = (gfloat) self->shadows_color_correct / 100.0f;
+ gfloat shadows_color_correct_inverted;
+ gfloat shadows_sign;
+ gfloat whitepoint = 1.0f - (gfloat) self->whitepoint / 100.0f;
+ glong i;
+
+ doublemax = lmax * 2.0f;
+ halfmax = lmax / 2.0f;
+
+ compress = fminf (compress_100, 0.99f);
+ g_return_val_if_fail (compress >= 0.0f, FALSE);
+
+ compress_inverted = 1.0f - compress;
+
+ g_return_val_if_fail (-1.0f <= highlights_100 && highlights_100 <= 1.0f, FALSE);
+ highlights = 2.0f * highlights_100;
+
+ g_return_val_if_fail (0.0f <= highlights_color_correct_100 && highlights_color_correct_100 <= 1.0f, FALSE);
+ highlights_sign_negated = -highlights < 0.0f ? -1.0f : 1.0f;
+ highlights_color_correct = (highlights_color_correct_100 - 0.5f) * highlights_sign_negated + 0.5f;
+ highlights_color_correct_inverted = 1.0f - highlights_color_correct;
+
+ g_return_val_if_fail (-1.0f <= shadows_100 && shadows_100 <= 1.0f, FALSE);
+ shadows = 2.0f * shadows_100;
+
+ g_return_val_if_fail (0.0f <= shadows_color_correct_100 && shadows_color_correct_100 <= 1.0f, FALSE);
+ shadows_sign = shadows < 0.0f ? -1.0f : 1.0f;
+ shadows_color_correct = (shadows_color_correct_100 - 0.5f) * shadows_sign + 0.5f;
+ shadows_color_correct_inverted = 1.0f - shadows_color_correct;
+
+ g_return_val_if_fail (whitepoint >= 0.01f, FALSE);
+
+ for (i = 0; i < n_pixels; i++)
+ {
+ gfloat ta[3];
+ gfloat tb[3];
+ gfloat highlights_xform;
+ gfloat highlights2 = highlights * highlights;
+ gfloat shadows_xform;
+ gfloat shadows2 = shadows * shadows;
+
+ ta[0] = in[0] / 100.0f;
+ ta[1] = in[1] / 128.0f;
+ ta[2] = in[2] / 128.0f;
+
+ tb[0] = (100.0f - aux[0]) / 100.0f;
+ tb[1] = 0.0f;
+ tb[2] = 0.0f;
+
+ ta[0] = ta[0] > 0.0f ? ta[0] / whitepoint : ta[0];
+ tb[0] = tb[0] > 0.0f ? tb[0] / whitepoint : tb[0];
+
+ highlights_xform = CLAMP (1.0f - tb[0] / compress_inverted, 0.0f, 1.0f);
+
+ while (highlights2 > 0.0f)
+ {
+ gfloat chunk;
+ gfloat href;
+ gfloat la;
+ gfloat la_abs;
+ gfloat la_inverted;
+ gfloat la_inverted_abs;
+ gfloat lb;
+ gfloat lmax_la_sign;
+ gfloat lref;
+ gfloat optrans;
+ gfloat optrans_inverted;
+
+ la = ta[0];
+ lmax_la_sign = lmax - la < 0.0f ? -1.0f : 1.0f;
+ lb = (tb[0] - halfmax) * highlights_sign_negated * lmax_la_sign + halfmax;
+
+ la_abs = fabsf (la);
+ lref = copysignf (la_abs > low_approximation ? 1.0f / la_abs : 1.0f / low_approximation, la);
+
+ la_inverted = 1.0f - la;
+ la_inverted_abs = fabsf (1.0f - la);
+ href = copysignf (la_inverted_abs > low_approximation ? 1.0f / la_inverted_abs : 1.0f /
low_approximation,
+ la_inverted);
+
+ chunk = fminf (highlights2, 1.0f);
+ optrans = chunk * highlights_xform;
+ optrans_inverted = 1.0f - optrans;
+
+ highlights2 -= 1.0f;
+
+ ta[0] = la * optrans_inverted
+ + (la > halfmax ? lmax - (lmax - doublemax * (la - halfmax)) * (lmax - lb) : doublemax * la *
lb) * optrans;
+
+ ta[1] = ta[1] * optrans_inverted
+ + (ta[1] + tb[1]) * (ta[0] * lref * highlights_color_correct_inverted
+ + (1.0f - ta[0]) * href * highlights_color_correct) * optrans;
+
+ ta[2] = ta[2] * optrans_inverted
+ + (ta[2] + tb[2]) * (ta[0] * lref * highlights_color_correct_inverted
+ + (1.0f - ta[0]) * href * highlights_color_correct) * optrans;
+ }
+
+ shadows_xform = CLAMP (tb[0] / compress_inverted - compress / compress_inverted, 0.0f, 1.0f);
+
+ while (shadows2 > 0.0f)
+ {
+ gfloat chunk;
+ gfloat href;
+ gfloat la;
+ gfloat la_abs;
+ gfloat la_inverted;
+ gfloat la_inverted_abs;
+ gfloat lb;
+ gfloat lmax_la_sign;
+ gfloat lref;
+ gfloat optrans;
+ gfloat optrans_inverted;
+
+ la = ta[0];
+ lmax_la_sign = lmax - la < 0.0f ? -1.0f : 1.0f;
+ lb = (tb[0] - halfmax) * shadows_sign * lmax_la_sign + halfmax;
+
+ la_abs = fabsf (la);
+ lref = copysignf (la_abs > low_approximation ? 1.0f / la_abs : 1.0f / low_approximation, la);
+
+ la_inverted = 1.0f - la;
+ la_inverted_abs = fabsf (1.0f - la);
+ href = copysignf (la_inverted_abs > low_approximation ? 1.0f / la_inverted_abs : 1.0f /
low_approximation,
+ la_inverted);
+
+ chunk = fminf (shadows2, 1.0f);
+ optrans = chunk * shadows_xform;
+ optrans_inverted = 1.0f - optrans;
+
+ shadows2 -= 1.0f;
+
+ ta[0] = la * optrans_inverted
+ + (la > halfmax ? lmax - (lmax - doublemax * (la - halfmax)) * (lmax - lb) : doublemax * la *
lb) * optrans;
+
+ ta[1] = ta[1] * optrans_inverted
+ + (ta[1] + tb[1]) * (ta[0] * lref * shadows_color_correct
+ + (1.0f - ta[0]) * href * shadows_color_correct_inverted) * optrans;
+
+ ta[2] = ta[2] * optrans_inverted
+ + (ta[2] + tb[2]) * (ta[0] * lref * shadows_color_correct
+ + (1.0f - ta[0]) * href * shadows_color_correct_inverted) * optrans;
+ }
+
+ out[0] = ta[0] * 100.0f;
+ out[1] = ta[1] * 128.0f;
+ out[2] = ta[2] * 128.0f;
+ out[3] = in[3];
+
+ aux++;
+ in += 4;
+ out += 4;
+ }
+
+ return TRUE;
+}
+
+
+static void
+photos_operation_shadows_highlights_correction_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PhotosOperationShadowsHighlightsCorrection *self = PHOTOS_OPERATION_SHADOWS_HIGHLIGHTS_CORRECTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_COMPRESS:
+ g_value_set_double (value, self->compress);
+ break;
+
+ case PROP_HIGHLIGHTS:
+ g_value_set_double (value, self->highlights);
+ break;
+
+ case PROP_HIGHLIGHTS_COLOR_CORRECT:
+ g_value_set_double (value, self->highlights_color_correct);
+ break;
+
+ case PROP_SHADOWS:
+ g_value_set_double (value, self->shadows);
+ break;
+
+ case PROP_SHADOWS_COLOR_CORRECT:
+ g_value_set_double (value, self->shadows_color_correct);
+ break;
+
+ case PROP_WHITEPOINT:
+ g_value_set_double (value, self->whitepoint);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+photos_operation_shadows_highlights_correction_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PhotosOperationShadowsHighlightsCorrection *self = PHOTOS_OPERATION_SHADOWS_HIGHLIGHTS_CORRECTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_COMPRESS:
+ self->compress = g_value_get_double (value);
+ break;
+
+ case PROP_HIGHLIGHTS:
+ self->highlights = g_value_get_double (value);
+ break;
+
+ case PROP_HIGHLIGHTS_COLOR_CORRECT:
+ self->highlights_color_correct = g_value_get_double (value);
+ break;
+
+ case PROP_SHADOWS:
+ self->shadows = g_value_get_double (value);
+ break;
+
+ case PROP_SHADOWS_COLOR_CORRECT:
+ self->shadows_color_correct = g_value_get_double (value);
+ break;
+
+ case PROP_WHITEPOINT:
+ self->whitepoint = g_value_get_double (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+photos_operation_shadows_highlights_correction_init (PhotosOperationShadowsHighlightsCorrection *self)
+{
+}
+
+
+static void
+photos_operation_shadows_highlights_correction_class_init (PhotosOperationShadowsHighlightsCorrectionClass
*class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (class);
+ GeglOperationPointComposerClass *point_composer_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (class);
+
+ operation_class->opencl_support = FALSE;
+
+ object_class->get_property = photos_operation_shadows_highlights_correction_get_property;
+ object_class->set_property = photos_operation_shadows_highlights_correction_set_property;
+ operation_class->get_bounding_box = photos_operation_shadows_highlights_correction_get_bounding_box;
+ operation_class->prepare = photos_operation_shadows_highlights_correction_prepare;
+ point_composer_class->process = photos_operation_shadows_highlights_correction_process;
+
+ g_object_class_install_property (object_class,
+ PROP_COMPRESS,
+ g_param_spec_double ("compress",
+ "Compress",
+ "Compress the effect on shadows/highlights and
preserve "
+ "midtones",
+ 0.0,
+ 100.0,
+ 50.0,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_HIGHLIGHTS,
+ g_param_spec_double ("highlights",
+ "Highlights",
+ "Adjust exposure of highlights",
+ -100.0,
+ 100.0,
+ -50.0,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_HIGHLIGHTS_COLOR_CORRECT,
+ g_param_spec_double ("highlights-color-correct",
+ "Highlights Color Correct",
+ "Adjust saturation of highlights",
+ 0.0,
+ 100.0,
+ 50.0,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_SHADOWS,
+ g_param_spec_double ("shadows",
+ "Shadows",
+ "Adjust exposure of shadows",
+ -100.0,
+ 100.0,
+ 50.0,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_SHADOWS_COLOR_CORRECT,
+ g_param_spec_double ("shadows-color-correct",
+ "Shadows Color Correct",
+ "Adjust saturation of shadows",
+ 0.0,
+ 100.0,
+ 100.0,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_WHITEPOINT,
+ g_param_spec_double ("whitepoint",
+ "Whitepoint",
+ "Shift white point",
+ -10.0,
+ 10.0,
+ 0.0,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
+ gegl_operation_class_set_keys (operation_class,
+ "name", "photos:shadows-highlights-correction",
+ "title", "Shadows Highlights Correction",
+ "description", "Adjust shadows and highlights using a blurred auxiliary",
+ "categories", "hidden",
+ "license", "GPL3+",
+ NULL);
+}
diff --git a/src/photos-operation-shadows-highlights-correction.h
b/src/photos-operation-shadows-highlights-correction.h
new file mode 100644
index 0000000..c280833
--- /dev/null
+++ b/src/photos-operation-shadows-highlights-correction.h
@@ -0,0 +1,42 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2017 Red Hat, Inc.
+ * Copyright © 2017 Thomas Manni
+ * Copyright © 2012 – 2015 Ulrich Pegelow
+ *
+ * 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/>.
+ */
+
+/* Based on code from:
+ * + Darktable
+ * + GEGL
+ */
+
+#ifndef PHOTOS_OPERATION_SHADOWS_HIGHLIGHTS_CORRECTION_H
+#define PHOTOS_OPERATION_SHADOWS_HIGHLIGHTS_CORRECTION_H
+
+#include <gegl-plugin.h>
+
+G_BEGIN_DECLS
+
+#define PHOTOS_TYPE_OPERATION_SHADOWS_HIGHLIGHTS_CORRECTION
(photos_operation_shadows_highlights_correction_get_type ())
+G_DECLARE_FINAL_TYPE (PhotosOperationShadowsHighlightsCorrection,
+ photos_operation_shadows_highlights_correction,
+ PHOTOS,
+ OPERATION_SHADOWS_HIGHLIGHTS_CORRECTION,
+ GeglOperationPointComposer);
+
+G_END_DECLS
+
+#endif /* PHOTOS_OPERATION_SHADOWS_HIGHLIGHTS_CORRECTION_H */
diff --git a/src/photos-operation-shadows-highlights.c b/src/photos-operation-shadows-highlights.c
new file mode 100644
index 0000000..7c51a5e
--- /dev/null
+++ b/src/photos-operation-shadows-highlights.c
@@ -0,0 +1,380 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2017 Red Hat, Inc.
+ * Copyright © 2017 Thomas Manni
+ * Copyright © 2012 – 2015 Ulrich Pegelow
+ *
+ * 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/>.
+ */
+
+/* Based on code from:
+ * + Darktable
+ * + GEGL
+ */
+
+
+#include "config.h"
+
+#include <math.h>
+
+#include <babl/babl.h>
+#include <gegl.h>
+
+#include "photos-operation-shadows-highlights.h"
+
+
+struct _PhotosOperationShadowsHighlights
+{
+ GeglOperationMeta parent_instance;
+ const Babl *format_blur;
+ GeglNode *convert_blur;
+ GeglNode *input;
+ GeglNode *output;
+ gfloat compress;
+ gfloat highlights;
+ gfloat highlights_color_correct;
+ gfloat radius;
+ gfloat shadows;
+ gfloat shadows_color_correct;
+ gfloat whitepoint;
+};
+
+enum
+{
+ PROP_0,
+ PROP_COMPRESS,
+ PROP_HIGHLIGHTS,
+ PROP_HIGHLIGHTS_COLOR_CORRECT,
+ PROP_RADIUS,
+ PROP_SHADOWS,
+ PROP_SHADOWS_COLOR_CORRECT,
+ PROP_WHITEPOINT
+};
+
+
+G_DEFINE_TYPE (PhotosOperationShadowsHighlights, photos_operation_shadows_highlights,
GEGL_TYPE_OPERATION_META);
+
+
+static gboolean
+photos_operation_shadows_highlights_is_nop (PhotosOperationShadowsHighlights *self)
+{
+ return GEGL_FLOAT_EQUAL (self->shadows, 0.0f)
+ && GEGL_FLOAT_EQUAL (self->highlights, 0.0f)
+ && GEGL_FLOAT_EQUAL (self->whitepoint, 0.0f);
+}
+
+
+static void
+photos_operation_shadows_highlights_setup (PhotosOperationShadowsHighlights *self)
+{
+ g_autoptr (GSList) children = NULL;
+ GSList *l;
+ GeglOperation *operation = GEGL_OPERATION (self);
+
+ g_return_if_fail (GEGL_IS_NODE (operation->node));
+ g_return_if_fail (GEGL_IS_NODE (self->input));
+ g_return_if_fail (GEGL_IS_NODE (self->output));
+
+ self->convert_blur = NULL;
+
+ children = gegl_node_get_children (operation->node);
+ for (l = children; l != NULL; l = l->next)
+ {
+ GeglNode *child = GEGL_NODE (l->data);
+
+ if (child == self->input || child == self->output)
+ continue;
+
+ gegl_node_remove_child (operation->node, child);
+ }
+
+ if (photos_operation_shadows_highlights_is_nop (self))
+ {
+ gegl_node_link (self->input, self->output);
+ }
+ else
+ {
+ GeglNode *blur;
+ GeglNode *shadows_highlights;
+
+ blur = gegl_node_new_child (operation->node,
+ "operation", "gegl:gaussian-blur",
+ "abyss-policy", 1,
+ NULL);
+
+ if (self->format_blur == NULL)
+ self->format_blur = babl_format ("YaA float");
+
+ self->convert_blur = gegl_node_new_child (operation->node,
+ "operation", "gegl:convert-format",
+ "format", self->format_blur,
+ NULL);
+
+ shadows_highlights = gegl_node_new_child (operation->node,
+ "operation", "photos:shadows-highlights-correction",
+ NULL);
+
+ gegl_node_link_many (self->input, self->convert_blur, blur, NULL);
+ gegl_node_connect_to (blur, "output", shadows_highlights, "aux");
+
+ gegl_node_link_many (self->input, shadows_highlights, self->output, NULL);
+
+ 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, "compress", shadows_highlights, "compress");
+ gegl_operation_meta_redirect (operation, "highlights", shadows_highlights, "highlights");
+ gegl_operation_meta_redirect (operation, "highlights-color-correct",
+ shadows_highlights, "highlights-color-correct");
+ gegl_operation_meta_redirect (operation, "shadows", shadows_highlights, "shadows");
+ gegl_operation_meta_redirect (operation, "shadows-color-correct", shadows_highlights,
"shadows-color-correct");
+ gegl_operation_meta_redirect (operation, "whitepoint", shadows_highlights, "whitepoint");
+
+ gegl_operation_meta_watch_nodes (operation, blur, self->convert_blur, shadows_highlights, NULL);
+ }
+}
+
+
+static void
+photos_operation_shadows_highlights_attach (GeglOperation *operation)
+{
+ PhotosOperationShadowsHighlights *self = PHOTOS_OPERATION_SHADOWS_HIGHLIGHTS (operation);
+
+ self->input = gegl_node_get_output_proxy (operation->node, "input");
+ self->output = gegl_node_get_output_proxy (operation->node, "output");
+ photos_operation_shadows_highlights_setup (self);
+}
+
+
+static void
+photos_operation_shadows_highlights_prepare (GeglOperation *operation)
+{
+ PhotosOperationShadowsHighlights *self = PHOTOS_OPERATION_SHADOWS_HIGHLIGHTS (operation);
+ const Babl *format_blur = NULL;
+ const Babl *format_input;
+
+ format_input = gegl_operation_get_source_format (operation, "input");
+ if (format_input == NULL)
+ {
+ format_blur = babl_format ("YaA float");
+ goto out;
+ }
+
+ if (babl_format_has_alpha (format_input))
+ format_blur = babl_format ("YaA float");
+ else
+ format_blur = babl_format ("Y float");
+
+ out:
+ g_return_if_fail (format_blur != NULL);
+
+ if (self->format_blur != format_blur)
+ {
+ self->format_blur = format_blur;
+ if (self->convert_blur != NULL)
+ gegl_node_set (self->convert_blur, "format", self->format_blur, NULL);
+ }
+}
+
+
+static void
+photos_operation_shadows_highlights_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec
*pspec)
+{
+ PhotosOperationShadowsHighlights *self = PHOTOS_OPERATION_SHADOWS_HIGHLIGHTS (object);
+
+ switch (prop_id)
+ {
+ case PROP_COMPRESS:
+ g_value_set_double (value, (gdouble) self->compress);
+ break;
+
+ case PROP_HIGHLIGHTS:
+ g_value_set_double (value, (gdouble) self->highlights);
+ break;
+
+ case PROP_HIGHLIGHTS_COLOR_CORRECT:
+ g_value_set_double (value, (gdouble) self->highlights_color_correct);
+ break;
+
+ case PROP_RADIUS:
+ g_value_set_double (value, (gdouble) self->radius);
+ break;
+
+ case PROP_SHADOWS:
+ g_value_set_double (value, (gdouble) self->shadows);
+ break;
+
+ case PROP_SHADOWS_COLOR_CORRECT:
+ g_value_set_double (value, (gdouble) self->shadows_color_correct);
+ break;
+
+ case PROP_WHITEPOINT:
+ g_value_set_double (value, (gdouble) self->whitepoint);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+photos_operation_shadows_highlights_set_property (GObject *object, guint prop_id, const GValue *value,
GParamSpec *pspec)
+{
+ PhotosOperationShadowsHighlights *self = PHOTOS_OPERATION_SHADOWS_HIGHLIGHTS (object);
+ gboolean is_nop;
+ gboolean was_nop;
+
+ was_nop = photos_operation_shadows_highlights_is_nop (self);
+
+ switch (prop_id)
+ {
+ case PROP_COMPRESS:
+ self->compress = (gfloat) g_value_get_double (value);
+ break;
+
+ case PROP_HIGHLIGHTS:
+ self->highlights = (gfloat) g_value_get_double (value);
+ break;
+
+ case PROP_HIGHLIGHTS_COLOR_CORRECT:
+ self->highlights_color_correct = (gfloat) g_value_get_double (value);
+ break;
+
+ case PROP_RADIUS:
+ self->radius = (gfloat) g_value_get_double (value);
+ break;
+
+ case PROP_SHADOWS:
+ self->shadows = (gfloat) g_value_get_double (value);
+ break;
+
+ case PROP_SHADOWS_COLOR_CORRECT:
+ self->shadows_color_correct = (gfloat) g_value_get_double (value);
+ break;
+
+ case PROP_WHITEPOINT:
+ self->whitepoint = (gfloat) g_value_get_double (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+
+ is_nop = photos_operation_shadows_highlights_is_nop (self);
+ if (GEGL_OPERATION (self)->node != NULL && is_nop != was_nop)
+ photos_operation_shadows_highlights_setup (self);
+}
+
+
+static void
+photos_operation_shadows_highlights_init (PhotosOperationShadowsHighlights *self)
+{
+}
+
+
+static void
+photos_operation_shadows_highlights_class_init (PhotosOperationShadowsHighlightsClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (class);
+
+ operation_class->opencl_support = FALSE;
+
+ object_class->get_property = photos_operation_shadows_highlights_get_property;
+ object_class->set_property = photos_operation_shadows_highlights_set_property;
+ operation_class->attach = photos_operation_shadows_highlights_attach;
+ operation_class->prepare = photos_operation_shadows_highlights_prepare;
+
+ g_object_class_install_property (object_class,
+ PROP_COMPRESS,
+ g_param_spec_double ("compress",
+ "Compress",
+ "Compress the effect on shadows/highlights and
preserve "
+ "midtones",
+ 0.0,
+ 100.0,
+ 50.0,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_HIGHLIGHTS,
+ g_param_spec_double ("highlights",
+ "Highlights",
+ "Adjust exposure of highlights",
+ -100.0,
+ 100.0,
+ -50.0,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_HIGHLIGHTS_COLOR_CORRECT,
+ g_param_spec_double ("highlights-color-correct",
+ "Highlights Color Correct",
+ "Adjust saturation of highlights",
+ 0.0,
+ 100.0,
+ 50.0,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_RADIUS,
+ g_param_spec_double ("radius",
+ "Radius",
+ "Spatial extent",
+ 0.1,
+ 1500.0,
+ 100.0,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_SHADOWS,
+ g_param_spec_double ("shadows",
+ "Shadows",
+ "Adjust exposure of shadows",
+ -100.0,
+ 100.0,
+ 50.0,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_SHADOWS_COLOR_CORRECT,
+ g_param_spec_double ("shadows-color-correct",
+ "Shadows Color Correct",
+ "Adjust saturation of shadows",
+ 0.0,
+ 100.0,
+ 100.0,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_WHITEPOINT,
+ g_param_spec_double ("whitepoint",
+ "Whitepoint",
+ "Shift white point",
+ -10.0,
+ 10.0,
+ 0.0,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
+ gegl_operation_class_set_keys (operation_class,
+ "name", "photos:shadows-highlights",
+ "title", "Shadows Highlights",
+ "description", "Adjust shadows and highlights",
+ "categories", "light",
+ "license", "GPL3+",
+ NULL);
+}
diff --git a/src/photos-operation-shadows-highlights.h b/src/photos-operation-shadows-highlights.h
new file mode 100644
index 0000000..65d93f5
--- /dev/null
+++ b/src/photos-operation-shadows-highlights.h
@@ -0,0 +1,42 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2017 Red Hat, Inc.
+ * Copyright © 2017 Thomas Manni
+ * Copyright © 2012 – 2015 Ulrich Pegelow
+ *
+ * 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/>.
+ */
+
+/* Based on code from:
+ * + Darktable
+ * + GEGL
+ */
+
+#ifndef PHOTOS_OPERATION_SHADOWS_HIGHLIGHTS_H
+#define PHOTOS_OPERATION_SHADOWS_HIGHLIGHTS_H
+
+#include <gegl-plugin.h>
+
+G_BEGIN_DECLS
+
+#define PHOTOS_TYPE_OPERATION_SHADOWS_HIGHLIGHTS (photos_operation_shadows_highlights_get_type ())
+G_DECLARE_FINAL_TYPE (PhotosOperationShadowsHighlights,
+ photos_operation_shadows_highlights,
+ PHOTOS,
+ OPERATION_SHADOWS_HIGHLIGHTS,
+ GeglOperationMeta);
+
+G_END_DECLS
+
+#endif /* PHOTOS_OPERATION_SHADOWS_HIGHLIGHTS_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]