[gegl] operations: rewrite noise-pick.c
- From: Téo Mazars <teom src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] operations: rewrite noise-pick.c
- Date: Fri, 11 Oct 2013 17:34:20 +0000 (UTC)
commit 3cd742de35c52f613947b51943b310bb3e9852b5
Author: Téo Mazars <teo mazars ensimag fr>
Date: Fri Oct 11 19:19:09 2013 +0200
operations: rewrite noise-pick.c
- don't try to allocate a too large array
- make it a proper GeglOperationAreaFilter,
the previous implementation was not seamless
- some performances improvement
- prettify the implementation
operations/common/noise-pick.c | 245 ++++++++++++++++++++--------------------
1 files changed, 122 insertions(+), 123 deletions(-)
---
diff --git a/operations/common/noise-pick.c b/operations/common/noise-pick.c
index 4231bd3..26af414 100644
--- a/operations/common/noise-pick.c
+++ b/operations/common/noise-pick.c
@@ -46,20 +46,82 @@ gegl_chant_int (repeat, _("Repeat"),
#include "gegl-chant.h"
+
+#define CHUNK_SIZE 1024
+#define MAX_HW_EXT 1224
+#define SQR(x) ((x)*(x))
+
static void
prepare (GeglOperation *operation)
{
GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation);
+ GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
- op_area->left = 1;
- op_area->right = 1;
- op_area->top = 1;
- op_area->bottom = 1;
+ op_area->left =
+ op_area->right =
+ op_area->top =
+ op_area->bottom = o->repeat;
gegl_operation_set_format (operation, "input" , babl_format ("RGBA float"));
gegl_operation_set_format (operation, "output", babl_format ("RGBA float"));
}
+static void
+iterate (GeglRectangle *buffers_roi,
+ GeglRectangle *current_roi,
+ gfloat *src,
+ gfloat *dst,
+ gint seed,
+ gfloat pct_random,
+ gint level)
+{
+ gint rowstride;
+ gint x, y, x_start, y_start;
+ GeglRectangle next_roi;
+
+ if (level < 1)
+ return;
+
+ rowstride = buffers_roi->width;
+
+ x_start = current_roi->x - buffers_roi->x;
+ y_start = current_roi->y - buffers_roi->y;
+
+ for(y = y_start; y < current_roi->height + y_start; y++)
+ for(x = x_start; x < current_roi->width + x_start; x++)
+ {
+ gint index_src, index_dst, b;
+ gint pos_x = buffers_roi->x + x;
+ gint pos_y = buffers_roi->y + y;
+ gint x2 = x;
+ gint y2 = y;
+ gfloat rand;
+
+ rand = gegl_random_float_range (seed, pos_x, pos_y, 0, level, 0.0, 100.0);
+
+ if (rand <= pct_random)
+ {
+ gint k = gegl_random_int_range (seed, pos_x, pos_y, 0, level, 0, 9);
+
+ x2 += (k % 3) - 1;
+ y2 += (k / 3) - 1;
+ }
+
+ index_src = (y2 * rowstride + x2) * 4;
+ index_dst = (y * rowstride + x) * 4;
+
+ for (b = 0; b < 4; b++)
+ dst[index_dst + b] = src[index_src + b];
+ }
+
+ next_roi = *GEGL_RECTANGLE (current_roi->x + 1,
+ current_roi->y + 1,
+ current_roi->width - 2,
+ current_roi->height - 2);
+
+ iterate (buffers_roi, &next_roi, dst, src, seed, pct_random, level - 1);
+}
+
static gboolean
process (GeglOperation *operation,
GeglBuffer *input,
@@ -69,125 +131,62 @@ process (GeglOperation *operation,
{
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation);
- GeglBuffer *tmp;
- gfloat *src_buf;
- gfloat *dst_buf;
- gfloat *in_pixel;
- gfloat *out_pixel;
- gint n_pixels = result->width * result->height;
- gint width = result->width;
- GeglRectangle src_rect;
- gint total_pixels;
- gint i;
-
- tmp = gegl_buffer_new (result, babl_format ("RGBA float"));
-
- src_rect.x = result->x - op_area->left;
- src_rect.width = result->width + op_area->left + op_area->right;
- src_rect.y = result->y - op_area->top;
- src_rect.height = result->height + op_area->top + op_area->bottom;
-
- total_pixels = src_rect.height * src_rect.width;
-
- src_buf = g_slice_alloc (4 * total_pixels * sizeof (gfloat));
- dst_buf = g_slice_alloc (4 * n_pixels * sizeof (gfloat));
-
- gegl_buffer_copy (input, NULL, tmp, NULL);
-
- for (i = 0; i < o->repeat; i++)
- {
- gint x, y, n;
-
- x = result->x;
- y = result->y;
- n = 0;
-
- n_pixels = result->width * result->height;
-
- gegl_buffer_get (tmp, &src_rect, 1.0,
- babl_format ("RGBA float"), src_buf,
- GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP);
-
- in_pixel = src_buf + (src_rect.width + 1) * 4;
- out_pixel = dst_buf;
-
- while (n_pixels--)
- {
- gint b;
-
- if (gegl_random_float_range (o->seed, x, y, 0, n++, 0.0, 100.0) <=
- o->pct_random)
- {
- gint k = gegl_random_int_range (o->seed, x, y, 0, n++, 0, 9);
-
- for (b = 0; b < 4; b++)
- {
- switch (k)
- {
- case 0:
- out_pixel[b] = in_pixel[b - src_rect.width * 4 - 4];
- break;
- case 1:
- out_pixel[b] = in_pixel[b - src_rect.width * 4];
- break;
- case 2:
- out_pixel[b] = in_pixel[b - src_rect.width * 4 + 4];
- break;
- case 3:
- out_pixel[b] = in_pixel[b - 4];
- break;
- case 4:
- out_pixel[b] = in_pixel[b];
- break;
- case 5:
- out_pixel[b] = in_pixel[b + 4];
- break;
- case 6:
- out_pixel[b] = in_pixel[b + src_rect.width * 4 - 4];
- break;
- case 7:
- out_pixel[b] = in_pixel[b + src_rect.width * 4];
- break;
- case 8:
- out_pixel[b] = in_pixel[b + src_rect.width * 4 + 4];
- break;
- }
- }
- }
- else
- {
- for (b = 0; b < 4; b++)
- {
- out_pixel[b] = in_pixel[b];
- }
- }
-
- if (n_pixels % width == 0)
- in_pixel += 12;
- else
- in_pixel += 4;
-
- out_pixel += 4;
-
- x++;
- if (x >= result->x + result->width)
- {
- x = result->x;
- y++;
- }
- }
-
- gegl_buffer_set (tmp, result, 0,
- babl_format ("RGBA float"), dst_buf,
- GEGL_AUTO_ROWSTRIDE);
- }
-
- gegl_buffer_copy (tmp, NULL, output, NULL);
-
- g_slice_free1 (4 * total_pixels * sizeof (gfloat), src_buf);
- g_slice_free1 (4 * n_pixels * sizeof (gfloat), dst_buf);
-
- g_object_unref (tmp);
+ GeglRectangle src_rect, init_rect, chunked_result;
+ gfloat *buf1, *buf2, *dst_buf;
+ gint rowstride, start_x, start_y;
+ gint i, j;
+
+ buf1 = g_new (gfloat, SQR (MAX_HW_EXT) * 4);
+ buf2 = g_new (gfloat, SQR (MAX_HW_EXT) * 4);
+
+ for (j = 0; (j-1) * CHUNK_SIZE < result->height; j++)
+ for (i = 0; (i-1) * CHUNK_SIZE < result->width; i++)
+ {
+ chunked_result = *GEGL_RECTANGLE (result->x + i * CHUNK_SIZE,
+ result->y + j * CHUNK_SIZE,
+ CHUNK_SIZE, CHUNK_SIZE);
+
+ gegl_rectangle_intersect (&chunked_result, &chunked_result, result);
+
+ if (chunked_result.width < 1 || chunked_result.height < 1)
+ continue;
+
+ src_rect.x = chunked_result.x - op_area->left;
+ src_rect.y = chunked_result.y - op_area->top;
+ src_rect.width = chunked_result.width + op_area->left + op_area->right;
+ src_rect.height = chunked_result.height + op_area->top + op_area->bottom;
+
+ init_rect.x = src_rect.x + 1;
+ init_rect.y = src_rect.y + 1;
+ init_rect.width = src_rect.width - 2;
+ init_rect.height = src_rect.height - 2;
+
+ gegl_buffer_get (input, &src_rect, 1.0,
+ babl_format ("RGBA float"), buf1,
+ GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP);
+
+ iterate (&src_rect, &init_rect, buf1, buf2, o->seed,
+ o->pct_random, o->repeat);
+
+ rowstride = src_rect.width;
+
+ start_x = o->repeat;
+ start_y = o->repeat;
+
+ if (o->repeat % 2)
+ dst_buf = buf2;
+ else
+ dst_buf = buf1;
+
+ dst_buf += (start_y * rowstride + start_x) * 4;
+
+ gegl_buffer_set (output, &chunked_result, 1.0,
+ babl_format ("RGBA float"), dst_buf,
+ rowstride * 4 * sizeof (gfloat));
+ }
+
+ g_free (buf1);
+ g_free (buf2);
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]