[gimp] app: add subtractive compositing functions to GimpOperationLayerMode
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: add subtractive compositing functions to GimpOperationLayerMode
- Date: Wed, 8 Mar 2017 19:19:00 +0000 (UTC)
commit 398a7b023c996e5f7b77db5419197424841b42c1
Author: Ell <ell_se yahoo com>
Date: Wed Mar 8 12:07:22 2017 -0500
app: add subtractive compositing functions to GimpOperationLayerMode
These are more general, and more expensive, versions of the non-
subtractive compositing functions. They are used with modes that
specify the SUBTRACTIVE flag. This doesn't affect anything yet, but
the next commit ports color-erase mode to a blendfun.
.../layer-modes/gimpoperationlayermode.c | 413 +++++++++++++++++---
1 files changed, 349 insertions(+), 64 deletions(-)
---
diff --git a/app/operations/layer-modes/gimpoperationlayermode.c
b/app/operations/layer-modes/gimpoperationlayermode.c
index afcafae..f53f1b0 100644
--- a/app/operations/layer-modes/gimpoperationlayermode.c
+++ b/app/operations/layer-modes/gimpoperationlayermode.c
@@ -73,43 +73,72 @@ static gboolean gimp_operation_layer_mode_process (GeglOperation *
static GimpLayerModeAffectMask
gimp_operation_layer_mode_real_get_affect_mask (GimpOperationLayerMode *layer_mode);
-static inline void composite_func_src_atop_core (gfloat *in,
- gfloat *layer,
- gfloat *comp,
- gfloat *mask,
- gfloat opacity,
- gfloat *out,
- gint samples);
-static inline void composite_func_dst_atop_core (gfloat *in,
- gfloat *layer,
- gfloat *comp,
- gfloat *mask,
- gfloat opacity,
- gfloat *out,
- gint samples);
-static inline void composite_func_src_in_core (gfloat *in,
- gfloat *layer,
- gfloat *comp,
- gfloat *mask,
- gfloat opacity,
- gfloat *out,
- gint samples);
-static inline void composite_func_src_over_core (gfloat *in,
- gfloat *layer,
- gfloat *comp,
- gfloat *mask,
- gfloat opacity,
- gfloat *out,
- gint samples);
+static inline void composite_func_src_atop_core (gfloat *in,
+ gfloat *layer,
+ gfloat *comp,
+ gfloat *mask,
+ gfloat opacity,
+ gfloat *out,
+ gint samples);
+static inline void composite_func_dst_atop_core (gfloat *in,
+ gfloat *layer,
+ gfloat *comp,
+ gfloat *mask,
+ gfloat opacity,
+ gfloat *out,
+ gint samples);
+static inline void composite_func_src_in_core (gfloat *in,
+ gfloat *layer,
+ gfloat *comp,
+ gfloat *mask,
+ gfloat opacity,
+ gfloat *out,
+ gint samples);
+static inline void composite_func_src_over_core (gfloat *in,
+ gfloat *layer,
+ gfloat *comp,
+ gfloat *mask,
+ gfloat opacity,
+ gfloat *out,
+ gint samples);
+
+static inline void composite_func_src_atop_sub_core (gfloat *in,
+ gfloat *layer,
+ gfloat *comp,
+ gfloat *mask,
+ gfloat opacity,
+ gfloat *out,
+ gint samples);
+static inline void composite_func_dst_atop_sub_core (gfloat *in,
+ gfloat *layer,
+ gfloat *comp,
+ gfloat *mask,
+ gfloat opacity,
+ gfloat *out,
+ gint samples);
+static inline void composite_func_src_sub_in_core (gfloat *in,
+ gfloat *layer,
+ gfloat *comp,
+ gfloat *mask,
+ gfloat opacity,
+ gfloat *out,
+ gint samples);
+static inline void composite_func_src_over_sub_core (gfloat *in,
+ gfloat *layer,
+ gfloat *comp,
+ gfloat *mask,
+ gfloat opacity,
+ gfloat *out,
+ gint samples);
#if COMPILE_SSE2_INTRINISICS
-static inline void composite_func_src_atop_sse2 (gfloat *in,
- gfloat *layer,
- gfloat *comp,
- gfloat *mask,
- gfloat opacity,
- gfloat *out,
- gint samples);
+static inline void composite_func_src_atop_sse2 (gfloat *in,
+ gfloat *layer,
+ gfloat *comp,
+ gfloat *mask,
+ gfloat opacity,
+ gfloat *out,
+ gint samples);
#endif
@@ -121,10 +150,15 @@ G_DEFINE_TYPE (GimpOperationLayerMode, gimp_operation_layer_mode,
static const Babl *gimp_layer_color_space_fish[3 /* from */][3 /* to */];
-static CompositeFunc composite_func_src_atop = composite_func_src_atop_core;
-static CompositeFunc composite_func_dst_atop = composite_func_dst_atop_core;
-static CompositeFunc composite_func_src_in = composite_func_src_in_core;
-static CompositeFunc composite_func_src_over = composite_func_src_over_core;
+static CompositeFunc composite_func_src_atop = composite_func_src_atop_core;
+static CompositeFunc composite_func_dst_atop = composite_func_dst_atop_core;
+static CompositeFunc composite_func_src_in = composite_func_src_in_core;
+static CompositeFunc composite_func_src_over = composite_func_src_over_core;
+
+static CompositeFunc composite_func_src_atop_sub = composite_func_src_atop_sub_core;
+static CompositeFunc composite_func_dst_atop_sub = composite_func_dst_atop_sub_core;
+static CompositeFunc composite_func_src_in_sub = composite_func_src_in_sub_core;
+static CompositeFunc composite_func_src_over_sub = composite_func_src_over_sub_core;
static void
@@ -498,6 +532,12 @@ gimp_operation_layer_mode_process_pixels (GeglOperation *operation,
}
+/* non-subtractive compositing functions. these functions expect comp[ALPHA]
+ * to be the same as layer[ALPHA]. when in[ALPHA] or layer[ALPHA] are zero,
+ * the value of comp[RED..BLUE] is unconstrained (in particular, it may be
+ * NaN).
+ */
+
static inline void
composite_func_src_atop_core (gfloat *in,
gfloat *layer,
@@ -680,6 +720,218 @@ composite_func_src_in_core (gfloat *in,
}
}
+/* subtractive compositing functions. these functions expect comp[ALPHA] to
+ * specify the modified alpha of the overlapping content, as a fraction of the
+ * original overlapping content (i.e., an alpha of 1.0 specifies that no
+ * content is subtracted.) when in[ALPHA] or layer[ALPHA] are zero, the value
+ * of comp[RED..BLUE] is unconstrained (in particular, it may be NaN).
+ */
+
+static inline void
+composite_func_src_atop_sub_core (gfloat *in,
+ gfloat *layer,
+ gfloat *comp,
+ gfloat *mask,
+ gfloat opacity,
+ gfloat *out,
+ gint samples)
+{
+ while (samples--)
+ {
+ gfloat layer_alpha = layer[ALPHA] * opacity;
+ gfloat comp_alpha = comp[ALPHA];
+ gfloat new_alpha;
+
+ if (mask)
+ layer_alpha *= *mask;
+
+ comp_alpha *= layer_alpha;
+
+ new_alpha = 1.0f - layer_alpha + comp_alpha;
+
+ if (in[ALPHA] == 0.0f || comp_alpha == 0.0f)
+ {
+ out[RED] = in[RED];
+ out[GREEN] = in[GREEN];
+ out[BLUE] = in[BLUE];
+ }
+ else
+ {
+ gfloat ratio = comp_alpha / new_alpha;
+ gint b;
+
+ for (b = RED; b < ALPHA; b++)
+ out[b] = comp[b] * ratio + in[b] * (1.0f - ratio);
+ }
+
+ new_alpha *= in[ALPHA];
+
+ out[ALPHA] = new_alpha;
+
+ in += 4;
+ layer += 4;
+ comp += 4;
+ out += 4;
+
+ if (mask)
+ mask++;
+ }
+}
+
+static inline void
+composite_func_src_over_sub_core (gfloat *in,
+ gfloat *layer,
+ gfloat *comp,
+ gfloat *mask,
+ gfloat opacity,
+ gfloat *out,
+ gint samples)
+{
+ while (samples--)
+ {
+ gfloat in_alpha = in[ALPHA];
+ gfloat layer_alpha = layer[ALPHA] * opacity;
+ gfloat comp_alpha = comp[ALPHA];
+ gfloat new_alpha;
+
+ if (mask)
+ layer_alpha *= *mask;
+
+ new_alpha = in_alpha + layer_alpha -
+ (2.0f - comp_alpha) * in_alpha * layer_alpha;
+
+ if (layer_alpha == 0.0f || new_alpha == 0.0f)
+ {
+ out[RED] = in[RED];
+ out[GREEN] = in[GREEN];
+ out[BLUE] = in[BLUE];
+ }
+ else if (in[ALPHA] == 0.0f)
+ {
+ out[RED] = layer[RED];
+ out[GREEN] = layer[GREEN];
+ out[BLUE] = layer[BLUE];
+ }
+ else
+ {
+ gfloat recip = 1.0f / new_alpha;
+ gint b;
+
+ for (b = RED; b < ALPHA; b++)
+ out[b] = (layer_alpha * (in_alpha * (comp_alpha * comp[b] - layer[b]) + layer[b] - in[b]) +
in[b]) * recip;
+ }
+
+ out[ALPHA] = new_alpha;
+
+ in += 4;
+ layer += 4;
+ comp += 4;
+ out += 4;
+
+ if (mask)
+ mask++;
+ }
+}
+
+static inline void
+composite_func_dst_atop_sub_core (gfloat *in,
+ gfloat *layer,
+ gfloat *comp,
+ gfloat *mask,
+ gfloat opacity,
+ gfloat *out,
+ gint samples)
+{
+ while (samples--)
+ {
+ gfloat in_alpha = in[ALPHA];
+ gfloat layer_alpha = layer[ALPHA] * opacity;
+ gfloat comp_alpha = comp[ALPHA];
+ gfloat new_alpha;
+
+ if (mask)
+ layer_alpha *= *mask;
+
+ comp_alpha *= in_alpha;
+
+ new_alpha = 1.0f - in_alpha + comp_alpha;
+
+ if (layer_alpha == 0.0f)
+ {
+ out[RED] = in[RED];
+ out[GREEN] = in[GREEN];
+ out[BLUE] = in[BLUE];
+ }
+ else if (in_alpha == 0.0f)
+ {
+ out[RED] = layer[RED];
+ out[GREEN] = layer[GREEN];
+ out[BLUE] = layer[BLUE];
+ }
+ else
+ {
+ gfloat ratio = comp_alpha / new_alpha;
+ gint b;
+
+ for (b = RED; b < ALPHA; b++)
+ out[b] = comp[b] * ratio + layer[b] * (1.0f - ratio);
+ }
+
+ new_alpha *= layer_alpha;
+
+ out[ALPHA] = new_alpha;
+
+ in += 4;
+ layer += 4;
+ comp += 4;
+ out += 4;
+
+ if (mask)
+ mask++;
+ }
+}
+
+static inline void
+composite_func_src_in_sub_core (gfloat *in,
+ gfloat *layer,
+ gfloat *comp,
+ gfloat *mask,
+ gfloat opacity,
+ gfloat *out,
+ gint samples)
+{
+ while (samples--)
+ {
+ gfloat new_alpha = in[ALPHA] * layer[ALPHA] * comp[ALPHA] * opacity;
+
+ if (mask)
+ new_alpha *= *mask;
+
+ if (new_alpha == 0.0f)
+ {
+ out[RED] = in[RED];
+ out[GREEN] = in[GREEN];
+ out[BLUE] = in[BLUE];
+ }
+ else
+ {
+ out[RED] = comp[RED];
+ out[GREEN] = comp[GREEN];
+ out[BLUE] = comp[BLUE];
+ }
+
+ out[ALPHA] = new_alpha;
+
+ in += 4;
+ layer += 4;
+ comp += 4;
+ out += 4;
+
+ if (mask)
+ mask++;
+ }
+}
+
#if COMPILE_SSE2_INTRINISICS
#include <emmintrin.h>
@@ -811,32 +1063,65 @@ gimp_composite_blend (GimpOperationLayerMode *layer_mode,
babl_process (blend_to_composite_fish, blend_out, blend_out, samples);
}
- switch (composite_mode)
+ if (! gimp_layer_mode_is_subtractive (layer_mode->layer_mode))
{
- case GIMP_LAYER_COMPOSITE_SRC_ATOP:
- default:
- composite_func_src_atop (in, layer, blend_out,
- mask, opacity,
- out, samples);
- break;
-
- case GIMP_LAYER_COMPOSITE_SRC_OVER:
- composite_func_src_over (in, layer, blend_out,
- mask, opacity,
- out, samples);
- break;
-
- case GIMP_LAYER_COMPOSITE_DST_ATOP:
- composite_func_dst_atop (in, layer, blend_out,
- mask, opacity,
- out, samples);
- break;
-
- case GIMP_LAYER_COMPOSITE_SRC_IN:
- composite_func_src_in (in, layer, blend_out,
- mask, opacity,
- out, samples);
- break;
+ switch (composite_mode)
+ {
+ case GIMP_LAYER_COMPOSITE_SRC_ATOP:
+ default:
+ composite_func_src_atop (in, layer, blend_out,
+ mask, opacity,
+ out, samples);
+ break;
+
+ case GIMP_LAYER_COMPOSITE_SRC_OVER:
+ composite_func_src_over (in, layer, blend_out,
+ mask, opacity,
+ out, samples);
+ break;
+
+ case GIMP_LAYER_COMPOSITE_DST_ATOP:
+ composite_func_dst_atop (in, layer, blend_out,
+ mask, opacity,
+ out, samples);
+ break;
+
+ case GIMP_LAYER_COMPOSITE_SRC_IN:
+ composite_func_src_in (in, layer, blend_out,
+ mask, opacity,
+ out, samples);
+ break;
+ }
+ }
+ else
+ {
+ switch (composite_mode)
+ {
+ case GIMP_LAYER_COMPOSITE_SRC_ATOP:
+ default:
+ composite_func_src_atop_sub (in, layer, blend_out,
+ mask, opacity,
+ out, samples);
+ break;
+
+ case GIMP_LAYER_COMPOSITE_SRC_OVER:
+ composite_func_src_over_sub (in, layer, blend_out,
+ mask, opacity,
+ out, samples);
+ break;
+
+ case GIMP_LAYER_COMPOSITE_DST_ATOP:
+ composite_func_dst_atop_sub (in, layer, blend_out,
+ mask, opacity,
+ out, samples);
+ break;
+
+ case GIMP_LAYER_COMPOSITE_SRC_IN:
+ composite_func_src_in_sub (in, layer, blend_out,
+ mask, opacity,
+ out, samples);
+ break;
+ }
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]