[gimp/pippin/linear-is-the-new-black: 7/17] app: give gimp_blend_composite() its own file, and use SIMD for over
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/pippin/linear-is-the-new-black: 7/17] app: give gimp_blend_composite() its own file, and use SIMD for over
- Date: Wed, 18 Jan 2017 23:11:37 +0000 (UTC)
commit 58a260c2a3a19aca87f16c252c036d260989cc31
Author: Øyvind Kolås <pippin gimp org>
Date: Wed Jan 18 23:21:03 2017 +0100
app: give gimp_blend_composite() its own file, and use SIMD for over
The SIMD code re-uses the existing optimized innerloop from the normal layer
mode.
app/operations/layer-modes/Makefile.am | 1 +
app/operations/layer-modes/gimpblendcomposite.h | 912 ++++++++++++++++++++
app/operations/layer-modes/gimpoperationaddition.c | 4 +-
app/operations/layer-modes/gimpoperationburn.c | 2 +-
.../layer-modes/gimpoperationdarkenonly.c | 1 +
.../layer-modes/gimpoperationdifference.c | 1 +
app/operations/layer-modes/gimpoperationdivide.c | 1 +
app/operations/layer-modes/gimpoperationdodge.c | 1 +
.../layer-modes/gimpoperationgrainextract.c | 1 +
.../layer-modes/gimpoperationgrainmerge.c | 1 +
.../layer-modes/gimpoperationhardlight.c | 1 +
app/operations/layer-modes/gimpoperationhsvcolor.c | 1 +
app/operations/layer-modes/gimpoperationhsvhue.c | 1 +
.../layer-modes/gimpoperationhsvsaturation.c | 1 +
app/operations/layer-modes/gimpoperationhsvvalue.c | 1 +
.../layer-modes/gimpoperationlchchroma.c | 1 +
app/operations/layer-modes/gimpoperationlchcolor.c | 1 +
app/operations/layer-modes/gimpoperationlchhue.c | 1 +
.../layer-modes/gimpoperationlchlightness.c | 1 +
.../layer-modes/gimpoperationlightenonly.c | 1 +
app/operations/layer-modes/gimpoperationmultiply.c | 1 +
app/operations/layer-modes/gimpoperationoverlay.c | 1 +
.../layer-modes/gimpoperationpointlayermode.h | 879 +-------------------
app/operations/layer-modes/gimpoperationscreen.c | 1 +
.../layer-modes/gimpoperationsoftlight.c | 1 +
app/operations/layer-modes/gimpoperationsubtract.c | 2 +-
26 files changed, 939 insertions(+), 881 deletions(-)
---
diff --git a/app/operations/layer-modes/Makefile.am b/app/operations/layer-modes/Makefile.am
index 55c3c3f..2f4d531 100644
--- a/app/operations/layer-modes/Makefile.am
+++ b/app/operations/layer-modes/Makefile.am
@@ -22,6 +22,7 @@ libapplayermodes_generic_a_sources = \
gimpoperationpointlayermode.h \
gimplayermodefunctions.c \
gimplayermodefunctions.h \
+ gimpblendcomposite.h \
\
gimpoperationaddition.c \
gimpoperationaddition.h \
diff --git a/app/operations/layer-modes/gimpblendcomposite.h b/app/operations/layer-modes/gimpblendcomposite.h
new file mode 100644
index 0000000..8ae3b10
--- /dev/null
+++ b/app/operations/layer-modes/gimpblendcomposite.h
@@ -0,0 +1,912 @@
+/* GIMP - The GNU Image Manipulation Program
+ * gimpblendcomposite
+ * Copyright (C) 2017 Øyvind Kolås <pippin gimp org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_BLEND_COMPOSITE_H__
+#define __GIMP_BLEND_COMPOSITE_H__
+
+
+#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"
+extern const Babl *_gimp_fish_rgba_to_perceptual;
+extern const Babl *_gimp_fish_perceptual_to_rgba;
+extern const Babl *_gimp_fish_perceptual_to_laba;
+extern const Babl *_gimp_fish_rgba_to_laba;
+extern const Babl *_gimp_fish_laba_to_rgba;
+extern const Babl *_gimp_fish_laba_to_perceptual;
+
+static inline void
+compfun_src_atop (gfloat *in,
+ gfloat *layer,
+ gfloat *mask,
+ gfloat opacity,
+ gfloat *out,
+ gint samples)
+{
+ while (samples--)
+ {
+ gfloat comp_alpha = layer[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] = layer[b] * comp_alpha + in[b] * (1.0f - comp_alpha);
+ }
+ out[ALPHA] = in[ALPHA];
+
+ in += 4;
+ out += 4;
+ layer += 4;
+
+ if (mask)
+ mask++;
+ }
+}
+
+static inline void
+compfun_src_over (gfloat *in,
+ gfloat *layer,
+ gfloat *mask,
+ gfloat *out,
+ gfloat opacity,
+ gint samples)
+{
+ while (samples--)
+ {
+ gfloat new_alpha;
+ gfloat comp_alpha = layer[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] = layer[b] * ratio + in[b] * (1.0f - ratio);
+ }
+
+ out[ALPHA] = new_alpha;
+
+ in += 4;
+ layer += 4;
+ out += 4;
+
+ if (mask)
+ mask++;
+ }
+}
+
+
+static inline void
+compfun_src_in (gfloat *in,
+ gfloat *layer,
+ gfloat *mask,
+ gfloat opacity,
+ gfloat *out,
+ gint samples)
+{
+ while (samples--)
+ {
+ gfloat new_alpha = in[ALPHA] * layer[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] = layer[RED];
+ out[GREEN] = layer[GREEN];
+ out[BLUE] = layer[BLUE];
+ }
+ out[ALPHA] = new_alpha;
+ in += 4;
+ out += 4;
+ layer += 4;
+
+ if (mask)
+ mask++;
+ }
+}
+
+static inline void
+gimp_composite_blend (gfloat *in,
+ gfloat *layer,
+ gfloat *mask,
+ gfloat *out,
+ gfloat opacity,
+ glong samples,
+ GimpLayerBlendTRC blend_trc,
+ GimpLayerBlendTRC composite_trc,
+ GimpLayerCompositeMode 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;
+
+ const Babl *fish_to_blend = NULL;
+ const Babl *fish_to_composite = NULL;
+ const Babl *fish_from_composite = NULL;
+
+ switch (blend_trc)
+ {
+ default:
+ case GIMP_LAYER_BLEND_RGB_LINEAR:
+ fish_to_blend = NULL;
+ switch (composite_trc)
+ {
+ case GIMP_LAYER_BLEND_LAB:
+ fish_to_composite = _gimp_fish_rgba_to_laba;
+ fish_from_composite = _gimp_fish_laba_to_rgba;
+ default:
+ case GIMP_LAYER_BLEND_RGB_LINEAR:
+ fish_to_composite = NULL;
+ fish_from_composite = NULL;
+ break;
+ case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
+ fish_to_composite = _gimp_fish_rgba_to_perceptual;
+ fish_from_composite = _gimp_fish_perceptual_to_rgba;
+ break;
+ }
+ break;
+ case GIMP_LAYER_BLEND_LAB:
+ fish_to_blend = _gimp_fish_rgba_to_laba;
+ switch (composite_trc)
+ {
+ case GIMP_LAYER_BLEND_LAB:
+ default:
+ fish_to_composite = NULL;
+ fish_from_composite = _gimp_fish_laba_to_rgba;
+ case GIMP_LAYER_BLEND_RGB_LINEAR:
+ fish_to_composite = _gimp_fish_laba_to_rgba;
+ fish_from_composite = NULL;
+ break;
+ case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
+ fish_to_composite = _gimp_fish_laba_to_perceptual;
+ fish_from_composite = _gimp_fish_perceptual_to_rgba;
+ break;
+ }
+ break;
+ case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
+ fish_to_blend = _gimp_fish_rgba_to_perceptual;
+ switch (composite_trc)
+ {
+ case GIMP_LAYER_BLEND_LAB:
+ default:
+ fish_to_composite = _gimp_fish_perceptual_to_laba;
+ fish_from_composite = NULL;
+ case GIMP_LAYER_BLEND_RGB_LINEAR:
+ fish_to_composite = _gimp_fish_perceptual_to_rgba;
+ fish_from_composite = NULL;
+ break;
+ case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
+ fish_to_composite = NULL;
+ fish_from_composite = _gimp_fish_perceptual_to_rgba;
+ break;
+ }
+ break;
+ }
+
+ if (in == out) /* in-place detected, avoid clobbering since we need to
+ read it for the compositing stage */
+ blend_out = alloca (sizeof (gfloat) * 4 * samples);
+
+ if (fish_to_blend)
+ {
+ blend_in = alloca (sizeof (gfloat) * 4 * samples);
+ blend_layer = alloca (sizeof (gfloat) * 4 * samples);
+ babl_process (fish_to_blend, in, blend_in, samples);
+ babl_process (fish_to_blend, layer, blend_layer, samples);
+ }
+
+ blendfun (blend_in, blend_layer, blend_out, samples);
+
+ if (fish_to_composite)
+ {
+ babl_process (fish_to_composite, blend_in, blend_in, samples);
+ babl_process (fish_to_composite, blend_out, blend_out, samples);
+ }
+
+ switch (composite_mode)
+ {
+ case GIMP_LAYER_COMPOSITE_SRC_ATOP:
+ default:
+ compfun_src_atop (blend_in, blend_out, mask, opacity, out, samples);
+ break;
+ case GIMP_LAYER_COMPOSITE_SRC_OVER:
+ //compfun_src_over (blend_in, blend_out, mask, opacity, out, samples);
+ gimp_operation_normal_process_pixels (blend_in, blend_out, mask, out, opacity, samples, NULL, 0, 0, 0,
0);
+ break;
+ case GIMP_LAYER_COMPOSITE_DST_ATOP:
+ if (fish_to_composite)
+ babl_process (fish_to_composite, blend_layer, blend_layer, samples);
+
+ compfun_src_atop (blend_out, blend_in, mask, opacity, out, samples); /* swapped arguments */
+ break;
+ case GIMP_LAYER_COMPOSITE_SRC_IN:
+ compfun_src_in (blend_in, blend_out, mask, opacity, out, samples);
+ break;
+ }
+
+ if (fish_from_composite)
+ {
+ babl_process (fish_from_composite, out, out, samples);
+ }
+}
+
+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
diff --git a/app/operations/layer-modes/gimpoperationaddition.c
b/app/operations/layer-modes/gimpoperationaddition.c
index d975b3c..bd0bf7c 100644
--- a/app/operations/layer-modes/gimpoperationaddition.c
+++ b/app/operations/layer-modes/gimpoperationaddition.c
@@ -27,6 +27,7 @@
#include "../operations-types.h"
#include "gimpoperationaddition.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_addition_process (GeglOperation *operation,
@@ -96,7 +97,8 @@ gimp_operation_addition_process_pixels (gfloat *in,
GimpLayerCompositeMode composite_mode)
{
gimp_composite_blend (in, layer, mask, out, opacity, samples,
- blend_trc, composite_trc, composite_mode, blendfun_addition);
+ blend_trc, composite_trc, composite_mode,
+ blendfun_addition);
return TRUE;
}
diff --git a/app/operations/layer-modes/gimpoperationburn.c b/app/operations/layer-modes/gimpoperationburn.c
index f77f71e..b73df72 100644
--- a/app/operations/layer-modes/gimpoperationburn.c
+++ b/app/operations/layer-modes/gimpoperationburn.c
@@ -27,7 +27,7 @@
#include "../operations-types.h"
#include "gimpoperationburn.h"
-
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_burn_process (GeglOperation *operation,
void *in_buf,
diff --git a/app/operations/layer-modes/gimpoperationdarkenonly.c
b/app/operations/layer-modes/gimpoperationdarkenonly.c
index 627af49..ff61d54 100644
--- a/app/operations/layer-modes/gimpoperationdarkenonly.c
+++ b/app/operations/layer-modes/gimpoperationdarkenonly.c
@@ -27,6 +27,7 @@
#include "../operations-types.h"
#include "gimpoperationdarkenonly.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_darken_only_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationdifference.c
b/app/operations/layer-modes/gimpoperationdifference.c
index 8244345..58646fb 100644
--- a/app/operations/layer-modes/gimpoperationdifference.c
+++ b/app/operations/layer-modes/gimpoperationdifference.c
@@ -27,6 +27,7 @@
#include "../operations-types.h"
#include "gimpoperationdifference.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_difference_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationdivide.c
b/app/operations/layer-modes/gimpoperationdivide.c
index e57d7c7..5b3795f 100644
--- a/app/operations/layer-modes/gimpoperationdivide.c
+++ b/app/operations/layer-modes/gimpoperationdivide.c
@@ -27,6 +27,7 @@
#include "../operations-types.h"
#include "gimpoperationdivide.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_divide_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationdodge.c b/app/operations/layer-modes/gimpoperationdodge.c
index 025eb38..fb29698 100644
--- a/app/operations/layer-modes/gimpoperationdodge.c
+++ b/app/operations/layer-modes/gimpoperationdodge.c
@@ -27,6 +27,7 @@
#include "operations/operations-types.h"
#include "gimpoperationdodge.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_dodge_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationgrainextract.c
b/app/operations/layer-modes/gimpoperationgrainextract.c
index 57756fb..c23659d 100644
--- a/app/operations/layer-modes/gimpoperationgrainextract.c
+++ b/app/operations/layer-modes/gimpoperationgrainextract.c
@@ -27,6 +27,7 @@
#include "../operations-types.h"
#include "gimpoperationgrainextract.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_grain_extract_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationgrainmerge.c
b/app/operations/layer-modes/gimpoperationgrainmerge.c
index f15d58e..813742f 100644
--- a/app/operations/layer-modes/gimpoperationgrainmerge.c
+++ b/app/operations/layer-modes/gimpoperationgrainmerge.c
@@ -27,6 +27,7 @@
#include "../operations-types.h"
#include "gimpoperationgrainmerge.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_grain_merge_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationhardlight.c
b/app/operations/layer-modes/gimpoperationhardlight.c
index 6127f1d..0ada97f 100644
--- a/app/operations/layer-modes/gimpoperationhardlight.c
+++ b/app/operations/layer-modes/gimpoperationhardlight.c
@@ -26,6 +26,7 @@
#include "../operations-types.h"
#include "gimpoperationhardlight.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_hardlight_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationhsvcolor.c
b/app/operations/layer-modes/gimpoperationhsvcolor.c
index 8c4ae94..401be9b 100644
--- a/app/operations/layer-modes/gimpoperationhsvcolor.c
+++ b/app/operations/layer-modes/gimpoperationhsvcolor.c
@@ -31,6 +31,7 @@
#include "../operations-types.h"
#include "gimpoperationhsvcolor.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_hsv_color_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationhsvhue.c
b/app/operations/layer-modes/gimpoperationhsvhue.c
index aa8a8aa..54865df 100644
--- a/app/operations/layer-modes/gimpoperationhsvhue.c
+++ b/app/operations/layer-modes/gimpoperationhsvhue.c
@@ -31,6 +31,7 @@
#include "../operations-types.h"
#include "gimpoperationhsvhue.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_hsv_hue_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationhsvsaturation.c
b/app/operations/layer-modes/gimpoperationhsvsaturation.c
index 32ce7f2..35d7b52 100644
--- a/app/operations/layer-modes/gimpoperationhsvsaturation.c
+++ b/app/operations/layer-modes/gimpoperationhsvsaturation.c
@@ -31,6 +31,7 @@
#include "../operations-types.h"
#include "gimpoperationhsvsaturation.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_hsv_saturation_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationhsvvalue.c
b/app/operations/layer-modes/gimpoperationhsvvalue.c
index f3ec3d1..d37e75a 100644
--- a/app/operations/layer-modes/gimpoperationhsvvalue.c
+++ b/app/operations/layer-modes/gimpoperationhsvvalue.c
@@ -31,6 +31,7 @@
#include "../operations-types.h"
#include "gimpoperationhsvvalue.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_hsv_value_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationlchchroma.c
b/app/operations/layer-modes/gimpoperationlchchroma.c
index 3e5d5c8..35f206f 100644
--- a/app/operations/layer-modes/gimpoperationlchchroma.c
+++ b/app/operations/layer-modes/gimpoperationlchchroma.c
@@ -26,6 +26,7 @@
#include <math.h>
#include "../operations-types.h"
#include "gimpoperationlchchroma.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_lch_chroma_process (GeglOperation *operation,
void *in_buf,
diff --git a/app/operations/layer-modes/gimpoperationlchcolor.c
b/app/operations/layer-modes/gimpoperationlchcolor.c
index 013f182..4efc26e 100644
--- a/app/operations/layer-modes/gimpoperationlchcolor.c
+++ b/app/operations/layer-modes/gimpoperationlchcolor.c
@@ -25,6 +25,7 @@
#include <gegl-plugin.h>
#include "../operations-types.h"
#include "gimpoperationlchcolor.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_lch_color_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationlchhue.c
b/app/operations/layer-modes/gimpoperationlchhue.c
index 543f689..0e89002 100644
--- a/app/operations/layer-modes/gimpoperationlchhue.c
+++ b/app/operations/layer-modes/gimpoperationlchhue.c
@@ -26,6 +26,7 @@
#include <math.h>
#include "../operations-types.h"
#include "gimpoperationlchhue.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_lch_hue_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationlchlightness.c
b/app/operations/layer-modes/gimpoperationlchlightness.c
index 3ba5a18..abcf698 100644
--- a/app/operations/layer-modes/gimpoperationlchlightness.c
+++ b/app/operations/layer-modes/gimpoperationlchlightness.c
@@ -27,6 +27,7 @@
#include "../operations-types.h"
#include "gimpoperationlchlightness.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_lch_lightness_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationlightenonly.c
b/app/operations/layer-modes/gimpoperationlightenonly.c
index 5273db9..b2c09f1 100644
--- a/app/operations/layer-modes/gimpoperationlightenonly.c
+++ b/app/operations/layer-modes/gimpoperationlightenonly.c
@@ -27,6 +27,7 @@
#include "../operations-types.h"
#include "gimpoperationlightenonly.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_lighten_only_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationmultiply.c
b/app/operations/layer-modes/gimpoperationmultiply.c
index eb0532f..2ae56e1 100644
--- a/app/operations/layer-modes/gimpoperationmultiply.c
+++ b/app/operations/layer-modes/gimpoperationmultiply.c
@@ -27,6 +27,7 @@
#include "operations/operations-types.h"
#include "gimpoperationmultiply.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_multiply_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationoverlay.c
b/app/operations/layer-modes/gimpoperationoverlay.c
index e674f0e..b3d551c 100644
--- a/app/operations/layer-modes/gimpoperationoverlay.c
+++ b/app/operations/layer-modes/gimpoperationoverlay.c
@@ -26,6 +26,7 @@
#include "../operations-types.h"
#include "gimpoperationoverlay.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_overlay_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationpointlayermode.h
b/app/operations/layer-modes/gimpoperationpointlayermode.h
index 5274f9a..93cc9ab 100644
--- a/app/operations/layer-modes/gimpoperationpointlayermode.h
+++ b/app/operations/layer-modes/gimpoperationpointlayermode.h
@@ -59,884 +59,7 @@ struct _GimpOperationPointLayerMode
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_perceptual_to_laba;
-extern const Babl *_gimp_fish_rgba_to_laba;
-extern const Babl *_gimp_fish_laba_to_rgba;
-extern const Babl *_gimp_fish_laba_to_perceptual;
+#include "gimpoperationnormal.h"
-static inline void
-compfun_src_atop (gfloat *in,
- gfloat *layer,
- gfloat *mask,
- gfloat opacity,
- gfloat *out,
- gint samples)
-{
- while (samples--)
- {
- gfloat comp_alpha = layer[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] = layer[b] * comp_alpha + in[b] * (1.0f - comp_alpha);
- }
- out[ALPHA] = in[ALPHA];
-
- in += 4;
- out += 4;
- layer += 4;
-
- if (mask)
- mask++;
- }
-}
-
-static inline void
-compfun_src_over (gfloat *in,
- gfloat *layer,
- gfloat *mask,
- gfloat opacity,
- gfloat *out,
- gint samples)
-{
- while (samples--)
- {
- gfloat new_alpha;
- gfloat comp_alpha = layer[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] = layer[b] * ratio + in[b] * (1.0f - ratio);
- }
-
- out[ALPHA] = new_alpha;
-
- in += 4;
- layer += 4;
- out += 4;
-
- if (mask)
- mask++;
- }
-}
-
-
-static inline void
-compfun_src_in (gfloat *in,
- gfloat *layer,
- gfloat *mask,
- gfloat opacity,
- gfloat *out,
- gint samples)
-{
- while (samples--)
- {
- gfloat new_alpha = in[ALPHA] * layer[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] = layer[RED];
- out[GREEN] = layer[GREEN];
- out[BLUE] = layer[BLUE];
- }
- out[ALPHA] = new_alpha;
- in += 4;
- out += 4;
- layer += 4;
-
- if (mask)
- mask++;
- }
-}
-
-static inline void
-gimp_composite_blend (gfloat *in,
- gfloat *layer,
- gfloat *mask,
- gfloat *out,
- gfloat opacity,
- glong samples,
- GimpLayerBlendTRC blend_trc,
- GimpLayerBlendTRC composite_trc,
- GimpLayerCompositeMode 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;
-
- const Babl *fish_to_blend = NULL;
- const Babl *fish_to_composite = NULL;
- const Babl *fish_from_composite = NULL;
-
- switch (blend_trc)
- {
- default:
- case GIMP_LAYER_BLEND_RGB_LINEAR:
- fish_to_blend = NULL;
- switch (composite_trc)
- {
- case GIMP_LAYER_BLEND_LAB:
- fish_to_composite = _gimp_fish_rgba_to_laba;
- fish_from_composite = _gimp_fish_laba_to_rgba;
- default:
- case GIMP_LAYER_BLEND_RGB_LINEAR:
- fish_to_composite = NULL;
- fish_from_composite = NULL;
- break;
- case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
- fish_to_composite = _gimp_fish_rgba_to_perceptual;
- fish_from_composite = _gimp_fish_perceptual_to_rgba;
- break;
- }
- break;
- case GIMP_LAYER_BLEND_LAB:
- fish_to_blend = _gimp_fish_rgba_to_laba;
- switch (composite_trc)
- {
- case GIMP_LAYER_BLEND_LAB:
- default:
- fish_to_composite = NULL;
- fish_from_composite = _gimp_fish_laba_to_rgba;
- case GIMP_LAYER_BLEND_RGB_LINEAR:
- fish_to_composite = _gimp_fish_laba_to_rgba;
- fish_from_composite = NULL;
- break;
- case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
- fish_to_composite = _gimp_fish_laba_to_perceptual;
- fish_from_composite = _gimp_fish_perceptual_to_rgba;
- break;
- }
- break;
- case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
- fish_to_blend = _gimp_fish_rgba_to_perceptual;
- switch (composite_trc)
- {
- case GIMP_LAYER_BLEND_LAB:
- default:
- fish_to_composite = _gimp_fish_perceptual_to_laba;
- fish_from_composite = NULL;
- case GIMP_LAYER_BLEND_RGB_LINEAR:
- fish_to_composite = _gimp_fish_perceptual_to_rgba;
- fish_from_composite = NULL;
- break;
- case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
- fish_to_composite = NULL;
- fish_from_composite = _gimp_fish_perceptual_to_rgba;
- break;
- }
- break;
- }
-
- if (in == out) /* in-place detected, avoid clobbering since we need to
- read it for the compositing stage */
- blend_out = alloca (sizeof (gfloat) * 4 * samples);
-
- if (fish_to_blend)
- {
- blend_in = alloca (sizeof (gfloat) * 4 * samples);
- blend_layer = alloca (sizeof (gfloat) * 4 * samples);
- babl_process (fish_to_blend, in, blend_in, samples);
- babl_process (fish_to_blend, layer, blend_layer, samples);
- }
-
- blendfun (blend_in, blend_layer, blend_out, samples);
-
- if (fish_to_composite)
- {
- babl_process (fish_to_composite, blend_in, blend_in, samples);
- babl_process (fish_to_composite, blend_out, blend_out, samples);
- }
-
- switch (composite_mode)
- {
- case GIMP_LAYER_COMPOSITE_SRC_ATOP:
- default:
- compfun_src_atop (blend_in, blend_out, mask, opacity, out, samples);
- break;
- case GIMP_LAYER_COMPOSITE_SRC_OVER:
- compfun_src_over (blend_in, blend_out, mask, opacity, out, samples);
- break;
- case GIMP_LAYER_COMPOSITE_DST_ATOP:
- if (fish_to_composite)
- babl_process (fish_to_composite, blend_layer, blend_layer, samples);
-
- compfun_src_atop (blend_out, blend_in, mask, opacity, out, samples); /* swapped arguments */
- break;
- case GIMP_LAYER_COMPOSITE_SRC_IN:
- compfun_src_in (blend_in, blend_out, mask, opacity, out, samples);
- break;
- }
-
- if (fish_from_composite)
- {
- babl_process (fish_from_composite, out, out, samples);
- }
-}
-
-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 90881be..76ac125 100644
--- a/app/operations/layer-modes/gimpoperationscreen.c
+++ b/app/operations/layer-modes/gimpoperationscreen.c
@@ -27,6 +27,7 @@
#include "../operations-types.h"
#include "gimpoperationscreen.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_screen_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationsoftlight.c
b/app/operations/layer-modes/gimpoperationsoftlight.c
index d35fa8c..9d7f06f 100644
--- a/app/operations/layer-modes/gimpoperationsoftlight.c
+++ b/app/operations/layer-modes/gimpoperationsoftlight.c
@@ -26,6 +26,7 @@
#include "../operations-types.h"
#include "gimpoperationsoftlight.h"
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_softlight_process (GeglOperation *operation,
diff --git a/app/operations/layer-modes/gimpoperationsubtract.c
b/app/operations/layer-modes/gimpoperationsubtract.c
index e8a1ade..b2b696d 100644
--- a/app/operations/layer-modes/gimpoperationsubtract.c
+++ b/app/operations/layer-modes/gimpoperationsubtract.c
@@ -27,7 +27,7 @@
#include "../operations-types.h"
#include "gimpoperationsubtract.h"
-
+#include "gimpblendcomposite.h"
static gboolean gimp_operation_subtract_process (GeglOperation *operation,
void *in_buf,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]