/* * libpipi Proper image processing implementation library * Copyright (c) 2004-2008 Sam Hocevar * All Rights Reserved * * $Id$ * * This library is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://sam.zoy.org/wtfpl/COPYING for more details. */ /* * blur.c: blur functions */ #include "config.h" #include "common.h" #include #include #include #include #include "pipi.h" #include "pipi_internals.h" /* Any standard deviation below this value will be rounded up, in order * to avoid ridiculously low values. exp(-1/(2*0.2*0.2)) is < 10^-5 so * there is little chance that any value below 0.2 will be useful. */ #define BLUR_EPSILON 0.2 pipi_image_t *pipi_gaussian_blur(pipi_image_t *src, float radius) { return pipi_gaussian_blur_ext(src, radius, radius, 0.0, 0.0); } pipi_image_t *pipi_gaussian_blur_ext(pipi_image_t *src, float rx, float ry, float dx, float dy) { pipi_image_t *ret; double *kernel; double Kx, Ky, t = 0.0; int i, j, krx, kry, m, n; if(rx < BLUR_EPSILON) rx = BLUR_EPSILON; if(ry < BLUR_EPSILON) ry = BLUR_EPSILON; /* 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))); m = 2 * krx + 1; Kx = -1. / (2. * rx * rx); kry = (int)(3. * ry + .99999 + ceil(abs(dy))); n = 2 * kry + 1; Ky = -1. / (2. * ry * ry); kernel = malloc(m * n * sizeof(double)); 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 d = exp(ex + ey); kernel[(j + kry) * m + i + krx] = d; t += d; } } for(j = 0; j < n; j++) for(i = 0; i < m; i++) kernel[j * m + i] /= t; ret = pipi_convolution(src, m, n, kernel); free(kernel); return ret; } /* FIXME: box blur would be incredibly faster using an accumulator instead * of a convolution filter... */ pipi_image_t *pipi_box_blur(pipi_image_t *src, int size) { return pipi_box_blur_ext(src, size, size); } pipi_image_t *pipi_box_blur_ext(pipi_image_t *src, int m, int n) { pipi_image_t *ret; double *kernel; int i; kernel = malloc(m * n * sizeof(double)); for(i = 0; i < m * n; i++) kernel[i] = 1. / (m * n); ret = pipi_convolution(src, m, n, kernel); free(kernel); return ret; }