Mathias Hasselmann

Blur Effect with cairo

Wondered how to apply convolution filters, like for instance gaussian blur in cairo. Doesn't seem to be possible yet. Well, unless you remember that cairo uses pixman as backend for its image surface. Result of my hacks below:

Blur Effect with cairo

The code is in the blur_image_surface() function of blur-effect.c. Now the question is how to make a nice cairo API for this code, and how to hardware accelerate this. At least XRender seems to define API for convolution filters.

Update: Get full code via git clone http://taschenorakel.de/git/playground

Comments

ciccio commented on November 24, 2008 at 2:39 p.m.

Hi Mathias, i had tried to compile it, but when i run an error is occurred.

(blur-effect:8711): GdkPixbuf-CRITICAL **: gdk_pixbuf_get_height: assertion `GDK_IS_PIXBUF (pixbuf)' failed

(blur-effect:8711): GdkPixbuf-CRITICAL **: gdk_pixbuf_get_height: assertion `GDK_IS_PIXBUF (pixbuf)' failed

(blur-effect:8711): GdkPixbuf-CRITICAL **: gdk_pixbuf_get_height: assertion `GDK_IS_PIXBUF (pixbuf)' failed

(blur-effect:8711): GdkPixbuf-CRITICAL **: gdk_pixbuf_get_width: assertion `GDK_IS_PIXBUF (pixbuf)' failed

(blur-effect:8711): GdkPixbuf-CRITICAL **: gdk_pixbuf_get_width: assertion `GDK_IS_PIXBUF (pixbuf)' failed

(blur-effect:8711): GdkPixbuf-CRITICAL **: gdk_pixbuf_get_width: assertion `GDK_IS_PIXBUF (pixbuf)' failed

(blur-effect:8711): GdkPixbuf-CRITICAL **: gdk_pixbuf_get_height: assertion `GDK_IS_PIXBUF (pixbuf)' failed

(blur-effect:8711): GdkPixbuf-CRITICAL **: gdk_pixbuf_get_width: assertion `GDK_IS_PIXBUF (pixbuf)' failed

(blur-effect:8711): GdkPixbuf-CRITICAL **: gdk_pixbuf_get_height: assertion `GDK_IS_PIXBUF (pixbuf)' failed

(blur-effect:8711): GdkPixbuf-CRITICAL **: gdk_pixbuf_get_pixels: assertion `GDK_IS_PIXBUF (pixbuf)' failed

(blur-effect:8711): GdkPixbuf-CRITICAL **: gdk_pixbuf_get_rowstride: assertion `GDK_IS_PIXBUF (pixbuf)' failed

(blur-effect:8711): GdkPixbuf-CRITICAL **: gdk_pixbuf_get_n_channels: assertion `GDK_IS_PIXBUF (pixbuf)' failed

why????

I'm sorry but i'm a newbie!!!! :D
Thanks...

TualatriX commented on November 24, 2008 at 2:49 p.m.

I've compiled and everything is OK.

Thanks of your great code!

@ciccio
Have you put the two images to the folder?

Mathias Hasselmann commented on November 24, 2008 at 3:14 p.m.

@ciccio: Like TualatriX said: You probably forgot the two images. The code has just demo quality, added some simple error handling.

@TualatriX: Thanks, added some few comments for convenience.

MacSlow commented on November 24, 2008 at 3:33 p.m.

Hey Mathias!

While XRender does allow you to do gaussian-blurs (among other convolution-based filtering), it's dead slow. Mainly because it's not hw-accelerated yet. Will it ever be? For example: updates of one "frame" make my GeForce 8800 almost come to a halt. See http://macslow.thepimp.net/?p=85 for my example XRender-based blur-toy.

I've also written some generic gaussian-blur code that operates on cairo-image surfaces and does not interface with pixman. Just giving your pixman-based example a spin for comparison. I'll get back to you later.

Best regards ...

MacSlow

ciccio commented on November 24, 2008 at 3:40 p.m.

thanks Mathias great job!!!
Now works fine ;)

...i don't why the file changed it's names :D

vito commented on November 24, 2008 at 7:04 p.m.

what is the name of that theme?

Martin Olsson commented on November 24, 2008 at 9:15 p.m.

Really nice code! Example comes buggy when you resize the window to be really big though (not maximize just resize it to like 1500x1000 or so).

Mathias Hasselmann commented on November 24, 2008 at 9:29 p.m.

@Martin: Thanks for reporting that issue. Bug fixed.

Lukeci commented on December 16, 2008 at 4:30 a.m.

Hi ,Mathias,

I got an error there.

CRITICAL **: blur_image_surface: assertion `cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_IMAGE' failed

g_return_val_if_fail
(cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_IMAGE,
NULL);

Is there something wrong?
Using "==" instead of "!=" is working fine for me.
Thanks.

Dov Grobgeld commented on March 12, 2009 at 7:41 a.m.

Since gaussian blur is independent for x and y you can carry out the blurring as two 1D convolutions instead of one 2D convolution, which should be much faster. The larger the kernel is, the faster the speed up.

Steve Hanov commented on March 14, 2009 at 5:39 a.m.

You only need a box blur for this. Gaussian is overkill.