From cf442d3386e8ace6367b2a1f30face3159de0855 Mon Sep 17 00:00:00 2001 From: Ville Sokk Date: Fri, 11 May 2012 20:37:47 +0300 Subject: [PATCH] app: added gegl value and behind blending modes --- app/gegl/gimp-gegl-nodes.c | 2 -- app/operations/gimpoperationbehindmode.c | 46 ++++++++++++++++++------ app/operations/gimpoperationvaluemode.c | 44 ++++++++++++++++++++--- 3 files changed, 74 insertions(+), 18 deletions(-) diff --git a/app/gegl/gimp-gegl-nodes.c b/app/gegl/gimp-gegl-nodes.c index 86d1a57f1a..21035f3aef 100644 --- a/app/gegl/gimp-gegl-nodes.c +++ b/app/gegl/gimp-gegl-nodes.c @@ -318,8 +318,6 @@ gimp_gegl_node_set_layer_mode (GeglNode *node, switch (mode) { - case GIMP_BEHIND_MODE: - case GIMP_VALUE_MODE: case GIMP_COLOR_ERASE_MODE: case GIMP_ANTI_ERASE_MODE: gegl_node_set (node, diff --git a/app/operations/gimpoperationbehindmode.c b/app/operations/gimpoperationbehindmode.c index ffb7d73348..9412579cda 100644 --- a/app/operations/gimpoperationbehindmode.c +++ b/app/operations/gimpoperationbehindmode.c @@ -3,6 +3,7 @@ * * gimpoperationbehindmode.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 @@ -72,20 +73,43 @@ gimp_operation_behind_mode_process (GeglOperation *operation, 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 *in = in_buf; + gfloat *layer = aux_buf; + gfloat *out = out_buf; - while (samples--) + if (point->premultiplied) { - 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] + layer[b] * (1 - in[ALPHA]); + } + + in += 4; + layer += 4; + out += 4; + } + } + else + { + while (samples--) + { + gint b; + + out[ALPHA] = in[ALPHA] + (1 - in[ALPHA]) * layer[ALPHA]; + for (b = RED; b < ALPHA; b++) + { + out[b] = (in[b] * in[ALPHA] + layer[b] * layer[ALPHA] * (1 - in[ALPHA])) / out[ALPHA]; + } + + in += 4; + layer += 4; + out += 4; + } } return TRUE; diff --git a/app/operations/gimpoperationvaluemode.c b/app/operations/gimpoperationvaluemode.c index 0bd80aa99d..e336901e76 100644 --- a/app/operations/gimpoperationvaluemode.c +++ b/app/operations/gimpoperationvaluemode.c @@ -3,6 +3,7 @@ * * gimpoperationvaluemode.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 @@ -22,12 +23,17 @@ #include "config.h" #include +#include +#include + +#include "libgimpcolor/gimpcolor.h" #include "operations-types.h" #include "gimpoperationvaluemode.h" +static void gimp_operation_value_mode_prepare (GeglOperation *operation); static gboolean gimp_operation_value_mode_process (GeglOperation *operation, void *in_buf, void *aux_buf, @@ -55,7 +61,8 @@ gimp_operation_value_mode_class_init (GimpOperationValueModeClass *klass) "description", "GIMP value mode operation", NULL); - point_class->process = gimp_operation_value_mode_process; + operation_class->prepare = gimp_operation_value_mode_prepare; + point_class->process = gimp_operation_value_mode_process; } static void @@ -63,6 +70,16 @@ gimp_operation_value_mode_init (GimpOperationValueMode *self) { } +static void +gimp_operation_value_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_value_mode_process (GeglOperation *operation, void *in_buf, @@ -78,10 +95,27 @@ gimp_operation_value_mode_process (GeglOperation *operation, while (samples--) { - out[RED] = in[RED]; - out[GREEN] = in[GREEN]; - out[BLUE] = in[BLUE]; - out[ALPHA] = in[ALPHA]; + gint b; + 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; + + 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; in += 4; layer += 4;