[gegl] saturation: add CIE Yuv and RGB interpolation methods, issue #171
- From: Øyvind "pippin" Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] saturation: add CIE Yuv and RGB interpolation methods, issue #171
- Date: Thu, 4 Jul 2019 12:43:41 +0000 (UTC)
commit 93c0fe7f5b56eafac051eb9dc9cefc3cbaafceaf
Author: Øyvind Kolås <pippin gimp org>
Date: Thu Jul 4 14:38:38 2019 +0200
saturation: add CIE Yuv and RGB interpolation methods, issue #171
All three methods are linear interpolations towards luminance desaturation of
the image, though in different color spaces - yielding slightly different
results. The default behavior remains the CIE Lab based interpolation for now.
Perhaps in a later release we will also change the default to be the
interpolation in linear native space, while adding CMYK support to desaturate
that does not lose the separation.
operations/common/saturation.c | 172 ++++++++++++++++++++++++++++++++---------
1 file changed, 134 insertions(+), 38 deletions(-)
---
diff --git a/operations/common/saturation.c b/operations/common/saturation.c
index 6c712717f..205ce6299 100644
--- a/operations/common/saturation.c
+++ b/operations/common/saturation.c
@@ -14,6 +14,7 @@
* License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
*
* Copyright 2016 Red Hat, Inc.
+ * 2019 Øyvind Kolås
*/
#include "config.h"
@@ -21,11 +22,23 @@
#ifdef GEGL_PROPERTIES
+enum_start (gegl_saturation_type)
+ enum_value (GEGL_SATURATION_TYPE_CIE_LAB, "CIE-Lab", N_("CIE Lab / Lch"))
+ enum_value (GEGL_SATURATION_TYPE_NATIVE, "linear", N_("linear data, RGB"))
+ /* will also work on CMYK in the future */
+ enum_value (GEGL_SATURATION_TYPE_CIE_YUV, "CIE-Yuv", N_("CIE Yuv"))
+enum_end (GeglSaturationType)
+
property_double (scale, _("Scale"), 1.0)
description(_("Scale, strength of effect"))
value_range (0.0, 10.0)
ui_range (0.0, 2.0)
+property_enum (colorspace, _("Color Space"),
+ description(_("Which color space to do interpolation in."))
+ GeglSaturationType, gegl_saturation_type,
+ GEGL_SATURATION_TYPE_NATIVE)
+
#else
#define GEGL_OP_POINT_FILTER
@@ -139,54 +152,137 @@ process_lch_alpha (GeglOperation *operation,
}
}
-static void prepare (GeglOperation *operation)
+
+static void
+process_cie_yuv_alpha (GeglOperation *operation,
+ void *in_buf,
+ void *out_buf,
+ glong n_pixels,
+ const GeglRectangle *roi,
+ gint level)
{
- const Babl *space = gegl_operation_get_source_space (operation, "input");
GeglProperties *o = GEGL_PROPERTIES (operation);
- const Babl *format;
- const Babl *input_format;
- const Babl *input_model;
- const Babl *lch_model;
+ gfloat *in = in_buf;
+ gfloat *out = out_buf;
+ glong i;
+ float scale = o->scale;
- input_format = gegl_operation_get_source_format (operation, "input");
- if (input_format == NULL)
+#define CIE_u_origin (4/19.0f)
+#define CIE_v_origin (9/19.0f)
+
+ for (i = 0; i < n_pixels; i++)
{
- format = babl_format_with_space ("CIE Lab alpha float", space);
- o->user_data = process_lab_alpha;
- goto out;
+ out[0] = in[0];
+ out[1] = (in[1] - CIE_u_origin) * scale + CIE_u_origin;
+ out[2] = (in[2] - CIE_v_origin) * scale + CIE_v_origin;
+ out[3] = in[3];
+
+ in += 4;
+ out += 4;
}
+}
- input_model = babl_format_get_model (input_format);
+static void
+process_rgb_alpha (GeglOperation *operation,
+ void *in_buf,
+ void *out_buf,
+ glong n_pixels,
+ const GeglRectangle *roi,
+ gint level)
+{
+ GeglProperties *o = GEGL_PROPERTIES (operation);
+ const Babl *space = gegl_operation_get_source_space (operation, "input");
+ gfloat *in = in_buf;
+ gfloat *out = out_buf;
+ glong i;
+ float scale = o->scale;
+ float rscale = 1.0f - o->scale;
+ double luminance[3];
+ float luminance_f[3];
- if (babl_format_has_alpha (input_format))
- {
- lch_model = babl_model_with_space ("CIE LCH(ab) alpha", space);
- if (input_model == lch_model)
- {
- format = babl_format_with_space ("CIE LCH(ab) alpha float", space);
- o->user_data = process_lch_alpha;
- }
- else
- {
- format = babl_format_with_space ("CIE Lab alpha float", space);
- o->user_data = process_lab_alpha;
- }
- }
- else
+ babl_space_get_rgb_luminance (space,
+ &luminance[0], &luminance[1], &luminance[2]);
+ for (int c = 0; c < 3; c ++)
+ luminance_f[c] = luminance[c];
+
+ for (i = 0; i < n_pixels; i++)
{
- lch_model = babl_model_with_space ("CIE LCH(ab)", space);
- if (input_model == lch_model)
- {
- format = babl_format_with_space ("CIE LCH(ab) float", space);
- o->user_data = process_lch;
- }
- else
- {
- format = babl_format_with_space ("CIE Lab float", space);
- o->user_data = process_lab;
- }
+ gfloat desaturated = (in[0] * luminance_f[0] +
+ in[1] * luminance_f[1] +
+ in[2] * luminance_f[2]) * rscale;
+ for (int c = 0; c < 3; c ++)
+ out[c] = desaturated + in[c] * scale;
+ out[3] = in[3];
+
+ in += 4;
+ out += 4;
}
+}
+
+
+static void prepare (GeglOperation *operation)
+{
+ const Babl *space = gegl_operation_get_source_space (operation, "input");
+ GeglProperties *o = GEGL_PROPERTIES (operation);
+ const Babl *format;
+
+ switch (o->colorspace)
+ {
+ case GEGL_SATURATION_TYPE_NATIVE:
+ format = babl_format_with_space ("RGBA float", space);
+ o->user_data = process_rgb_alpha;
+ break;
+ case GEGL_SATURATION_TYPE_CIE_YUV:
+ format = babl_format_with_space ("CIE Yuv alpha float", space);
+ o->user_data = process_cie_yuv_alpha;
+ break;
+ case GEGL_SATURATION_TYPE_CIE_LAB:
+ {
+ const Babl *input_format;
+ const Babl *input_model;
+ const Babl *lch_model;
+
+ input_format = gegl_operation_get_source_format (operation, "input");
+ if (input_format == NULL)
+ {
+ format = babl_format_with_space ("CIE Lab alpha float", space);
+ o->user_data = process_lab_alpha;
+ goto out;
+ }
+
+ input_model = babl_format_get_model (input_format);
+ if (babl_format_has_alpha (input_format))
+ {
+ lch_model = babl_model_with_space ("CIE LCH(ab) alpha", space);
+ if (input_model == lch_model)
+ {
+ format = babl_format_with_space ("CIE LCH(ab) alpha float", space);
+ o->user_data = process_lch_alpha;
+ }
+ else
+ {
+ format = babl_format_with_space ("CIE Lab alpha float", space);
+ o->user_data = process_lab_alpha;
+ }
+ }
+ else
+ {
+ lch_model = babl_model_with_space ("CIE LCH(ab)", space);
+ if (input_model == lch_model)
+ {
+ format = babl_format_with_space ("CIE LCH(ab) float", space);
+ o->user_data = process_lch;
+ }
+ else
+ {
+ format = babl_format_with_space ("CIE Lab float", space);
+ o->user_data = process_lab;
+ }
+ }
+ }
+ break;
+ }
out:
gegl_operation_set_format (operation, "input", format);
gegl_operation_set_format (operation, "output", format);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]