Faster blurring with box blur (will use in compositor in future)

This commit is contained in:
Kevin Lange 2014-06-01 01:33:25 -07:00
parent 9eb63b4bfd
commit eb4d05b86b
3 changed files with 123 additions and 19 deletions

View File

@ -157,14 +157,6 @@ int main (int argc, char ** argv) {
}
/* Generate surface for background */
#if 0
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, y->display_width);
cairo_surface_t * bg_surf = cairo_image_surface_create_for_data(
yg->framebuffer_surface = cairo_image_surface_create_for_data(
yg->backend_framebuffer, CAIRO_FORMAT_ARGB32, yg->width, yg->height, stride);
#endif
sprite_t * bg_sprite;
cairo_surface_t * bg_surf;
@ -189,25 +181,20 @@ int main (int argc, char ** argv) {
int nh = (int)(x * (float)sprites[1]->height);
int nw = (int)(y * (float)sprites[1]->width);;
sprite_t * tmp = create_sprite(width, height, ALPHA_OPAQUE);
gfx_context_t * bg_tmp = init_graphics_sprite(tmp);
bg_sprite = create_sprite(width, height, ALPHA_OPAQUE);
gfx_context_t * bg = init_graphics_sprite(bg_sprite);
if (nw > width) {
draw_sprite_scaled(bg_tmp, sprites[1], (width - nw) / 2, 0, nw, height);
draw_sprite_scaled(bg, sprites[1], (width - nw) / 2, 0, nw, height);
} else {
draw_sprite_scaled(bg_tmp, sprites[1], 0, (height - nh) / 2, width, nh);
draw_sprite_scaled(bg, sprites[1], 0, (height - nh) / 2, width, nh);
}
blur_context_no_vignette(bg, bg_tmp, 80.0);
blur_context_no_vignette(bg_tmp, bg, 400.0);
blur_context_no_vignette(bg, bg_tmp, 200.0);
/* Three box blurs = good enough approximation of a guassian, but faster*/
blur_context_box(bg, 20);
blur_context_box(bg, 20);
blur_context_box(bg, 20);
sprite_free(tmp);
free(bg_tmp);
free(bg);
}

View File

@ -312,6 +312,122 @@ void blur_context_no_vignette(gfx_context_t * _dst, gfx_context_t * _src, double
}
}
static int clamp(int a, int l, int h) {
return a < l ? l : (a > h ? h : a);
}
static void _box_blur_horizontal(gfx_context_t * _src, int radius) {
uint32_t * p = (uint32_t *)_src->backbuffer;
int w = _src->width;
int h = _src->height;
int half_radius = radius / 2;
int index = 0;
uint32_t * out_color = calloc(sizeof(uint32_t), w);
for (int y = 0; y < h; y++) {
int hits = 0;
int r = 0;
int g = 0;
int b = 0;
for (int x = -half_radius; x < w; x++) {
int old_p = x - half_radius - 1;
if (old_p >= 0)
{
uint32_t col = p[clamp(index + old_p, 0, w*h-1)];
if (col) {
r -= _RED(col);
g -= _GRE(col);
b -= _BLU(col);
}
hits--;
}
int newPixel = x + half_radius;
if (newPixel < w) {
int col = p[clamp(index + newPixel, 0, w*h-1)];
if (col != 0) {
r += _RED(col);
g += _GRE(col);
b += _BLU(col);
}
hits++;
}
if (x >= 0) {
out_color[x] = rgba(r / hits, g / hits, b / hits, 255);
}
}
for (int x = 0; x < w; x++) {
p[index + x] = out_color[x];
}
index += w;
}
free(out_color);
}
static void _box_blur_vertical(gfx_context_t * _src, int radius) {
uint32_t * p = (uint32_t *)_src->backbuffer;
int w = _src->width;
int h = _src->height;
int half_radius = radius / 2;
uint32_t * out_color = calloc(sizeof(uint32_t), h);
int old_offset = -(half_radius + 1) * w;
int new_offset = (half_radius) * w;
for (int x = 0; x < w; x++) {
int hits = 0;
int r = 0;
int g = 0;
int b = 0;
int index = -half_radius * w + x;
for (int y = -half_radius; y < h; y++) {
int old_p = y - half_radius - 1;
if (old_p >= 0) {
uint32_t col = p[clamp(index + old_offset, 0, w*h-1)];
if (col != 0) {
r -= _RED(col);
g -= _GRE(col);
b -= _BLU(col);
}
hits--;
}
int newPixel = y + half_radius;
if (newPixel < h) {
uint32_t col = p[clamp(index + new_offset, 0, w*h-1)];
if (col != 0)
{
r += _RED(col);
g += _GRE(col);
b += _BLU(col);
}
hits++;
}
if (y >= 0) {
out_color[y] = rgba(r / hits, g / hits, b / hits, 255);
}
index += w;
}
for (int y = 0; y < h; y++) {
p[y * w + x] = out_color[y];
}
}
free(out_color);
}
void blur_context_box(gfx_context_t * _src, int radius) {
_box_blur_horizontal(_src,radius);
_box_blur_vertical(_src,radius);
}
void load_sprite(sprite_t * sprite, char * filename) {
/* Open the requested binary */
FILE * image = fopen(filename, "r");

View File

@ -65,6 +65,7 @@ sprite_t * create_sprite(size_t width, size_t height, int alpha);
void blur_context(gfx_context_t * _dst, gfx_context_t * _src, double amount);
void blur_context_no_vignette(gfx_context_t * _dst, gfx_context_t * _src, double amount);
void blur_context_box(gfx_context_t * _src, int radius);
void sprite_free(sprite_t * sprite);
void load_sprite(sprite_t * sprite, char * filename);