[gegl] Use 3x3 boxfilter for most buffer_get formats
- From: Daniel Sabo <daniels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] Use 3x3 boxfilter for most buffer_get formats
- Date: Wed, 13 Nov 2013 15:18:43 +0000 (UTC)
commit f6f56b477330f1f9d588dea2da60f629b9fc6ef1
Author: Daniel Sabo <DanielSabo gmail com>
Date: Wed Nov 13 05:51:45 2013 -0800
Use 3x3 boxfilter for most buffer_get formats
u8, u16, u32, and float are supported now
gegl/Makefile.am | 3 +
gegl/buffer/gegl-buffer-access.c | 200 ++++++------------------------------
gegl/gegl-algorithms-boxfilter.inc | 71 +++++++++++++
gegl/gegl-algorithms.c | 164 +++++++++++++++++++++++++++++
gegl/gegl-algorithms.h | 101 ++++++++++++++++++
5 files changed, 369 insertions(+), 170 deletions(-)
---
diff --git a/gegl/Makefile.am b/gegl/Makefile.am
index 4ab8abe..4e38bf1 100644
--- a/gegl/Makefile.am
+++ b/gegl/Makefile.am
@@ -68,6 +68,7 @@ GEGL_public_HEADERS = \
GEGL_sources = \
gegl-c.c \
+ gegl-algorithms.c \
gegl-apply.c \
gegl-config.c \
gegl-cpuaccel.c \
@@ -83,6 +84,7 @@ GEGL_sources = \
gegl-random.c \
gegl-matrix.c \
\
+ gegl-algorithms.h \
gegl-apply.h \
gegl-chant.h \
gegl-config.h \
@@ -102,6 +104,7 @@ GEGL_sources = \
gegl-types-internal.h \
gegl-xml.h
+EXTRA_DIST = gegl-algorithms-boxfilter.inc
lib_LTLIBRARIES = libgegl- GEGL_API_VERSION@.la
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index 0a5c9ed..896b303 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -42,6 +42,8 @@
#include "gegl-buffer-iterator.h"
#include "gegl-buffer-cl-cache.h"
+ #include "gegl-algorithms.h"
+
#if 0
static inline void
gegl_buffer_pixel_set (GeglBuffer *buffer,
@@ -1301,146 +1303,6 @@ gegl_buffer_set (GeglBuffer *buffer,
gegl_buffer_unlock (buffer);
}
-#ifdef BOXFILTER_FLOAT
-typedef float T;
-#define double2T(a) (a)
-#define projectionT babl_type ("float")
-#define T_components babl_format_get_n_components (format)
-#else
-typedef guchar T;
-#define double2T(a) (lrint (a))
-#define projectionT babl_type ("u8")
-#define T_components bpp
-#endif
-#define EPSILON 1.e-6
-
-static void
-resample_nearest (guchar *dst,
- const guchar *src,
- const GeglRectangle *dst_rect,
- const GeglRectangle *src_rect,
- const gint src_stride,
- const gdouble scale,
- const gint bpp,
- const gint dst_stride)
-{
- int i, j;
-
- for (i = 0; i < dst_rect->height; i++)
- {
- const gdouble sy = (dst_rect->y + .5 + i) / scale - src_rect->y;
- const gint ii = floor (sy + EPSILON);
-
- for (j = 0; j < dst_rect->width; j++)
- {
- const gdouble sx = (dst_rect->x + .5 + j) / scale - src_rect->x;
- const gint jj = floor (sx + EPSILON);
-
- memcpy (&dst[i * dst_stride + j * bpp],
- &src[ii * src_stride + jj * bpp],
- bpp);
- }
- }
-}
-
-static inline void
-box_filter (gdouble left_weight,
- gdouble center_weight,
- gdouble right_weight,
- gdouble top_weight,
- gdouble middle_weight,
- gdouble bottom_weight,
- const T **src, /* the 9 surrounding source pixels */
- T *dest,
- gint components)
-{
- const gdouble lt = left_weight * top_weight;
- const gdouble lm = left_weight * middle_weight;
- const gdouble lb = left_weight * bottom_weight;
- const gdouble ct = center_weight * top_weight;
- const gdouble cm = center_weight * middle_weight;
- const gdouble cb = center_weight * bottom_weight;
- const gdouble rt = right_weight * top_weight;
- const gdouble rm = right_weight * middle_weight;
- const gdouble rb = right_weight * bottom_weight;
-
-#define docomponent(i) \
- dest[i] = double2T (src[0][i] * lt + src[3][i] * lm + src[6][i] * lb + \
- src[1][i] * ct + src[4][i] * cm + src[7][i] * cb + \
- src[2][i] * rt + src[5][i] * rm + src[8][i] * rb)
- switch (components)
- {
- case 5: docomponent(4);
- case 4: docomponent(3);
- case 3: docomponent(2);
- case 2: docomponent(1);
- case 1: docomponent(0);
- }
-#undef docomponent
-}
-
-static void
-resample_boxfilter_T (guchar *dest_buf,
- const guchar *source_buf,
- const GeglRectangle *dst_rect,
- const GeglRectangle *src_rect,
- const gint s_rowstride,
- const gdouble scale,
- const gint components,
- const gint d_rowstride)
-{
- gdouble left_weight, center_weight, right_weight;
- gdouble top_weight, middle_weight, bottom_weight;
- const T *src[9];
- gint x, y;
-
- for (y = 0; y < dst_rect->height; y++)
- {
- const gdouble sy = (dst_rect->y + y + .5) / scale - src_rect->y;
- const gint ii = floor (sy);
- T *dst = (T*)(dest_buf + y * d_rowstride);
- const guchar *src_base = source_buf + ii * s_rowstride;
-
- top_weight = MAX (0., .5 - scale * (sy - ii));
- bottom_weight = MAX (0., .5 - scale * ((ii + 1 ) - sy));
- middle_weight = 1. - top_weight - bottom_weight;
-
- for (x = 0; x < dst_rect->width; x++)
- {
- const gdouble sx = (dst_rect->x + x + .5) / scale - src_rect->x;
- const gint jj = floor (sx);
-
- left_weight = MAX (0., .5 - scale * (sx - jj));
- right_weight = MAX (0., .5 - scale * ((jj + 1) - sx));
- center_weight = 1. - left_weight - right_weight;
-
- src[4] = (const T*)src_base + jj * components;
- src[1] = (const T*)(src_base - s_rowstride) + jj * components;
- src[7] = (const T*)(src_base + s_rowstride) + jj * components;
-
- src[2] = src[1] + components;
- src[5] = src[4] + components;
- src[8] = src[7] + components;
-
- src[0] = src[1] - components;
- src[3] = src[4] - components;
- src[6] = src[7] - components;
-
- box_filter (left_weight,
- center_weight,
- right_weight,
- top_weight,
- middle_weight,
- bottom_weight,
- src, /* the 9 surrounding source pixels */
- dst,
- components);
-
- dst += components;
- }
- }
-}
-
/* Expand roi by scale so it uncludes all pixels needed
* to satisfy a gegl_buffer_get() call at level 0.
*/
@@ -1453,15 +1315,14 @@ _gegl_get_required_for_scale (const Babl *format,
return *roi;
else
{
- gint x1 = floor (roi->x / scale + EPSILON);
- gint x2 = ceil ((roi->x + roi->width) / scale - EPSILON);
- gint y1 = floor (roi->y / scale + EPSILON);
- gint y2 = ceil ((roi->y + roi->height) / scale - EPSILON);
+ gint x1 = floor (roi->x / scale + GEGL_SCALE_EPSILON);
+ gint x2 = ceil ((roi->x + roi->width) / scale - GEGL_SCALE_EPSILON);
+ gint y1 = floor (roi->y / scale + GEGL_SCALE_EPSILON);
+ gint y2 = ceil ((roi->y + roi->height) / scale - GEGL_SCALE_EPSILON);
gint pad = (1.0 / scale > 1.0) ? ceil (1.0 / scale) : 1;
- if ((babl_format_get_type (format, 0) == projectionT) ||
- (scale < 1.0))
+ if (scale < 1.0)
{
return *GEGL_RECTANGLE (x1 - pad,
y1 - pad,
@@ -1536,10 +1397,10 @@ gegl_buffer_get_unlocked (GeglBuffer *buffer,
gint bpp = babl_format_get_bytes_per_pixel (format);
GeglRectangle sample_rect;
void *sample_buf;
- gint x1 = floor (rect->x / scale + EPSILON);
- gint x2 = ceil ((rect->x + rect->width) / scale - EPSILON);
- gint y1 = floor (rect->y / scale + EPSILON);
- gint y2 = ceil ((rect->y + rect->height) / scale - EPSILON);
+ gint x1 = floor (rect->x / scale + GEGL_SCALE_EPSILON);
+ gint x2 = ceil ((rect->x + rect->width) / scale - GEGL_SCALE_EPSILON);
+ gint y1 = floor (rect->y / scale + GEGL_SCALE_EPSILON);
+ gint y2 = ceil ((rect->y + rect->height) / scale - GEGL_SCALE_EPSILON);
gint factor = 1;
gint stride;
gint offset = 0;
@@ -1559,8 +1420,7 @@ gegl_buffer_get_unlocked (GeglBuffer *buffer,
buf_height = y2 - y1;
/* ensure we always have some data to sample from */
- if (scale != 1.0 && scale < 1.99 &&
- babl_format_get_type (format, 0) == projectionT)
+ if (scale != 1.0 && scale <= 1.99)
{
buf_width += 2;
buf_height += 2;
@@ -1584,21 +1444,21 @@ gegl_buffer_get_unlocked (GeglBuffer *buffer,
if (rowstride == GEGL_AUTO_ROWSTRIDE)
rowstride = rect->width * bpp;
- if (scale <= 1.99 && babl_format_get_type (format, 0) == projectionT)
- { /* do box-filter resampling if we're 8bit (which projections are) */
+ if (scale <= 1.99)
+ {
sample_rect.x = x1 - 1;
sample_rect.y = y1 - 1;
sample_rect.width = x2 - x1 + 2;
sample_rect.height = y2 - y1 + 2;
- resample_boxfilter_T (dest_buf,
- sample_buf,
- rect,
- &sample_rect,
- buf_width * bpp,
- scale,
- T_components,
- rowstride);
+ gegl_resample_boxfilter (dest_buf,
+ sample_buf,
+ rect,
+ &sample_rect,
+ buf_width * bpp,
+ scale,
+ format,
+ rowstride);
}
else
{
@@ -1607,14 +1467,14 @@ gegl_buffer_get_unlocked (GeglBuffer *buffer,
sample_rect.width = x2 - x1;
sample_rect.height = y2 - y1;
- resample_nearest (dest_buf,
- sample_buf,
- rect,
- &sample_rect,
- buf_width * bpp,
- scale,
- bpp,
- rowstride);
+ gegl_resample_nearest (dest_buf,
+ sample_buf,
+ rect,
+ &sample_rect,
+ buf_width * bpp,
+ scale,
+ bpp,
+ rowstride);
}
g_free (sample_buf);
}
diff --git a/gegl/gegl-algorithms-boxfilter.inc b/gegl/gegl-algorithms-boxfilter.inc
new file mode 100644
index 0000000..21514eb
--- /dev/null
+++ b/gegl/gegl-algorithms-boxfilter.inc
@@ -0,0 +1,71 @@
+void
+BOXFILTER_FUNCNAME (guchar *dest_buf,
+ const guchar *source_buf,
+ const GeglRectangle *dst_rect,
+ const GeglRectangle *src_rect,
+ const gint s_rowstride,
+ const gdouble scale,
+ const gint components,
+ const gint d_rowstride)
+{
+ gdouble left_weight, center_weight, right_weight;
+ gdouble top_weight, middle_weight, bottom_weight;
+ const BOXFILTER_TYPE *src[9];
+ gint x, y;
+
+ for (y = 0; y < dst_rect->height; y++)
+ {
+ const gdouble sy = (dst_rect->y + y + .5) / scale - src_rect->y;
+ const gint ii = floor (sy);
+ BOXFILTER_TYPE *dst = (BOXFILTER_TYPE*)(dest_buf + y * d_rowstride);
+ const guchar *src_base = source_buf + ii * s_rowstride;
+
+ top_weight = MAX (0., .5 - scale * (sy - ii));
+ bottom_weight = MAX (0., .5 - scale * ((ii + 1 ) - sy));
+ middle_weight = 1. - top_weight - bottom_weight;
+
+ for (x = 0; x < dst_rect->width; x++)
+ {
+ const gdouble sx = (dst_rect->x + x + .5) / scale - src_rect->x;
+ const gint jj = floor (sx);
+
+ left_weight = MAX (0., .5 - scale * (sx - jj));
+ right_weight = MAX (0., .5 - scale * ((jj + 1) - sx));
+ center_weight = 1. - left_weight - right_weight;
+
+ src[4] = (const BOXFILTER_TYPE*)src_base + jj * components;
+ src[1] = (const BOXFILTER_TYPE*)(src_base - s_rowstride) + jj * components;
+ src[7] = (const BOXFILTER_TYPE*)(src_base + s_rowstride) + jj * components;
+
+ src[2] = src[1] + components;
+ src[5] = src[4] + components;
+ src[8] = src[7] + components;
+
+ src[0] = src[1] - components;
+ src[3] = src[4] - components;
+ src[6] = src[7] - components;
+
+ {
+ const gdouble lt = left_weight * top_weight;
+ const gdouble lm = left_weight * middle_weight;
+ const gdouble lb = left_weight * bottom_weight;
+ const gdouble ct = center_weight * top_weight;
+ const gdouble cm = center_weight * middle_weight;
+ const gdouble cb = center_weight * bottom_weight;
+ const gdouble rt = right_weight * top_weight;
+ const gdouble rm = right_weight * middle_weight;
+ const gdouble rb = right_weight * bottom_weight;
+
+ for (gint i = 0; i < components; ++i)
+ {
+ dst[i] = BOXFILTER_ROUND(
+ src[0][i] * lt + src[3][i] * lm + src[6][i] * lb +
+ src[1][i] * ct + src[4][i] * cm + src[7][i] * cb +
+ src[2][i] * rt + src[5][i] * rm + src[8][i] * rb);
+ }
+ }
+
+ dst += components;
+ }
+ }
+}
diff --git a/gegl/gegl-algorithms.c b/gegl/gegl-algorithms.c
new file mode 100644
index 0000000..273f20c
--- /dev/null
+++ b/gegl/gegl-algorithms.c
@@ -0,0 +1,164 @@
+/* This file is part of GEGL.
+ *
+ * This library 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.
+ *
+ * This library 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 this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright 2006,2007 Øyvind Kolås <pippin gimp org>
+ * 2013 Daniel Sabo
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <glib-object.h>
+
+#include <babl/babl.h>
+
+#include "gegl-types.h"
+#include "gegl-algorithms.h"
+
+#include <math.h>
+
+void gegl_resample_boxfilter (guchar *dest_buf,
+ const guchar *source_buf,
+ const GeglRectangle *dst_rect,
+ const GeglRectangle *src_rect,
+ gint s_rowstride,
+ gdouble scale,
+ const Babl *format,
+ gint d_rowstride)
+{
+ const Babl *comp_type = babl_format_get_type (format, 0);
+ guint num_componenets;
+
+ void (*resample_boxfilter_func) (guchar *dest_buf,
+ const guchar *source_buf,
+ const GeglRectangle *dst_rect,
+ const GeglRectangle *src_rect,
+ gint s_rowstride,
+ gdouble scale,
+ gint components,
+ gint d_rowstride) = NULL;
+
+ if (comp_type == babl_type ("u8"))
+ {
+ resample_boxfilter_func = gegl_resample_boxfilter_u8;
+ }
+ else if (comp_type == babl_type ("u16"))
+ {
+ resample_boxfilter_func = gegl_resample_boxfilter_u16;
+ }
+ else if (comp_type == babl_type ("u32"))
+ {
+ resample_boxfilter_func = gegl_resample_boxfilter_u32;
+ }
+ else if (comp_type == babl_type ("float"))
+ {
+ resample_boxfilter_func = gegl_resample_boxfilter_float;
+ }
+ else
+ {
+ gegl_resample_nearest (dest_buf,
+ source_buf,
+ dst_rect,
+ src_rect,
+ s_rowstride,
+ scale,
+ babl_format_get_bytes_per_pixel (format),
+ d_rowstride);
+ return;
+ }
+
+ num_componenets = babl_format_get_n_components (format);
+
+ resample_boxfilter_func (dest_buf,
+ source_buf,
+ dst_rect,
+ src_rect,
+ s_rowstride,
+ scale,
+ num_componenets,
+ d_rowstride);
+}
+
+void
+gegl_resample_nearest (guchar *dst,
+ const guchar *src,
+ const GeglRectangle *dst_rect,
+ const GeglRectangle *src_rect,
+ const gint src_stride,
+ const gdouble scale,
+ const gint bpp,
+ const gint dst_stride)
+{
+ int i, j;
+
+ for (i = 0; i < dst_rect->height; i++)
+ {
+ const gdouble sy = (dst_rect->y + .5 + i) / scale - src_rect->y;
+ const gint ii = floor (sy + GEGL_SCALE_EPSILON);
+
+ for (j = 0; j < dst_rect->width; j++)
+ {
+ const gdouble sx = (dst_rect->x + .5 + j) / scale - src_rect->x;
+ const gint jj = floor (sx + GEGL_SCALE_EPSILON);
+
+ memcpy (&dst[i * dst_stride + j * bpp],
+ &src[ii * src_stride + jj * bpp],
+ bpp);
+ }
+ }
+}
+
+/*
+#define BOXFILTER_FUNCNAME gegl_resample_boxfilter_double
+#define BOXFILTER_TYPE gdouble
+#define BOXFILTER_ROUND(val) (val)
+#include "gegl-algorithms-boxfilter.inc"
+#undef BOXFILTER_FUNCNAME
+#undef BOXFILTER_TYPE
+#undef BOXFILTER_ROUND
+*/
+
+#define BOXFILTER_FUNCNAME gegl_resample_boxfilter_float
+#define BOXFILTER_TYPE gfloat
+#define BOXFILTER_ROUND(val) (val)
+#include "gegl-algorithms-boxfilter.inc"
+#undef BOXFILTER_FUNCNAME
+#undef BOXFILTER_TYPE
+#undef BOXFILTER_ROUND
+
+#define BOXFILTER_FUNCNAME gegl_resample_boxfilter_u8
+#define BOXFILTER_TYPE guchar
+#define BOXFILTER_ROUND(val) (lrint(val))
+#include "gegl-algorithms-boxfilter.inc"
+#undef BOXFILTER_FUNCNAME
+#undef BOXFILTER_TYPE
+#undef BOXFILTER_ROUND
+
+#define BOXFILTER_FUNCNAME gegl_resample_boxfilter_u16
+#define BOXFILTER_TYPE guint16
+#define BOXFILTER_ROUND(val) (lrint(val))
+#include "gegl-algorithms-boxfilter.inc"
+#undef BOXFILTER_FUNCNAME
+#undef BOXFILTER_TYPE
+#undef BOXFILTER_ROUND
+
+#define BOXFILTER_FUNCNAME gegl_resample_boxfilter_u32
+#define BOXFILTER_TYPE guint32
+#define BOXFILTER_ROUND(val) (lrint(val))
+#include "gegl-algorithms-boxfilter.inc"
+#undef BOXFILTER_FUNCNAME
+#undef BOXFILTER_TYPE
+#undef BOXFILTER_ROUND
\ No newline at end of file
diff --git a/gegl/gegl-algorithms.h b/gegl/gegl-algorithms.h
new file mode 100644
index 0000000..8008f28
--- /dev/null
+++ b/gegl/gegl-algorithms.h
@@ -0,0 +1,101 @@
+/* This file is part of GEGL.
+ *
+ * This library 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.
+ *
+ * This library 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 this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * 2013 Daniel Sabo
+ */
+
+
+#ifndef __GEGL_ALGORITHMS_H__
+#define __GEGL_ALGORITHMS_H__
+
+G_BEGIN_DECLS
+
+#define GEGL_SCALE_EPSILON 1.e-6
+
+/*
+typedef void (GeglBoxfilterFunction *) (guchar *dest_buf,
+ const guchar *source_buf,
+ const GeglRectangle *dst_rect,
+ const GeglRectangle *src_rect,
+ gint s_rowstride,
+ gdouble scale,
+ gint components,
+ gint d_rowstride);
+
+GeglBoxfilterFunction *
+gegl_resample_get_boxfilter_function (const Babl *format);
+*/
+
+/* Attempt to resable with a 3x3 boxfilter, if no boxfilter is
+ * available for #format fall back to nearest neighbor.
+ * #scale is assumed to be between 0.5 and +inf.
+ */
+void gegl_resample_boxfilter (guchar *dest_buf,
+ const guchar *source_buf,
+ const GeglRectangle *dst_rect,
+ const GeglRectangle *src_rect,
+ gint s_rowstride,
+ gdouble scale,
+ const Babl *format,
+ gint d_rowstride);
+
+void gegl_resample_boxfilter_float (guchar *dest_buf,
+ const guchar *source_buf,
+ const GeglRectangle *dst_rect,
+ const GeglRectangle *src_rect,
+ gint s_rowstride,
+ gdouble scale,
+ gint components,
+ gint d_rowstride);
+
+void gegl_resample_boxfilter_u32 (guchar *dest_buf,
+ const guchar *source_buf,
+ const GeglRectangle *dst_rect,
+ const GeglRectangle *src_rect,
+ gint s_rowstride,
+ gdouble scale,
+ gint components,
+ gint d_rowstride);
+
+void gegl_resample_boxfilter_u16 (guchar *dest_buf,
+ const guchar *source_buf,
+ const GeglRectangle *dst_rect,
+ const GeglRectangle *src_rect,
+ gint s_rowstride,
+ gdouble scale,
+ gint components,
+ gint d_rowstride);
+
+void gegl_resample_boxfilter_u8 (guchar *dest_buf,
+ const guchar *source_buf,
+ const GeglRectangle *dst_rect,
+ const GeglRectangle *src_rect,
+ gint s_rowstride,
+ gdouble scale,
+ gint components,
+ gint d_rowstride);
+
+void gegl_resample_nearest (guchar *dst,
+ const guchar *src,
+ const GeglRectangle *dst_rect,
+ const GeglRectangle *src_rect,
+ gint src_stride,
+ gdouble scale,
+ gint bpp,
+ gint dst_stride);
+
+G_END_DECLS
+
+#endif /* __GEGL_ALGORITHMS_H__ */
\ No newline at end of file
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]