Dissolve blending mode. The category should be changed, I don't know
about the compositor categories so I just left it at
"compositors:math". I tried to follow the way GIMP's dissolve works
but gegl is obviously different. There's no mask or opacity input like
in GIMP, I assume masking or gegl:opacity is already done on the
inputs. Tell me if I need to change something or add those properties.
#include "config.h"
#include <glib/gi18n-lib.h>
#ifdef GEGL_CHANT_PROPERTIES
/* no properties */
#else
#define GEGL_CHANT_TYPE_COMPOSER
#define GEGL_CHANT_C_FILE "dissolve.c"
#include "gegl-chant.h"
#define RANDOM_TABLE_SIZE 4096
static gint32 random_table[RANDOM_TABLE_SIZE];
static void prepare (GeglOperation *operation)
{
Babl *format = babl_format ("RGBA float");
GRand *gr;
gint i;
#define RANDOM_SEED 314159265
gegl_operation_set_format (operation, "input", format);
gegl_operation_set_format (operation, "aux", format);
gegl_operation_set_format (operation, "output", format);
/* generate a table of random seeds */
gr = g_rand_new_with_seed (RANDOM_SEED);
for (i = 0; i < RANDOM_TABLE_SIZE; i++)
{
random_table[i] = g_rand_int (gr);
}
g_rand_free (gr);
}
static GeglRectangle
get_required_for_output (GeglOperation *operation,
const gchar *input_pad,
const GeglRectangle *region)
{
GeglRectangle result = *gegl_operation_source_get_bounding_box (operation, "input");
return result;
}
static gboolean
process (GeglOperation *operation,
GeglBuffer *input,
GeglBuffer *aux,
GeglBuffer *output,
const GeglRectangle *result)
{
GeglBufferIterator *it;
GRand *gr;
Babl *format;
gint index_in, index_out, index_aux;
if (aux == NULL)
{
gegl_buffer_copy (input, result, output, result);
return TRUE;
}
format = babl_format ("RGBA float");
it = gegl_buffer_iterator_new (output, result, format, GEGL_BUFFER_WRITE);
index_out = 0;
index_in = gegl_buffer_iterator_add (it, input, result, format, GEGL_BUFFER_READ);
index_aux = gegl_buffer_iterator_add (it, aux, result, format, GEGL_BUFFER_READ);
while (gegl_buffer_iterator_next (it))
{
gint row, pix, i;
gdouble rand_val;
gint x = it->roi->x;
gint y = it->roi->y;
gint width = it->roi->width;
gint height = it->roi->height;
gfloat *in = it->data[index_in];
gfloat *out = it->data[index_out];
gfloat *aux = it->data[index_aux];
for (row = 0; row < height; row++)
{
gr = g_rand_new_with_seed (random_table[(y + row) % RANDOM_TABLE_SIZE]);
for (i = 0; i < x; i++)
{
g_rand_int (gr);
}
for (pix = 0; pix < width; pix++)
{
/* dissolve if random value is >= opacity */
rand_val = g_rand_double_range (gr, 0., 1.);
/* colour channels */
for (i = 0; i < 3; i++)
{
out[i] = rand_val >= aux[3] ? in[i] : aux[i];
}
/* alpha channel */
out[3] = rand_val >= aux[3] ? 1. : in[3];
in += 4;
aux += 4;
out+= 4;
}
}
}
g_rand_free (gr);
return TRUE;
}
static void
gegl_chant_class_init (GeglChantClass *klass)
{
GeglOperationClass *operation_class;
GeglOperationComposerClass *composer_class;
operation_class = GEGL_OPERATION_CLASS (klass);
composer_class = GEGL_OPERATION_COMPOSER_CLASS (klass);
composer_class->process = process;
operation_class->prepare = prepare;
operation_class->get_required_for_output = get_required_for_output;
operation_class->name = "gegl:dissolve";
operation_class->categories = "compositors:math";
operation_class->description = _("Dissolve blend operation");
}
#endif
_______________________________________________
gegl-developer-list mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/gegl-developer-list