[cairo-commit] [cairo-www] src/cookbook src/cookbook.mdwn

Chris Wilson ickle at freedesktop.org
Thu Jun 18 00:00:01 PDT 2009


 src/cookbook.mdwn   |    1 
 src/cookbook/blur.c |  121 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 122 insertions(+)

New commits:
commit 3c51b7372f93347ca470e69807b0437dd9e76f2f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jun 18 07:59:09 2009 +0100

    [cookbook] Add an example on to blur
    
    This commit is to primarily test linking to C-files.

diff --git a/src/cookbook.mdwn b/src/cookbook.mdwn
index 754e33f..6c874b9 100644
--- a/src/cookbook.mdwn
+++ b/src/cookbook.mdwn
@@ -18,3 +18,4 @@
 * [[How_to:Using_PyCairo_and_Pyrsvg_to_handle_SVG_graphics|pyrsvg]]
 * [[How_to:Do_timeout_animation_(Also_shows_rotation_around_a_point)|animationRotation]]
 * [[How_to:Render_PDF_and_PostScript_files_with_cairo|renderpdf]]
+* [[How_to:Perform a Gaussian blur on an image surface|blur_surface.c]]
diff --git a/src/cookbook/blur.c b/src/cookbook/blur.c
new file mode 100644
index 0000000..622ff86
--- /dev/null
+++ b/src/cookbook/blur.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright © 2008 Kristian Høgsberg
+ * Copyright © 2009 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <math.h>
+#include <stdint.h>
+
+#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
+
+/* Performs a simple 2D Gaussian blur of radius @radius on surface @surface. */
+void
+blur_surface (cairo_surface_t *surface, int radius)
+{
+    cairo_surface_t *tmp;
+    int width, height;
+    int src_stride, dst_stride;
+    int x, y, z, w;
+    uint8_t *src, *dst;
+    uint32_t *s, *d, a, p;
+    int i, j, k;
+    uint8_t kernel[17];
+    const int size = ARRAY_LENGTH (kernel);
+    const int half = size / 2;
+
+    if (cairo_surface_status (surface))
+	return;
+
+    width = cairo_image_surface_get_width (surface);
+    height = cairo_image_surface_get_height (surface);
+
+    tmp = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
+    if (cairo_surface_status (tmp))
+	return;
+
+    src_stride = cairo_image_surface_get_stride (surface);
+    src = cairo_image_surface_get_data (surface);
+
+    dst = cairo_image_surface_get_data (tmp);
+    dst_stride = cairo_image_surface_get_stride (tmp);
+
+    a = 0;
+    for (i = 0; i < size; i++) {
+	double f = i - half;
+	a += kernel[i] = exp (- f * f / 30.0) * 80;
+    }
+
+    /* horizontally blur from surface -> tmp */
+    for (i = 0; i < height; i++) {
+	s = (uint32_t *) (src + i * src_stride);
+	d = (uint32_t *) (dst + i * dst_stride);
+	for (j = 0; j < width; j++) {
+	    if (radius < j && j < width - radius) {
+		d[j] = s[j];
+		continue;
+	    }
+
+	    x = y = z = w = 0;
+	    for (k = 0; k < size; k++) {
+		if (j - half + k < 0 || j - half + k >= width)
+		    continue;
+
+		p = s[j - half + k];
+
+		x += ((p >> 24) & 0xff) * kernel[k];
+		y += ((p >> 16) & 0xff) * kernel[k];
+		z += ((p >>  8) & 0xff) * kernel[k];
+		w += ((p >>  0) & 0xff) * kernel[k];
+	    }
+	    d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a;
+	}
+    }
+
+    /* then vertically blur from tmp -> surface */
+    for (i = 0; i < height; i++) {
+	s = (uint32_t *) (dst + i * dst_stride);
+	d = (uint32_t *) (src + i * src_stride);
+	for (j = 0; j < width; j++) {
+	    if (radius <= i && i < height - radius) {
+		d[j] = s[j];
+		continue;
+	    }
+
+	    x = y = z = w = 0;
+	    for (k = 0; k < size; k++) {
+		if (i - half + k < 0 || i - half + k >= height)
+		    continue;
+
+		s = (uint32_t *) (dst + (i - half + k) * dst_stride);
+		p = s[j];
+
+		x += ((p >> 24) & 0xff) * kernel[k];
+		y += ((p >> 16) & 0xff) * kernel[k];
+		z += ((p >>  8) & 0xff) * kernel[k];
+		w += ((p >>  0) & 0xff) * kernel[k];
+	    }
+	    d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a;
+	}
+    }
+
+    cairo_surface_destroy (tmp);
+    cairo_surface_mark_dirty (surface);
+}


More information about the cairo-commit mailing list