2 * Copyright (C) 2012 Canonical Ltd
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
19 * Authored by Andrea Cimitan <andrea.cimitan@canonical.com>
20 * Original code from Mirco Mueller <mirco.mueller@canonical.com>
24 #include "gtkcairoblurprivate.h"
30 * based on exponential-blur algorithm by Jani Huhtanen
33 _blurinner (guchar* pixel,
52 *zR += (alpha * ((R << zprec) - *zR)) >> aprec;
53 *zG += (alpha * ((G << zprec) - *zG)) >> aprec;
54 *zB += (alpha * ((B << zprec) - *zB)) >> aprec;
55 *zA += (alpha * ((A << zprec) - *zA)) >> aprec;
57 *pixel = *zR >> zprec;
58 *(pixel + 1) = *zG >> zprec;
59 *(pixel + 2) = *zB >> zprec;
60 *(pixel + 3) = *zA >> zprec;
64 _blurrow (guchar* pixels,
81 scanline = &pixels[line * rowstride];
83 zR = *scanline << zprec;
84 zG = *(scanline + 1) << zprec;
85 zB = *(scanline + 2) << zprec;
86 zA = *(scanline + 3) << zprec;
88 for (index = 0; index < width; index ++)
89 _blurinner (&scanline[index * channels],
98 for (index = width - 2; index >= 0; index--)
99 _blurinner (&scanline[index * channels],
110 _blurcol (guchar* pixels,
131 zR = *((guchar*) ptr ) << zprec;
132 zG = *((guchar*) ptr + 1) << zprec;
133 zB = *((guchar*) ptr + 2) << zprec;
134 zA = *((guchar*) ptr + 3) << zprec;
136 for (index = 0; index < height; index++)
137 _blurinner (&ptr[index * rowstride],
146 for (index = height - 2; index >= 0; index--)
147 _blurinner (&ptr[index * rowstride],
159 * @pixels: image data
160 * @width: image width
161 * @height: image height
162 * @rowstride: image rowstride
163 * @channels: image channels
164 * @radius: kernel radius
165 * @aprec: precision of alpha parameter in fixed-point format 0.aprec
166 * @zprec: precision of state parameters zR,zG,zB and zA in fp format 8.zprec
168 * Performs an in-place blur of image data 'pixels'
169 * with kernel of approximate radius 'radius'.
171 * Blurs with two sided exponential impulse response.
175 _expblur (guchar* pixels,
187 /* Calculate the alpha such that 90% of
188 * the kernel is within the radius.
189 * (Kernel extends to infinity) */
190 alpha = (gint) ((1 << aprec) * (1.0f - expf (-2.3f / (radius + 1.f))));
192 for (row = 0; row < height; row++)
203 for(col = 0; col < width; col++)
217 * _gtk_cairo_blur_surface:
218 * @surface: a cairo image surface.
219 * @radius: the blur radius.
221 * Blurs the cairo image surface at the given radius.
224 _gtk_cairo_blur_surface (cairo_surface_t* surface,
227 cairo_format_t format;
229 g_return_if_fail (surface != NULL);
230 g_return_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE);
232 format = cairo_image_surface_get_format (surface);
233 g_return_if_fail (format == CAIRO_FORMAT_RGB24 ||
234 format == CAIRO_FORMAT_ARGB32);
239 /* Before we mess with the surface execute any pending drawing. */
240 cairo_surface_flush (surface);
242 _expblur (cairo_image_surface_get_data (surface),
243 cairo_image_surface_get_width (surface),
244 cairo_image_surface_get_height (surface),
245 cairo_image_surface_get_stride (surface),
251 /* Inform cairo we altered the surfaces contents. */
252 cairo_surface_mark_dirty (surface);