cairo blur image surface
This is used in the back-end for www.websequencediagrams.com.
// to build: // gcc -I/usr/include/cairo -lcairo -o blur blur.c #include#include #include #include "cairo.h" void cairo_image_surface_blur( cairo_surface_t* surface, double radius ) { // Steve Hanov, 2009 // Released into the public domain. // get width, height int width = cairo_image_surface_get_width( surface ); int height = cairo_image_surface_get_height( surface ); unsigned char* dst = (unsigned char*)malloc(width*height*4); unsigned* precalc = (unsigned*)malloc(width*height*sizeof(unsigned)); unsigned char* src = cairo_image_surface_get_data( surface ); double mul=1.f/((radius*2)*(radius*2)); int channel; // The number of times to perform the averaging. According to wikipedia, // three iterations is good enough to pass for a gaussian. const MAX_ITERATIONS = 3; int iteration; memcpy( dst, src, width*height*4 ); for ( iteration = 0; iteration < MAX_ITERATIONS; iteration++ ) { for( channel = 0; channel < 4; channel++ ) { int x,y; // precomputation step. unsigned char* pix = src; unsigned* pre = precalc; pix += channel; for (y=0;y 0) tot+=pre[-1]; if (y>0) tot+=pre[-width]; if (x>0 && y>0) tot-=pre[-width-1]; *pre++=tot; pix += 4; } } // blur step. pix = dst + (int)radius * width * 4 + (int)radius * 4 + channel; for (y=radius;y = width ? width - 1 : x + radius; int b = y + radius >= height ? height - 1 : y + radius; int tot = precalc[r+b*width] + precalc[l+t*width] - precalc[l+b*width] - precalc[r+t*width]; *pix=(unsigned char)(tot*mul); pix += 4; } pix += (int)radius * 2 * 4; } } memcpy( src, dst, width*height*4 ); } free( dst ); free( precalc ); } int main(int argc, char* argv[]) { cairo_surface_t* surface; cairo_t* ctx; cairo_text_extents_t text_extents; cairo_font_extents_t font_extents; double FontSize = 100; double radius = 7; double width, height; if ( argc != 3 ) { printf("Syntax: %s " "n", argv[0]); return -1; } // Get text size. surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, 10, 10 ); ctx = cairo_create( surface ); cairo_set_font_size( ctx, FontSize ); cairo_font_extents( ctx, &font_extents ); cairo_text_extents( ctx, argv[2], &text_extents ); height = font_extents.ascent + font_extents.descent + radius * 2; width = text_extents.x_advance + radius * 2; cairo_destroy( ctx ); cairo_surface_destroy( surface ); // Draw text. surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height ); ctx = cairo_create( surface ); cairo_set_font_size( ctx, FontSize ); cairo_move_to( ctx, 0 + radius, font_extents.ascent + radius ); cairo_show_text( ctx, argv[2] ); cairo_fill( ctx ); cairo_image_surface_blur( surface, 5 ); cairo_move_to( ctx, 0, font_extents.ascent ); cairo_show_text( ctx, argv[2] ); cairo_fill( ctx ); cairo_destroy( ctx ); cairo_surface_write_to_png( surface, argv[1] ); cairo_surface_destroy( surface ); return 0; }
please somebody, can explain the meaning of each line in this code...
I just only a little bit get the meaning of this code.. made compilation.. it work fantastic... BUT where in this code exactly place of put and get the pixels (alpha and color) from the surface?
Do anyone have any documentation to Cairo.. Please help.
2009-03-15 00:54:21
"Tor
2009-03-14 20:45:53
Why not just release it under the same copyright as cairo itself?
Crutcher
2009-03-14 22:11:13
Why not send them a patch?"
It's public domain, you can do it.
2009-03-14 20:45:53
Why not just release it under the same copyright as cairo itself?
Crutcher
2009-03-14 22:11:13
Why not send them a patch?"
It's public domain, you can do it.
Lastly, if you don't mind reduced readability, you can vectorize the precomputation and blur steps. The precalc lookups don't look like they can really be vectorized, though, so it might not help much for the blur step.
I realize that you're probably not interested in speeding it up at all, unless you're using it in animated sequences, but you could probably get it 3-10 times faster than it is now if you'd like. :) If you are interested, just give me a shout.
Cheers