This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project gfxprim.git.
The branch, generate has been updated via 96956ac4fbd2c35d57c122ecd44a88c352153a5e (commit) from 8de6ee02d1d25d761c590a1bdaeb142fd04191e3 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- http://repo.or.cz/w/gfxprim.git/commit/96956ac4fbd2c35d57c122ecd44a88c352153...
commit 96956ac4fbd2c35d57c122ecd44a88c352153a5e Author: Cyril Hrubis metan@ucw.cz Date: Sat Oct 1 13:58:00 2011 +0200
Implemented linear convolution and gaussian blur.
diff --git a/demos/grinder/grinder.c b/demos/grinder/grinder.c index 803570d..82e7228 100644 --- a/demos/grinder/grinder.c +++ b/demos/grinder/grinder.c @@ -292,17 +292,25 @@ static GP_RetCode invert(GP_Context **c, const char *params) }
static struct param blur_params[] = { + {"sigma", PARAM_FLOAT, "sigma parameter (eg. radii of blur)", NULL, NULL}, {NULL, 0, NULL, NULL, NULL} };
static GP_RetCode blur(GP_Context **c, const char *params) { - if (param_parse(params, blur_params, "blur", param_err)) + float sigma = 0; + + if (param_parse(params, blur_params, "blur", param_err, &sigma)) return GP_EINVAL;
+ if (sigma <= 0) { + print_error("blur: sigma parameter must be >= 0"); + return GP_EINVAL; + } + GP_Context *res = NULL;
- res = GP_FilterBlur(*c); + res = GP_FilterGaussianBlur(*c, sigma);
if (res == NULL) return GP_EINVAL; diff --git a/include/filters/GP_Linear.h b/include/filters/GP_Linear.h index 2ef5a0e..98e53f0 100644 --- a/include/filters/GP_Linear.h +++ b/include/filters/GP_Linear.h @@ -31,6 +31,6 @@
#include <GP_Context.h>
-GP_Context *GP_FilterBlur(GP_Context *src); +GP_Context *GP_FilterGaussianBlur(GP_Context *src, float sigma);
#endif /* GP_LINEAR_H */ diff --git a/libs/filters/GP_Linear.c b/libs/filters/GP_Linear.c index 66c0db6..bf41660 100644 --- a/libs/filters/GP_Linear.c +++ b/libs/filters/GP_Linear.c @@ -20,6 +20,8 @@ * * *****************************************************************************/
+#include <math.h> + #include <GP_Context.h> #include <GP_GetPutPixel.h>
@@ -27,13 +29,13 @@
#include <GP_Linear.h>
-static float HX[] = {0.17, 0.66, 0.17}; -static float HY[] = {0.17, 0.66, 0.17}; +static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *dst, + float kernel[], uint32_t kw, uint32_t kh);
-GP_Context *GP_FilterBlur(GP_Context *src) +GP_Context *GP_FilterGaussianBlur(GP_Context *src, float sigma) { GP_Context *dst; - + if (src->pixel_type != GP_PIXEL_RGB888) return NULL;
@@ -42,89 +44,113 @@ GP_Context *GP_FilterBlur(GP_Context *src) if (dst == NULL) return NULL;
- GP_DEBUG(1, "Linear blur filter (3x3 kernel) %ux%u", src->w, src->h);
- GP_Coord x, y; + /* compute kernel */ + int i, center = 3 * sigma; + int N = 2 * center + 1; + float kernel[N];
- for (y = 0; y < (GP_Coord)dst->h; y++) { - GP_Pixel pix; - uint32_t R1, R2, R3; - uint32_t G1, G2, G3; - uint32_t B1, B2, B3; - - pix = GP_GetPixel_Raw_24BPP(src, 0, y); - - R1 = GP_Pixel_GET_R_RGB888(pix); - G1 = GP_Pixel_GET_G_RGB888(pix); - B1 = GP_Pixel_GET_B_RGB888(pix); - - R2 = R1; - G2 = G1; - B2 = B1; + double sigma2 = sigma * sigma;
- for (x = 0; x < (GP_Coord)dst->w; x++) { - float r, g, b; + for (i = 0; i < N; i++) { + double r = center - i; + + kernel[i] = exp(-0.5 * (r * r) / sigma2); + }
- pix = GP_GetPixel_Raw_24BPP(src, x, y); - - R3 = GP_Pixel_GET_R_RGB888(pix); - G3 = GP_Pixel_GET_G_RGB888(pix); - B3 = GP_Pixel_GET_B_RGB888(pix); + GP_DEBUG(1, "Gaussian blur sigma=%2.3f kernel %ix%i image %ux%u", + sigma, N, N, src->w, src->h);
- r = R1 * HX[0] + R2 * HX[1] + R3 * HX[2]; - g = G1 * HX[0] + G2 * HX[1] + G3 * HX[2]; - b = B1 * HX[0] + B2 * HX[1] + B3 * HX[2]; + /* apply in both directions */ + GP_FilterLinearConvolution(src, dst, kernel, N, 1); + GP_FilterLinearConvolution(dst, dst, kernel, 1, N);
- if (r > 255) - r = 255; - if (g > 255) - g = 255; - if (b > 255) - b = 255; + return dst; +}
- pix = GP_Pixel_CREATE_RGB888((uint32_t)r, (uint32_t)g, (uint32_t)b); +static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *dst, + float kernel[], uint32_t kw, uint32_t kh) +{ + float kernel_sum = 0; + GP_Coord x, y; + uint32_t i, j;
- GP_PutPixel_Raw_24BPP(dst, x, y, pix); - - R1 = R2; - G1 = G2; - B1 = B2; - - R2 = R3; - G2 = G3; - B2 = B3; - } - } - - for (x = 0; x < (GP_Coord)dst->w; x++) { - GP_Pixel pix; - uint32_t R1, R2, R3; - uint32_t G1, G2, G3; - uint32_t B1, B2, B3; - - pix = GP_GetPixel_Raw_24BPP(src, x, 0); + GP_DEBUG(1, "Linear convolution kernel %ix%i image %ux%u", + kw, kh, src->w, src->h);
- R1 = GP_Pixel_GET_R_RGB888(pix); - G1 = GP_Pixel_GET_G_RGB888(pix); - B1 = GP_Pixel_GET_B_RGB888(pix); - - R2 = R1; - G2 = G1; - B2 = B1; + /* count kernel sum for normalization */ + for (i = 0; i < kw * kh; i++) + kernel_sum += kernel[i];
- for (y = 0; y < (GP_Coord)dst->h; y++) { - float r, g, b; + /* do linear convolution */ + for (y = 0; y < (GP_Coord)dst->h; y++) { + GP_Pixel pix; + uint32_t R[kw][kh], G[kw][kh], B[kw][kh]; + + /* prefill the buffer on the start */ + for (j = 0; j < kh; j++) { + for (i = 0; i < kw - 1; i++) { + int cx = i - kw/2; + int cy = y + j - kh/2; + + if (cx < 0) + cx = 0; + + if (cy < 0) + cy = 0; + + if (cy >= (int)src->h) + cy = src->h - 1; + + pix = GP_GetPixel_Raw_24BPP(src, cx, cy); + + R[i][j] = GP_Pixel_GET_R_RGB888(pix); + G[i][j] = GP_Pixel_GET_G_RGB888(pix); + B[i][j] = GP_Pixel_GET_B_RGB888(pix); + } + }
- pix = GP_GetPixel_Raw_24BPP(src, x, y); - - R3 = GP_Pixel_GET_R_RGB888(pix); - G3 = GP_Pixel_GET_G_RGB888(pix); - B3 = GP_Pixel_GET_B_RGB888(pix); + int idx = kw - 1;
- r = R1 * HY[0] + R2 * HY[1] + R3 * HY[2]; - g = G1 * HY[0] + G2 * HY[1] + G3 * HY[2]; - b = B1 * HY[0] + B2 * HY[1] + B3 * HY[2]; + for (x = 0; x < (GP_Coord)dst->w; x++) { + float r = 0, g = 0, b = 0; + + for (j = 0; j < kh; j++) { + int cy = y + j - kh/2; + + if (cy < 0) + cy = 0; + + if (cy >= (int)src->h) + cy = src->h - 1; + + pix = GP_GetPixel_Raw_24BPP(src, x, cy); + + R[idx][j] = GP_Pixel_GET_R_RGB888(pix); + G[idx][j] = GP_Pixel_GET_G_RGB888(pix); + B[idx][j] = GP_Pixel_GET_B_RGB888(pix); + } + /* count the pixel value from neighbours weighted by kernel */ + for (i = 0; i < kw; i++) { + int k = i - idx; + + if (k < 0) + k += kw; + + for (j = 0; j < kh; j++) { + r += R[i][j] * kernel[k + j * kw]; + g += G[i][j] * kernel[k + j * kw]; + b += B[i][j] * kernel[k + j * kw]; + } + } + + /* normalize the result */ + r /= kernel_sum; + g /= kernel_sum; + b /= kernel_sum; + + /* and clamp just to be extra sure */ if (r > 255) r = 255; if (g > 255) @@ -136,15 +162,11 @@ GP_Context *GP_FilterBlur(GP_Context *src)
GP_PutPixel_Raw_24BPP(dst, x, y, pix); - R1 = R2; - G1 = G2; - B1 = B2; - - R2 = R3; - G2 = G3; - B2 = B3; + idx++; + + if (idx >= (int)kw) + idx = 0; } } - - return dst; } +
-----------------------------------------------------------------------
Summary of changes: demos/grinder/grinder.c | 12 +++- include/filters/GP_Linear.h | 2 +- libs/filters/GP_Linear.c | 188 ++++++++++++++++++++++++------------------- 3 files changed, 116 insertions(+), 86 deletions(-)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos@gmail.com if you want to unsubscribe, or site admin admin@repo.or.cz if you receive no reply.