1
////////////////////////////////////////////////////////////////////////////////
2
//3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
3
// 10 20 30 40 50 60 70 80
7
// gaussian-blur.c - implements gaussian-blur function
9
// Copyright 2009 Canonical Ltd.
12
// Mirco "MacSlow" Mueller <mirco.mueller@canonical.com>
15
// based on filters in libpixman
17
// This program is free software: you can redistribute it and/or modify it
18
// under the terms of the GNU General Public License version 3, as published
19
// by the Free Software Foundation.
21
// This program is distributed in the hope that it will be useful, but
22
// WITHOUT ANY WARRANTY; without even the implied warranties of
23
// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
24
// PURPOSE. See the GNU General Public License for more details.
26
// You should have received a copy of the GNU General Public License along
27
// with this program. If not, see <http://www.gnu.org/licenses/>.
29
////////////////////////////////////////////////////////////////////////////////
34
#include "gaussian-blur.h"
37
create_gaussian_blur_kernel (gint radius,
41
const gdouble scale2 = 2.0f * sigma * sigma;
42
const gdouble scale1 = 1.0f / (G_PI * scale2);
43
const gint size = 2 * radius + 1;
44
const gint n_params = size * size;
45
pixman_fixed_t* params;
52
tmp = g_newa (double, n_params);
54
// caluclate gaussian kernel in floating point format
55
for (i = 0, sum = 0, x = -radius; x <= radius; ++x) {
56
for (y = -radius; y <= radius; ++y, ++i) {
57
const gdouble u = x * x;
58
const gdouble v = y * y;
60
tmp[i] = scale1 * exp (-(u+v)/scale2);
66
// normalize gaussian kernel and convert to fixed point format
67
params = g_new (pixman_fixed_t, n_params + 2);
69
params[0] = pixman_int_to_fixed (size);
70
params[1] = pixman_int_to_fixed (size);
72
for (i = 0; i < n_params; ++i)
73
params[2 + i] = pixman_double_to_fixed (tmp[i] / sum);
76
*length = n_params + 2;
82
_blur_image_surface (cairo_surface_t* surface,
84
gdouble sigma /* pass 0.0f for auto-calculation */)
86
pixman_fixed_t* params = NULL;
95
radiusf = fabs (radius) + 1.0f;
97
sigma = sqrt (-(radiusf * radiusf) / (2.0f * log (1.0f / 255.0f)));
99
w = cairo_image_surface_get_width (surface);
100
h = cairo_image_surface_get_height (surface);
101
s = cairo_image_surface_get_stride (surface);
103
// create pixman image for cairo image surface
104
p = cairo_image_surface_get_data (surface);
105
src = pixman_image_create_bits (PIXMAN_a8r8g8b8, w, h, p, s);
107
// attach gaussian kernel to pixman image
108
params = create_gaussian_blur_kernel (radius, sigma, &n_params);
109
pixman_image_set_filter (src,
110
PIXMAN_FILTER_CONVOLUTION,
115
// render blured image to new pixman image
116
pixman_image_composite (PIXMAN_OP_SRC,
128
pixman_image_unref (src);
132
surface_gaussian_blur (cairo_surface_t* surface,
135
cairo_format_t format;
137
// sanity checks are done in raico-blur.c
139
// before we mess with the surface execute any pending drawing
140
cairo_surface_flush (surface);
142
format = cairo_image_surface_get_format (surface);
146
case CAIRO_FORMAT_ARGB32:
147
_blur_image_surface (surface, radius, 0.0f);
150
case CAIRO_FORMAT_RGB24:
151
// do nothing, for now
154
case CAIRO_FORMAT_A8:
155
// do nothing, for now
163
// inform cairo we altered the surfaces contents
164
cairo_surface_mark_dirty (surface);