From 143c156ed8a46947ba6ddb912f2e7f2965f1908c Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Fri, 14 Sep 2012 10:10:15 -0500 Subject: Initial import of renamed Unico engine, ready for hacking! --- tdegtk/exponential-blur.c | 288 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 tdegtk/exponential-blur.c (limited to 'tdegtk/exponential-blur.c') diff --git a/tdegtk/exponential-blur.c b/tdegtk/exponential-blur.c new file mode 100644 index 0000000..95515c5 --- /dev/null +++ b/tdegtk/exponential-blur.c @@ -0,0 +1,288 @@ +/* The TdeGtk Theming Engine for Gtk+. + * Copyright (C) 2009 Canonical Ltd + * + * This library 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 of the License, or (at your option) any later version. + * + * This library 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 this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Authored by Mirco "MacSlow" Mueller + * + * Notes: + * based on exponential-blur algorithm by Jani Huhtanen + * + */ + +/* FIXME: not working yet, unfinished */ + +#include + +#include "exponential-blur.h" + +static inline void +_blurinner (guchar* pixel, + gint *zR, + gint *zG, + gint *zB, + gint *zA, + gint alpha, + gint aprec, + gint zprec); + +static inline void +_blurrow (guchar* pixels, + gint width, + gint height, + gint channels, + gint line, + gint alpha, + gint aprec, + gint zprec); + +static inline void +_blurcol (guchar* pixels, + gint width, + gint height, + gint channels, + gint col, + gint alpha, + gint aprec, + gint zprec); + +void +_expblur (guchar* pixels, + gint width, + gint height, + gint channels, + gint radius, + gint aprec, + gint zprec); + +void +surface_exponential_blur (cairo_surface_t* surface, + guint radius) +{ + guchar* pixels; + guint width; + guint height; + cairo_format_t format; + + /* sanity checks are done in raico-blur.c */ + + /* before we mess with the surface execute any pending drawing */ + cairo_surface_flush (surface); + + pixels = cairo_image_surface_get_data (surface); + width = cairo_image_surface_get_width (surface); + height = cairo_image_surface_get_height (surface); + format = cairo_image_surface_get_format (surface); + + switch (format) + { + case CAIRO_FORMAT_ARGB32: + _expblur (pixels, width, height, 4, radius, 16, 7); + break; + case CAIRO_FORMAT_RGB24: + _expblur (pixels, width, height, 3, radius, 16, 7); + break; + case CAIRO_FORMAT_A8: + _expblur (pixels, width, height, 1, radius, 16, 7); + break; + default: + break; + } + + /* inform cairo we altered the surfaces contents */ + cairo_surface_mark_dirty (surface); +} + +/* + * pixels image-data + * width image-width + * height image-height + * channels image-channels + * + * in-place blur of image 'img' with kernel of approximate radius 'radius' + * + * blurs with two sided exponential impulse response + * + * aprec = precision of alpha parameter in fixed-point format 0.aprec + * + * zprec = precision of state parameters zR,zG,zB and zA in fp format 8.zprec + */ +void +_expblur (guchar* pixels, + gint width, + gint height, + gint channels, + gint radius, + gint aprec, + gint zprec) +{ + gint alpha; + gint row = 0; + gint col = 0; + + if (radius < 1) + return; + + /* calculate the alpha such that 90% of + * the kernel is within the radius. + * (Kernel extends to infinity) */ + alpha = (gint) ((1 << aprec) * (1.0f - expf (-2.3f / (radius + 1.f)))); + + for (; row < height; row++) + _blurrow (pixels, + width, + height, + channels, + row, + alpha, + aprec, + zprec); + + for(; col < width; col++) + _blurcol (pixels, + width, + height, + channels, + col, + alpha, + aprec, + zprec); + + return; +} + +static inline void +_blurinner (guchar* pixel, + gint *zR, + gint *zG, + gint *zB, + gint *zA, + gint alpha, + gint aprec, + gint zprec) +{ + gint R; + gint G; + gint B; + guchar A; + + R = *pixel; + G = *(pixel + 1); + B = *(pixel + 2); + A = *(pixel + 3); + + *zR += (alpha * ((R << zprec) - *zR)) >> aprec; + *zG += (alpha * ((G << zprec) - *zG)) >> aprec; + *zB += (alpha * ((B << zprec) - *zB)) >> aprec; + *zA += (alpha * ((A << zprec) - *zA)) >> aprec; + + *pixel = *zR >> zprec; + *(pixel + 1) = *zG >> zprec; + *(pixel + 2) = *zB >> zprec; + *(pixel + 3) = *zA >> zprec; +} + +static inline void +_blurrow (guchar* pixels, + gint width, + gint height, + gint channels, + gint line, + gint alpha, + gint aprec, + gint zprec) +{ + gint zR; + gint zG; + gint zB; + gint zA; + gint index; + guchar* scanline; + + scanline = &(pixels[line * width * channels]); + + zR = *scanline << zprec; + zG = *(scanline + 1) << zprec; + zB = *(scanline + 2) << zprec; + zA = *(scanline + 3) << zprec; + + for (index = 0; index < width; index ++) + _blurinner (&scanline[index * channels], + &zR, + &zG, + &zB, + &zA, + alpha, + aprec, + zprec); + + for (index = width - 2; index >= 0; index--) + _blurinner (&scanline[index * channels], + &zR, + &zG, + &zB, + &zA, + alpha, + aprec, + zprec); +} + +static inline void +_blurcol (guchar* pixels, + gint width, + gint height, + gint channels, + gint x, + gint alpha, + gint aprec, + gint zprec) +{ + gint zR; + gint zG; + gint zB; + gint zA; + gint index; + guchar* ptr; + + ptr = pixels; + + ptr += x * channels; + + zR = *((guchar*) ptr ) << zprec; + zG = *((guchar*) ptr + 1) << zprec; + zB = *((guchar*) ptr + 2) << zprec; + zA = *((guchar*) ptr + 3) << zprec; + + for (index = width; index < (height - 1) * width; index += width) + _blurinner ((guchar*) &ptr[index * channels], + &zR, + &zG, + &zB, + &zA, + alpha, + aprec, + zprec); + + for (index = (height - 2) * width; index >= 0; index -= width) + _blurinner ((guchar*) &ptr[index * channels], + &zR, + &zG, + &zB, + &zA, + alpha, + aprec, + zprec); +} -- cgit v1.2.3