diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c index a40d194d8d..a98c46b87c 100644 --- a/app/core/gimplayer.c +++ b/app/core/gimplayer.c @@ -1942,7 +1942,7 @@ gimp_layer_set_opacity (GimpLayer *layer, if (gimp_item_peek_node (GIMP_ITEM (layer))) { gegl_node_set (gimp_drawable_get_mode_node (GIMP_DRAWABLE (layer)), - "value", layer->opacity, + "opacity", layer->opacity, NULL); } diff --git a/app/gegl/gimp-gegl-nodes.c b/app/gegl/gimp-gegl-nodes.c index 21035f3aef..11e3d11a8d 100644 --- a/app/gegl/gimp-gegl-nodes.c +++ b/app/gegl/gimp-gegl-nodes.c @@ -316,21 +316,6 @@ gimp_gegl_node_set_layer_mode (GeglNode *node, g_return_if_fail (GEGL_IS_NODE (node)); - switch (mode) - { - case GIMP_COLOR_ERASE_MODE: - case GIMP_ANTI_ERASE_MODE: - gegl_node_set (node, - "operation", "gimp:point-layer-mode", - "blend-mode", mode, - "premultiplied", premultiplied, - NULL); - return; - - default: - break; - } - switch (mode) { case GIMP_NORMAL_MODE: operation = "gimp:normal-mode"; break; diff --git a/app/operations/gimpoperationadditionmode.c b/app/operations/gimpoperationadditionmode.c index ce606e5690..dda4585b91 100644 --- a/app/operations/gimpoperationadditionmode.c +++ b/app/operations/gimpoperationadditionmode.c @@ -33,6 +33,7 @@ static void gimp_operation_addition_mode_prepare (GeglOperation *opera static gboolean gimp_operation_addition_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -46,11 +47,11 @@ G_DEFINE_TYPE (GimpOperationAdditionMode, gimp_operation_addition_mode, static void gimp_operation_addition_mode_class_init (GimpOperationAdditionModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:addition-mode", @@ -73,6 +74,7 @@ gimp_operation_addition_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -80,35 +82,95 @@ static gboolean gimp_operation_addition_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; - while (samples--) + if (mask) { - gint b; - gfloat comp_alpha = MIN (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++) + while (samples--) { - gfloat comp = in[b] + layer[b]; - comp = CLAMP (comp, 0, 1); + gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity * (*mask); + gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + if (comp_alpha && new_alpha) + { + gfloat ratio = comp_alpha / new_alpha; + gint b; + + for (b = RED; b < ALPHA; b++) + { + gfloat comp = in[b] + layer[b]; + comp = CLAMP (comp, 0, 1); + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + gint b; + + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } + + in += 4; + layer += 4; + mask += 1; + out += 4; } + } + else + { + while (samples--) + { + gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - out[ALPHA] = in[ALPHA]; + if (comp_alpha && new_alpha) + { + gfloat ratio = comp_alpha / new_alpha; + gint b; - in += 4; - layer += 4; - out += 4; + for (b = RED; b < ALPHA; b++) + { + gfloat comp = in[b] + layer[b]; + comp = CLAMP (comp, 0, 1); + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + gint b; + + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } + + out[ALPHA] = in[ALPHA]; + + in += 4; + layer += 4; + out += 4; + } } return TRUE; diff --git a/app/operations/gimpoperationantierasemode.c b/app/operations/gimpoperationantierasemode.c index 4116ef5ed1..355361318d 100644 --- a/app/operations/gimpoperationantierasemode.c +++ b/app/operations/gimpoperationantierasemode.c @@ -3,6 +3,7 @@ * * gimpoperationantierasemode.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,9 +29,11 @@ #include "gimpoperationantierasemode.h" +static void gimp_operation_anti_erase_mode_prepare (GeglOperation *operation); static gboolean gimp_operation_anti_erase_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -45,17 +48,18 @@ static void gimp_operation_anti_erase_mode_class_init (GimpOperationAntiEraseModeClass *klass) { GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:anti-erase-mode", "description", "GIMP anti erase mode operation", NULL); - point_class->process = gimp_operation_anti_erase_mode_process; + operation_class->prepare = gimp_operation_anti_erase_mode_prepare; + point_class->process = gimp_operation_anti_erase_mode_process; } static void @@ -63,29 +67,70 @@ gimp_operation_anti_erase_mode_init (GimpOperationAntiEraseMode *self) { } +static void +gimp_operation_anti_erase_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, "aux2", babl_format ("Y float")); + gegl_operation_set_format (operation, "output", format); +} + static gboolean gimp_operation_anti_erase_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; - while (samples--) + if (mask) { - out[RED] = in[RED]; - out[GREEN] = in[GREEN]; - out[BLUE] = in[BLUE]; - out[ALPHA] = in[ALPHA]; + while (samples--) + { + gint b; - in += 4; - layer += 4; - out += 4; + for (b = RED; b < ALPHA; b++) + { + out[b] = in[b]; + } + + out[ALPHA] = in[ALPHA] + (1 - in[ALPHA]) * layer[ALPHA] * opacity * (*mask); + + in += 4; + layer += 4; + mask += 1; + out += 4; + } + } + else + { + while (samples--) + { + gint b; + + for (b = RED; b < ALPHA; b++) + { + out[b] = in[b]; + } + + out[ALPHA] = in[ALPHA] + (1 - in[ALPHA]) * layer[ALPHA] * opacity; + + in += 4; + layer += 4; + out += 4; + } } return TRUE; diff --git a/app/operations/gimpoperationbehindmode.c b/app/operations/gimpoperationbehindmode.c index 9412579cda..857cc3030f 100644 --- a/app/operations/gimpoperationbehindmode.c +++ b/app/operations/gimpoperationbehindmode.c @@ -32,6 +32,7 @@ static gboolean gimp_operation_behind_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -46,10 +47,10 @@ static void gimp_operation_behind_mode_class_init (GimpOperationBehindModeClass *klass) { GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:behind-mode", @@ -68,47 +69,113 @@ static gboolean gimp_operation_behind_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; if (point->premultiplied) { - while (samples--) + if (mask) { - gint b; - - for (b = RED; b <= ALPHA; b++) + while (samples--) { - out[b] = in[b] + layer[b] * (1 - in[ALPHA]); - } + gint b; + gfloat value = opacity * (*mask); - in += 4; - layer += 4; - out += 4; + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b] + layer[b] * value * (1 - in[ALPHA]); + } + + in += 4; + layer += 4; + mask += 1; + out += 4; + } + } + else + { + while (samples--) + { + gint b; + + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b] + layer[b] * opacity * (1 - in[ALPHA]); + } + + in += 4; + layer += 4; + out += 4; + } } } else { - while (samples--) + if (mask) { - gint b; - - out[ALPHA] = in[ALPHA] + (1 - in[ALPHA]) * layer[ALPHA]; - for (b = RED; b < ALPHA; b++) + while (samples--) { - out[b] = (in[b] * in[ALPHA] + layer[b] * layer[ALPHA] * (1 - in[ALPHA])) / out[ALPHA]; - } + gint b; + gfloat value = opacity * (*mask); - in += 4; - layer += 4; - out += 4; + out[ALPHA] = in[ALPHA] + (1 - in[ALPHA]) * layer[ALPHA] * value; + if (out[ALPHA]) + { + for (b = RED; b < ALPHA; b++) + { + out[b] = (in[b] * in[ALPHA] + layer[b] * value * layer[ALPHA] * value * (1 - in[ALPHA])) / out[ALPHA]; + } + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } + + in += 4; + layer += 4; + mask += 1; + out += 4; + } + } + else + { + while (samples--) + { + gint b; + + out[ALPHA] = in[ALPHA] + (1 - in[ALPHA]) * layer[ALPHA] * opacity; + if (out[ALPHA]) + { + for (b = RED; b < ALPHA; b++) + { + out[b] = (in[b] * in[ALPHA] + layer[b] * opacity * layer[ALPHA] * opacity * (1 - in[ALPHA])) / out[ALPHA]; + } + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } + + in += 4; + layer += 4; + out += 4; + } } } diff --git a/app/operations/gimpoperationburnmode.c b/app/operations/gimpoperationburnmode.c index 3c8147faf0..f2ea7fb8ef 100644 --- a/app/operations/gimpoperationburnmode.c +++ b/app/operations/gimpoperationburnmode.c @@ -33,6 +33,7 @@ static void gimp_operation_burn_mode_prepare (GeglOperation *operation static gboolean gimp_operation_burn_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -46,11 +47,11 @@ G_DEFINE_TYPE (GimpOperationBurnMode, gimp_operation_burn_mode, static void gimp_operation_burn_mode_class_init (GimpOperationBurnModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:burn-mode", @@ -73,6 +74,7 @@ gimp_operation_burn_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -80,35 +82,58 @@ static gboolean gimp_operation_burn_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; while (samples--) { gint b; - gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]); - gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - gfloat ratio = comp_alpha / new_alpha; + gfloat comp_alpha, new_alpha, ratio; - for (b = RED; b < ALPHA; b++) + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= (*mask); + + new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; + + if (comp_alpha && new_alpha) { - gfloat comp = (1 - in[b]) / layer[b]; - comp = CLAMP (1 - comp, 0, 1); + ratio = comp_alpha / new_alpha; - out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + for (b = RED; b < ALPHA; b++) + { + gfloat comp = (1 - in[b]) / layer[b]; + comp = CLAMP (1 - comp, 0, 1); + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } } - - out[ALPHA] = in[ALPHA]; in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } return TRUE; diff --git a/app/operations/gimpoperationcolorerasemode.c b/app/operations/gimpoperationcolorerasemode.c index 4c8cf4c2d0..cce0ce923d 100644 --- a/app/operations/gimpoperationcolorerasemode.c +++ b/app/operations/gimpoperationcolorerasemode.c @@ -31,6 +31,7 @@ static gboolean gimp_operation_color_erase_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -44,11 +45,11 @@ G_DEFINE_TYPE (GimpOperationColorEraseMode, gimp_operation_color_erase_mode, static void gimp_operation_color_erase_mode_class_init (GimpOperationColorEraseModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:color-erase-mode", @@ -67,6 +68,7 @@ static gboolean gimp_operation_color_erase_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, diff --git a/app/operations/gimpoperationcolormode.c b/app/operations/gimpoperationcolormode.c index 762753f1f9..caa19f6853 100644 --- a/app/operations/gimpoperationcolormode.c +++ b/app/operations/gimpoperationcolormode.c @@ -37,6 +37,7 @@ static void gimp_operation_color_mode_prepare (GeglOperation *operatio static gboolean gimp_operation_color_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -50,11 +51,11 @@ G_DEFINE_TYPE (GimpOperationColorMode, gimp_operation_color_mode, static void gimp_operation_color_mode_class_init (GimpOperationColorModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:color-mode", @@ -77,6 +78,7 @@ gimp_operation_color_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -84,14 +86,18 @@ static gboolean gimp_operation_color_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; while (samples--) { @@ -99,28 +105,47 @@ gimp_operation_color_mode_process (GeglOperation *operation, GimpHSL layer_hsl, out_hsl; GimpRGB layer_rgb = {layer[0], layer[1], layer[2]}; GimpRGB out_rgb = {in[0], in[1], in[2]}; - gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]); - gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - gfloat ratio = comp_alpha / new_alpha; + gfloat comp_alpha, new_alpha, ratio; - gimp_rgb_to_hsl (&layer_rgb, &layer_hsl); - gimp_rgb_to_hsl (&out_rgb, &out_hsl); + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= (*mask); - out_hsl.h = layer_hsl.h; - out_hsl.s = layer_hsl.s; - gimp_hsl_to_rgb (&out_hsl, &out_rgb); + new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - out[0] = out_rgb.r; - out[1] = out_rgb.g; - out[2] = out_rgb.b; - out[3] = in[3]; + if (comp_alpha && new_alpha) + { + ratio = comp_alpha / new_alpha; - for (b = RED; b < ALPHA; b++) - out[b] = out[b] * ratio + in[b] * (1 - ratio) + 0.0001; + gimp_rgb_to_hsl (&layer_rgb, &layer_hsl); + gimp_rgb_to_hsl (&out_rgb, &out_hsl); + + out_hsl.h = layer_hsl.h; + out_hsl.s = layer_hsl.s; + gimp_hsl_to_rgb (&out_hsl, &out_rgb); + + out[0] = out_rgb.r; + out[1] = out_rgb.g; + out[2] = out_rgb.b; + out[3] = in[3]; + + for (b = RED; b < ALPHA; b++) + out[b] = out[b] * ratio + in[b] * (1 - ratio) + 0.0001; + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } return TRUE; diff --git a/app/operations/gimpoperationdarkenonlymode.c b/app/operations/gimpoperationdarkenonlymode.c index 5f82bdf21e..b4a6e7406b 100644 --- a/app/operations/gimpoperationdarkenonlymode.c +++ b/app/operations/gimpoperationdarkenonlymode.c @@ -33,6 +33,7 @@ static void gimp_operation_darken_only_mode_prepare (GeglOperation *op static gboolean gimp_operation_darken_only_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -46,11 +47,11 @@ G_DEFINE_TYPE (GimpOperationDarkenOnlyMode, gimp_operation_darken_only_mode, static void gimp_operation_darken_only_mode_class_init (GimpOperationDarkenOnlyModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:darken-only-mode", @@ -58,7 +59,6 @@ gimp_operation_darken_only_mode_class_init (GimpOperationDarkenOnlyModeClass *kl NULL); operation_class->prepare = gimp_operation_darken_only_mode_prepare; - point_class->process = gimp_operation_darken_only_mode_process; } @@ -74,6 +74,7 @@ gimp_operation_darken_only_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -81,34 +82,57 @@ static gboolean gimp_operation_darken_only_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; while (samples--) { gint b; - gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]); - gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - gfloat ratio = comp_alpha / new_alpha; + gfloat comp_alpha, new_alpha, ratio; - for (b = RED; b < ALPHA; b++) + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= (*mask); + + new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; + + if (new_alpha && comp_alpha) { - gfloat comp = MIN (in[b], layer[b]); + ratio = comp_alpha / new_alpha; - out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + for (b = RED; b < ALPHA; b++) + { + gfloat comp = MIN (in[b], layer[b]); + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } } - - out[ALPHA] = in[ALPHA]; in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } return TRUE; diff --git a/app/operations/gimpoperationdifferencemode.c b/app/operations/gimpoperationdifferencemode.c index 143188bec8..dcca241011 100644 --- a/app/operations/gimpoperationdifferencemode.c +++ b/app/operations/gimpoperationdifferencemode.c @@ -33,6 +33,7 @@ static void gimp_operation_difference_mode_prepare (GeglOperation *ope static gboolean gimp_operation_difference_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -46,11 +47,11 @@ G_DEFINE_TYPE (GimpOperationDifferenceMode, gimp_operation_difference_mode, static void gimp_operation_difference_mode_class_init (GimpOperationDifferenceModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:difference-mode", @@ -73,6 +74,7 @@ gimp_operation_difference_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -80,35 +82,93 @@ static gboolean gimp_operation_difference_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; - while (samples--) + if (mask) { - gint b; - gfloat comp_alpha = MIN (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++) + while (samples--) { - gfloat comp = in[b] - layer[b]; - comp = (comp < 0) ? -comp : comp; + gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity * (*mask); + gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + if (comp_alpha && new_alpha) + { + gfloat ratio = comp_alpha / new_alpha; + gint b; + + for (b = RED; b < ALPHA; b++) + { + gfloat comp = in[b] - layer[b]; + comp = (comp < 0) ? -comp : comp; + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + gint b; + + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } + + in += 4; + layer += 4; + mask += 1; + out += 4; } + } + else + { + while (samples--) + { + gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - out[ALPHA] = in[ALPHA]; + if (comp_alpha && new_alpha) + { + gfloat ratio = comp_alpha / new_alpha; + gint b; - in += 4; - layer += 4; - out += 4; + for (b = RED; b < ALPHA; b++) + { + gfloat comp = in[b] - layer[b]; + comp = (comp < 0) ? -comp : comp; + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + gint b; + + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } + + in += 4; + layer += 4; + out += 4; + } } return TRUE; diff --git a/app/operations/gimpoperationdissolvemode.c b/app/operations/gimpoperationdissolvemode.c index f3de692ed1..c9064169e5 100644 --- a/app/operations/gimpoperationdissolvemode.c +++ b/app/operations/gimpoperationdissolvemode.c @@ -36,6 +36,7 @@ static void gimp_operation_dissolve_mode_prepare (GeglOperation *opera static gboolean gimp_operation_dissolve_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *result, @@ -51,13 +52,13 @@ static gint32 random_table[RANDOM_TABLE_SIZE]; static void gimp_operation_dissolve_mode_class_init (GimpOperationDissolveModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_composer_class; - GRand *gr; - gint i; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_composer_class; + GRand *gr; + gint i; operation_class = GEGL_OPERATION_CLASS (klass); - point_composer_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_composer_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:dissolve-mode", @@ -88,6 +89,7 @@ gimp_operation_dissolve_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -95,45 +97,89 @@ static gboolean gimp_operation_dissolve_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *result, gint level) { - gint x, y; - gfloat *in = in_buf; - gfloat *out = out_buf; - gfloat *aux = aux_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *out = out_buf; + gfloat *aux = aux_buf; + gfloat *mask = aux2_buf; + gint x, y; - for (y = result->y; y < result->y + result->height; y++) + if (mask) { - GRand *gr = g_rand_new_with_seed (random_table[y % RANDOM_TABLE_SIZE]); - - /* fast forward through the rows pseudo random sequence */ - for (x = 0; x < result->x; x++) - g_rand_int (gr); - - for (x = result->x; x < result->x + result->width; x++) + for (y = result->y; y < result->y + result->height; y++) { - if (g_rand_int_range (gr, 0, 255) >= aux[3] * 255) + GRand *gr = g_rand_new_with_seed (random_table[y % RANDOM_TABLE_SIZE]); + + /* fast forward through the rows pseudo random sequence */ + for (x = 0; x < result->x; x++) + g_rand_int (gr); + + for (x = result->x; x < result->x + result->width; x++) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; + gfloat value = opacity * (*mask); + + if (g_rand_int_range (gr, 0, 255) >= aux[3] * value * 255) + { + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; + } + else + { + out[0] = aux[0]; + out[1] = aux[1]; + out[2] = aux[2]; + out[3] = 1.0; + } + + in += 4; + out += 4; + aux += 4; + mask += 1; } - else - { - out[0] = aux[0]; - out[1] = aux[1]; - out[2] = aux[2]; - out[3] = 1.0; - } - in += 4; - out += 4; - aux += 4; + g_rand_free (gr); + } + } + else + { + for (y = result->y; y < result->y + result->height; y++) + { + GRand *gr = g_rand_new_with_seed (random_table[y % RANDOM_TABLE_SIZE]); + + /* fast forward through the rows pseudo random sequence */ + for (x = 0; x < result->x; x++) + g_rand_int (gr); + + for (x = result->x; x < result->x + result->width; x++) + { + if (g_rand_int_range (gr, 0, 255) >= aux[3] * opacity * 255) + { + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; + } + else + { + out[0] = aux[0]; + out[1] = aux[1]; + out[2] = aux[2]; + out[3] = 1.0; + } + in += 4; + out += 4; + aux += 4; + } + g_rand_free (gr); } - g_rand_free (gr); } return TRUE; diff --git a/app/operations/gimpoperationdividemode.c b/app/operations/gimpoperationdividemode.c index 1d4a27a06d..7840821fcd 100644 --- a/app/operations/gimpoperationdividemode.c +++ b/app/operations/gimpoperationdividemode.c @@ -33,6 +33,7 @@ static void gimp_operation_divide_mode_prepare (GeglOperation *operati static gboolean gimp_operation_divide_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -46,11 +47,11 @@ G_DEFINE_TYPE (GimpOperationDivideMode, gimp_operation_divide_mode, static void gimp_operation_divide_mode_class_init (GimpOperationDivideModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:divide-mode", @@ -73,6 +74,7 @@ gimp_operation_divide_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -80,35 +82,58 @@ static gboolean gimp_operation_divide_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; while (samples--) { gint b; - gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]); - gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - gfloat ratio = comp_alpha / new_alpha; + gfloat comp_alpha, new_alpha, ratio; - for (b = RED; b < ALPHA; b++) + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= (*mask); + + new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; + + if (comp_alpha && new_alpha) { - gfloat comp = (256 / 255.0 * in[b]) / (1 / 255.0 + layer[b]); - comp = MIN (comp, 1); + ratio = comp_alpha / new_alpha; - out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + for (b = RED; b < ALPHA; b++) + { + gfloat comp = (256 / 255.0 * in[b]) / (1 / 255.0 + layer[b]); + comp = MIN (comp, 1); + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } } - - out[ALPHA] = in[ALPHA]; in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } return TRUE; diff --git a/app/operations/gimpoperationdodgemode.c b/app/operations/gimpoperationdodgemode.c index 8f28928615..992532e0ea 100644 --- a/app/operations/gimpoperationdodgemode.c +++ b/app/operations/gimpoperationdodgemode.c @@ -33,6 +33,7 @@ static void gimp_operation_dodge_mode_prepare (GeglOperation *operatio static gboolean gimp_operation_dodge_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -46,11 +47,11 @@ G_DEFINE_TYPE (GimpOperationDodgeMode, gimp_operation_dodge_mode, static void gimp_operation_dodge_mode_class_init (GimpOperationDodgeModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:dodge-mode", @@ -73,6 +74,7 @@ gimp_operation_dodge_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -80,35 +82,58 @@ static gboolean gimp_operation_dodge_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; while (samples--) { gint b; - gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]); - gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - gfloat ratio = comp_alpha / new_alpha; + gfloat comp_alpha, new_alpha, ratio; - for (b = RED; b < ALPHA; b++) + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= (*mask); + + new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; + + if (comp_alpha && new_alpha) { - gfloat comp = in[b] / (1 - layer[b]); - comp = MIN (comp, 1); + ratio = comp_alpha / new_alpha; - out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + for (b = RED; b < ALPHA; b++) + { + gfloat comp = in[b] / (1 - layer[b]); + comp = MIN (comp, 1); + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } } - - out[ALPHA] = in[ALPHA]; in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } return TRUE; diff --git a/app/operations/gimpoperationerasemode.c b/app/operations/gimpoperationerasemode.c index 8ded88bd3f..b027474239 100644 --- a/app/operations/gimpoperationerasemode.c +++ b/app/operations/gimpoperationerasemode.c @@ -32,6 +32,7 @@ static gboolean gimp_operation_erase_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -45,11 +46,11 @@ G_DEFINE_TYPE (GimpOperationEraseMode, gimp_operation_erase_mode, static void gimp_operation_erase_mode_class_init (GimpOperationEraseModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:erase-mode", @@ -68,23 +69,29 @@ static gboolean gimp_operation_erase_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; if (point->premultiplied) { while (samples--) { gint b; + gfloat value = opacity; + if (mask) + value *= (*mask); - out[ALPHA] = in[ALPHA] - in[ALPHA] * layer[ALPHA]; + out[ALPHA] = in[ALPHA] - in[ALPHA] * layer[ALPHA] * value; for (b = RED; b < ALPHA; b++) { out[b] = in[b] / in[ALPHA] * out[ALPHA]; @@ -93,6 +100,9 @@ gimp_operation_erase_mode_process (GeglOperation *operation, in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } } else @@ -100,16 +110,22 @@ gimp_operation_erase_mode_process (GeglOperation *operation, while (samples--) { gint b; + gfloat value = opacity; + if (mask) + value *= (*mask); for (b = RED; b < ALPHA; b++) { out[b] = in[b]; } - out[ALPHA] = in[ALPHA] - in[ALPHA] * layer[ALPHA];; + out[ALPHA] = in[ALPHA] - in[ALPHA] * layer[ALPHA] * value; in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } } diff --git a/app/operations/gimpoperationgrainextractmode.c b/app/operations/gimpoperationgrainextractmode.c index 3acccaeb79..c30a55f845 100644 --- a/app/operations/gimpoperationgrainextractmode.c +++ b/app/operations/gimpoperationgrainextractmode.c @@ -33,6 +33,7 @@ static void gimp_operation_grain_extract_mode_prepare (GeglOperation * static gboolean gimp_operation_grain_extract_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -46,11 +47,11 @@ G_DEFINE_TYPE (GimpOperationGrainExtractMode, gimp_operation_grain_extract_mode, static void gimp_operation_grain_extract_mode_class_init (GimpOperationGrainExtractModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:grain-extract-mode", @@ -73,6 +74,7 @@ gimp_operation_grain_extract_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -81,35 +83,58 @@ static gboolean gimp_operation_grain_extract_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; while (samples--) { gint b; - gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]); - gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - gfloat ratio = comp_alpha / new_alpha; + gfloat comp_alpha, new_alpha, ratio; - for (b = RED; b < ALPHA; b++) + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= (*mask); + + new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; + + if (comp_alpha && new_alpha) { - gfloat comp = in[b] - layer[b] + 0.5; - comp = CLAMP (comp, 0, 1); + ratio = comp_alpha / new_alpha; - out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + for (b = RED; b < ALPHA; b++) + { + gfloat comp = in[b] - layer[b] + 0.5; + comp = CLAMP (comp, 0, 1); + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } } - - out[ALPHA] = in[ALPHA]; in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } return TRUE; diff --git a/app/operations/gimpoperationgrainmergemode.c b/app/operations/gimpoperationgrainmergemode.c index fe9903c7e7..5c707ba449 100644 --- a/app/operations/gimpoperationgrainmergemode.c +++ b/app/operations/gimpoperationgrainmergemode.c @@ -33,6 +33,7 @@ static void gimp_operation_grain_merge_mode_prepare (GeglOperation *op static gboolean gimp_operation_grain_merge_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -46,11 +47,11 @@ G_DEFINE_TYPE (GimpOperationGrainMergeMode, gimp_operation_grain_merge_mode, static void gimp_operation_grain_merge_mode_class_init (GimpOperationGrainMergeModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:grain-merge-mode", @@ -73,6 +74,7 @@ gimp_operation_grain_merge_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -81,35 +83,58 @@ static gboolean gimp_operation_grain_merge_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; while (samples--) { gint b; - gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]); - gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - gfloat ratio = comp_alpha / new_alpha; + gfloat comp_alpha, new_alpha, ratio; - for (b = RED; b < ALPHA; b++) + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= (*mask); + + new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; + + if (comp_alpha && new_alpha) { - gfloat comp = in[b] + layer[b] - 0.5; - comp = CLAMP (comp, 0, 1); + ratio = comp_alpha / new_alpha; - out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + for (b = RED; b < ALPHA; b++) + { + gfloat comp = in[b] + layer[b] - 0.5; + comp = CLAMP (comp, 0, 1); + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } } - - out[ALPHA] = in[ALPHA]; in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } return TRUE; diff --git a/app/operations/gimpoperationhardlightmode.c b/app/operations/gimpoperationhardlightmode.c index 2706ea4965..b682cb713c 100644 --- a/app/operations/gimpoperationhardlightmode.c +++ b/app/operations/gimpoperationhardlightmode.c @@ -33,6 +33,7 @@ static void gimp_operation_hardlight_mode_prepare (GeglOperation *oper static gboolean gimp_operation_hardlight_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -46,11 +47,11 @@ G_DEFINE_TYPE (GimpOperationHardlightMode, gimp_operation_hardlight_mode, static void gimp_operation_hardlight_mode_class_init (GimpOperationHardlightModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:hardlight-mode", @@ -73,6 +74,7 @@ gimp_operation_hardlight_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -80,45 +82,68 @@ static gboolean gimp_operation_hardlight_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; while (samples--) { gint b; - gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]); - gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - gfloat ratio = comp_alpha / new_alpha; + gfloat comp_alpha, new_alpha, ratio; - for (b = RED; b < ALPHA; b++) + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= (*mask); + + new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; + + if (comp_alpha && new_alpha) { - gfloat comp; + ratio = comp_alpha / new_alpha; - if (layer[b] > 0.5) + for (b = RED; b < ALPHA; b++) { - comp = (1 - in[b]) * (1 - (layer[b] - 0.5) * 2); - comp = MIN (1 - comp, 1); - } - else - { - comp = in[b] * (layer[b] * 2); - comp = MIN (comp, 1); + gfloat comp; + + if (layer[b] > 0.5) + { + comp = (1 - in[b]) * (1 - (layer[b] - 0.5) * 2); + comp = MIN (1 - comp, 1); + } + else + { + comp = in[b] * (layer[b] * 2); + comp = MIN (comp, 1); + } + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; } - out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + out[ALPHA] = in[ALPHA]; + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } } - - out[ALPHA] = in[ALPHA]; in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } return TRUE; diff --git a/app/operations/gimpoperationhuemode.c b/app/operations/gimpoperationhuemode.c index 2483f8f9e7..aaae343ad2 100644 --- a/app/operations/gimpoperationhuemode.c +++ b/app/operations/gimpoperationhuemode.c @@ -37,6 +37,7 @@ static void gimp_operation_hue_mode_prepare (GeglOperation *operation) static gboolean gimp_operation_hue_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -50,11 +51,11 @@ G_DEFINE_TYPE (GimpOperationHueMode, gimp_operation_hue_mode, static void gimp_operation_hue_mode_class_init (GimpOperationHueModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:hue-mode", @@ -77,6 +78,7 @@ gimp_operation_hue_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -84,14 +86,18 @@ static gboolean gimp_operation_hue_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; while (samples--) { @@ -99,31 +105,50 @@ gimp_operation_hue_mode_process (GeglOperation *operation, GimpHSV layer_hsv, out_hsv; GimpRGB layer_rgb = {layer[0], layer[1], layer[2]}; GimpRGB out_rgb = {in[0], in[1], in[2]}; - gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]); - gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - gfloat ratio = comp_alpha / new_alpha; + gfloat comp_alpha, new_alpha, ratio; - gimp_rgb_to_hsv (&layer_rgb, &layer_hsv); - gimp_rgb_to_hsv (&out_rgb, &out_hsv); + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= (*mask); - /* Composition should have no effect if saturation is zero. - * otherwise, black would be painted red (see bug #123296). - */ - if (layer_hsv.s) - out_hsv.h = layer_hsv.h; - gimp_hsv_to_rgb (&out_hsv, &out_rgb); + new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - out[0] = out_rgb.r; - out[1] = out_rgb.g; - out[2] = out_rgb.b; - out[3] = in[3]; + if (comp_alpha && new_alpha) + { + ratio = comp_alpha / new_alpha; - for (b = RED; b < ALPHA; b++) - out[b] = out[b] * ratio + in[b] * (1 - ratio) + 0.0001; + gimp_rgb_to_hsv (&layer_rgb, &layer_hsv); + gimp_rgb_to_hsv (&out_rgb, &out_hsv); + + /* Composition should have no effect if saturation is zero. + * otherwise, black would be painted red (see bug #123296). + */ + if (layer_hsv.s) + out_hsv.h = layer_hsv.h; + gimp_hsv_to_rgb (&out_hsv, &out_rgb); + + out[0] = out_rgb.r; + out[1] = out_rgb.g; + out[2] = out_rgb.b; + out[3] = in[3]; + + for (b = RED; b < ALPHA; b++) + out[b] = out[b] * ratio + in[b] * (1 - ratio) + 0.0001; + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } return TRUE; diff --git a/app/operations/gimpoperationlightenonlymode.c b/app/operations/gimpoperationlightenonlymode.c index 6cca8a1d6d..9bd7343cae 100644 --- a/app/operations/gimpoperationlightenonlymode.c +++ b/app/operations/gimpoperationlightenonlymode.c @@ -32,6 +32,7 @@ static void gimp_operation_lighten_only_mode_prepare (GeglOperation *o static gboolean gimp_operation_lighten_only_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -45,11 +46,11 @@ G_DEFINE_TYPE (GimpOperationLightenOnlyMode, gimp_operation_lighten_only_mode, static void gimp_operation_lighten_only_mode_class_init (GimpOperationLightenOnlyModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:lighten-only-mode", @@ -57,7 +58,6 @@ gimp_operation_lighten_only_mode_class_init (GimpOperationLightenOnlyModeClass * NULL); operation_class->prepare = gimp_operation_lighten_only_mode_prepare; - point_class->process = gimp_operation_lighten_only_mode_process; } @@ -73,6 +73,7 @@ gimp_operation_lighten_only_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -80,34 +81,57 @@ static gboolean gimp_operation_lighten_only_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *result, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; while (samples--) { gint b; - gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]); - gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - gfloat ratio = comp_alpha / new_alpha; + gfloat comp_alpha, new_alpha, ratio; - for (b = RED; b < ALPHA; b++) + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= (*mask); + + new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; + + if (comp_alpha && new_alpha) { - gfloat comp = MAX (layer[b], in[b]); + ratio = comp_alpha / new_alpha; - out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + for (b = RED; b < ALPHA; b++) + { + gfloat comp = MAX (layer[b], in[b]); + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } } - - out[ALPHA] = in[ALPHA]; in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } return TRUE; diff --git a/app/operations/gimpoperationmultiplymode.c b/app/operations/gimpoperationmultiplymode.c index 6fba66e324..8d690c9664 100644 --- a/app/operations/gimpoperationmultiplymode.c +++ b/app/operations/gimpoperationmultiplymode.c @@ -33,6 +33,7 @@ static void gimp_operation_multiply_mode_prepare (GeglOperation *opera static gboolean gimp_operation_multiply_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -47,10 +48,10 @@ static void gimp_operation_multiply_mode_class_init (GimpOperationMultiplyModeClass *klass) { GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:multiply-mode", @@ -73,6 +74,7 @@ gimp_operation_multiply_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -80,35 +82,93 @@ static gboolean gimp_operation_multiply_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; - while (samples--) + if (mask) { - gint b; - gfloat comp_alpha = MIN (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++) + while (samples--) { - gfloat comp = layer[b] * in[b]; - comp = CLAMP (comp, 0, 1); + gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity * (*mask); + gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + if (comp_alpha && new_alpha) + { + gfloat ratio = comp_alpha / new_alpha; + gint b; + + for (b = RED; b < ALPHA; b++) + { + gfloat comp = layer[b] * in[b]; + comp = CLAMP (comp, 0, 1); + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + gint b; + + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } + + in += 4; + layer += 4; + mask += 1; + out += 4; } + } + else + { + while (samples--) + { + gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - out[ALPHA] = in[ALPHA]; + if (comp_alpha && new_alpha) + { + gfloat ratio = comp_alpha / new_alpha; + gint b; - in += 4; - layer += 4; - out += 4; + for (b = RED; b < ALPHA; b++) + { + gfloat comp = layer[b] * in[b]; + comp = CLAMP (comp, 0, 1); + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + gint b; + + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } + + in += 4; + layer += 4; + out += 4; + } } return TRUE; diff --git a/app/operations/gimpoperationnormalmode.c b/app/operations/gimpoperationnormalmode.c index d5037380cf..5321e7c70d 100644 --- a/app/operations/gimpoperationnormalmode.c +++ b/app/operations/gimpoperationnormalmode.c @@ -36,6 +36,7 @@ static gboolean gimp_operation_normal_parent_process (GeglOperation *oper static gboolean gimp_operation_normal_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -51,11 +52,11 @@ G_DEFINE_TYPE (GimpOperationNormalMode, gimp_operation_normal_mode, static void gimp_operation_normal_mode_class_init (GimpOperationNormalModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:normal-mode", @@ -124,42 +125,101 @@ static gboolean gimp_operation_normal_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); - gfloat *in = in_buf; - gfloat *aux = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat *in = in_buf; + gfloat *aux = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; + gdouble opacity = point->opacity; if (point->premultiplied) { - while (samples--) + if (mask) { - out[0] = aux[0] + in[0] * (1.0f - aux[3]); - out[1] = aux[1] + in[1] * (1.0f - aux[3]); - out[2] = aux[2] + in[2] * (1.0f - aux[3]); - out[3] = aux[3] + in[3] - aux[3] * in[3]; + while (samples--) + { + gfloat value = opacity * (*mask); + gfloat aux_alpha = aux[ALPHA] * value; + gint b; - in += 4; - aux += 4; - out += 4; + for (b = RED; b < ALPHA; b++) + { + out[b] = aux[b] * value + in[b] * (1.0f - aux_alpha); + } + + out[ALPHA] = aux_alpha + in[ALPHA] - aux_alpha * in[ALPHA]; + + in += 4; + aux += 4; + mask += 1; + out += 4; + } + } + else + { + while (samples--) + { + gfloat aux_alpha = aux[ALPHA] * opacity; + gint b; + + for (b = RED; b < ALPHA; b++) + { + out[b] = aux[b] * opacity + in[b] * (1.0f - aux_alpha); + } + + out[ALPHA] = aux_alpha + in[ALPHA] - aux_alpha * in[ALPHA]; + + in += 4; + aux += 4; + out += 4; + } } } else { - while (samples--) + if (mask) { - out[0] = aux[0] * aux[3] + in[0] * in[3] * (1.0 - aux[3]); - out[1] = aux[1] * aux[3] + in[1] * in[3] * (1.0 - aux[3]); - out[2] = aux[2] * aux[3] + in[2] * in[3] * (1.0 - aux[3]); - out[3] = aux[3] + in[3] - aux[3] * in[3]; + while (samples--) + { + gfloat value = opacity * (*mask); + gfloat aux_alpha = aux[ALPHA] * value; + gint b; - in += 4; - aux += 4; - out += 4; + out[ALPHA] = aux_alpha + in[ALPHA] - aux_alpha * in[ALPHA]; + for (b = RED; b < ALPHA; b++) + { + out[b] = (aux[b] * aux_alpha + in[b] * in[ALPHA] * (1.0 - aux_alpha)) / out[ALPHA]; + } + + in += 4; + aux += 4; + mask += 1; + out += 4; + } + } + else + { + while (samples--) + { + gfloat aux_alpha = aux[ALPHA] * opacity; + gint b; + + out[ALPHA] = aux_alpha + in[ALPHA] - aux_alpha * in[ALPHA]; + for (b = RED; b < ALPHA; b++) + { + out[b] = (aux[b] * aux_alpha + in[b] * in[ALPHA] * (1.0 - aux_alpha)) / out[ALPHA]; + } + + in += 4; + aux += 4; + out += 4; + } } } diff --git a/app/operations/gimpoperationoverlaymode.c b/app/operations/gimpoperationoverlaymode.c index 49f068a3a0..3174a6054f 100644 --- a/app/operations/gimpoperationoverlaymode.c +++ b/app/operations/gimpoperationoverlaymode.c @@ -33,6 +33,7 @@ static void gimp_operation_overlay_mode_prepare (GeglOperation *operat static gboolean gimp_operation_overlay_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -46,11 +47,11 @@ G_DEFINE_TYPE (GimpOperationOverlayMode, gimp_operation_overlay_mode, static void gimp_operation_overlay_mode_class_init (GimpOperationOverlayModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:overlay-mode", @@ -58,7 +59,6 @@ gimp_operation_overlay_mode_class_init (GimpOperationOverlayModeClass *klass) NULL); operation_class->prepare = gimp_operation_overlay_mode_prepare; - point_class->process = gimp_operation_overlay_mode_process; } @@ -74,6 +74,7 @@ gimp_operation_overlay_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -81,34 +82,91 @@ static gboolean gimp_operation_overlay_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; - while (samples--) + if (mask) { - gint b; - gfloat comp_alpha = MIN (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++) + while (samples--) { - gfloat comp = in[b] * (in[b] + (2 * layer[b]) * (1 - in[b])); + gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity * (*mask); + gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + if (comp_alpha && new_alpha) + { + gint b; + 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) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + gint b; + + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } + + in += 4; + layer += 4; + mask += 1; + out += 4; } + } + else + { + while (samples--) + { + gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - out[ALPHA] = in[ALPHA]; + if (comp_alpha && new_alpha) + { + gfloat ratio = comp_alpha / new_alpha; + gint b; - in += 4; - layer += 4; - out += 4; + 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) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + gint b; + + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } + + in += 4; + layer += 4; + out += 4; + } } return TRUE; diff --git a/app/operations/gimpoperationpointlayermode.c b/app/operations/gimpoperationpointlayermode.c index 3b100c1be3..09c513a81b 100644 --- a/app/operations/gimpoperationpointlayermode.c +++ b/app/operations/gimpoperationpointlayermode.c @@ -72,7 +72,8 @@ enum { PROP_0, PROP_BLEND_MODE, - PROP_PREMULTIPLIED + PROP_PREMULTIPLIED, + PROP_OPACITY }; @@ -89,6 +90,7 @@ static void gimp_operation_point_layer_mode_prepare (GeglOperation static gboolean gimp_operation_point_layer_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -96,7 +98,7 @@ static gboolean gimp_operation_point_layer_mode_process (GeglOperation G_DEFINE_TYPE (GimpOperationPointLayerMode, gimp_operation_point_layer_mode, - GEGL_TYPE_OPERATION_POINT_COMPOSER) + GEGL_TYPE_OPERATION_POINT_COMPOSER3) static guint32 dissolve_lut[DISSOLVE_REPEAT_WIDTH * DISSOLVE_REPEAT_HEIGHT]; @@ -105,11 +107,11 @@ static guint32 dissolve_lut[DISSOLVE_REPEAT_WIDTH * DISSOLVE_REPEAT_HEIGHT]; static void gimp_operation_point_layer_mode_class_init (GimpOperationPointLayerModeClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass); - GeglOperationPointComposerClass *point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); - GRand *rand = g_rand_new_with_seed (DISSOLVE_SEED); - int i; + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass); + GeglOperationPointComposer3Class *point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); + GRand *rand = g_rand_new_with_seed (DISSOLVE_SEED); + int i; object_class->set_property = gimp_operation_point_layer_mode_set_property; object_class->get_property = gimp_operation_point_layer_mode_get_property; @@ -138,6 +140,13 @@ gimp_operation_point_layer_mode_class_init (GimpOperationPointLayerModeClass *kl GIMP_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_OPACITY, + g_param_spec_double ("opacity", + NULL, NULL, + 0.0, 1.0, 1.0, + GIMP_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + for (i = 0; i < DISSOLVE_REPEAT_WIDTH * DISSOLVE_REPEAT_HEIGHT; i++) dissolve_lut[i] = g_rand_int (rand); @@ -167,6 +176,10 @@ gimp_operation_point_layer_mode_set_property (GObject *object, self->premultiplied = g_value_get_boolean (value); break; + case PROP_OPACITY: + self->opacity = g_value_get_double (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -191,6 +204,10 @@ gimp_operation_point_layer_mode_get_property (GObject *object, g_value_set_boolean (value, self->premultiplied); break; + case PROP_OPACITY: + g_value_set_double (value, self->opacity); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -211,6 +228,7 @@ gimp_operation_point_layer_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "output", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); } static void @@ -294,6 +312,7 @@ static gboolean gimp_operation_point_layer_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -301,9 +320,11 @@ gimp_operation_point_layer_mode_process (GeglOperation *operation, { GimpOperationPointLayerMode *self = GIMP_OPERATION_POINT_LAYER_MODE (operation); GimpLayerModeEffects blend_mode = self->blend_mode; + gdouble opacity = self->opacity; gfloat *in = in_buf; /* composite of layers below */ gfloat *lay = aux_buf; /* layer */ + gfloat *mask = aux2_buf; /* mask */ gfloat *out = out_buf; /* resulting composite */ glong sample = samples; gint c = 0; @@ -313,6 +334,11 @@ gimp_operation_point_layer_mode_process (GeglOperation *operation, while (sample--) { + if (mask) + in[ALPHA] *= (*mask) * opacity; + else + in[ALPHA] *= opacity; + /* XXX: having such a switch in an innerloop is a horrible idea */ switch (blend_mode) { @@ -584,6 +610,9 @@ gimp_operation_point_layer_mode_process (GeglOperation *operation, in += 4; lay += 4; out += 4; + + if (mask) + mask += 4; } return TRUE; diff --git a/app/operations/gimpoperationpointlayermode.h b/app/operations/gimpoperationpointlayermode.h index f077024b1e..a9ccec13ff 100644 --- a/app/operations/gimpoperationpointlayermode.h +++ b/app/operations/gimpoperationpointlayermode.h @@ -34,15 +34,16 @@ typedef struct _GimpOperationPointLayerModeClass GimpOperationPointLayerModeClas struct _GimpOperationPointLayerModeClass { - GeglOperationPointComposerClass parent_class; + GeglOperationPointComposer3Class parent_class; }; struct _GimpOperationPointLayerMode { - GeglOperationPointComposer parent_instance; + GeglOperationPointComposer3 parent_instance; GimpLayerModeEffects blend_mode; gboolean premultiplied; + gdouble opacity; }; diff --git a/app/operations/gimpoperationreplacemode.c b/app/operations/gimpoperationreplacemode.c index 30c64c1ead..6a38896308 100644 --- a/app/operations/gimpoperationreplacemode.c +++ b/app/operations/gimpoperationreplacemode.c @@ -28,22 +28,6 @@ #include "gimpoperationreplacemode.h" -enum -{ - PROP_0, - PROP_PREMULTIPLIED, - PROP_OPACITY -}; - - -static void gimp_operation_replace_mode_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); -static void gimp_operation_replace_mode_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); static void gimp_operation_replace_mode_prepare (GeglOperation *operation); static gboolean gimp_operation_replace_mode_process (GeglOperation *operation, void *in_buf, @@ -56,23 +40,18 @@ static gboolean gimp_operation_replace_mode_process (GeglOperation *o G_DEFINE_TYPE (GimpOperationReplaceMode, gimp_operation_replace_mode, - GEGL_TYPE_OPERATION_POINT_COMPOSER3) + GIMP_TYPE_OPERATION_POINT_LAYER_MODE) static void gimp_operation_replace_mode_class_init (GimpOperationReplaceModeClass *klass) { - GObjectClass *object_class; GeglOperationClass *operation_class; GeglOperationPointComposer3Class *point_class; - object_class = G_OBJECT_CLASS (klass); operation_class = GEGL_OPERATION_CLASS (klass); point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); - object_class->set_property = gimp_operation_replace_mode_set_property; - object_class->get_property = gimp_operation_replace_mode_get_property; - gegl_operation_class_set_keys (operation_class, "name", "gimp:replace-mode", "description", "GIMP replace mode operation", @@ -80,21 +59,6 @@ gimp_operation_replace_mode_class_init (GimpOperationReplaceModeClass *klass) operation_class->prepare = gimp_operation_replace_mode_prepare; point_class->process = gimp_operation_replace_mode_process; - - g_object_class_install_property (object_class, PROP_PREMULTIPLIED, - g_param_spec_boolean ("premultiplied", - NULL, NULL, - TRUE, - GIMP_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, PROP_OPACITY, - g_param_spec_double ("opacity", - NULL, NULL, - 0.0, 1.0, - 1.0, - GIMP_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); } static void @@ -102,50 +66,6 @@ gimp_operation_replace_mode_init (GimpOperationReplaceMode *self) { } -static void -gimp_operation_replace_mode_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - GimpOperationReplaceMode *self = GIMP_OPERATION_REPLACE_MODE (object); - - switch (property_id) - { - case PROP_PREMULTIPLIED: - self->premultiplied = g_value_get_boolean (value); - break; - case PROP_OPACITY: - self->opacity = g_value_get_double (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gimp_operation_replace_mode_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - GimpOperationReplaceMode *self = GIMP_OPERATION_REPLACE_MODE (object); - - switch (property_id) - { - case PROP_PREMULTIPLIED: - g_value_set_boolean (value, self->premultiplied); - break; - case PROP_OPACITY: - g_value_set_double (value, self->opacity); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - static void gimp_operation_replace_mode_prepare (GeglOperation *operation) { @@ -167,12 +87,12 @@ gimp_operation_replace_mode_process (GeglOperation *operation, const GeglRectangle *roi, gint level) { - GimpOperationReplaceMode *self = GIMP_OPERATION_REPLACE_MODE (operation); - gfloat opacity = self->opacity; - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *mask = aux2_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; while (samples--) { diff --git a/app/operations/gimpoperationreplacemode.h b/app/operations/gimpoperationreplacemode.h index 3d09c34591..46712b4796 100644 --- a/app/operations/gimpoperationreplacemode.h +++ b/app/operations/gimpoperationreplacemode.h @@ -23,6 +23,9 @@ #define __GIMP_OPERATION_REPLACE_MODE_H__ +#include "gimpoperationpointlayermode.h" + + #define GIMP_TYPE_OPERATION_REPLACE_MODE (gimp_operation_replace_mode_get_type ()) #define GIMP_OPERATION_REPLACE_MODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_OPERATION_REPLACE_MODE, GimpOperationReplaceMode)) #define GIMP_OPERATION_REPLACE_MODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_OPERATION_REPLACE_MODE, GimpOperationReplaceModeClass)) @@ -36,7 +39,7 @@ typedef struct _GimpOperationReplaceModeClass GimpOperationReplaceModeClass; struct _GimpOperationReplaceMode { - GeglOperationPointComposer3 parent_instance; + GimpOperationPointLayerMode parent_instance; gdouble opacity; gboolean premultiplied; @@ -44,7 +47,7 @@ struct _GimpOperationReplaceMode struct _GimpOperationReplaceModeClass { - GeglOperationPointComposer3Class parent_class; + GimpOperationPointLayerModeClass parent_class; }; diff --git a/app/operations/gimpoperationsaturationmode.c b/app/operations/gimpoperationsaturationmode.c index 20f142b772..f9cdfe6610 100644 --- a/app/operations/gimpoperationsaturationmode.c +++ b/app/operations/gimpoperationsaturationmode.c @@ -37,6 +37,7 @@ static void gimp_operation_saturation_mode_prepare (GeglOperation *ope static gboolean gimp_operation_saturation_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -50,11 +51,11 @@ G_DEFINE_TYPE (GimpOperationSaturationMode, gimp_operation_saturation_mode, static void gimp_operation_saturation_mode_class_init (GimpOperationSaturationModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:saturation-mode", @@ -77,6 +78,7 @@ gimp_operation_saturation_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -84,14 +86,18 @@ static gboolean gimp_operation_saturation_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; while (samples--) { @@ -99,27 +105,46 @@ gimp_operation_saturation_mode_process (GeglOperation *operation, GimpHSV layer_hsv, out_hsv; GimpRGB layer_rgb = {layer[0], layer[1], layer[2]}; GimpRGB out_rgb = {in[0], in[1], in[2]}; - gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]); - gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - gfloat ratio = comp_alpha / new_alpha; + gfloat comp_alpha, new_alpha, ratio; - gimp_rgb_to_hsv (&layer_rgb, &layer_hsv); - gimp_rgb_to_hsv (&out_rgb, &out_hsv); + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= (*mask); - out_hsv.s = layer_hsv.s; - gimp_hsv_to_rgb (&out_hsv, &out_rgb); + new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - out[0] = out_rgb.r; - out[1] = out_rgb.g; - out[2] = out_rgb.b; - out[3] = in[3]; + if (comp_alpha && new_alpha) + { + ratio = comp_alpha / new_alpha; - for (b = RED; b < ALPHA; b++) - out[b] = out[b] * ratio + in[b] * (1 - ratio) + 0.0001; + gimp_rgb_to_hsv (&layer_rgb, &layer_hsv); + gimp_rgb_to_hsv (&out_rgb, &out_hsv); + + out_hsv.s = layer_hsv.s; + gimp_hsv_to_rgb (&out_hsv, &out_rgb); + + out[0] = out_rgb.r; + out[1] = out_rgb.g; + out[2] = out_rgb.b; + out[3] = in[3]; + + for (b = RED; b < ALPHA; b++) + out[b] = out[b] * ratio + in[b] * (1 - ratio) + 0.0001; + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } return TRUE; diff --git a/app/operations/gimpoperationscreenmode.c b/app/operations/gimpoperationscreenmode.c index 975d0d2049..5cffcaa937 100644 --- a/app/operations/gimpoperationscreenmode.c +++ b/app/operations/gimpoperationscreenmode.c @@ -33,6 +33,7 @@ static void gimp_operation_screen_mode_prepare (GeglOperation *operati static gboolean gimp_operation_screen_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -47,10 +48,10 @@ static void gimp_operation_screen_mode_class_init (GimpOperationScreenModeClass *klass) { GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:screen-mode", @@ -73,6 +74,7 @@ gimp_operation_screen_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -80,34 +82,91 @@ static gboolean gimp_operation_screen_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; - while (samples--) + if (mask) { - gint b; - gfloat comp_alpha = MIN (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++) + while (samples--) { - gfloat comp = 1 - (1 - in[b]) * (1 - layer[b]); + gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity * (*mask); + gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + if (comp_alpha && new_alpha) + { + gfloat ratio = comp_alpha / new_alpha; + gint b; + + for (b = RED; b < ALPHA; b++) + { + gfloat comp = 1 - (1 - in[b]) * (1 - layer[b]); + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + gint b; + + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } + + in += 4; + layer += 4; + mask += 1; + out += 4; } + } + else + { + while (samples--) + { + gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - out[ALPHA] = in[ALPHA]; + if (comp_alpha && new_alpha) + { + gfloat ratio = comp_alpha / new_alpha; + gint b; - in += 4; - layer += 4; - out += 4; + for (b = RED; b < ALPHA; b++) + { + gfloat comp = 1 - (1 - in[b]) * (1 - layer[b]); + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + gint b; + + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } + + in += 4; + layer += 4; + out += 4; + } } return TRUE; diff --git a/app/operations/gimpoperationsoftlightmode.c b/app/operations/gimpoperationsoftlightmode.c index e9c1b82938..d4d32bb55c 100644 --- a/app/operations/gimpoperationsoftlightmode.c +++ b/app/operations/gimpoperationsoftlightmode.c @@ -33,6 +33,7 @@ static void gimp_operation_softlight_mode_prepare (GeglOperation *oper static gboolean gimp_operation_softlight_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -46,11 +47,11 @@ G_DEFINE_TYPE (GimpOperationSoftlightMode, gimp_operation_softlight_mode, static void gimp_operation_softlight_mode_class_init (GimpOperationSoftlightModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:softlight-mode", @@ -58,7 +59,6 @@ gimp_operation_softlight_mode_class_init (GimpOperationSoftlightModeClass *klass NULL); operation_class->prepare = gimp_operation_softlight_mode_prepare; - point_class->process = gimp_operation_softlight_mode_process; } @@ -74,6 +74,7 @@ gimp_operation_softlight_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -81,36 +82,59 @@ static gboolean gimp_operation_softlight_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; while (samples--) { gint b; - gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]); - gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - gfloat ratio = comp_alpha / new_alpha; + gfloat comp_alpha, new_alpha, ratio; - for (b = RED; b < ALPHA; b++) + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= (*mask); + + new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; + + if (comp_alpha && new_alpha) { - gfloat multiply = in[b] * layer[b]; - gfloat screen = 1 - (1 - in[b]) * (1 - layer[b]); - gfloat comp = (1 - in[b]) * multiply + in[b] * screen; + ratio = comp_alpha / new_alpha; - out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + 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) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } } - - out[ALPHA] = in[ALPHA]; in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } return TRUE; diff --git a/app/operations/gimpoperationsubtractmode.c b/app/operations/gimpoperationsubtractmode.c index 3c22d086d6..a1de134f34 100644 --- a/app/operations/gimpoperationsubtractmode.c +++ b/app/operations/gimpoperationsubtractmode.c @@ -33,6 +33,7 @@ static void gimp_operation_subtract_mode_prepare (GeglOperation *opera static gboolean gimp_operation_subtract_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -46,11 +47,11 @@ G_DEFINE_TYPE (GimpOperationSubtractMode, gimp_operation_subtract_mode, static void gimp_operation_subtract_mode_class_init (GimpOperationSubtractModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:subtract-mode", @@ -73,6 +74,7 @@ gimp_operation_subtract_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -80,35 +82,59 @@ static gboolean gimp_operation_subtract_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; while (samples--) { gint b; - gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]); - gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - gfloat ratio = comp_alpha / new_alpha; + gfloat comp_alpha, new_alpha, ratio; - for (b = RED; b < ALPHA; b++) + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + + if (mask) + comp_alpha *= (*mask); + + new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; + + if (comp_alpha && new_alpha) { - gfloat comp = in[b] - layer[b]; - comp = (comp < 0) ? 0 : comp; + ratio = comp_alpha / new_alpha; - out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + for (b = RED; b < ALPHA; b++) + { + gfloat comp = in[b] - layer[b]; + comp = (comp < 0) ? 0 : comp; + + out[b] = comp * ratio + in[b] * (1 - ratio) + 0.0001; + } + + out[ALPHA] = in[ALPHA]; + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } } - - out[ALPHA] = in[ALPHA]; in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } return TRUE; diff --git a/app/operations/gimpoperationvaluemode.c b/app/operations/gimpoperationvaluemode.c index e336901e76..c4eb38936a 100644 --- a/app/operations/gimpoperationvaluemode.c +++ b/app/operations/gimpoperationvaluemode.c @@ -37,6 +37,7 @@ static void gimp_operation_value_mode_prepare (GeglOperation *operatio static gboolean gimp_operation_value_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, @@ -50,11 +51,11 @@ G_DEFINE_TYPE (GimpOperationValueMode, gimp_operation_value_mode, static void gimp_operation_value_mode_class_init (GimpOperationValueModeClass *klass) { - GeglOperationClass *operation_class; - GeglOperationPointComposerClass *point_class; + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; operation_class = GEGL_OPERATION_CLASS (klass); - point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); gegl_operation_class_set_keys (operation_class, "name", "gimp:value-mode", @@ -77,6 +78,7 @@ gimp_operation_value_mode_prepare (GeglOperation *operation) gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); gegl_operation_set_format (operation, "output", format); } @@ -84,14 +86,18 @@ static gboolean gimp_operation_value_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, + void *aux2_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { - gfloat *in = in_buf; - gfloat *layer = aux_buf; - gfloat *out = out_buf; + GimpOperationPointLayerMode *point = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = point->opacity; + gfloat *in = in_buf; + gfloat *layer = aux_buf; + gfloat *mask = aux2_buf; + gfloat *out = out_buf; while (samples--) { @@ -99,27 +105,46 @@ gimp_operation_value_mode_process (GeglOperation *operation, GimpHSV layer_hsv, out_hsv; GimpRGB layer_rgb = {layer[0], layer[1], layer[2]}; GimpRGB out_rgb = {in[0], in[1], in[2]}; - gfloat comp_alpha = MIN (in[ALPHA], layer[ALPHA]); - gfloat new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - gfloat ratio = comp_alpha / new_alpha; + gfloat comp_alpha, new_alpha, ratio; - gimp_rgb_to_hsv (&layer_rgb, &layer_hsv); - gimp_rgb_to_hsv (&out_rgb, &out_hsv); + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= (*mask); - out_hsv.v = layer_hsv.v; - gimp_hsv_to_rgb (&out_hsv, &out_rgb); + new_alpha = in[ALPHA] + (1 - in[ALPHA]) * comp_alpha; - out[0] = out_rgb.r; - out[1] = out_rgb.g; - out[2] = out_rgb.b; - out[3] = in[3]; + if (comp_alpha && new_alpha) + { + ratio = comp_alpha / new_alpha; - for (b = RED; b < ALPHA; b++) - out[b] = out[b] * ratio + in[b] * (1 - ratio) + 0.0001; + gimp_rgb_to_hsv (&layer_rgb, &layer_hsv); + gimp_rgb_to_hsv (&out_rgb, &out_hsv); + + out_hsv.v = layer_hsv.v; + gimp_hsv_to_rgb (&out_hsv, &out_rgb); + + out[0] = out_rgb.r; + out[1] = out_rgb.g; + out[2] = out_rgb.b; + out[3] = in[3]; + + for (b = RED; b < ALPHA; b++) + out[b] = out[b] * ratio + in[b] * (1 - ratio) + 0.0001; + } + else + { + for (b = RED; b <= ALPHA; b++) + { + out[b] = in[b]; + } + } in += 4; layer += 4; out += 4; + + if (mask) + mask += 1; } return TRUE;