diff --git a/examples/edd.c b/examples/edd.c index 648b758..d1e0af7 100644 --- a/examples/edd.c +++ b/examples/edd.c @@ -61,7 +61,7 @@ int main(int argc, char *argv[]) pipi_free(tmp); /* Compute the fast error */ - tmp = pipi_gaussian_blur_ext(dither, sigma, sigma, 0.16, 0.26); + tmp = pipi_gaussian_blur_ext(dither, sigma, sigma, 0.0, 0.16, 0.26); e1 = pipi_measure_msd(gauss, tmp); pipi_free(tmp); @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) for(dy = 0; dy <= Z; dy++) for(dx = 0; dx <= Z; dx++) { - tmp = pipi_gaussian_blur_ext(dither, sigma, sigma, + tmp = pipi_gaussian_blur_ext(dither, sigma, sigma, 0.0, fx + step * dx / Z, fy + step * dy / Z); e = pipi_measure_msd(gauss, tmp); diff --git a/pipi/context.c b/pipi/context.c index 31e3bb5..0cb0ad7 100644 --- a/pipi/context.c +++ b/pipi/context.c @@ -118,7 +118,7 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...) pipi_image_t *src, *dst; char const *arg; va_list ap; - double w, h; + double w, h, a = 0.0; if(ctx->nimages < 1) return -1; @@ -128,9 +128,14 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...) w = h = atof(arg); arg = strchr(arg, 'x'); if(arg) + { h = atof(arg + 1); + arg = strchr(arg, 'r'); + if(arg) + a = atof(arg + 1); + } src = ctx->images[ctx->nimages - 1]; - dst = pipi_gaussian_blur_ext(src, w, h, 0.0, 0.0); + dst = pipi_gaussian_blur_ext(src, w, h, a, 0.0, 0.0); if(dst == NULL) return -1; pipi_free(src); diff --git a/pipi/filter/blur.c b/pipi/filter/blur.c index f01727f..1533cdc 100644 --- a/pipi/filter/blur.c +++ b/pipi/filter/blur.c @@ -34,27 +34,34 @@ pipi_image_t *pipi_gaussian_blur(pipi_image_t *src, float radius) { - return pipi_gaussian_blur_ext(src, radius, radius, 0.0, 0.0); + return pipi_gaussian_blur_ext(src, radius, radius, 0.0, 0.0, 0.0); } pipi_image_t *pipi_gaussian_blur_ext(pipi_image_t *src, float rx, float ry, - float dx, float dy) + float angle, float dx, float dy) { pipi_image_t *ret; double *kernel; - double Kx, Ky, t = 0.0; + double Kx, Ky, t = 0.0, sint, cost, bbx, bby; int i, j, krx, kry, m, n; if(rx < BLUR_EPSILON) rx = BLUR_EPSILON; if(ry < BLUR_EPSILON) ry = BLUR_EPSILON; + sint = sin(angle * M_PI / 180.); + cost = cos(angle * M_PI / 180.); + + /* Compute the final ellipse's bounding box */ + bbx = sqrt(rx * rx * cost * cost + ry * ry * sint * sint); + bby = sqrt(ry * ry * cost * cost + rx * rx * sint * sint); + /* FIXME: the kernel becomes far too big with large values of dx, because * we grow both left and right. Fix the growing direction. */ - krx = (int)(3. * rx + .99999 + ceil(abs(dx))); + krx = (int)(3. * bbx + .99999 + ceil(abs(dx))); m = 2 * krx + 1; Kx = -1. / (2. * rx * rx); - kry = (int)(3. * ry + .99999 + ceil(abs(dy))); + kry = (int)(3. * bby + .99999 + ceil(abs(dy))); n = 2 * kry + 1; Ky = -1. / (2. * ry * ry); @@ -62,11 +69,12 @@ pipi_image_t *pipi_gaussian_blur_ext(pipi_image_t *src, float rx, float ry, for(j = -kry; j <= kry; j++) { - double ey = Ky * ((double)j + dy) * ((double)j + dy); - for(i = -krx; i <= krx; i++) { - double ex = Kx * ((double)i + dx) * ((double)i + dx); + double u = (double)i * cost - (double)j * sint + dx; + double v = (double)j * cost + (double)i * sint + dy; + double ex = Kx * u * u; + double ey = Ky * v * v; double d = exp(ex + ey); kernel[(j + kry) * m + i + krx] = d; diff --git a/pipi/pipi.h b/pipi/pipi.h index 545c08b..b12ba89 100644 --- a/pipi/pipi.h +++ b/pipi/pipi.h @@ -99,7 +99,7 @@ extern pipi_image_t *pipi_overlay(pipi_image_t *, pipi_image_t *); extern pipi_image_t *pipi_convolution(pipi_image_t *, int, int, double[]); extern pipi_image_t *pipi_gaussian_blur(pipi_image_t *, float); extern pipi_image_t *pipi_gaussian_blur_ext(pipi_image_t *, - float, float, float, float); + float, float, float, float, float); extern pipi_image_t *pipi_box_blur(pipi_image_t *, int); extern pipi_image_t *pipi_box_blur_ext(pipi_image_t *, int, int); extern pipi_image_t *pipi_autocontrast(pipi_image_t *);