app: modified gegl blending modes to take mask and opacity inputs

This commit is contained in:
Ville Sokk 2012-05-18 23:35:00 +03:00 committed by Michael Natterer
parent efa52edf6e
commit e377eb01cd
31 changed files with 1379 additions and 558 deletions

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
};

View File

@ -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--)
{

View File

@ -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;
};

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;