Faster blurring with box blur (will use in compositor in future)
This commit is contained in:
parent
9eb63b4bfd
commit
eb4d05b86b
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user