|
Hate UML?Draw sequence diagrams in seconds.http://www.websequencediagrams.com |

This is used in the back-end for www.websequencediagrams.com.
// to build:
// gcc -I/usr/include/cairo -lcairo -o blur blur.c
#include <stdlib.h>
#include <memory.h>
#include <stdio.h>
#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<height;y++) {
for (x=0;x<width;x++) {
int tot=pix[0];
if (x>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<height-radius;y++) {
for (x=radius;x<width-radius;x++) {
int l = x < radius ? 0 : x - radius;
int t = y < radius ? 0 : y - radius;
int r = x + radius >= 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 <outfile.png> \"<text to display>\"\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;
}
Want more programming tech talk?
Add to Circles on Google Plus
Subscribe to posts
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
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-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.
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.
Post comment