[gimp/pippin/linear-is-the-new-black] 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] app: add abstraction for separate blend and composite modes, like LCH mods already do
- Date: Sun, 15 Jan 2017 20:11:21 +0000 (UTC)
commit df026e49b5fb05b63355efa08dc658f2f9bf49bf
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
.../layer-modes/gimpoperationpointlayermode.h | 178 ++++++++++++++++++++
app/operations/layer-modes/gimpoperationscreen.c | 66 +++-----
2 files changed, 202 insertions(+), 42 deletions(-)
---
diff --git a/app/operations/layer-modes/gimpoperationpointlayermode.h
b/app/operations/layer-modes/gimpoperationpointlayermode.h
index af0a6e0..33569de 100644
--- a/app/operations/layer-modes/gimpoperationpointlayermode.h
+++ b/app/operations/layer-modes/gimpoperationpointlayermode.h
@@ -90,4 +90,182 @@ 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_ATOP,
+ GIMP_LAYER_COMPOSITE_OVER,
+ GIMP_LAYER_COMPOSITE_IN
+} GimpLayerComposite;
+
+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));
+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_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.0 - comp_alpha);
+ }
+
+ out[ALPHA] = in[ALPHA];
+
+ in += 4;
+ out += 4;
+
+ if (mask)
+ mask++;
+ }
+ break;
+ case GIMP_LAYER_COMPOSITE_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.0 - comp_alpha);
+ }
+
+ out[ALPHA] = comp_alpha + in[ALPHA] * (1.0 - comp_alpha);
+
+ in += 4;
+ out += 4;
+
+ if (mask)
+ mask++;
+ }
+ break;
+ case GIMP_LAYER_COMPOSITE_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.0 - comp_alpha);
+ }
+ out[ALPHA] = comp_alpha + in[ALPHA];
+ in += 4;
+ out += 4;
+
+ if (mask)
+ mask++;
+ }
+ break;
+ }
+}
+
+
#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..b386417 100644
--- a/app/operations/layer-modes/gimpoperationscreen.c
+++ b/app/operations/layer-modes/gimpoperationscreen.c
@@ -65,6 +65,23 @@ gimp_operation_screen_init (GimpOperationScreen *self)
{
}
+static void blendfun_screen (const float *dest, const float *src, float *out, int samples)
+{
+ while (--samples)
+ {
+ if (src[ALPHA] != 0.0f)
+ {
+ out[RED] = 1.0f - (1.0f - dest[RED]) * (1.0f - src[RED]);
+ out[GREEN] = 1.0f - (1.0f - dest[GREEN]) * (1.0f - src[GREEN]);
+ out[BLUE] = 1.0f - (1.0f - dest[BLUE]) * (1.0f - src[BLUE]);
+ }
+ out[ALPHA] = dest[ALPHA];
+ out += 4;
+ src += 4;
+ dest += 4;
+ }
+}
+
static gboolean
gimp_operation_screen_process (GeglOperation *operation,
void *in_buf,
@@ -76,7 +93,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 +106,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_ATOP,
+ blendfun_screen
+ );
return TRUE;
}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]