From c24d9d76e5f1f50e8d3982e286424c749ee8c6f8 Mon Sep 17 00:00:00 2001 From: Ville Sokk Date: Fri, 20 Apr 2012 21:42:54 +0300 Subject: [PATCH] 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 2038488cde..45506ebe15 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 a403564063..2685faa6f2 100644 --- a/app/gegl/gimpoperationadditionmode.c +++ b/app/gegl/gimpoperationadditionmode.c @@ -3,6 +3,7 @@ * * gimpoperationadditionmode.c * Copyright (C) 2008 Michael Natterer + * 2012 Ville Sokk * * 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 625e547924..6893fafb3f 100644 --- a/app/gegl/gimpoperationburnmode.c +++ b/app/gegl/gimpoperationburnmode.c @@ -3,6 +3,7 @@ * * gimpoperationburnmode.c * Copyright (C) 2008 Michael Natterer + * 2012 Ville Sokk * * 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 657903ef0d..43c99422ac 100644 --- a/app/gegl/gimpoperationdarkenonlymode.c +++ b/app/gegl/gimpoperationdarkenonlymode.c @@ -3,6 +3,7 @@ * * gimpoperationdarkenonlymode.c * Copyright (C) 2008 Michael Natterer + * 2012 Ville Sokk * * 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 f3eabdcbb5..acf6afe1bb 100644 --- a/app/gegl/gimpoperationdodgemode.c +++ b/app/gegl/gimpoperationdodgemode.c @@ -3,6 +3,7 @@ * * gimpoperationdodgemode.c * Copyright (C) 2008 Michael Natterer + * 2012 Ville Sokk * * 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 7063ee73ae..11e118b893 100644 --- a/app/gegl/gimpoperationmultiplymode.c +++ b/app/gegl/gimpoperationmultiplymode.c @@ -3,6 +3,7 @@ * * gimpoperationmultiplymode.c * Copyright (C) 2008 Michael Natterer + * 2012 Ville Sokk * * 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 e762e7f884..640362ffb1 100644 --- a/app/gegl/gimpoperationoverlaymode.c +++ b/app/gegl/gimpoperationoverlaymode.c @@ -3,6 +3,7 @@ * * gimpoperationoverlaymode.c * Copyright (C) 2008 Michael Natterer + * 2012 Ville Sokk * * 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 55ab3944aa..a23d3bbae1 100644 --- a/app/gegl/gimpoperationscreenmode.c +++ b/app/gegl/gimpoperationscreenmode.c @@ -3,6 +3,7 @@ * * gimpoperationscreenmode.c * Copyright (C) 2008 Michael Natterer + * 2012 Ville Sokk * * 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 d5eeb86983..ad3a313682 100644 --- a/app/gegl/gimpoperationsoftlightmode.c +++ b/app/gegl/gimpoperationsoftlightmode.c @@ -3,6 +3,7 @@ * * gimpoperationsoftlightmode.c * Copyright (C) 2008 Michael Natterer + * 2012 Ville Sokk * * 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;