[gimp/pippin/linear-is-the-new-black: 9/9] app: add abstraction for separate blend and composite modes, like LCH mods already do
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/pippin/linear-is-the-new-black: 9/9] app: add abstraction for separate blend and composite modes, like LCH mods already do
- Date: Mon, 16 Jan 2017 01:09:38 +0000 (UTC)
commit c78a594333171d8817f44e7313abe1d5e0b7aa51
Author: Øyvind Kolås <pippin gimp org>
Date: Sun Jan 15 21:11:00 2017 +0100
app: add abstraction for separate blend and composite modes, like LCH mods already do
app/operations/layer-modes/gimpoperationaddition.c | 49 +-
app/operations/layer-modes/gimpoperationburn.c | 53 +--
.../layer-modes/gimpoperationdarkenonly.c | 47 +-
.../layer-modes/gimpoperationdifference.c | 48 +-
app/operations/layer-modes/gimpoperationdivide.c | 52 +--
app/operations/layer-modes/gimpoperationdodge.c | 49 +-
.../layer-modes/gimpoperationgrainextract.c | 48 +-
.../layer-modes/gimpoperationgrainmerge.c | 47 +-
.../layer-modes/gimpoperationhardlight.c | 61 +--
app/operations/layer-modes/gimpoperationhsvcolor.c | 60 +--
app/operations/layer-modes/gimpoperationhsvhue.c | 65 +--
.../layer-modes/gimpoperationhsvsaturation.c | 59 +--
app/operations/layer-modes/gimpoperationhsvvalue.c | 47 +-
.../layer-modes/gimpoperationlchchroma.c | 43 +-
app/operations/layer-modes/gimpoperationlchcolor.c | 48 +-
app/operations/layer-modes/gimpoperationlchhue.c | 45 +-
.../layer-modes/gimpoperationlchlightness.c | 48 +-
.../layer-modes/gimpoperationpointlayermode.c | 2 +-
.../layer-modes/gimpoperationpointlayermode.h | 829 ++++++++++++++++++++
app/operations/layer-modes/gimpoperationscreen.c | 50 +-
app/operations/layer-modes/gimpoperationsubtract.c | 46 +-
21 files changed, 1007 insertions(+), 789 deletions(-)
---
diff --git a/app/operations/layer-modes/gimpoperationaddition.c
b/app/operations/layer-modes/gimpoperationaddition.c
index df412f9..922bf24 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,12 @@ 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_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..080a5e6 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,12 @@ 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_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..869c6d8 100644
--- a/app/operations/layer-modes/gimpoperationdarkenonly.c
+++ b/app/operations/layer-modes/gimpoperationdarkenonly.c
@@ -90,46 +90,11 @@ 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_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..6b30f29 100644
--- a/app/operations/layer-modes/gimpoperationdifference.c
+++ b/app/operations/layer-modes/gimpoperationdifference.c
@@ -90,47 +90,11 @@ 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_COMPOSITE_SRC_ATOP,
+ blendfun_difference
+ );
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationdivide.c
b/app/operations/layer-modes/gimpoperationdivide.c
index d56534d..4bb47f7 100644
--- a/app/operations/layer-modes/gimpoperationdivide.c
+++ b/app/operations/layer-modes/gimpoperationdivide.c
@@ -90,51 +90,11 @@ 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 < 4294967296.0f))
- comp = 4294967296.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_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..8c5da9b 100644
--- a/app/operations/layer-modes/gimpoperationdodge.c
+++ b/app/operations/layer-modes/gimpoperationdodge.c
@@ -90,48 +90,11 @@ 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_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..36539e3 100644
--- a/app/operations/layer-modes/gimpoperationgrainextract.c
+++ b/app/operations/layer-modes/gimpoperationgrainextract.c
@@ -90,47 +90,11 @@ 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_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..1c079b5 100644
--- a/app/operations/layer-modes/gimpoperationgrainmerge.c
+++ b/app/operations/layer-modes/gimpoperationgrainmerge.c
@@ -90,46 +90,11 @@ 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_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..a1f83b4 100644
--- a/app/operations/layer-modes/gimpoperationhardlight.c
+++ b/app/operations/layer-modes/gimpoperationhardlight.c
@@ -89,60 +89,11 @@ 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_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..6c9b0f9 100644
--- a/app/operations/layer-modes/gimpoperationhsvcolor.c
+++ b/app/operations/layer-modes/gimpoperationhsvcolor.c
@@ -94,59 +94,11 @@ 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_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..da18bd2 100644
--- a/app/operations/layer-modes/gimpoperationhsvhue.c
+++ b/app/operations/layer-modes/gimpoperationhsvhue.c
@@ -94,64 +94,11 @@ 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_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..24a18db 100644
--- a/app/operations/layer-modes/gimpoperationhsvsaturation.c
+++ b/app/operations/layer-modes/gimpoperationhsvsaturation.c
@@ -94,58 +94,11 @@ 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_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..87276eb 100644
--- a/app/operations/layer-modes/gimpoperationhsvvalue.c
+++ b/app/operations/layer-modes/gimpoperationhsvvalue.c
@@ -94,46 +94,11 @@ 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_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..71ce2dd 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,21 @@ 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_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..004d4b4 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,23 @@ 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_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..36ef390 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,23 @@ 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_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..b31c9a3 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,23 @@ 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_COMPOSITE_SRC_ATOP,
+ blendfun_lch_lightness
+ );
+ return TRUE;
+}
diff --git a/app/operations/layer-modes/gimpoperationpointlayermode.c
b/app/operations/layer-modes/gimpoperationpointlayermode.c
index 3b19cc8..94c0e1b 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"
diff --git a/app/operations/layer-modes/gimpoperationpointlayermode.h
b/app/operations/layer-modes/gimpoperationpointlayermode.h
index af0a6e0..65239e0 100644
--- a/app/operations/layer-modes/gimpoperationpointlayermode.h
+++ b/app/operations/layer-modes/gimpoperationpointlayermode.h
@@ -23,7 +23,11 @@
#include <gegl-plugin.h>
+#include <math.h>
+#include <cairo.h>
+#include <gdk-pixbuf/gdk-pixbuf.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))
@@ -88,6 +92,831 @@ gimp_operation_layer_composite (const gfloat *in,
}
}
+typedef enum {
+ GIMP_LAYER_BLEND_RGB_LINEAR,
+ GIMP_LAYER_BLEND_RGB_PERCEPTUAL,
+ GIMP_LAYER_BLEND_LAB,
+} GimpBlendTRC;
+
+typedef enum {
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ GIMP_LAYER_COMPOSITE_SRC_OVER,
+ GIMP_LAYER_COMPOSITE_SRC_IN,
+ GIMP_LAYER_COMPOSITE_DST_OVER
+} GimpLayerComposite;
+
+static inline void
+gimp_composite_blend (gfloat *in,
+ gfloat *layer,
+ gfloat *mask,
+ gfloat *out,
+ gfloat opacity,
+ glong samples,
+ GimpBlendTRC blend_trc,
+ GimpLayerComposite composite_mode,
+ void (*blendfun) (const float *dst,
+ const float *src,
+ float *out,
+ int samples))
+{
+ gfloat *blend_in = in;
+ gfloat *blend_layer = layer;
+
+ if (blend_trc == GIMP_LAYER_BLEND_RGB_LINEAR || blendfun == NULL)
+ {
+ if (blendfun)
+ blendfun (blend_in, blend_layer, out, samples);
+ else
+ memcpy (out, blend_layer, sizeof (gfloat) * 4 * samples);
+ }
+ else if (blend_trc == GIMP_LAYER_BLEND_RGB_PERCEPTUAL)
+ {
+ static const Babl *fish_to_perceptual = NULL;
+ static const Babl *fish_to_linear = NULL;
+ if (!fish_to_perceptual)
+ fish_to_perceptual = babl_fish("RGBA float", "R'G'B'A float");
+ if (!fish_to_linear)
+ fish_to_linear = babl_fish("R'G'B'A float", "RGBA float");
+
+ blend_in = alloca (sizeof (gfloat) * 4 * samples);
+ babl_process (fish_to_perceptual, in, blend_in, samples);
+ blend_layer = alloca (sizeof (gfloat) * 4 * samples);
+ babl_process (fish_to_perceptual, layer, blend_layer, samples);
+
+ blendfun (blend_in, blend_layer, out, samples);
+
+ babl_process (fish_to_linear, out, out, samples);
+ }
+ else if (blend_trc == GIMP_LAYER_BLEND_LAB)
+ {
+ static const Babl *fish_to_lab = NULL;
+ static const Babl *fish_to_rgb = NULL;
+ if (!fish_to_lab)
+ fish_to_lab = babl_fish("RGBA float", "CIE Lab alpha float");
+ if (!fish_to_rgb)
+ fish_to_rgb = babl_fish("CIE Lab alpha float", "RGBA float");
+
+ blend_in = alloca (sizeof (gfloat) * 4 * samples);
+ babl_process (fish_to_lab, in, blend_in, samples);
+ blend_layer = alloca (sizeof (gfloat) * 4 * samples);
+ babl_process (fish_to_lab, layer, blend_layer, samples);
+
+ blendfun (blend_in, blend_layer, out, samples);
+
+ babl_process (fish_to_rgb, out, out, samples);
+ }
+
+ switch (composite_mode)
+ {
+ case GIMP_LAYER_COMPOSITE_SRC_ATOP:
+ default:
+ while (samples--)
+ {
+ gfloat comp_alpha = 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] = out[b] * comp_alpha + in[b] * (1.0f - comp_alpha);
+ }
+
+ out[ALPHA] = in[ALPHA];
+
+ in += 4;
+ out += 4;
+
+ if (mask)
+ mask++;
+ }
+ break;
+ case GIMP_LAYER_COMPOSITE_SRC_OVER:
+ while (samples--)
+ {
+ gfloat comp_alpha = 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] = out[b] * comp_alpha + in[b] * (1.0f - comp_alpha);
+ }
+
+ out[ALPHA] = comp_alpha + in[ALPHA] * (1.0f - comp_alpha);
+
+ in += 4;
+ out += 4;
+
+ if (mask)
+ mask++;
+ }
+ break;
+ case GIMP_LAYER_COMPOSITE_DST_OVER: // XXX: strong need to verify visual results of this mode
+ while (samples--)
+ {
+ gfloat comp_alpha = 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] = out[b] * (1.0f - comp_alpha) + in[b] * (comp_alpha);
+ }
+
+ out[ALPHA] = (1.0f - comp_alpha) + in[ALPHA] * (comp_alpha);
+
+ in += 4;
+ out += 4;
+
+ if (mask)
+ mask++;
+ }
+ break;
+ case GIMP_LAYER_COMPOSITE_SRC_IN:
+ while (samples--)
+ {
+ gfloat comp_alpha = 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] = out[b] * comp_alpha + in[b] * (1.0f - comp_alpha);
+ }
+ out[ALPHA] = comp_alpha + in[ALPHA];
+ in += 4;
+ out += 4;
+
+ if (mask)
+ mask++;
+ }
+ 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 infitinities(or NaN) correspond to a really high number,
+ * to get more predictable math */
+ if (!(comp > -4294967296.0f && comp < 4294967296.0f))
+ comp = 4294967296.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)
+ {
+ 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..ecad8d6 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,12 @@ 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_LINEAR,
+ GIMP_LAYER_COMPOSITE_SRC_ATOP,
+ blendfun_screen
+ );
return TRUE;
}
+
diff --git a/app/operations/layer-modes/gimpoperationsubtract.c
b/app/operations/layer-modes/gimpoperationsubtract.c
index 6fbc5e4..b97f17c 100644
--- a/app/operations/layer-modes/gimpoperationsubtract.c
+++ b/app/operations/layer-modes/gimpoperationsubtract.c
@@ -90,45 +90,11 @@ 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_COMPOSITE_SRC_ATOP,
+ blendfun_subtract
+ );
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]