[gimp/pippin/linear-is-the-new-black: 1/17] app: add abstraction for separate blend and composite space
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/pippin/linear-is-the-new-black: 1/17] app: add abstraction for separate blend and composite space
- Date: Wed, 18 Jan 2017 23:11:07 +0000 (UTC)
commit 4f8f92e093e09092e9e66b27e486e75e041f1ded
Author: Øyvind Kolås <pippin gimp org>
Date: Sun Jan 15 21:11:00 2017 +0100
app: add abstraction for separate blend and composite space
app/operations/layer-modes/gimpoperationaddition.c | 50 +-
app/operations/layer-modes/gimpoperationburn.c | 54 +-
.../layer-modes/gimpoperationdarkenonly.c | 48 +-
.../layer-modes/gimpoperationdifference.c | 49 +-
app/operations/layer-modes/gimpoperationdivide.c | 53 +-
app/operations/layer-modes/gimpoperationdodge.c | 50 +-
.../layer-modes/gimpoperationgrainextract.c | 49 +-
.../layer-modes/gimpoperationgrainmerge.c | 48 +-
.../layer-modes/gimpoperationhardlight.c | 62 +--
app/operations/layer-modes/gimpoperationhsvcolor.c | 61 +--
app/operations/layer-modes/gimpoperationhsvhue.c | 66 +--
.../layer-modes/gimpoperationhsvsaturation.c | 60 +--
app/operations/layer-modes/gimpoperationhsvvalue.c | 48 +-
.../layer-modes/gimpoperationlchchroma.c | 44 +-
app/operations/layer-modes/gimpoperationlchcolor.c | 49 +-
app/operations/layer-modes/gimpoperationlchhue.c | 46 +-
.../layer-modes/gimpoperationlchlightness.c | 49 +-
.../layer-modes/gimpoperationlightenonly.c | 48 +-
app/operations/layer-modes/gimpoperationmultiply.c | 47 +-
app/operations/layer-modes/gimpoperationoverlay.c | 57 +--
.../layer-modes/gimpoperationpointlayermode.c | 14 +-
.../layer-modes/gimpoperationpointlayermode.h | 893 +++++++++++++++++++-
app/operations/layer-modes/gimpoperationscreen.c | 51 +-
.../layer-modes/gimpoperationsoftlight.c | 62 +--
app/operations/layer-modes/gimpoperationsubtract.c | 47 +-
25 files changed, 1129 insertions(+), 976 deletions(-)
---
diff --git a/app/operations/layer-modes/gimpoperationaddition.c
b/app/operations/layer-modes/gimpoperationaddition.c
index df412f9..0d6c2e6 100644
--- a/app/operations/layer-modes/gimpoperationaddition.c
+++ b/app/operations/layer-modes/gimpoperationaddition.c
@@ -76,7 +76,6 @@ gimp_operation_addition_process (GeglOperation *operation,
gint level)
{
gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
-
return gimp_operation_addition_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi,
level);
}
@@ -90,46 +89,13 @@ gimp_operation_addition_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0)
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- gfloat comp = in[b] + layer[b];
-
- out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_addition
+ );
return TRUE;
}
+
diff --git a/app/operations/layer-modes/gimpoperationburn.c b/app/operations/layer-modes/gimpoperationburn.c
index d35737e..3cffe69 100644
--- a/app/operations/layer-modes/gimpoperationburn.c
+++ b/app/operations/layer-modes/gimpoperationburn.c
@@ -80,6 +80,7 @@ gimp_operation_burn_process (GeglOperation *operation,
return gimp_operation_burn_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi,
level);
}
+
gboolean
gimp_operation_burn_process_pixels (gfloat *in,
gfloat *layer,
@@ -90,50 +91,13 @@ gimp_operation_burn_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0)
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- gfloat comp = 1.0 - (1.0 - in[b]) / layer[b];
- /* The CLAMP macro is deliberately inlined and
- * written to map comp == NAN (0 / 0) -> 1
- */
- comp = comp < 0 ? 0.0 : comp < 1.0 ? comp : 1.0;
-
- out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_burn
+ );
return TRUE;
}
+
diff --git a/app/operations/layer-modes/gimpoperationdarkenonly.c
b/app/operations/layer-modes/gimpoperationdarkenonly.c
index 5ce6dca..0eae2d9 100644
--- a/app/operations/layer-modes/gimpoperationdarkenonly.c
+++ b/app/operations/layer-modes/gimpoperationdarkenonly.c
@@ -90,46 +90,12 @@ gimp_operation_darken_only_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0)
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- gfloat comp = MIN (in[b], layer[b]);
-
- out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_darken_only
+ );
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationdifference.c
b/app/operations/layer-modes/gimpoperationdifference.c
index fc52ca9..ae5d697 100644
--- a/app/operations/layer-modes/gimpoperationdifference.c
+++ b/app/operations/layer-modes/gimpoperationdifference.c
@@ -90,47 +90,12 @@ gimp_operation_difference_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0f)
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- gfloat comp = in[b] - layer[b];
- comp = (comp < 0) ? -comp : comp;
-
- out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_difference
+ );
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationdivide.c
b/app/operations/layer-modes/gimpoperationdivide.c
index fc8c897..92014b0 100644
--- a/app/operations/layer-modes/gimpoperationdivide.c
+++ b/app/operations/layer-modes/gimpoperationdivide.c
@@ -90,51 +90,12 @@ gimp_operation_divide_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0f)
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- gfloat comp = in[b] / layer[b];
-
- /* make infitinities(or NaN) correspond to a really high number,
- * to get more predictable math */
- if (!(comp > -4294967296.0f && comp < 5.0f))
- comp = 5.0f;
-
- out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_divide
+ );
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationdodge.c b/app/operations/layer-modes/gimpoperationdodge.c
index 57488ff..1097ece 100644
--- a/app/operations/layer-modes/gimpoperationdodge.c
+++ b/app/operations/layer-modes/gimpoperationdodge.c
@@ -90,48 +90,12 @@ gimp_operation_dodge_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
-
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0f)
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- gfloat comp = in[b] / (1.0 - layer[b]);
- comp = MIN (comp, 1.0);
-
- out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_dodge
+ );
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationgrainextract.c
b/app/operations/layer-modes/gimpoperationgrainextract.c
index a298f99..6d89d57 100644
--- a/app/operations/layer-modes/gimpoperationgrainextract.c
+++ b/app/operations/layer-modes/gimpoperationgrainextract.c
@@ -90,47 +90,12 @@ gimp_operation_grain_extract_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
-
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0f)
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- gfloat comp = in[b] - layer[b] + 0.5;
-
- out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_grain_extract
+ );
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationgrainmerge.c
b/app/operations/layer-modes/gimpoperationgrainmerge.c
index f822225..8102164 100644
--- a/app/operations/layer-modes/gimpoperationgrainmerge.c
+++ b/app/operations/layer-modes/gimpoperationgrainmerge.c
@@ -90,46 +90,12 @@ gimp_operation_grain_merge_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0)
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- gfloat comp = in[b] + layer[b] - 0.5;
-
- out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask ++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_grain_merge
+ );
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationhardlight.c
b/app/operations/layer-modes/gimpoperationhardlight.c
index 34b8db2..fa410ad 100644
--- a/app/operations/layer-modes/gimpoperationhardlight.c
+++ b/app/operations/layer-modes/gimpoperationhardlight.c
@@ -89,60 +89,12 @@ gimp_operation_hardlight_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- gfloat comp_alpha, new_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- new_alpha = in[ALPHA] + (1.0 - in[ALPHA]) * comp_alpha;
-
- if (comp_alpha && new_alpha)
- {
- gfloat ratio = comp_alpha / new_alpha;
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- gfloat comp;
-
- if (layer[b] > 0.5)
- {
- comp = (1.0 - in[b]) * (1.0 - (layer[b] - 0.5) * 2.0);
- comp = MIN (1 - comp, 1);
- }
- else
- {
- comp = in[b] * (layer[b] * 2.0);
- comp = MIN (comp, 1.0);
- }
-
- out[b] = comp * ratio + in[b] * (1.0 - ratio);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask ++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_hardlight
+ );
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationhsvcolor.c
b/app/operations/layer-modes/gimpoperationhsvcolor.c
index 756bcb9..3b2e182 100644
--- a/app/operations/layer-modes/gimpoperationhsvcolor.c
+++ b/app/operations/layer-modes/gimpoperationhsvcolor.c
@@ -94,59 +94,12 @@ gimp_operation_hsv_color_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- GimpHSL layer_hsl, out_hsl;
- GimpRGB layer_rgb = {layer[0], layer[1], layer[2]};
- GimpRGB out_rgb = {in[0], in[1], in[2]};
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha)
- {
- gint b;
- gfloat out_tmp[3];
-
- gimp_rgb_to_hsl (&layer_rgb, &layer_hsl);
- gimp_rgb_to_hsl (&out_rgb, &out_hsl);
-
- out_hsl.h = layer_hsl.h;
- out_hsl.s = layer_hsl.s;
- gimp_hsl_to_rgb (&out_hsl, &out_rgb);
-
- out_tmp[0] = out_rgb.r;
- out_tmp[1] = out_rgb.g;
- out_tmp[2] = out_rgb.b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = out_tmp[b] * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_hsv_color
+ );
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationhsvhue.c
b/app/operations/layer-modes/gimpoperationhsvhue.c
index e5b2595..92603cc 100644
--- a/app/operations/layer-modes/gimpoperationhsvhue.c
+++ b/app/operations/layer-modes/gimpoperationhsvhue.c
@@ -94,64 +94,12 @@ gimp_operation_hsv_hue_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- GimpHSV layer_hsv, out_hsv;
- GimpRGB layer_rgb = {layer[0], layer[1], layer[2]};
- GimpRGB out_rgb = {in[0], in[1], in[2]};
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0f)
- {
- gint b;
- gfloat out_tmp[3];
-
- gimp_rgb_to_hsv (&layer_rgb, &layer_hsv);
- gimp_rgb_to_hsv (&out_rgb, &out_hsv);
-
- /* Composition should have no effect if saturation is zero.
- * otherwise, black would be painted red (see bug #123296).
- */
- if (layer_hsv.s)
- {
- out_hsv.h = layer_hsv.h;
- }
- gimp_hsv_to_rgb (&out_hsv, &out_rgb);
-
- out_tmp[0] = out_rgb.r;
- out_tmp[1] = out_rgb.g;
- out_tmp[2] = out_rgb.b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = out_tmp[b] * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_hsv_hue
+ );
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationhsvsaturation.c
b/app/operations/layer-modes/gimpoperationhsvsaturation.c
index 88e6ddb..1cba1b7 100644
--- a/app/operations/layer-modes/gimpoperationhsvsaturation.c
+++ b/app/operations/layer-modes/gimpoperationhsvsaturation.c
@@ -94,58 +94,12 @@ gimp_operation_hsv_saturation_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- GimpHSV layer_hsv, out_hsv;
- GimpRGB layer_rgb = {layer[0], layer[1], layer[2]};
- GimpRGB out_rgb = {in[0], in[1], in[2]};
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0f)
- {
- gint b;
- gfloat out_tmp[3];
-
- gimp_rgb_to_hsv (&layer_rgb, &layer_hsv);
- gimp_rgb_to_hsv (&out_rgb, &out_hsv);
-
- out_hsv.s = layer_hsv.s;
- gimp_hsv_to_rgb (&out_hsv, &out_rgb);
-
- out_tmp[0] = out_rgb.r;
- out_tmp[1] = out_rgb.g;
- out_tmp[2] = out_rgb.b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = out_tmp[b] * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_hsv_saturation
+ );
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationhsvvalue.c
b/app/operations/layer-modes/gimpoperationhsvvalue.c
index 4d1c2c3..3843bdb 100644
--- a/app/operations/layer-modes/gimpoperationhsvvalue.c
+++ b/app/operations/layer-modes/gimpoperationhsvvalue.c
@@ -94,46 +94,12 @@ gimp_operation_hsv_value_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- GimpHSV layer_hsv, out_hsv;
- GimpRGB layer_rgb = {layer[0], layer[1], layer[2]};
- GimpRGB out_rgb = {in[0], in[1], in[2]};
- gfloat comp_alpha = layer[ALPHA] * opacity;
-
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0f)
- {
- gimp_rgb_to_hsv (&layer_rgb, &layer_hsv);
- gimp_rgb_to_hsv (&out_rgb, &out_hsv);
-
- out_hsv.v = layer_hsv.v;
- gimp_hsv_to_rgb (&out_hsv, &out_rgb);
-
- out[RED] = out_rgb.r * comp_alpha + in[RED] * (1.0 - comp_alpha);
- out[GREEN] = out_rgb.g * comp_alpha + in[GREEN] * (1.0 - comp_alpha);
- out[BLUE] = out_rgb.b * comp_alpha + in[BLUE] * (1.0 - comp_alpha);
- }
- else
- {
- out[RED] = in[RED];
- out[GREEN] = in[GREEN];
- out[BLUE] = in[BLUE];
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_hsv_value
+ );
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationlchchroma.c
b/app/operations/layer-modes/gimpoperationlchchroma.c
index 5a08911..7a8c705 100644
--- a/app/operations/layer-modes/gimpoperationlchchroma.c
+++ b/app/operations/layer-modes/gimpoperationlchchroma.c
@@ -122,30 +122,7 @@ chroma_pre_process (const Babl *from_fish,
babl_process (to_fish, out, out, samples);
}
-gboolean
-gimp_operation_lch_chroma_process_pixels_linear (gfloat *in,
- gfloat *layer,
- gfloat *mask,
- gfloat *out,
- gfloat opacity,
- glong samples,
- const GeglRectangle *roi,
- gint level)
-{
- static const Babl *from_fish;
- static const Babl *to_fish;
-
- if (!from_fish)
- from_fish = babl_fish ("RGBA float", "CIE Lab alpha float");
- if (!to_fish)
- to_fish = babl_fish ("CIE Lab alpha float", "RGBA float");
-
- chroma_pre_process (from_fish, to_fish, in, layer, out, samples);
- gimp_operation_layer_composite (in, layer, mask, out, opacity, samples);
-
- return TRUE;
-}
-
+/* XXX: this and pre_process should be removed */
gboolean
gimp_operation_lch_chroma_process_pixels (gfloat *in,
gfloat *layer,
@@ -170,3 +147,22 @@ gimp_operation_lch_chroma_process_pixels (gfloat *in,
return TRUE;
}
+gboolean
+gimp_operation_lch_chroma_process_pixels_linear (gfloat *in,
+ gfloat *layer,
+ gfloat *mask,
+ gfloat *out,
+ gfloat opacity,
+ glong samples,
+ const GeglRectangle *roi,
+ gint level)
+{
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_LAB,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_lch_chroma
+ );
+ return TRUE;
+}
diff --git a/app/operations/layer-modes/gimpoperationlchcolor.c
b/app/operations/layer-modes/gimpoperationlchcolor.c
index 05badeb..3985422 100644
--- a/app/operations/layer-modes/gimpoperationlchcolor.c
+++ b/app/operations/layer-modes/gimpoperationlchcolor.c
@@ -112,33 +112,7 @@ color_pre_process (const Babl *from_fish_la,
babl_process (to_fish, out, out, samples);
}
-gboolean
-gimp_operation_lch_color_process_pixels_linear (gfloat *in,
- gfloat *layer,
- gfloat *mask,
- gfloat *out,
- gfloat opacity,
- glong samples,
- const GeglRectangle *roi,
- gint level)
-{
- static const Babl *from_fish_laba = NULL;
- static const Babl *from_fish_la = NULL;
- static const Babl *to_fish = NULL;
-
- if (!from_fish_laba)
- from_fish_laba = babl_fish ("RGBA float", "CIE Lab alpha float");
- if (!from_fish_la)
- from_fish_la = babl_fish ("RGBA float", "CIE L alpha float");
- if (!to_fish)
- to_fish = babl_fish ("CIE Lab alpha float", "RGBA float");
-
- color_pre_process (from_fish_la, from_fish_laba, to_fish, in, layer, out, samples);
- gimp_operation_layer_composite (in, layer, mask, out, opacity, samples);
-
- return TRUE;
-}
-
+/* XXX: should be removed along with the pre_process fun */
gboolean
gimp_operation_lch_color_process_pixels (gfloat *in,
gfloat *layer,
@@ -165,3 +139,24 @@ gimp_operation_lch_color_process_pixels (gfloat *in,
return TRUE;
}
+
+
+gboolean
+gimp_operation_lch_color_process_pixels_linear (gfloat *in,
+ gfloat *layer,
+ gfloat *mask,
+ gfloat *out,
+ gfloat opacity,
+ glong samples,
+ const GeglRectangle *roi,
+ gint level)
+{
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_LAB,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_lch_color
+ );
+ return TRUE;
+}
diff --git a/app/operations/layer-modes/gimpoperationlchhue.c
b/app/operations/layer-modes/gimpoperationlchhue.c
index 38265f6..ea21e0b 100644
--- a/app/operations/layer-modes/gimpoperationlchhue.c
+++ b/app/operations/layer-modes/gimpoperationlchhue.c
@@ -123,30 +123,7 @@ hue_pre_process (const Babl *from_fish,
babl_process (to_fish, out, out, samples);
}
-gboolean
-gimp_operation_lch_hue_process_pixels_linear (gfloat *in,
- gfloat *layer,
- gfloat *mask,
- gfloat *out,
- gfloat opacity,
- glong samples,
- const GeglRectangle *roi,
- gint level)
-{
- static const Babl *from_fish = NULL;
- static const Babl *to_fish = NULL;
-
- if (!from_fish)
- from_fish = babl_fish ("RGBA float", "CIE Lab alpha float");
- if (!to_fish)
- to_fish = babl_fish ("CIE Lab alpha float", "RGBA float");
-
- hue_pre_process (from_fish, to_fish, in, layer, out, samples);
- gimp_operation_layer_composite (in, layer, mask, out, opacity, samples);
-
- return TRUE;
-}
-
+/* XXX: this should be removed along with _pre_process */
gboolean
gimp_operation_lch_hue_process_pixels (gfloat *in,
gfloat *layer,
@@ -170,3 +147,24 @@ gimp_operation_lch_hue_process_pixels (gfloat *in,
return TRUE;
}
+
+
+gboolean
+gimp_operation_lch_hue_process_pixels_linear (gfloat *in,
+ gfloat *layer,
+ gfloat *mask,
+ gfloat *out,
+ gfloat opacity,
+ glong samples,
+ const GeglRectangle *roi,
+ gint level)
+{
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_LAB,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_lch_hue
+ );
+ return TRUE;
+}
diff --git a/app/operations/layer-modes/gimpoperationlchlightness.c
b/app/operations/layer-modes/gimpoperationlchlightness.c
index f452352..c9bc3b5 100644
--- a/app/operations/layer-modes/gimpoperationlchlightness.c
+++ b/app/operations/layer-modes/gimpoperationlchlightness.c
@@ -108,33 +108,7 @@ lightness_pre_process (const Babl *from_fish_la,
babl_process (to_fish, out, out, samples);
}
-gboolean
-gimp_operation_lch_lightness_process_pixels_linear (gfloat *in,
- gfloat *layer,
- gfloat *mask,
- gfloat *out,
- gfloat opacity,
- glong samples,
- const GeglRectangle *roi,
- gint level)
-{
- static const Babl *from_fish_laba = NULL;
- static const Babl *from_fish_la = NULL;
- static const Babl *to_fish = NULL;
-
- if (!from_fish_laba)
- from_fish_laba = babl_fish ("RGBA float", "CIE Lab alpha float");
- if (!from_fish_la)
- from_fish_la = babl_fish ("RGBA float", "CIE L alpha float");
- if (!to_fish)
- to_fish = babl_fish ("CIE Lab alpha float", "RGBA float");
-
- lightness_pre_process (from_fish_la, from_fish_laba, to_fish, in, layer, out, samples);
- gimp_operation_layer_composite (in, layer, mask, out, opacity, samples);
-
- return TRUE;
-}
-
+/* XXX: this should be remove along with _pre_process */
gboolean
gimp_operation_lch_lightness_process_pixels (gfloat *in,
gfloat *layer,
@@ -162,3 +136,24 @@ gimp_operation_lch_lightness_process_pixels (gfloat *in,
return TRUE;
}
+
+
+gboolean
+gimp_operation_lch_lightness_process_pixels_linear (gfloat *in,
+ gfloat *layer,
+ gfloat *mask,
+ gfloat *out,
+ gfloat opacity,
+ glong samples,
+ const GeglRectangle *roi,
+ gint level)
+{
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_LAB,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_lch_lightness
+ );
+ return TRUE;
+}
diff --git a/app/operations/layer-modes/gimpoperationlightenonly.c
b/app/operations/layer-modes/gimpoperationlightenonly.c
index a0fff11..a67e7f0 100644
--- a/app/operations/layer-modes/gimpoperationlightenonly.c
+++ b/app/operations/layer-modes/gimpoperationlightenonly.c
@@ -90,46 +90,12 @@ gimp_operation_lighten_only_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0)
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- gfloat comp = MAX (layer[b], in[b]);
-
- out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_lighten_only
+ );
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationmultiply.c
b/app/operations/layer-modes/gimpoperationmultiply.c
index 4c77376..4367062 100644
--- a/app/operations/layer-modes/gimpoperationmultiply.c
+++ b/app/operations/layer-modes/gimpoperationmultiply.c
@@ -90,45 +90,12 @@ gimp_operation_multiply_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0f)
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- gfloat comp = layer[b] * in[b];
- out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_multiply
+ );
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationoverlay.c
b/app/operations/layer-modes/gimpoperationoverlay.c
index ca67587..34229a7 100644
--- a/app/operations/layer-modes/gimpoperationoverlay.c
+++ b/app/operations/layer-modes/gimpoperationoverlay.c
@@ -89,54 +89,13 @@ gimp_operation_overlay_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- gfloat comp_alpha, new_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- new_alpha = in[ALPHA] + (1.0 - in[ALPHA]) * comp_alpha;
-
- if (comp_alpha && new_alpha)
- {
- gint b;
- gfloat ratio = comp_alpha / new_alpha;
-
- for (b = RED; b < ALPHA; b++)
- {
- gfloat comp;
-
- if (in[b] < 0.5)
- comp = 2.0 * in[b] * layer[b];
- else
- comp = 1.0 - 2.0 * (1.0 - layer[b]) * (1.0 - in[b]);
-
- out[b] = comp * ratio + in[b] * (1.0 - ratio);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_overlay
+ );
return TRUE;
}
+
diff --git a/app/operations/layer-modes/gimpoperationpointlayermode.c
b/app/operations/layer-modes/gimpoperationpointlayermode.c
index 419f1c1..aca474c 100644
--- a/app/operations/layer-modes/gimpoperationpointlayermode.c
+++ b/app/operations/layer-modes/gimpoperationpointlayermode.c
@@ -21,8 +21,8 @@
#include "config.h"
-#include <cairo.h>
#include <gegl-plugin.h>
+#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "libgimpcolor/gimpcolor.h"
@@ -66,6 +66,11 @@ G_DEFINE_TYPE (GimpOperationPointLayerMode, gimp_operation_point_layer_mode,
#define parent_class gimp_operation_point_layer_mode_parent_class
+const Babl *_gimp_fish_rgba_to_perceptual = NULL;
+const Babl *_gimp_fish_perceptual_to_rgba = NULL;
+const Babl *_gimp_fish_rgba_to_laba = NULL;
+const Babl *_gimp_fish_laba_to_rgba = NULL;
+
static void
gimp_operation_point_layer_mode_class_init (GimpOperationPointLayerModeClass *klass)
{
@@ -117,6 +122,13 @@ gimp_operation_point_layer_mode_class_init (GimpOperationPointLayerModeClass *kl
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
+ if (_gimp_fish_rgba_to_perceptual == NULL)
+ {
+ _gimp_fish_rgba_to_perceptual = babl_fish ("RGBA float", "R'G'B'A float");
+ _gimp_fish_perceptual_to_rgba = babl_fish ("R'G'B'A float", "RGBA float");
+ _gimp_fish_rgba_to_laba = babl_fish ("RGBA float", "CIE Lab alpha float");
+ _gimp_fish_laba_to_rgba = babl_fish ("CIE Lab alpha float", "RGBA float");
+ }
}
static void
diff --git a/app/operations/layer-modes/gimpoperationpointlayermode.h
b/app/operations/layer-modes/gimpoperationpointlayermode.h
index 630e060..66539cb 100644
--- a/app/operations/layer-modes/gimpoperationpointlayermode.h
+++ b/app/operations/layer-modes/gimpoperationpointlayermode.h
@@ -23,7 +23,13 @@
#include <gegl-plugin.h>
-
+#include <math.h>
+#include <alloca.h>
+#include <cairo.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "../operations-enums.h"
+#include "../operations-types.h"
+#include "libgimpcolor/gimpcolor.h"
#define GIMP_TYPE_OPERATION_POINT_LAYER_MODE (gimp_operation_point_layer_mode_get_type ())
#define GIMP_OPERATION_POINT_LAYER_MODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GIMP_TYPE_OPERATION_POINT_LAYER_MODE, GimpOperationPointLayerMode))
@@ -51,9 +57,12 @@ struct _GimpOperationPointLayerMode
GimpLayerCompositeMode composite_mode;
};
-
GType gimp_operation_point_layer_mode_get_type (void) G_GNUC_CONST;
+extern const Babl *_gimp_fish_rgba_to_perceptual;
+extern const Babl *_gimp_fish_perceptual_to_rgba;
+extern const Babl *_gimp_fish_rgba_to_laba;
+extern const Babl *_gimp_fish_laba_to_rgba;
static inline void
gimp_operation_layer_composite (const gfloat *in,
@@ -92,5 +101,885 @@ gimp_operation_layer_composite (const gfloat *in,
}
+static inline void
+gimp_composite_blend (gfloat *in,
+ gfloat *layer,
+ gfloat *mask,
+ gfloat *out,
+ gfloat opacity,
+ glong samples,
+ GimpBlendBlend blend_trc,
+ GimpBlendBlend composite_trc,
+ GimpLayerComposite composite_mode,
+ void (*blendfun) (const float *dst,
+ const float *src,
+ float *out,
+ int samples))
+{
+ gfloat *blend_in = in;
+ gfloat *blend_layer = layer;
+ gfloat *blend_out = out;
+
+ if (blendfun == NULL)
+ {
+ switch (composite_trc)
+ {
+ case GIMP_LAYER_BLEND_RGB_LINEAR:
+ blend_out = layer;
+ break;
+ case GIMP_LAYER_BLEND_LAB:
+ blend_out = alloca (sizeof (gfloat) * 4 * samples);
+ babl_process (_gimp_fish_rgba_to_laba, layer, blend_out, samples);
+ break;
+ case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
+ blend_out = alloca (sizeof (gfloat) * 4 * samples);
+ babl_process (_gimp_fish_rgba_to_perceptual, layer, blend_out, samples);
+ break;
+ }
+ }
+ else if (blend_trc == GIMP_LAYER_BLEND_RGB_LINEAR)
+ {
+ if (in == out)
+ blend_out = alloca (sizeof (gfloat) * 4 * samples);
+
+ blendfun (blend_in, blend_layer, blend_out, samples);
+
+ switch (composite_trc)
+ {
+ case GIMP_LAYER_BLEND_RGB_LINEAR:
+ break;
+ case GIMP_LAYER_BLEND_LAB:
+ babl_process (_gimp_fish_rgba_to_laba, blend_out, blend_out, samples);
+ break;
+ case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
+ babl_process (_gimp_fish_rgba_to_perceptual, blend_out, blend_out, samples);
+ break;
+ }
+ }
+ else if (blend_trc == GIMP_LAYER_BLEND_RGB_PERCEPTUAL)
+ {
+ blend_in = alloca (sizeof (gfloat) * 4 * samples);
+ blend_layer = alloca (sizeof (gfloat) * 4 * samples);
+
+ if (in == out)
+ blend_out = alloca (sizeof (gfloat) * 4 * samples);
+
+ babl_process (_gimp_fish_rgba_to_perceptual, in, blend_in, samples);
+ babl_process (_gimp_fish_rgba_to_perceptual, layer, blend_layer, samples);
+
+ blendfun (blend_in, blend_layer, blend_out, samples);
+
+ switch (composite_trc)
+ {
+ case GIMP_LAYER_BLEND_RGB_LINEAR:
+ babl_process (_gimp_fish_perceptual_to_rgba, blend_out, blend_out, samples);
+ break;
+ case GIMP_LAYER_BLEND_LAB:
+ babl_process (_gimp_fish_perceptual_to_rgba, blend_out, blend_out, samples);
+ // XXX : double conversion - could be avoided with custom fish
+ babl_process (_gimp_fish_rgba_to_laba, blend_out, blend_out, samples);
+ break;
+ case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
+ break;
+ }
+ }
+ else if (blend_trc == GIMP_LAYER_BLEND_LAB)
+ {
+ blend_in = alloca (sizeof (gfloat) * 4 * samples);
+ blend_layer = alloca (sizeof (gfloat) * 4 * samples);
+ babl_process (_gimp_fish_rgba_to_laba, in, blend_in, samples);
+ babl_process (_gimp_fish_rgba_to_laba, layer, blend_layer, samples);
+ if (in == out)
+ blend_out = alloca (sizeof (gfloat) * 4 * samples);
+
+ blendfun (blend_in, blend_layer, blend_out, samples);
+
+ switch (composite_trc)
+ {
+ case GIMP_LAYER_BLEND_RGB_LINEAR:
+ babl_process (_gimp_fish_laba_to_rgba, blend_out, blend_out, samples);
+ break;
+ case GIMP_LAYER_BLEND_LAB:
+ break;
+ case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
+ babl_process (_gimp_fish_laba_to_rgba, blend_out, blend_out, samples);
+ babl_process (_gimp_fish_perceptual_to_rgba, blend_out, blend_out, samples);
+ break;
+ }
+ }
+
+ switch (composite_mode)
+ {
+ case GIMP_LAYER_COMPOSITE_SRC_ATOP:
+ default:
+ while (samples--)
+ {
+ gfloat comp_alpha = blend_out[ALPHA] * opacity;
+ if (mask)
+ comp_alpha *= *mask;
+
+ if (comp_alpha == 0.0f)
+ {
+ out[RED] = in[RED];
+ out[GREEN] = in[GREEN];
+ out[BLUE] = in[BLUE];
+ }
+ else
+ {
+ gint b;
+ for (b = RED; b < ALPHA; b++)
+ out[b] = blend_out[b] * comp_alpha + in[b] * (1.0f - comp_alpha);
+ }
+
+ out[ALPHA] = in[ALPHA];
+
+ in += 4;
+ out += 4;
+ blend_out += 4;
+
+ if (mask)
+ mask++;
+ }
+ break;
+ case GIMP_LAYER_COMPOSITE_SRC_OVER:
+ while (samples--)
+ {
+ gfloat new_alpha;
+ gfloat comp_alpha = blend_out[ALPHA] * opacity;
+ if (mask)
+ comp_alpha *= *mask;
+
+ new_alpha = comp_alpha + (1.0f - comp_alpha) * in[ALPHA];
+
+ if (comp_alpha == 0.0f || new_alpha == 0.0f)
+ {
+ out[RED] = in[RED];
+ out[GREEN] = in[GREEN];
+ out[BLUE] = in[BLUE];
+ }
+ else
+ {
+ gint b;
+ gfloat ratio = comp_alpha / new_alpha;
+
+ for (b = RED; b < ALPHA; b++)
+ out[b] = ratio * (in[ALPHA] * (blend_out[b] - layer[b]) + layer[b] - in[b]) + in[b];
+ }
+
+ out[ALPHA] = new_alpha;
+
+ in += 4;
+ layer += 4;
+ out += 4;
+ blend_out += 4;
+
+ if (mask)
+ mask++;
+ }
+ break;
+ case GIMP_LAYER_COMPOSITE_DST_ATOP:
+ while (samples--)
+ {
+ gfloat comp_alpha = in[ALPHA];
+
+ out[ALPHA] = blend_out[ALPHA] * opacity;
+ if (mask)
+ out[ALPHA] *= *mask;
+
+ if (comp_alpha == 0.0f)
+ {
+ out[RED] = layer[RED];
+ out[GREEN] = layer[GREEN];
+ out[BLUE] = layer[BLUE];
+ }
+ else
+ {
+ gint b;
+ for (b = RED; b < ALPHA; b++)
+ out[b] = layer[b] * (1.0f -comp_alpha) + blend_out[b] * (comp_alpha);
+ }
+
+ in += 4;
+ layer += 4;
+ out += 4;
+ blend_out += 4;
+
+ if (mask)
+ mask++;
+ }
+ break;
+ case GIMP_LAYER_COMPOSITE_SRC_IN:
+ while (samples--)
+ {
+ gfloat new_alpha = in[ALPHA] * blend_out[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] = blend_out[RED];
+ out[GREEN] = blend_out[GREEN];
+ out[BLUE] = blend_out[BLUE];
+ }
+ out[ALPHA] = new_alpha;
+ in += 4;
+ out += 4;
+ blend_out += 4;
+
+ if (mask)
+ mask++;
+ }
+ break;
+ }
+
+ switch (composite_trc)
+ {
+ case GIMP_LAYER_BLEND_RGB_LINEAR:
+ break;
+ case GIMP_LAYER_BLEND_LAB:
+ out -= 4 * samples;
+ babl_process (_gimp_fish_laba_to_rgba, out, out, samples);
+ break;
+ case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
+ out -= 4 * samples;
+ babl_process (_gimp_fish_perceptual_to_rgba, out, out, samples);
+ break;
+ }
+}
+
+static inline void
+blendfun_screen (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ out[c] = 1.0f - (1.0f - dest[c]) * (1.0f - src[c]);
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_addition (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ out[c] = dest[c] + src[c];
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_subtract (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ out[c] = dest[c] - src[c];
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_multiply (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ out[c] = dest[c] * src[c];
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_normal (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ out[c] = src[c];
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_burn (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ {
+ gfloat comp = 1.0f - (1.0f - dest[c]) / src[c];
+ /* The CLAMP macro is deliberately inlined and written to map comp ==
+ * NAN (0 / 0) -> 1 */
+ out[c] = comp < 0 ? 0.0f : comp < 1.0f ? comp : 1.0f;
+ }
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_darken_only (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ {
+ out[c] = MIN(dest[c], src[c]);
+ }
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_lighten_only (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ {
+ out[c] = MAX(dest[c], src[c]);
+ }
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_difference (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ {
+ out[c] = dest[c] - src[c];
+ if (out[c] < 0)
+ out[c] = -out[c];
+ }
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_divide (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ {
+ gfloat comp = dest[c] / src[c];
+
+ /* make infinities(or NaN) correspond to a high number, to get more
+ * predictable math, ideally higher than 5.0 but it seems like some
+ * babl conversions might be acting up then
+ */
+ if (!(comp > -42949672.0f && comp < 5.0f))
+ comp = 5.0f;
+
+ out[c] = comp;
+ }
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_dodge (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ {
+ gfloat comp = dest[c] / (1.0f - src[c]);
+ comp = MIN (comp, 1.0f);
+
+ out[c] = comp;
+ }
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+
+static inline void
+blendfun_grain_extract (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ {
+ out[c] = dest[c] - src[c] + 0.5f;
+ }
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_grain_merge (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ {
+ out[c] = dest[c] + src[c] - 0.5f;
+ }
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+
+static inline void
+blendfun_hardlight (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ {
+ gfloat comp;
+ if (src[c] > 0.5f)
+ {
+ comp = (1.0f - dest[c]) * (1.0f - (src[c] - 0.5f) * 2.0f);
+ comp = MIN (1 - comp, 1);
+ }
+ else
+ {
+ comp = dest[c] * (src[c] * 2.0f);
+ comp = MIN (comp, 1.0f);
+ }
+ out[c] = comp;
+ }
+ out[ALPHA] = src[ALPHA];
+ }
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_softlight (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ {
+ gfloat multiply = dest[c] * src[c];
+ gfloat screen = 1.0f - (1.0f - dest[c]) * (1.0f - src[c]);
+ gfloat comp = (1.0f - src[c]) * multiply + dest[c] * screen;
+ out[c] = comp;
+ }
+ out[ALPHA] = src[ALPHA];
+ }
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+
+static inline void
+blendfun_overlay (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ {
+ gfloat comp;
+ if (src[c] < 0.5f)
+ {
+ comp = 2.0f * dest[c] * src[c];
+ }
+ else
+ {
+ comp = 1.0f - 2.0f * (1.0f - src[c]) * (1.0f - dest[c]);
+ }
+ out[c] = comp;
+ }
+ out[ALPHA] = src[ALPHA];
+ }
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_hsv_color (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ GimpRGB dest_rgb = {dest[0], dest[1], dest[2]};
+ GimpRGB src_rgb = {src[0], src[1], src[2]};
+ GimpHSL src_hsl, dest_hsl;
+ gimp_rgb_to_hsl (&dest_rgb, &dest_hsl);
+ gimp_rgb_to_hsl (&src_rgb, &src_hsl);
+ dest_hsl.h = src_hsl.h;
+ dest_hsl.s = src_hsl.s;
+ gimp_hsl_to_rgb (&dest_hsl, &dest_rgb);
+ out[RED] = dest_rgb.r;
+ out[GREEN] = dest_rgb.g;
+ out[BLUE] = dest_rgb.b;
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_hsv_hue (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ GimpRGB dest_rgb = {dest[0], dest[1], dest[2]};
+ GimpRGB src_rgb = {src[0], src[1], src[2]};
+ GimpHSV src_hsv, dest_hsv;
+ gimp_rgb_to_hsv (&dest_rgb, &dest_hsv);
+ gimp_rgb_to_hsv (&src_rgb, &src_hsv);
+ dest_hsv.h = src_hsv.h;
+ gimp_hsv_to_rgb (&dest_hsv, &dest_rgb);
+ out[RED] = dest_rgb.r;
+ out[GREEN] = dest_rgb.g;
+ out[BLUE] = dest_rgb.b;
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_hsv_saturation (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ GimpRGB dest_rgb = {dest[0], dest[1], dest[2]};
+ GimpRGB src_rgb = {src[0], src[1], src[2]};
+ GimpHSV src_hsv, dest_hsv;
+ gimp_rgb_to_hsv (&dest_rgb, &dest_hsv);
+ gimp_rgb_to_hsv (&src_rgb, &src_hsv);
+ dest_hsv.s = src_hsv.s;
+ gimp_hsv_to_rgb (&dest_hsv, &dest_rgb);
+ out[RED] = dest_rgb.r;
+ out[GREEN] = dest_rgb.g;
+ out[BLUE] = dest_rgb.b;
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_hsv_value (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ GimpRGB dest_rgb = {dest[0], dest[1], dest[2]};
+ GimpRGB src_rgb = {src[0], src[1], src[2]};
+ GimpHSV src_hsv, dest_hsv;
+ gimp_rgb_to_hsv (&dest_rgb, &dest_hsv);
+ gimp_rgb_to_hsv (&src_rgb, &src_hsv);
+ dest_hsv.v = src_hsv.v;
+ gimp_hsv_to_rgb (&dest_hsv, &dest_rgb);
+ out[RED] = dest_rgb.r;
+ out[GREEN] = dest_rgb.g;
+ out[BLUE] = dest_rgb.b;
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_lch_chroma (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ gfloat A1 = dest[1];
+ gfloat B1 = dest[2];
+ gfloat c1 = hypotf (A1, B1);
+
+ if (c1 != 0.0f)
+ {
+ gfloat A2 = src[1];
+ gfloat B2 = src[2];
+ gfloat c2 = hypotf (A2, B2);
+ gfloat A = c2 * A1 / c1;
+ gfloat B = c2 * B1 / c1;
+ out[0] = dest[0];
+ out[1] = A;
+ out[2] = B;
+ }
+ }
+ out[ALPHA] = src[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_lch_color (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ out[0] = dest[0];
+ out[1] = src[1];
+ out[2] = src[2];
+ }
+ out[3] = src[3];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_lch_hue (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ gfloat A2 = src[1];
+ gfloat B2 = src[2];
+ gfloat c2 = hypotf (A2, B2);
+
+ if (c2 > 0.1f)
+ {
+ gfloat A1 = dest[1];
+ gfloat B1 = dest[2];
+ gfloat c1 = hypotf (A1, B1);
+ gfloat A = c1 * A2 / c2;
+ gfloat B = c1 * B2 / c2;
+
+ out[0] = dest[0];
+ out[1] = A;
+ out[2] = B;
+ }
+ else
+ {
+ out[0] = dest[0];
+ out[1] = dest[1];
+ out[2] = dest[2];
+ }
+ }
+ out[3] = src[3];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
+static inline void
+blendfun_lch_lightness (const float *dest,
+ const float *src,
+ float *out,
+ int samples)
+{
+ while (samples--)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ out[0] = src[0];
+ out[1] = dest[1];
+ out[2] = dest[2];
+ }
+ out[3] = src[3];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
#endif /* __GIMP_OPERATION_POINT_LAYER_MODE_H__ */
diff --git a/app/operations/layer-modes/gimpoperationscreen.c
b/app/operations/layer-modes/gimpoperationscreen.c
index d2622c9..2c1451f 100644
--- a/app/operations/layer-modes/gimpoperationscreen.c
+++ b/app/operations/layer-modes/gimpoperationscreen.c
@@ -65,6 +65,7 @@ gimp_operation_screen_init (GimpOperationScreen *self)
{
}
+
static gboolean
gimp_operation_screen_process (GeglOperation *operation,
void *in_buf,
@@ -76,7 +77,6 @@ gimp_operation_screen_process (GeglOperation *operation,
gint level)
{
gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
-
return gimp_operation_screen_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi,
level);
}
@@ -90,46 +90,13 @@ gimp_operation_screen_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0f)
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- gfloat comp = 1.0 - (1.0 - in[b]) * (1.0 - layer[b]);
-
- out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_screen
+ );
return TRUE;
}
+
diff --git a/app/operations/layer-modes/gimpoperationsoftlight.c
b/app/operations/layer-modes/gimpoperationsoftlight.c
index 74b3ea1..3020acd 100644
--- a/app/operations/layer-modes/gimpoperationsoftlight.c
+++ b/app/operations/layer-modes/gimpoperationsoftlight.c
@@ -107,60 +107,12 @@ gimp_operation_softlight_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0f)
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
-#if 0
- /* softlight is now used for what GIMP formerly called
- * OVERLAY. We fixed OVERLAY to use the right math
- * (under the name NEW_OVERLAY), and redirect uses of
- * the old OVERLAY blend mode here. This math was
- * formerly used for OVERLAY and is exactly the same as
- * the multiply, screen, comp math used below.
- * See bug #673501.
- */
- gfloat comp = in[b] * (in[b] + (2.0 * layer[b]) * (1.0 - in[b]));
-#endif
-
- gfloat multiply = in[b] * layer[b];
- gfloat screen = 1.0 - (1.0 - in[b]) * (1.0 - layer[b]);
- gfloat comp = (1.0 - in[b]) * multiply + in[b] * screen;
-
- out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask ++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_softlight
+ );
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationsubtract.c
b/app/operations/layer-modes/gimpoperationsubtract.c
index 6fbc5e4..90ade4e 100644
--- a/app/operations/layer-modes/gimpoperationsubtract.c
+++ b/app/operations/layer-modes/gimpoperationsubtract.c
@@ -90,45 +90,12 @@ gimp_operation_subtract_process_pixels (gfloat *in,
const GeglRectangle *roi,
gint level)
{
- const gboolean has_mask = mask != NULL;
-
- while (samples--)
- {
- gfloat comp_alpha;
-
- comp_alpha = layer[ALPHA] * opacity;
- if (has_mask)
- comp_alpha *= *mask;
-
- if (comp_alpha != 0.0)
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- gfloat comp = in[b] - layer[b];
- out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
- }
- }
- else
- {
- gint b;
-
- for (b = RED; b < ALPHA; b++)
- {
- out[b] = in[b];
- }
- }
-
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (has_mask)
- mask++;
- }
-
+ gimp_composite_blend (
+ in, layer, mask, out, opacity, samples,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_subtract
+ );
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]