[gtk+/wip/blur: 2/7] Add code for blurring (original code from Unico, copyright fine for Gtk+)
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/blur: 2/7] Add code for blurring (original code from Unico, copyright fine for Gtk+)
- Date: Tue, 17 Apr 2012 20:22:30 +0000 (UTC)
commit 285474332294653cc685de9c131fd244811ac70b
Author: Andrea Cimitan <andrea cimitan canonical com>
Date: Fri Apr 13 11:59:26 2012 +0200
Add code for blurring (original code from Unico, copyright fine for Gtk+)
gtk/Makefile.am | 2 +
gtk/gtkcairoblur.c | 267 ++++++++++++++++++++++++++++++++++++++++++++++++++++
gtk/gtkcairoblur.h | 37 +++++++
3 files changed, 306 insertions(+), 0 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index e31feb2..798a76a 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -415,6 +415,7 @@ gtk_private_h_sources = \
gtkboxprivate.h \
gtkbuilderprivate.h \
gtkbuttonprivate.h \
+ gtkcairoblurprivate.h \
gtkcellareaboxcontextprivate.h \
gtkcolorswatchprivate.h \
gtkcoloreditorprivate.h \
@@ -607,6 +608,7 @@ gtk_base_c_sources = \
gtkbuilderparser.c \
gtkbuilder-menus.c \
gtkbutton.c \
+ gtkcairoblur.c \
gtkcalendar.c \
gtkcellarea.c \
gtkcellareabox.c \
diff --git a/gtk/gtkcairoblur.c b/gtk/gtkcairoblur.c
new file mode 100644
index 0000000..ce90175
--- /dev/null
+++ b/gtk/gtkcairoblur.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2012 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 Andrea Cimitan <andrea cimitan canonical com>
+ * Original code from Mirco Mueller <mirco mueller canonical com>
+ *
+ */
+
+#include "gtkcairoblur.h"
+
+#include <math.h>
+
+/*
+ * Notes:
+ * based on exponential-blur algorithm by Jani Huhtanen
+ */
+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);
+}
+
+/*
+ * _expblur:
+ * @pixels: image data
+ * @width: image width
+ * @height: image height
+ * @channels: image channels
+ * @radius: kernel radius
+ * @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
+ *
+ * Performs an in-place blur of image data 'pixels'
+ * with kernel of approximate radius 'radius'.
+ *
+ * Blurs with two sided exponential impulse response.
+ *
+ */
+static 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);
+}
+
+
+/*
+ * _gtk_cairo_blur_surface:
+ * @surface: a cairo image surface.
+ * @radius: the blur radius.
+ *
+ * Blurs the cairo image surface at the given radius.
+ *
+ */
+void
+_gtk_cairo_blur_surface (cairo_surface_t* surface,
+ guint radius)
+{
+ cairo_format_t format;
+ guchar* pixels;
+ guint width;
+ guint height;
+
+ g_return_if_fail (surface != NULL);
+ g_return_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE);
+
+ format = cairo_image_surface_get_format (surface);
+ g_return_if_fail (format == CAIRO_FORMAT_A8 ||
+ format == CAIRO_FORMAT_RGB24 ||
+ format == CAIRO_FORMAT_ARGB32);
+
+ if (radius == 0)
+ return;
+
+ /* 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);
+}
diff --git a/gtk/gtkcairoblur.h b/gtk/gtkcairoblur.h
new file mode 100644
index 0000000..0b93bb5
--- /dev/null
+++ b/gtk/gtkcairoblur.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 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 Andrea Cimitan <andrea cimitan canonical com>
+ * Original code from Mirco Mueller <mirco mueller canonical com>
+ *
+ */
+
+#ifndef _GTK_CAIRO_BLUR_H
+#define _GTK_CAIRO_BLUR_H
+
+#include <glib.h>
+#include <cairo.h>
+
+G_BEGIN_DECLS
+
+void _gtk_cairo_blur_surface (cairo_surface_t* surface,
+ guint radius);
+
+G_END_DECLS
+
+#endif /* _GTK_CAIRO_BLUR_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]