[gegl] operations: merge pixelize and dot
- From: Téo Mazars <teom src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] operations: merge pixelize and dot
- Date: Mon, 11 Nov 2013 15:29:49 +0000 (UTC)
commit 76448875780f6064551a5a7cf928e3e8ed399036
Author: Téo Mazars <teo mazars ensimag fr>
Date: Mon Nov 11 15:56:55 2013 +0100
operations: merge pixelize and dot
... since they are similar
- fix Bug 710059
- add a "diamond" shape
- don't try to allocate too much memory
- handle edges properly
- the opencl version follows the change
opencl/pixelize.cl | 143 ++++++++++++++-----
opencl/pixelize.cl.h | 143 ++++++++++++++-----
operations/common/pixelize.c | 331 ++++++++++++++++++++++++++++++++++--------
3 files changed, 486 insertions(+), 131 deletions(-)
---
diff --git a/opencl/pixelize.cl b/opencl/pixelize.cl
index 2e22476..bb75963 100644
--- a/opencl/pixelize.cl
+++ b/opencl/pixelize.cl
@@ -1,48 +1,123 @@
+/* This file is an image processing operation for GEGL
+ *
+ * GEGL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * GEGL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright 2013 Victor Oliveira <victormatheus gmail com>
+ * Copyright 2013 Carlos Zubieta <czubieta dev gmail com>
+ */
+
__kernel void calc_block_color(__global float4 *in,
- __global float4 *out,
- int xsize,
- int ysize,
- int roi_x,
- int roi_y,
- int line_width,
- int block_count_x )
+ __global float4 *out,
+ int xsize,
+ int ysize,
+ int roi_x,
+ int roi_y,
+ int total_width_x,
+ int total_width_y,
+ int line_width,
+ int block_count_x )
{
- int gidx = get_global_id(0);
- int gidy = get_global_id(1);
- int cx = roi_x / xsize + gidx;
- int cy = roi_y / ysize + gidy;
+ int gidx = get_global_id(0);
+ int gidy = get_global_id(1);
+
+ int cx = roi_x / xsize + gidx;
+ int cy = roi_y / ysize + gidy;
+
+ int px = cx * xsize - roi_x;
+ int py = cy * ysize - roi_y;
+
+ int i, j;
+
+ float4 col = (float4)(0.0f, 0.0f, 0.0f, 0.0f);
- float weight = 1.0f / (xsize * ysize);
+ int real_xsize = min (total_width_x - px - roi_x, xsize);
+ int real_ysize = min (total_width_y - py - roi_y, ysize);
- int px = cx * xsize + xsize - roi_x;
- int py = cy * ysize + ysize - roi_y;
+ float weight = 1.0f / (real_xsize * real_ysize);
- int i,j;
- float4 col = 0.0f;
- for (j = py;j < py + ysize; ++j)
+ for (j = py; j < py + real_ysize; ++j)
{
- for (i = px;i < px + xsize; ++i)
+ for (i = px; i < px + real_xsize; ++i)
{
- col += in[j * line_width + i];
+ col += in[(j + ysize) * line_width + i + xsize];
}
}
- out[gidy * block_count_x + gidx] = col * weight;
-
+ out[gidy * block_count_x + gidx] = col * weight;
}
-__kernel void kernel_pixelise (__global float4 *in,
- __global float4 *out,
- int xsize,
- int ysize,
- int roi_x,
- int roi_y,
- int block_count_x)
+
+#define NORM_MANHATTAN 0
+#define NORM_EUCLIDEAN 1
+#define NORM_INFINITY 2
+#define SQR(x) ((x)*(x))
+
+__kernel void kernel_pixelize(__global float4 *in,
+ __global float4 *out,
+ int xsize,
+ int ysize,
+ float xratio,
+ float yratio,
+ int roi_x,
+ int roi_y,
+ float4 bg_color,
+ int norm,
+ int block_count_x)
{
- int gidx = get_global_id(0);
- int gidy = get_global_id(1);
+ int gidx = get_global_id(0);
+ int gidy = get_global_id(1);
+
+ int src_width = get_global_size(0);
+ int cx = (gidx + roi_x) / xsize - roi_x / xsize;
+ int cy = (gidy + roi_y) / ysize - roi_y / ysize;
+
+ float4 grid_color = in[cx + cy * block_count_x];
+ float4 out_color = bg_color;
+
+ int x_pos = gidx + roi_x;
+ int y_pos = gidy + roi_y;
+
+ int rect_shape_width = ceil (xsize * xratio);
+ int rect_shape_height = ceil (ysize * yratio);
+
+ int off_shape_x = floor ((xsize - xratio * xsize) / 2.0f);
+ int off_shape_y = floor ((ysize - yratio * ysize) / 2.0f);
+
+ int start_x = (x_pos / xsize) * xsize - roi_x;
+ int start_y = (y_pos / ysize) * ysize - roi_y;
+
+ float shape_area = rect_shape_width * rect_shape_height;
+
+ float center_x = start_x + off_shape_x + (float)(rect_shape_width) / 2.0f;
+ float center_y = start_y + off_shape_y + (float)(rect_shape_height) / 2.0f;
+
+ if (norm == NORM_MANHATTAN &&
+ (fabs (gidx - center_x) * rect_shape_height +
+ fabs (gidy - center_y) * rect_shape_width
+ < shape_area))
+ out_color = grid_color;
+
+ if (norm == NORM_EUCLIDEAN &&
+ SQR ((gidx - center_x) / (float)rect_shape_width) +
+ SQR ((gidy - center_y) / (float)rect_shape_height) <= 1.0f)
+ out_color = grid_color;
+
+ if (norm == NORM_INFINITY &&
+ (gidx >= start_x + off_shape_x &&
+ gidy >= start_y + off_shape_y &&
+ gidx < start_x + off_shape_x + rect_shape_width &&
+ gidy < start_y + off_shape_y + rect_shape_height))
+ out_color = grid_color;
- int src_width = get_global_size(0);
- int cx = (gidx + roi_x) / xsize - roi_x / xsize;
- int cy = (gidy + roi_y) / ysize - roi_y / ysize;
- out[gidx + gidy * src_width] = in[cx + cy * block_count_x];
+ out[gidx + gidy * src_width] = out_color;
}
diff --git a/opencl/pixelize.cl.h b/opencl/pixelize.cl.h
index 3715450..00b3ac7 100644
--- a/opencl/pixelize.cl.h
+++ b/opencl/pixelize.cl.h
@@ -1,50 +1,125 @@
static const char* pixelize_cl_source =
+"/* This file is an image processing operation for GEGL \n"
+" * \n"
+" * GEGL is free software; you can redistribute it and/or \n"
+" * modify it under the terms of the GNU Lesser General Public \n"
+" * License as published by the Free Software Foundation; either \n"
+" * version 3 of the License, or (at your option) any later version. \n"
+" * \n"
+" * GEGL is distributed in the hope that it will be useful, \n"
+" * but WITHOUT ANY WARRANTY; without even the implied warranty of \n"
+" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU \n"
+" * Lesser General Public License for more details. \n"
+" * \n"
+" * You should have received a copy of the GNU Lesser General Public \n"
+" * License along with GEGL; if not, see <http://www.gnu.org/licenses/>. \n"
+" * \n"
+" * Copyright 2013 Victor Oliveira <victormatheus gmail com> \n"
+" * Copyright 2013 Carlos Zubieta <czubieta dev gmail com> \n"
+" */ \n"
+" \n"
"__kernel void calc_block_color(__global float4 *in, \n"
-" __global float4 *out, \n"
-" int xsize, \n"
-" int ysize, \n"
-" int roi_x, \n"
-" int roi_y, \n"
-" int line_width, \n"
-" int block_count_x ) \n"
+" __global float4 *out, \n"
+" int xsize, \n"
+" int ysize, \n"
+" int roi_x, \n"
+" int roi_y, \n"
+" int total_width_x, \n"
+" int total_width_y, \n"
+" int line_width, \n"
+" int block_count_x ) \n"
"{ \n"
-" int gidx = get_global_id(0); \n"
-" int gidy = get_global_id(1); \n"
-" int cx = roi_x / xsize + gidx; \n"
-" int cy = roi_y / ysize + gidy; \n"
+" int gidx = get_global_id(0); \n"
+" int gidy = get_global_id(1); \n"
+" \n"
+" int cx = roi_x / xsize + gidx; \n"
+" int cy = roi_y / ysize + gidy; \n"
+" \n"
+" int px = cx * xsize - roi_x; \n"
+" int py = cy * ysize - roi_y; \n"
+" \n"
+" int i, j; \n"
+" \n"
+" float4 col = (float4)(0.0f, 0.0f, 0.0f, 0.0f); \n"
" \n"
-" float weight = 1.0f / (xsize * ysize); \n"
+" int real_xsize = min (total_width_x - px - roi_x, xsize); \n"
+" int real_ysize = min (total_width_y - py - roi_y, ysize); \n"
" \n"
-" int px = cx * xsize + xsize - roi_x; \n"
-" int py = cy * ysize + ysize - roi_y; \n"
+" float weight = 1.0f / (real_xsize * real_ysize); \n"
" \n"
-" int i,j; \n"
-" float4 col = 0.0f; \n"
-" for (j = py;j < py + ysize; ++j) \n"
+" for (j = py; j < py + real_ysize; ++j) \n"
" { \n"
-" for (i = px;i < px + xsize; ++i) \n"
+" for (i = px; i < px + real_xsize; ++i) \n"
" { \n"
-" col += in[j * line_width + i]; \n"
+" col += in[(j + ysize) * line_width + i + xsize]; \n"
" } \n"
" } \n"
-" out[gidy * block_count_x + gidx] = col * weight; \n"
-" \n"
+" out[gidy * block_count_x + gidx] = col * weight; \n"
"} \n"
" \n"
-"__kernel void kernel_pixelise (__global float4 *in, \n"
-" __global float4 *out, \n"
-" int xsize, \n"
-" int ysize, \n"
-" int roi_x, \n"
-" int roi_y, \n"
-" int block_count_x) \n"
+" \n"
+"#define NORM_MANHATTAN 0 \n"
+"#define NORM_EUCLIDEAN 1 \n"
+"#define NORM_INFINITY 2 \n"
+"#define SQR(x) ((x)*(x)) \n"
+" \n"
+"__kernel void kernel_pixelize(__global float4 *in, \n"
+" __global float4 *out, \n"
+" int xsize, \n"
+" int ysize, \n"
+" float xratio, \n"
+" float yratio, \n"
+" int roi_x, \n"
+" int roi_y, \n"
+" float4 bg_color, \n"
+" int norm, \n"
+" int block_count_x) \n"
"{ \n"
-" int gidx = get_global_id(0); \n"
-" int gidy = get_global_id(1); \n"
+" int gidx = get_global_id(0); \n"
+" int gidy = get_global_id(1); \n"
+" \n"
+" int src_width = get_global_size(0); \n"
+" int cx = (gidx + roi_x) / xsize - roi_x / xsize; \n"
+" int cy = (gidy + roi_y) / ysize - roi_y / ysize; \n"
+" \n"
+" float4 grid_color = in[cx + cy * block_count_x]; \n"
+" float4 out_color = bg_color; \n"
+" \n"
+" int x_pos = gidx + roi_x; \n"
+" int y_pos = gidy + roi_y; \n"
+" \n"
+" int rect_shape_width = ceil (xsize * xratio); \n"
+" int rect_shape_height = ceil (ysize * yratio); \n"
+" \n"
+" int off_shape_x = floor ((xsize - xratio * xsize) / 2.0f); \n"
+" int off_shape_y = floor ((ysize - yratio * ysize) / 2.0f); \n"
+" \n"
+" int start_x = (x_pos / xsize) * xsize - roi_x; \n"
+" int start_y = (y_pos / ysize) * ysize - roi_y; \n"
+" \n"
+" float shape_area = rect_shape_width * rect_shape_height; \n"
+" \n"
+" float center_x = start_x + off_shape_x + (float)(rect_shape_width) / 2.0f; \n"
+" float center_y = start_y + off_shape_y + (float)(rect_shape_height) / 2.0f; \n"
+" \n"
+" if (norm == NORM_MANHATTAN && \n"
+" (fabs (gidx - center_x) * rect_shape_height + \n"
+" fabs (gidy - center_y) * rect_shape_width \n"
+" < shape_area)) \n"
+" out_color = grid_color; \n"
+" \n"
+" if (norm == NORM_EUCLIDEAN && \n"
+" SQR ((gidx - center_x) / (float)rect_shape_width) + \n"
+" SQR ((gidy - center_y) / (float)rect_shape_height) <= 1.0f) \n"
+" out_color = grid_color; \n"
+" \n"
+" if (norm == NORM_INFINITY && \n"
+" (gidx >= start_x + off_shape_x && \n"
+" gidy >= start_y + off_shape_y && \n"
+" gidx < start_x + off_shape_x + rect_shape_width && \n"
+" gidy < start_y + off_shape_y + rect_shape_height)) \n"
+" out_color = grid_color; \n"
" \n"
-" int src_width = get_global_size(0); \n"
-" int cx = (gidx + roi_x) / xsize - roi_x / xsize; \n"
-" int cy = (gidy + roi_y) / ysize - roi_y / ysize; \n"
-" out[gidx + gidy * src_width] = in[cx + cy * block_count_x]; \n"
+" out[gidx + gidy * src_width] = out_color; \n"
"} \n"
;
diff --git a/operations/common/pixelize.c b/operations/common/pixelize.c
index 23d1fa7..fe5251f 100644
--- a/operations/common/pixelize.c
+++ b/operations/common/pixelize.c
@@ -14,6 +14,7 @@
* License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2006 Øyvind Kolås <pippin gimp org>
+ * Copyright 2013 Téo Mazars <teo mazars ensimag fr>
*/
#include "config.h"
@@ -22,6 +23,18 @@
#ifdef GEGL_CHANT_PROPERTIES
+gegl_chant_register_enum (gegl_pixelize_norm)
+ enum_value (GEGL_PIXELIZE_NORM_MANHATTAN, "Diamond")
+ enum_value (GEGL_PIXELIZE_NORM_EUCLIDEAN, "Round")
+ enum_value (GEGL_PIXELIZE_NORM_INFINITY, "Square")
+gegl_chant_register_enum_end (GeglPixelizeNorm)
+
+gegl_chant_enum (norm, _("Shape"),
+ GeglPixelizeNorm,
+ gegl_pixelize_norm,
+ GEGL_PIXELIZE_NORM_INFINITY,
+ _("The shape of pixels"))
+
gegl_chant_int_ui (size_x, _("Block Width"),
1, 123456, 16, 1, 2048, 1.5,
_("Width of blocks in pixels"))
@@ -30,6 +43,18 @@ gegl_chant_int_ui (size_y, _("Block Height"),
1, 123456, 16, 1, 2048, 1.5,
_("Height of blocks in pixels"))
+gegl_chant_double (ratio_x, _("X size ratio"),
+ 0.0, 1.0, 1.0,
+ _("Horizontal size ratio of a pixel inside each block"))
+
+gegl_chant_double (ratio_y, _("Y size ratio"),
+ 0.0, 1.0, 1.0,
+ _("Vertical size ratio of a pixel inside each block"))
+
+gegl_chant_color (background, _("Background color"),
+ "white",
+ _("Color used to fill the background"))
+
#else
#define GEGL_CHANT_TYPE_AREA_FILTER
@@ -37,12 +62,9 @@ gegl_chant_int_ui (size_y, _("Block Height"),
#include "gegl-chant.h"
-#define CELL_X(px, cell_width) ((px) / (cell_width))
-#define CELL_Y(py, cell_height) ((py) / (cell_height))
-
-#define CHUNK_SIZE (1024)
-#define ALLOC_THRESHOLD_SIZE (128)
-#define SQR(x) ((x)*(x))
+#define CHUNK_SIZE (1024)
+#define ALLOC_THRESHOLD_SIZE (64)
+#define SQR(x) ((x)*(x))
static void
prepare (GeglOperation *operation)
@@ -62,6 +84,20 @@ prepare (GeglOperation *operation)
gegl_operation_set_format (operation, "output", babl_format ("RaGaBaA float"));
}
+static GeglRectangle
+get_bounding_box (GeglOperation *self)
+{
+ GeglRectangle result = { 0, 0, 0, 0 };
+ GeglRectangle *in_rect;
+
+ in_rect = gegl_operation_source_get_bounding_box (self, "input");
+ if (in_rect)
+ {
+ result = *in_rect;
+ }
+
+ return result;
+}
static void
mean_rectangle_noalloc (GeglBuffer *input,
@@ -77,7 +113,7 @@ mean_rectangle_noalloc (GeglBuffer *input,
while (gegl_buffer_iterator_next (gi))
{
- gint k;
+ gint k;
gfloat *data = (gfloat*) gi->data[0];
for (k = 0; k < gi->length; k++)
@@ -116,38 +152,147 @@ mean_rectangle (gfloat *input,
}
static void
-set_rectangle (gfloat *output,
- GeglRectangle *rect,
- gint rowstride,
- gfloat *color)
+set_rectangle (gfloat *output,
+ GeglRectangle *rect,
+ GeglRectangle *rect_shape,
+ gint rowstride,
+ gfloat *color,
+ GeglPixelizeNorm norm)
{
gint c, x, y;
+ gfloat center_x, center_y;
+ GeglRectangle rect2;
- for (y = rect->y; y < rect->y + rect->height; y++)
- for (x = rect->x; x < rect->x + rect->width; x++)
- for (c = 0; c < 4; c++)
- output [4 * (y * rowstride + x) + c] = color[c];
+ gfloat shape_area = rect_shape->width * rect_shape->height;
+
+ center_x = rect_shape->x + rect_shape->width / 2.0f;
+ center_y = rect_shape->y + rect_shape->height / 2.0f;
+
+ gegl_rectangle_intersect (&rect2, rect, rect_shape);
+
+ switch (norm)
+ {
+ case (GEGL_PIXELIZE_NORM_INFINITY):
+
+ for (y = rect2.y; y < rect2.y + rect2.height; y++)
+ for (x = rect2.x; x < rect2.x + rect2.width; x++)
+ for (c = 0; c < 4; c++)
+ output [4 * (y * rowstride + x) + c] = color[c];
+ break;
+
+ case (GEGL_PIXELIZE_NORM_EUCLIDEAN):
+
+ for (y = rect->y; y < rect->y + rect->height; y++)
+ for (x = rect->x; x < rect->x + rect->width; x++)
+ if (SQR ((x - center_x) / (gfloat) rect_shape->width) +
+ SQR ((y - center_y) / (gfloat) rect_shape->height) <= 1.0f)
+ for (c = 0; c < 4; c++)
+ output [4 * (y * rowstride + x) + c] = color[c];
+ break;
+
+ case (GEGL_PIXELIZE_NORM_MANHATTAN):
+
+ for (y = rect->y; y < rect->y + rect->height; y++)
+ for (x = rect->x; x < rect->x + rect->width; x++)
+ if (fabsf (center_x - x) * rect_shape->height +
+ fabsf (center_y - y) * rect_shape->width < shape_area)
+ for (c = 0; c < 4; c++)
+ output [4 * (y * rowstride + x) + c] = color[c];
+
+ break;
+ }
}
+static void
+set_rectangle_noalloc (GeglBuffer *output,
+ GeglRectangle *rect,
+ GeglRectangle *rect_shape,
+ GeglColor *color,
+ GeglPixelizeNorm norm)
+{
+ if (norm == GEGL_PIXELIZE_NORM_INFINITY)
+ {
+ GeglRectangle rect2;
+ gegl_rectangle_intersect (&rect2, rect, rect_shape);
+ gegl_buffer_set_color (output, &rect2, color);
+ }
+ else
+ {
+ GeglBufferIterator *gi;
+ gint c, x, y;
+ gfloat col[4];
+ gfloat center_x, center_y;
+ gfloat shape_area = rect_shape->width * rect_shape->height;
+
+ center_x = rect_shape->x + rect_shape->width / 2.0f;
+ center_y = rect_shape->y + rect_shape->height / 2.0f;
+
+ gegl_color_get_pixel (color, babl_format ("RaGaBaA float"), col);
+
+ gi = gegl_buffer_iterator_new (output, rect, 0, babl_format ("RaGaBaA float"),
+ GEGL_BUFFER_WRITE, GEGL_ABYSS_CLAMP);
+
+ while (gegl_buffer_iterator_next (gi))
+ {
+ gfloat *data = (gfloat*) gi->data[0];
+ GeglRectangle roi = gi->roi[0];
+
+ switch (norm)
+ {
+ case (GEGL_PIXELIZE_NORM_EUCLIDEAN):
+
+ for (y = 0; y < roi.height; y++)
+ for (x = 0; x < roi.width; x++)
+ if (SQR ((x + roi.x - center_x) / (gfloat) rect_shape->width) +
+ SQR ((y + roi.y - center_y) / (gfloat) rect_shape->height) <= 1.0f)
+ for (c = 0; c < 4; c++)
+ data [4 * (y * roi.width + x) + c] = col[c];
+ break;
+
+ case (GEGL_PIXELIZE_NORM_MANHATTAN):
+
+ for (y = 0; y < roi.height; y++)
+ for (x = 0; x < roi.width; x++)
+ if (fabsf (x + roi.x - center_x) * rect_shape->height +
+ fabsf (y + roi.y - center_y) * rect_shape->width
+ < shape_area)
+ for (c = 0; c < 4; c++)
+ data [4 * (y * roi.width + x) + c] = col[c];
+ break;
+
+ case (GEGL_PIXELIZE_NORM_INFINITY):
+ break;
+ }
+ }
+ }
+}
static void
pixelize_noalloc (GeglBuffer *input,
GeglBuffer *output,
const GeglRectangle *roi,
const GeglRectangle *whole_region,
- gint size_x,
- gint size_y)
+ GeglChantO *o)
{
- gint start_x = (roi->x / size_x) * size_x;
- gint start_y = (roi->y / size_y) * size_y;
+ gint start_x = (roi->x / o->size_x) * o->size_x;
+ gint start_y = (roi->y / o->size_y) * o->size_y;
gint x, y;
+ gint off_shape_x, off_shape_y;
GeglColor *color = gegl_color_new ("white");
- for (y = start_y; y < roi->y + roi->height; y += size_y)
- for (x = start_x; x < roi->x + roi->width; x += size_x)
+ GeglRectangle rect_shape;
+
+ rect_shape.width = ceilf (o->size_x * (gfloat)o->ratio_x);
+ rect_shape.height = ceilf (o->size_y * (gfloat)o->ratio_y);
+
+ off_shape_x = floorf ((o->size_x - (gfloat)o->ratio_x * o->size_x) / 2.0f);
+ off_shape_y = floorf ((o->size_y - (gfloat)o->ratio_y * o->size_y) / 2.0f);
+
+ for (y = start_y; y < roi->y + roi->height; y += o->size_y)
+ for (x = start_x; x < roi->x + roi->width; x += o->size_x)
{
- GeglRectangle rect = {x, y, size_x, size_y};
+ GeglRectangle rect = {x, y, o->size_x, o->size_y};
gegl_rectangle_intersect (&rect, whole_region, &rect);
@@ -158,7 +303,10 @@ pixelize_noalloc (GeglBuffer *input,
gegl_rectangle_intersect (&rect, roi, &rect);
- gegl_buffer_set_color (output, &rect, color);
+ rect_shape.x = x + off_shape_x;
+ rect_shape.y = y + off_shape_y;
+
+ set_rectangle_noalloc (output, &rect, &rect_shape, color, o->norm);
}
g_object_unref (color);
@@ -170,20 +318,30 @@ pixelize (gfloat *input,
const GeglRectangle *roi,
const GeglRectangle *extended_roi,
const GeglRectangle *whole_region,
- gint size_x,
- gint size_y)
+ GeglChantO *o)
{
- gint start_x = (roi->x / size_x) * size_x;
- gint start_y = (roi->y / size_y) * size_y;
- gint x, y;
- gfloat color[4];
+ gint start_x = (roi->x / o->size_x) * o->size_x;
+ gint start_y = (roi->y / o->size_y) * o->size_y;
+ gint x, y;
+ gint off_shape_x, off_shape_y;
+ gfloat color[4];
+ GeglRectangle rect_shape;
+
+ rect_shape.width = ceilf (o->size_x * (gfloat)o->ratio_x);
+ rect_shape.height = ceilf (o->size_y * (gfloat)o->ratio_y);
+
+ off_shape_x = floorf ((o->size_x - (gfloat)o->ratio_x * o->size_x) / 2.0f);
+ off_shape_y = floorf ((o->size_y - (gfloat)o->ratio_y * o->size_y) / 2.0f);
- for (y = start_y; y < roi->y + roi->height; y += size_y)
- for (x = start_x; x < roi->x + roi->width; x += size_x)
+ for (y = start_y; y < roi->y + roi->height; y += o->size_y)
+ for (x = start_x; x < roi->x + roi->width; x += o->size_x)
{
- GeglRectangle rect = {x, y, size_x, size_y};
+ GeglRectangle rect = {x, y, o->size_x, o->size_y};
GeglRectangle rect2;
+ rect_shape.x = x + off_shape_x;
+ rect_shape.y = y + off_shape_y;
+
gegl_rectangle_intersect (&rect, whole_region, &rect);
if (rect.width < 1 || rect.height < 1)
@@ -203,7 +361,11 @@ pixelize (gfloat *input,
rect2.width = rect.width;
rect2.height = rect.height;
- set_rectangle (output, &rect2, roi->width, color);
+ rect_shape.x -= roi->x;
+ rect_shape.y -= roi->y;
+
+ set_rectangle (output, &rect2, &rect_shape,
+ roi->width, color, o->norm);
}
}
@@ -215,28 +377,34 @@ pixelize (gfloat *input,
static GeglClRunData *cl_data = NULL;
static gboolean
-cl_pixelise (cl_mem in_tex,
- cl_mem aux_tex,
- cl_mem out_tex,
- const GeglRectangle *src_rect,
- const GeglRectangle *roi,
- gint xsize,
- gint ysize)
+cl_pixelize (cl_mem in_tex,
+ cl_mem aux_tex,
+ cl_mem out_tex,
+ const GeglRectangle *src_rect,
+ const GeglRectangle *roi,
+ gint xsize,
+ gint ysize,
+ gfloat xratio,
+ gfloat yratio,
+ gfloat bg_color[4],
+ gint norm,
+ GeglRectangle *image_extent)
{
cl_int cl_err = 0;
const size_t gbl_size[2]= {roi->width, roi->height};
- gint cx0 = CELL_X(roi->x ,xsize);
- gint cy0 = CELL_Y(roi->y ,ysize);
- gint block_count_x = CELL_X(roi->x+roi->width - 1, xsize)-cx0 + 1;
- gint block_count_y = CELL_Y(roi->y+roi->height - 1, ysize)-cy0 + 1;
+ gint cx0 = roi->x / xsize;
+ gint cy0 = roi->y / ysize;
+ gint block_count_x = ((roi->x + roi->width + xsize - 1) / xsize) - cx0;
+ gint block_count_y = ((roi->y + roi->height + ysize - 1) / ysize) - cy0;
+
cl_int line_width = roi->width + 2 * xsize;
- size_t gbl_size_tmp[2] = {block_count_x,block_count_y};
+ size_t gbl_size_tmp[2] = {block_count_x, block_count_y};
if (!cl_data)
{
- const char *kernel_name[] = {"calc_block_color", "kernel_pixelise", NULL};
+ const char *kernel_name[] = {"calc_block_color", "kernel_pixelize", NULL};
cl_data = gegl_cl_compile_and_build (pixelize_cl_source, kernel_name);
}
@@ -249,6 +417,8 @@ cl_pixelise (cl_mem in_tex,
sizeof(cl_int), (void*)&ysize,
sizeof(cl_int), (void*)&roi->x,
sizeof(cl_int), (void*)&roi->y,
+ sizeof(cl_int), (void*)&image_extent->width,
+ sizeof(cl_int), (void*)&image_extent->height,
sizeof(cl_int), (void*)&line_width,
sizeof(cl_int), (void*)&block_count_x,
NULL);
@@ -261,13 +431,17 @@ cl_pixelise (cl_mem in_tex,
CL_CHECK;
cl_err = gegl_cl_set_kernel_args (cl_data->kernel[1],
- sizeof(cl_mem), (void*)&aux_tex,
- sizeof(cl_mem), (void*)&out_tex,
- sizeof(cl_int), (void*)&xsize,
- sizeof(cl_int), (void*)&ysize,
- sizeof(cl_int), (void*)&roi->x,
- sizeof(cl_int), (void*)&roi->y,
- sizeof(cl_int), (void*)&block_count_x,
+ sizeof(cl_mem), (void*)&aux_tex,
+ sizeof(cl_mem), (void*)&out_tex,
+ sizeof(cl_int), (void*)&xsize,
+ sizeof(cl_int), (void*)&ysize,
+ sizeof(cl_float), (void*)&xratio,
+ sizeof(cl_float), (void*)&yratio,
+ sizeof(cl_int), (void*)&roi->x,
+ sizeof(cl_int), (void*)&roi->y,
+ sizeof(cl_float4),(void*)bg_color,
+ sizeof(cl_int), (void*)&norm,
+ sizeof(cl_int), (void*)&block_count_x,
NULL);
CL_CHECK;
@@ -291,10 +465,13 @@ cl_process (GeglOperation *operation,
{
const Babl *in_format = babl_format ("RaGaBaA float");
const Babl *out_format = babl_format ("RaGaBaA float");
- gint err;
+ gint err;
+ gfloat bg_color[4];
+ gint norm;
GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation);
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+ GeglRectangle *image_extent;
GeglBufferClIterator *i = gegl_buffer_cl_iterator_new (output,
roi,
@@ -321,15 +498,28 @@ cl_process (GeglOperation *operation,
op_area->bottom);
+ gegl_color_get_pixel (o->background, babl_format ("RaGaBaA float"), bg_color);
+
+ norm = 0;
+ norm = o->norm == GEGL_PIXELIZE_NORM_EUCLIDEAN ? 1 : norm;
+ norm = o->norm == GEGL_PIXELIZE_NORM_INFINITY ? 2 : norm;
+
+ image_extent = gegl_operation_source_get_bounding_box (operation, "input");
+
while (gegl_buffer_cl_iterator_next (i, &err) && !err)
{
- err = cl_pixelise(i->tex[read],
+ err = cl_pixelize(i->tex[read],
i->tex[aux],
i->tex[0],
&i->roi[read],
&i->roi[0],
o->size_x,
- o->size_y);
+ o->size_y,
+ o->ratio_x,
+ o->ratio_y,
+ bg_color,
+ norm,
+ image_extent);
if (err)
{
@@ -363,16 +553,21 @@ process (GeglOperation *operation,
if (o->size_x * o->size_y < SQR (ALLOC_THRESHOLD_SIZE))
{
+ gfloat background_color[4];
gfloat *input_buf = g_new (gfloat,
(CHUNK_SIZE + o->size_x * 2) *
(CHUNK_SIZE + o->size_y * 2) * 4);
gfloat *output_buf = g_new (gfloat, SQR (CHUNK_SIZE) * 4);
gint i, j;
+ gegl_color_get_pixel (o->background, babl_format("RaGaBaA float"),
+ background_color);
+
for (j = 0; (j-1) * CHUNK_SIZE < roi->height; j++)
for (i = 0; (i-1) * CHUNK_SIZE < roi->width; i++)
{
GeglRectangle chunked_result;
+ GeglRectangle chunked_sizes;
chunked_result = *GEGL_RECTANGLE (roi->x + i * CHUNK_SIZE,
roi->y + j * CHUNK_SIZE,
@@ -392,10 +587,19 @@ process (GeglOperation *operation,
gegl_buffer_get (input, &src_rect, 1.0, babl_format ("RaGaBaA float"),
input_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP);
- pixelize (input_buf, output_buf, &chunked_result, &src_rect, whole_region,
- o->size_x, o->size_y);
+ gegl_rectangle_copy (&chunked_sizes, &chunked_result);
+ chunked_sizes.x = 0;
+ chunked_sizes.y = 0;
+
+ set_rectangle (output_buf, &chunked_sizes, &chunked_sizes,
+ chunked_result.width, background_color,
+ GEGL_PIXELIZE_NORM_INFINITY);
+
+ pixelize (input_buf, output_buf, &chunked_result, &src_rect,
+ whole_region, o);
- gegl_buffer_set (output, &chunked_result, 1.0, babl_format ("RaGaBaA float"),
+ gegl_buffer_set (output, &chunked_result, 1.0,
+ babl_format ("RaGaBaA float"),
output_buf, GEGL_AUTO_ROWSTRIDE);
}
@@ -404,8 +608,8 @@ process (GeglOperation *operation,
}
else
{
- pixelize_noalloc (input, output, roi, whole_region,
- o->size_x, o->size_y);
+ gegl_buffer_set_color (output, roi, o->background);
+ pixelize_noalloc (input, output, roi, whole_region, o);
}
return TRUE;
@@ -421,8 +625,9 @@ gegl_chant_class_init (GeglChantClass *klass)
operation_class = GEGL_OPERATION_CLASS (klass);
filter_class = GEGL_OPERATION_FILTER_CLASS (klass);
- operation_class->prepare = prepare;
- operation_class->opencl_support = TRUE;
+ operation_class->prepare = prepare;
+ operation_class->get_bounding_box = get_bounding_box;
+ operation_class->opencl_support = TRUE;
filter_class->process = process;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]