From b949577b1a210f9822c39afcbe914e9d5c5bec05 Mon Sep 17 00:00:00 2001 From: Cyril Hrubis Date: Sun, 1 Jul 2012 18:22:55 +0200 Subject: [PATCH] filters: Move gaussian blur into separate file. --- include/filters/{GP_Filters.h => GP_Blur.h} | 69 +++++++------- include/filters/GP_Filters.h | 3 + libs/filters/GP_Blur.c | 143 ++++++++++++++++++++++++++++ libs/filters/GP_Linear.c | 116 ---------------------- 4 files changed, 180 insertions(+), 151 deletions(-) copy include/filters/{GP_Filters.h => GP_Blur.h} (57%) create mode 100644 libs/filters/GP_Blur.c diff --git a/include/filters/GP_Filters.h b/include/filters/GP_Blur.h similarity index 57% copy from include/filters/GP_Filters.h copy to include/filters/GP_Blur.h index 3b0a95f5..22694bc1 100644 --- a/include/filters/GP_Filters.h +++ b/include/filters/GP_Blur.h @@ -16,50 +16,49 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos * - * * - * * - * Copyright (C) 2009-2011 Cyril Hrubis * + * Copyright (C) 2009-2012 Cyril Hrubis * * * *****************************************************************************/ /* - GP_Context filters. + Gaussian blur implementation. */ -#ifndef GP_FILTERS_H -#define GP_FILTERS_H - -/* Filter per channel parameter passing interface */ -#include "filters/GP_FilterParam.h" - -/* Point filters, brightness, contrast ... */ -#include "filters/GP_Point.h" - -/* Addition, difference, min, max ... */ -#include "filters/GP_Arithmetic.h" - -/* Histograms, ... */ -#include "filters/GP_Stats.h" - -/* Image rotations (90 180 270 grads) and mirroring */ -#include "filters/GP_Rotate.h" +#ifndef FILTERS_GP_BLUR_H +#define FILTERS_GP_BLUR_H -/* Linear convolution Raw API */ -#include "filters/GP_Linear.h" +#include "GP_Filter.h" -/* Convolution filters */ -#include "filters/GP_Convolution.h" - -/* Image scaling (resampling) */ -#include "filters/GP_Resize.h" - -/* Bitmap dithering */ -#include "filters/GP_Dither.h" +/* + * Gaussian blur + * + * The sigma parameters defines the blur radii in horizontal and vertical + * direction. + * + * Internaly this is implemented as separable linear filter (calls vertical and + * horizontal convolution with generated gaussian kernel). + * + * This variant could work in-place so it's perectly okay to call + * + * GP_FilterGaussianBlur_Raw(context, context, ...); + */ +int GP_FilterGaussianBlur_Raw(const GP_Context *src, GP_Context *dst, + float sigma_x, float sigma_y, + GP_ProgressCallback *callback); -/* Laplace based filters */ -#include "filters/GP_Laplace.h" +/* + * Gaussian blur. + * + * If dst is NULL, new bitmap is allocated. + * + * This variant could work in-place. + * + * Returns pointer to destination bitmap or NULL if allocation failed. + */ +GP_Context *GP_FilterGaussianBlur(const GP_Context *src, GP_Context *dst, + float sigma_x, float sigma_y, + GP_ProgressCallback *callback); -#endif /* GP_FILTERS_H */ +#endif /* FILTERS_GP_BLUR_H */ diff --git a/include/filters/GP_Filters.h b/include/filters/GP_Filters.h index 3b0a95f5..1bcc6f8a 100644 --- a/include/filters/GP_Filters.h +++ b/include/filters/GP_Filters.h @@ -53,6 +53,9 @@ /* Convolution filters */ #include "filters/GP_Convolution.h" +/* Blur filters */ +#include "filters/GP_Blur.h" + /* Image scaling (resampling) */ #include "filters/GP_Resize.h" diff --git a/libs/filters/GP_Blur.c b/libs/filters/GP_Blur.c new file mode 100644 index 00000000..22b99fd8 --- /dev/null +++ b/libs/filters/GP_Blur.c @@ -0,0 +1,143 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim 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 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim 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 gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2012 Cyril Hrubis * + * * + *****************************************************************************/ + +#include + +#include "core/GP_Debug.h" + +#include "GP_Linear.h" + +#include "GP_Blur.h" + +static inline unsigned int gaussian_kernel_size(float sigma) +{ + int center = 3 * sigma; + + return 2 * center + 1; +} + +static inline float gaussian_kernel_init(float sigma, float *kernel) +{ + int i, center = 3 * sigma; + int N = 2 * center + 1; + float ret = 0; + + double sigma2 = sigma * sigma; + + for (i = 0; i < N; i++) { + double r = center - i; + kernel[i] = exp(-0.5 * (r * r) / sigma2); + ret += kernel[i]; + } + + return ret; +} + +static int gaussian_callback_horiz(GP_ProgressCallback *self) +{ + GP_ProgressCallback *callback = self->priv; + + callback->percentage = self->percentage / 2; + return callback->callback(callback); +} + +static int gaussian_callback_vert(GP_ProgressCallback *self) +{ + GP_ProgressCallback *callback = self->priv; + + callback->percentage = self->percentage / 2 + 50; + return callback->callback(callback); +} + +int GP_FilterGaussianBlur_Raw(const GP_Context *src, GP_Context *dst, + float sigma_x, float sigma_y, + GP_ProgressCallback *callback) +{ + unsigned int size_x = gaussian_kernel_size(sigma_x); + unsigned int size_y = gaussian_kernel_size(sigma_y); + + GP_DEBUG(1, "Gaussian blur sigma_x=%2.3f sigma_y=%2.3f kernel %ix%i image %ux%u", + sigma_x, sigma_y, size_x, size_y, src->w, src->h); + + GP_ProgressCallback *new_callback = NULL; + + GP_ProgressCallback gaussian_callback = { + .callback = gaussian_callback_horiz, + .priv = callback + }; + + if (callback != NULL) + new_callback = &gaussian_callback; + + /* compute kernel and apply in horizontal direction */ + if (sigma_x > 0) { + float kernel_x[size_x]; + float sum = gaussian_kernel_init(sigma_x, kernel_x); + + if (GP_FilterHLinearConvolution_Raw(src, 0, 0, src->w, src->h, + dst, 0, 0, kernel_x, size_x, + sum, new_callback)) + return 1; + } + + if (new_callback != NULL) + new_callback->callback = gaussian_callback_vert; + + /* compute kernel and apply in vertical direction */ + if (sigma_y > 0) { + float kernel_y[size_y]; + float sum = gaussian_kernel_init(sigma_y, kernel_y); + + if (GP_FilterVLinearConvolution_Raw(dst, 0, 0, src->w, src->h, + dst, 0, 0, kernel_y, size_y, + sum, new_callback)) + return 1; + } + + GP_ProgressCallbackDone(callback); + return 0; +} + +GP_Context *GP_FilterGaussianBlur(const GP_Context *src, GP_Context *dst, + float sigma_x, float sigma_y, + GP_ProgressCallback *callback) +{ + /* TODO: templatetize */ + if (src->pixel_type != GP_PIXEL_RGB888) + return NULL; + + if (dst == NULL) { + dst = GP_ContextCopy(src, 0); + + if (dst == NULL) + return NULL; + } else { + GP_ASSERT(src->pixel_type == dst->pixel_type, + "The src and dst pixel types must match"); + GP_ASSERT(src->w <= dst->w && src->h <= dst->h, + "Destination is not big enough"); + } + + GP_FilterGaussianBlur_Raw(src, dst, sigma_x, sigma_y, callback); + + return dst; +} diff --git a/libs/filters/GP_Linear.c b/libs/filters/GP_Linear.c index 54ec6c9a..27575a67 100644 --- a/libs/filters/GP_Linear.c +++ b/libs/filters/GP_Linear.c @@ -20,8 +20,6 @@ * * *****************************************************************************/ -#include - #include "core/GP_Context.h" #include "core/GP_GetPutPixel.h" @@ -29,120 +27,6 @@ #include "GP_Linear.h" -static inline unsigned int gaussian_kernel_size(float sigma) -{ - int center = 3 * sigma; - - return 2 * center + 1; -} - -static inline float gaussian_kernel_init(float sigma, float *kernel) -{ - int i, center = 3 * sigma; - int N = 2 * center + 1; - float ret = 0; - - double sigma2 = sigma * sigma; - - for (i = 0; i < N; i++) { - double r = center - i; - kernel[i] = exp(-0.5 * (r * r) / sigma2); - ret += kernel[i]; - } - - return ret; -} - -static int gaussian_callback_horiz(GP_ProgressCallback *self) -{ - GP_ProgressCallback *callback = self->priv; - - callback->percentage = self->percentage / 2; - return callback->callback(callback); -} - -static int gaussian_callback_vert(GP_ProgressCallback *self) -{ - GP_ProgressCallback *callback = self->priv; - - callback->percentage = self->percentage / 2 + 50; - return callback->callback(callback); -} - -int GP_FilterGaussianBlur_Raw(const GP_Context *src, GP_Context *dst, - float sigma_x, float sigma_y, - GP_ProgressCallback *callback) -{ - unsigned int size_x = gaussian_kernel_size(sigma_x); - unsigned int size_y = gaussian_kernel_size(sigma_y); - - GP_DEBUG(1, "Gaussian blur sigma_x=%2.3f sigma_y=%2.3f kernel %ix%i image %ux%u", - sigma_x, sigma_y, size_x, size_y, src->w, src->h); - - GP_ProgressCallback *new_callback = NULL; - - GP_ProgressCallback gaussian_callback = { - .callback = gaussian_callback_horiz, - .priv = callback - }; - - if (callback != NULL) - new_callback = &gaussian_callback; - - /* compute kernel and apply in horizontal direction */ - if (sigma_x > 0) { - float kernel_x[size_x]; - float sum = gaussian_kernel_init(sigma_x, kernel_x); - - if (GP_FilterHLinearConvolution_Raw(src, 0, 0, src->w, src->h, - dst, 0, 0, kernel_x, size_x, - sum, new_callback)) - return 1; - } - - if (new_callback != NULL) - new_callback->callback = gaussian_callback_vert; - - /* compute kernel and apply in vertical direction */ - if (sigma_y > 0) { - float kernel_y[size_y]; - float sum = gaussian_kernel_init(sigma_y, kernel_y); - - if (GP_FilterVLinearConvolution_Raw(dst, 0, 0, src->w, src->h, - dst, 0, 0, kernel_y, size_y, - sum, new_callback)) - return 1; - } - - GP_ProgressCallbackDone(callback); - return 0; -} - -GP_Context *GP_FilterGaussianBlur(const GP_Context *src, GP_Context *dst, - float sigma_x, float sigma_y, - GP_ProgressCallback *callback) -{ - /* TODO: templatetize */ - if (src->pixel_type != GP_PIXEL_RGB888) - return NULL; - - if (dst == NULL) { - dst = GP_ContextCopy(src, 0); - - if (dst == NULL) - return NULL; - } else { - GP_ASSERT(src->pixel_type == dst->pixel_type, - "The src and dst pixel types must match"); - GP_ASSERT(src->w <= dst->w && src->h <= dst->h, - "Destination is not big enough"); - } - - GP_FilterGaussianBlur_Raw(src, dst, sigma_x, sigma_y, callback); - - return dst; -} - #define MUL 1024 #define CLAMP(val) do { \ -- 2.11.4.GIT