#include "config.h" #include #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