[gimp] app: added addition, burn, darken only, dodge, multiply, overlay, screen and soft light gegl blendin



commit c24d9d76e5f1f50e8d3982e286424c749ee8c6f8
Author: Ville Sokk <ville sokk gmail com>
Date:   Fri Apr 20 21:42:54 2012 +0300

    app: added addition, burn, darken only, dodge, multiply, overlay, screen and soft light gegl blending modes

 app/gegl/gimp-gegl-nodes.c             |   10 +---------
 app/gegl/gimpoperationadditionmode.c   |   30 ++++++++++++++++++++++++++----
 app/gegl/gimpoperationburnmode.c       |   31 +++++++++++++++++++++++++++----
 app/gegl/gimpoperationdarkenonlymode.c |   30 ++++++++++++++++++++++++++----
 app/gegl/gimpoperationdodgemode.c      |   30 ++++++++++++++++++++++++++----
 app/gegl/gimpoperationmultiplymode.c   |   30 ++++++++++++++++++++++++++----
 app/gegl/gimpoperationoverlaymode.c    |   30 ++++++++++++++++++++++++++----
 app/gegl/gimpoperationscreenmode.c     |   30 ++++++++++++++++++++++++++----
 app/gegl/gimpoperationsoftlightmode.c  |   32 ++++++++++++++++++++++++++++----
 9 files changed, 212 insertions(+), 41 deletions(-)
---
diff --git a/app/gegl/gimp-gegl-nodes.c b/app/gegl/gimp-gegl-nodes.c
index 2038488..45506eb 100644
--- a/app/gegl/gimp-gegl-nodes.c
+++ b/app/gegl/gimp-gegl-nodes.c
@@ -250,22 +250,14 @@ gimp_gegl_node_set_layer_mode (GeglNode             *node,
   switch (mode)
     {
     case GIMP_BEHIND_MODE:
-    case GIMP_MULTIPLY_MODE:
-    case GIMP_SCREEN_MODE:
-    case GIMP_OVERLAY_MODE:
     case GIMP_DIFFERENCE_MODE:
-    case GIMP_ADDITION_MODE:
     case GIMP_SUBTRACT_MODE:
-    case GIMP_DARKEN_ONLY_MODE:
     case GIMP_HUE_MODE:
     case GIMP_SATURATION_MODE:
     case GIMP_COLOR_MODE:
     case GIMP_VALUE_MODE:
     case GIMP_DIVIDE_MODE:
-    case GIMP_DODGE_MODE:
-    case GIMP_BURN_MODE:
     case GIMP_HARDLIGHT_MODE:
-    case GIMP_SOFTLIGHT_MODE:
     case GIMP_GRAIN_EXTRACT_MODE:
     case GIMP_GRAIN_MERGE_MODE:
     case GIMP_COLOR_ERASE_MODE:
@@ -294,7 +286,7 @@ gimp_gegl_node_set_layer_mode (GeglNode             *node,
     case GIMP_DIFFERENCE_MODE:    operation = "gimp:difference-mode"; break;
     case GIMP_ADDITION_MODE:      operation = "gimp:addition-mode"; break;
     case GIMP_SUBTRACT_MODE:      operation = "gimp:subtract-mode"; break;
-    case GIMP_DARKEN_ONLY_MODE:   operation = "gimp:darken-mode"; break;
+    case GIMP_DARKEN_ONLY_MODE:   operation = "gimp:darken-only-mode"; break;
     case GIMP_LIGHTEN_ONLY_MODE:  operation = "gimp:lighten-only-mode"; break;
     case GIMP_HUE_MODE:           operation = "gimp:hue-mode"; break;
     case GIMP_SATURATION_MODE:    operation = "gimp:saturation-mode"; break;
diff --git a/app/gegl/gimpoperationadditionmode.c b/app/gegl/gimpoperationadditionmode.c
index a403564..2685faa 100644
--- a/app/gegl/gimpoperationadditionmode.c
+++ b/app/gegl/gimpoperationadditionmode.c
@@ -3,6 +3,7 @@
  *
  * gimpoperationadditionmode.c
  * Copyright (C) 2008 Michael Natterer <mitch gimp org>
+ *               2012 Ville Sokk <ville sokk gmail com>
  *
  * 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
@@ -28,6 +29,7 @@
 #include "gimpoperationadditionmode.h"
 
 
+static void gimp_operation_addition_mode_prepare     (GeglOperation       *operation);
 static gboolean gimp_operation_addition_mode_process (GeglOperation       *operation,
                                                       void                *in_buf,
                                                       void                *aux_buf,
@@ -55,7 +57,8 @@ gimp_operation_addition_mode_class_init (GimpOperationAdditionModeClass *klass)
            "description", "GIMP addition mode operation",
            NULL);
 
-  point_class->process         = gimp_operation_addition_mode_process;
+  point_class->process     = gimp_operation_addition_mode_process;
+  operation_class->prepare = gimp_operation_addition_mode_prepare;
 }
 
 static void
@@ -63,6 +66,16 @@ gimp_operation_addition_mode_init (GimpOperationAdditionMode *self)
 {
 }
 
+static void
+gimp_operation_addition_mode_prepare (GeglOperation *operation)
+{
+  const Babl *format = babl_format ("R'G'B'A float");
+
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
+  gegl_operation_set_format (operation, "output", format);
+}
+
 static gboolean
 gimp_operation_addition_mode_process (GeglOperation       *operation,
                                       void                *in_buf,
@@ -78,9 +91,18 @@ gimp_operation_addition_mode_process (GeglOperation       *operation,
 
   while (samples--)
     {
-      out[RED]   = in[RED];
-      out[GREEN] = in[GREEN];
-      out[BLUE]  = in[BLUE];
+      gint b;
+      gfloat comp_alpha = in[ALPHA] * layer[ALPHA];
+      gfloat new_alpha  = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha;
+      gfloat ratio      = comp_alpha / new_alpha;
+
+      for (b = RED; b < ALPHA; b++)
+        {
+          gfloat comp = CLAMP (in[b] + layer[b], 0.0, 1.0);
+
+          out[b] = comp * ratio + in[b] * (1 - ratio);
+        }
+
       out[ALPHA] = in[ALPHA];
 
       in    += 4;
diff --git a/app/gegl/gimpoperationburnmode.c b/app/gegl/gimpoperationburnmode.c
index 625e547..6893faf 100644
--- a/app/gegl/gimpoperationburnmode.c
+++ b/app/gegl/gimpoperationburnmode.c
@@ -3,6 +3,7 @@
  *
  * gimpoperationburnmode.c
  * Copyright (C) 2008 Michael Natterer <mitch gimp org>
+ *               2012 Ville Sokk <ville sokk gmail com>
  *
  * 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
@@ -28,6 +29,7 @@
 #include "gimpoperationburnmode.h"
 
 
+static void gimp_operation_burn_mode_prepare     (GeglOperation       *operation);
 static gboolean gimp_operation_burn_mode_process (GeglOperation       *operation,
                                                   void                *in_buf,
                                                   void                *aux_buf,
@@ -55,7 +57,8 @@ gimp_operation_burn_mode_class_init (GimpOperationBurnModeClass *klass)
            "description", "GIMP burn mode operation",
            NULL);
 
-  point_class->process         = gimp_operation_burn_mode_process;
+  point_class->process     = gimp_operation_burn_mode_process;
+  operation_class->prepare = gimp_operation_burn_mode_prepare;
 }
 
 static void
@@ -63,6 +66,16 @@ gimp_operation_burn_mode_init (GimpOperationBurnMode *self)
 {
 }
 
+static void
+gimp_operation_burn_mode_prepare (GeglOperation *operation)
+{
+  const Babl *format = babl_format ("R'G'B'A float");
+
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
+  gegl_operation_set_format (operation, "output", format);
+}
+
 static gboolean
 gimp_operation_burn_mode_process (GeglOperation       *operation,
                                   void                *in_buf,
@@ -78,9 +91,19 @@ gimp_operation_burn_mode_process (GeglOperation       *operation,
 
   while (samples--)
     {
-      out[RED]   = in[RED];
-      out[GREEN] = in[GREEN];
-      out[BLUE]  = in[BLUE];
+      gint b;
+      gfloat comp_alpha = in[ALPHA] * layer[ALPHA];
+      gfloat new_alpha  = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha;
+      gfloat ratio      = comp_alpha / new_alpha;
+
+      for (b = RED; b < ALPHA; b++)
+        {
+          gfloat comp = (1 - in[b]) / layer[b];
+          comp = CLAMP (1 - comp, 0.0, 1.0);
+
+          out[b] = comp * ratio + in[b] * (1 - ratio);
+        }
+
       out[ALPHA] = in[ALPHA];
 
       in    += 4;
diff --git a/app/gegl/gimpoperationdarkenonlymode.c b/app/gegl/gimpoperationdarkenonlymode.c
index 657903e..43c9942 100644
--- a/app/gegl/gimpoperationdarkenonlymode.c
+++ b/app/gegl/gimpoperationdarkenonlymode.c
@@ -3,6 +3,7 @@
  *
  * gimpoperationdarkenonlymode.c
  * Copyright (C) 2008 Michael Natterer <mitch gimp org>
+ *               2012 Ville Sokk <ville sokk gmail com>
  *
  * 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
@@ -28,6 +29,7 @@
 #include "gimpoperationdarkenonlymode.h"
 
 
+static void gimp_operation_darken_only_mode_prepare     (GeglOperation       *operation);
 static gboolean gimp_operation_darken_only_mode_process (GeglOperation       *operation,
                                                          void                *in_buf,
                                                          void                *aux_buf,
@@ -55,7 +57,8 @@ gimp_operation_darken_only_mode_class_init (GimpOperationDarkenOnlyModeClass *kl
            "description", "GIMP darken only mode operation",
            NULL);
 
-  point_class->process         = gimp_operation_darken_only_mode_process;
+  point_class->process     = gimp_operation_darken_only_mode_process;
+  operation_class->prepare = gimp_operation_darken_only_mode_prepare;
 }
 
 static void
@@ -63,6 +66,16 @@ gimp_operation_darken_only_mode_init (GimpOperationDarkenOnlyMode *self)
 {
 }
 
+static void
+gimp_operation_darken_only_mode_prepare (GeglOperation *operation)
+{
+  const Babl *format = babl_format ("R'G'B'A float");
+
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
+  gegl_operation_set_format (operation, "output", format);
+}
+
 static gboolean
 gimp_operation_darken_only_mode_process (GeglOperation       *operation,
                                          void                *in_buf,
@@ -78,9 +91,18 @@ gimp_operation_darken_only_mode_process (GeglOperation       *operation,
 
   while (samples--)
     {
-      out[RED]   = in[RED];
-      out[GREEN] = in[GREEN];
-      out[BLUE]  = in[BLUE];
+      gint b;
+      gfloat comp_alpha = in[ALPHA] * layer[ALPHA];
+      gfloat new_alpha  = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha;
+      gfloat ratio      = comp_alpha / new_alpha;
+
+      for (b = RED; b < ALPHA; b++)
+        {
+          gfloat comp = MIN (in[b], layer[b]);
+
+          out[b] = comp * ratio + in[b] * (1 - ratio);
+        }
+
       out[ALPHA] = in[ALPHA];
 
       in    += 4;
diff --git a/app/gegl/gimpoperationdodgemode.c b/app/gegl/gimpoperationdodgemode.c
index f3eabdc..acf6afe 100644
--- a/app/gegl/gimpoperationdodgemode.c
+++ b/app/gegl/gimpoperationdodgemode.c
@@ -3,6 +3,7 @@
  *
  * gimpoperationdodgemode.c
  * Copyright (C) 2008 Michael Natterer <mitch gimp org>
+ *               2012 Ville Sokk <ville sokk gmail com>
  *
  * 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
@@ -28,6 +29,7 @@
 #include "gimpoperationdodgemode.h"
 
 
+static void gimp_operation_dodge_mode_prepare     (GeglOperation       *operation);
 static gboolean gimp_operation_dodge_mode_process (GeglOperation       *operation,
                                                    void                *in_buf,
                                                    void                *aux_buf,
@@ -55,7 +57,8 @@ gimp_operation_dodge_mode_class_init (GimpOperationDodgeModeClass *klass)
            "description", "GIMP dodge mode operation",
            NULL);
 
-  point_class->process         = gimp_operation_dodge_mode_process;
+  point_class->process     = gimp_operation_dodge_mode_process;
+  operation_class->prepare = gimp_operation_dodge_mode_prepare;
 }
 
 static void
@@ -63,6 +66,16 @@ gimp_operation_dodge_mode_init (GimpOperationDodgeMode *self)
 {
 }
 
+static void
+gimp_operation_dodge_mode_prepare (GeglOperation *operation)
+{
+  const Babl *format = babl_format ("R'G'B'A float");
+
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
+  gegl_operation_set_format (operation, "output", format);
+}
+
 static gboolean
 gimp_operation_dodge_mode_process (GeglOperation       *operation,
                                    void                *in_buf,
@@ -78,9 +91,18 @@ gimp_operation_dodge_mode_process (GeglOperation       *operation,
 
   while (samples--)
     {
-      out[RED]   = in[RED];
-      out[GREEN] = in[GREEN];
-      out[BLUE]  = in[BLUE];
+      gint b;
+      gfloat comp_alpha = in[ALPHA] * layer[ALPHA];
+      gfloat new_alpha  = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha;
+      gfloat ratio      = comp_alpha / new_alpha;
+
+      for (b = RED; b < ALPHA; b++)
+        {
+          gfloat comp = MIN (in[b] / (1 - layer[b]), 1);
+
+          out[b] = comp * ratio + in[b] * (1 - ratio);
+        }
+
       out[ALPHA] = in[ALPHA];
 
       in    += 4;
diff --git a/app/gegl/gimpoperationmultiplymode.c b/app/gegl/gimpoperationmultiplymode.c
index 7063ee7..11e118b 100644
--- a/app/gegl/gimpoperationmultiplymode.c
+++ b/app/gegl/gimpoperationmultiplymode.c
@@ -3,6 +3,7 @@
  *
  * gimpoperationmultiplymode.c
  * Copyright (C) 2008 Michael Natterer <mitch gimp org>
+ *               2012 Ville Sokk <ville sokk gmail com>
  *
  * 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
@@ -28,6 +29,7 @@
 #include "gimpoperationmultiplymode.h"
 
 
+static void gimp_operation_multiply_mode_prepare     (GeglOperation       *operation);
 static gboolean gimp_operation_multiply_mode_process (GeglOperation       *operation,
                                                       void                *in_buf,
                                                       void                *aux_buf,
@@ -55,7 +57,8 @@ gimp_operation_multiply_mode_class_init (GimpOperationMultiplyModeClass *klass)
            "description", "GIMP multiply mode operation",
            NULL);
 
-  point_class->process         = gimp_operation_multiply_mode_process;
+  point_class->process     = gimp_operation_multiply_mode_process;
+  operation_class->prepare = gimp_operation_multiply_mode_prepare;
 }
 
 static void
@@ -63,6 +66,16 @@ gimp_operation_multiply_mode_init (GimpOperationMultiplyMode *self)
 {
 }
 
+static void
+gimp_operation_multiply_mode_prepare (GeglOperation *operation)
+{
+  const Babl *format = babl_format ("R'G'B'A float");
+
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
+  gegl_operation_set_format (operation, "output", format);
+}
+
 static gboolean
 gimp_operation_multiply_mode_process (GeglOperation       *operation,
                                       void                *in_buf,
@@ -78,9 +91,18 @@ gimp_operation_multiply_mode_process (GeglOperation       *operation,
 
   while (samples--)
     {
-      out[RED]   = in[RED];
-      out[GREEN] = in[GREEN];
-      out[BLUE]  = in[BLUE];
+      gint b;
+      gfloat comp_alpha = in[ALPHA] * layer[ALPHA];
+      gfloat new_alpha  = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha;
+      gfloat ratio      = comp_alpha / new_alpha;
+
+      for (b = RED; b < ALPHA; b++)
+        {
+          gfloat comp = CLAMP (layer[b] * in[b], 0.0, 1.0);
+
+          out[b] = comp * ratio + in[b] * (1 - ratio);
+        }
+
       out[ALPHA] = in[ALPHA];
 
       in    += 4;
diff --git a/app/gegl/gimpoperationoverlaymode.c b/app/gegl/gimpoperationoverlaymode.c
index e762e7f..640362f 100644
--- a/app/gegl/gimpoperationoverlaymode.c
+++ b/app/gegl/gimpoperationoverlaymode.c
@@ -3,6 +3,7 @@
  *
  * gimpoperationoverlaymode.c
  * Copyright (C) 2008 Michael Natterer <mitch gimp org>
+ *               2012 Ville Sokk <ville sokk gmail com>
  *
  * 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
@@ -28,6 +29,7 @@
 #include "gimpoperationoverlaymode.h"
 
 
+static void gimp_operation_overlay_mode_prepare     (GeglOperation       *operation);
 static gboolean gimp_operation_overlay_mode_process (GeglOperation       *operation,
                                                      void                *in_buf,
                                                      void                *aux_buf,
@@ -55,7 +57,8 @@ gimp_operation_overlay_mode_class_init (GimpOperationOverlayModeClass *klass)
            "description", "GIMP overlay mode operation",
            NULL);
 
-  point_class->process         = gimp_operation_overlay_mode_process;
+  point_class->process     = gimp_operation_overlay_mode_process;
+  operation_class->prepare = gimp_operation_overlay_mode_prepare;
 }
 
 static void
@@ -63,6 +66,16 @@ gimp_operation_overlay_mode_init (GimpOperationOverlayMode *self)
 {
 }
 
+static void
+gimp_operation_overlay_mode_prepare (GeglOperation *operation)
+{
+  const Babl *format = babl_format ("R'G'B'A float");
+
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
+  gegl_operation_set_format (operation, "output", format);
+}
+
 static gboolean
 gimp_operation_overlay_mode_process (GeglOperation       *operation,
                                      void                *in_buf,
@@ -78,9 +91,18 @@ gimp_operation_overlay_mode_process (GeglOperation       *operation,
 
   while (samples--)
     {
-      out[RED]   = in[RED];
-      out[GREEN] = in[GREEN];
-      out[BLUE]  = in[BLUE];
+      gint b;
+      gfloat comp_alpha = in[ALPHA] * layer[ALPHA];
+      gfloat new_alpha  = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha;
+      gfloat ratio      = comp_alpha / new_alpha;
+
+      for (b = RED; b < ALPHA; b++)
+        {
+          gfloat comp = in[b] * (in[b] + (2 * layer[b]) * (1 - in[b]));
+
+          out[b] = comp * ratio + in[b] * (1 - ratio);
+        }
+
       out[ALPHA] = in[ALPHA];
 
       in    += 4;
diff --git a/app/gegl/gimpoperationscreenmode.c b/app/gegl/gimpoperationscreenmode.c
index 55ab394..a23d3bb 100644
--- a/app/gegl/gimpoperationscreenmode.c
+++ b/app/gegl/gimpoperationscreenmode.c
@@ -3,6 +3,7 @@
  *
  * gimpoperationscreenmode.c
  * Copyright (C) 2008 Michael Natterer <mitch gimp org>
+ *               2012 Ville Sokk <ville sokk gmail com>
  *
  * 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
@@ -28,6 +29,7 @@
 #include "gimpoperationscreenmode.h"
 
 
+static void gimp_operation_screen_mode_prepare     (GeglOperation       *operation);
 static gboolean gimp_operation_screen_mode_process (GeglOperation       *operation,
                                                     void                *in_buf,
                                                     void                *aux_buf,
@@ -55,7 +57,8 @@ gimp_operation_screen_mode_class_init (GimpOperationScreenModeClass *klass)
            "description", "GIMP screen mode operation",
            NULL);
 
-  point_class->process         = gimp_operation_screen_mode_process;
+  point_class->process     = gimp_operation_screen_mode_process;
+  operation_class->prepare = gimp_operation_screen_mode_prepare;
 }
 
 static void
@@ -63,6 +66,16 @@ gimp_operation_screen_mode_init (GimpOperationScreenMode *self)
 {
 }
 
+static void
+gimp_operation_screen_mode_prepare (GeglOperation *operation)
+{
+  const Babl *format = babl_format ("R'G'B'A float");
+
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
+  gegl_operation_set_format (operation, "output", format);
+}
+
 static gboolean
 gimp_operation_screen_mode_process (GeglOperation       *operation,
                                     void                *in_buf,
@@ -78,9 +91,18 @@ gimp_operation_screen_mode_process (GeglOperation       *operation,
 
   while (samples--)
     {
-      out[RED]   = in[RED];
-      out[GREEN] = in[GREEN];
-      out[BLUE]  = in[BLUE];
+      gint b;
+      gfloat comp_alpha = in[ALPHA] * layer[ALPHA];
+      gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha;
+      gfloat ratio = comp_alpha / new_alpha;
+
+      for (b = RED; b < ALPHA; b++)
+        {
+          gfloat comp = 1 - (1 - in[b]) * (1 - layer[b]);
+
+          out[b] = comp * ratio + in[b] * (1 - ratio);
+        }
+
       out[ALPHA] = in[ALPHA];
 
       in    += 4;
diff --git a/app/gegl/gimpoperationsoftlightmode.c b/app/gegl/gimpoperationsoftlightmode.c
index d5eeb86..ad3a313 100644
--- a/app/gegl/gimpoperationsoftlightmode.c
+++ b/app/gegl/gimpoperationsoftlightmode.c
@@ -3,6 +3,7 @@
  *
  * gimpoperationsoftlightmode.c
  * Copyright (C) 2008 Michael Natterer <mitch gimp org>
+ *               2012 Ville Sokk <ville sokk gmail com>
  *
  * 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
@@ -28,6 +29,7 @@
 #include "gimpoperationsoftlightmode.h"
 
 
+static void gimp_operation_softlight_mode_prepare     (GeglOperation       *operation);
 static gboolean gimp_operation_softlight_mode_process (GeglOperation       *operation,
                                                        void                *in_buf,
                                                        void                *aux_buf,
@@ -55,7 +57,8 @@ gimp_operation_softlight_mode_class_init (GimpOperationSoftlightModeClass *klass
            "description", "GIMP softlight mode operation",
            NULL);
 
-  point_class->process         = gimp_operation_softlight_mode_process;
+  point_class->process     = gimp_operation_softlight_mode_process;
+  operation_class->prepare = gimp_operation_softlight_mode_prepare;
 }
 
 static void
@@ -63,6 +66,16 @@ gimp_operation_softlight_mode_init (GimpOperationSoftlightMode *self)
 {
 }
 
+static void
+gimp_operation_softlight_mode_prepare (GeglOperation *operation)
+{
+  const Babl *format = babl_format ("R'G'B'A float");
+
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
+  gegl_operation_set_format (operation, "output", format);
+}
+
 static gboolean
 gimp_operation_softlight_mode_process (GeglOperation       *operation,
                                        void                *in_buf,
@@ -78,9 +91,20 @@ gimp_operation_softlight_mode_process (GeglOperation       *operation,
 
   while (samples--)
     {
-      out[RED]   = in[RED];
-      out[GREEN] = in[GREEN];
-      out[BLUE]  = in[BLUE];
+      gint b;
+      gfloat comp_alpha = in[ALPHA] * layer[ALPHA];
+      gfloat new_alpha  = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha;
+      gfloat ratio      = comp_alpha / new_alpha;
+
+      for (b = RED; b < ALPHA; b++)
+        {
+          gfloat multiply = in[b] * layer[b];
+          gfloat screen = 1 - (1 - in[b]) * (1 - layer[b]);
+          gfloat comp = (1 - in[b]) * multiply + in[b] * screen;
+
+          out[b] = comp * ratio + in[b] * (1 - ratio);
+        }
+
       out[ALPHA] = in[ALPHA];
 
       in    += 4;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]