Graphics library functions for Gaussian blur

And a demo app. Going to use this for soft shadows somewhere.
This commit is contained in:
Kevin Lange 2012-10-15 23:04:33 -07:00
parent 6515e90b10
commit 8ef81b6924
5 changed files with 230 additions and 1 deletions

View File

@ -293,6 +293,29 @@ ToAruOS contains additional software with the following copyright notices:
Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
* The code to perform a Gaussian blur on a graphics context (part of userspace/lib/graphics.c) comes from sample code for Cairo and carries the following license:
Copyright © 2008 Kristian Høgsberg
Copyright © 2009 Chris Wilson
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting documentation, and
that the name of the copyright holders not be used in advertising or
publicity pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no representations
about the suitability of this software for any purpose. It is provided "as
is" without express or implied warranty.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
OF THIS SOFTWARE.
* Some icons from the Elementary Icons set are included. These are icons are released under the GPL. You may find a list of authors and contributors alongside the icon files.
* Build scripts will retrieve copies of [GCC](http://gcc.gnu.org/), [Newlib](http://sourceware.org/newlib/), [FreeType](http://www.freetype.org/), [libpng](http://www.libpng.org/pub/png/libpng.html) and [zlib](http://www.zlib.net/) Patches for these software packages are provided under the same license as the package they are for.

View File

@ -23,7 +23,7 @@ LIBM = ${TOOLCHAIN}/lib/libm.a
LIBZ = ${TOOLCHAIN}/lib/libz.a
TARGETDIR = ../hdd/bin/
ETARGETS = terminal login compositor view game drawlines glogin julia solver wallpaper panel glock clock-win draw test-gfx threadtest bim
ETARGETS = terminal login compositor view game drawlines glogin julia solver wallpaper panel glock clock-win draw test-gfx threadtest bim blur_test
FTARGETS = $(ETARGETS:%=$(TARGETDIR)%)
LOCAL_LIBS = $(patsubst %.c,%.o,$(wildcard lib/*.c))

86
userspace/blur_test.c Normal file
View File

@ -0,0 +1,86 @@
#include <stdio.h>
#include "lib/window.h"
#include "lib/graphics.h"
#include "lib/shmemfonts.h"
gfx_context_t * ctx;
window_t * window;
void display() {
gfx_context_t * tmp_c, * out_c;
sprite_t * tmp_s, * out_s;
tmp_s = create_sprite(window->width, window->height, ALPHA_EMBEDDED);
tmp_c = init_graphics_sprite(tmp_s);
out_s = create_sprite(window->width, window->height, ALPHA_EMBEDDED);
out_c = init_graphics_sprite(out_s);
draw_fill(tmp_c, rgba(0,0,0,0));
draw_string(tmp_c, 20, 20, rgb(0,0,0), "Hello World");
blur_context(out_c, tmp_c, 3);
draw_string(out_c, 19, 19, rgb(255,255,255), "Hello World");
draw_fill(ctx, rgba(0,0,0,0));
draw_sprite(ctx, out_s, 0, 0);
draw_sprite(ctx, out_s, 0, 0);
draw_sprite(ctx, out_s, 0, 0);
draw_sprite(ctx, out_s, 0, 0);
sprite_free(tmp_s);
free(tmp_c);
sprite_free(out_s);
free(out_c);
flip(ctx);
}
void resize_callback(window_t * win) {
reinit_graphics_window(ctx, window);
draw_fill(ctx, rgb(0,0,0));
display();
}
int main(int argc, char * argv[]) {
setup_windowing();
resize_window_callback = resize_callback;
window = window_create(40, 40, 200, 30);
ctx = init_graphics_window_double_buffer(window);
draw_fill(ctx, rgba(0,0,0,0));
window_enable_alpha(window);
init_shmemfonts();
display();
int playing = 1;
while (playing) {
char ch = 0;
w_keyboard_t * kbd;
do {
kbd = poll_keyboard();
if (kbd != NULL) {
ch = kbd->key;
free(kbd);
}
} while (kbd != NULL);
switch (ch) {
case 'q':
playing = 0;
break;
}
}
teardown_windowing();
return 0;
}

View File

@ -71,6 +71,49 @@ void reinit_graphics_window(gfx_context_t * out, window_t * window) {
}
}
gfx_context_t * init_graphics_sprite(sprite_t * sprite) {
gfx_context_t * out = malloc(sizeof(gfx_context_t));
out->width = sprite->width;
out->height = sprite->height;
out->depth = 32;
out->size = GFX_H(out) * GFX_W(out) * GFX_B(out);
out->buffer = (char *)sprite->bitmap;
out->backbuffer = out->buffer;
return out;
}
sprite_t * create_sprite(size_t width, size_t height, int alpha) {
sprite_t * out = malloc(sizeof(sprite_t));
/*
uint16_t width;
uint16_t height;
uint32_t * bitmap;
uint32_t * masks;
uint32_t blank;
uint8_t alpha;
*/
out->width = width;
out->height = height;
out->bitmap = malloc(sizeof(uint32_t) * out->width * out->height);
out->masks = NULL;
out->blank = 0x00000000;
out->alpha = alpha;
return out;
}
void sprite_free(sprite_t * sprite) {
if (sprite->masks) {
free(sprite->masks);
}
free(sprite->bitmap);
free(sprite);
}
uint32_t rgb(uint8_t r, uint8_t g, uint8_t b) {
return 0xFF000000 + (r * 0x10000) + (g * 0x100) + (b * 0x1);
}
@ -98,6 +141,77 @@ uint32_t alpha_blend_rgba(uint32_t bottom, uint32_t top) {
return rgba(red,gre,blu,alp);
}
/*
* based on the blur.c demo for Cairo
* Copyright © 2008 Kristian Høgsberg
* Copyright © 2009 Chris Wilson
*/
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
void blur_context(gfx_context_t * _dst, gfx_context_t * _src, double amount) {
int width, height;
int x, y, z, w, i, j, k;
uint32_t *s, *d, a, p;
uint8_t * src, * dst;
uint8_t kernel[17];
const int size = ARRAY_LENGTH(kernel);
const int half = size / 2;
width = _src->width;
height = _src->height;
src = _src->backbuffer;
dst = _dst->backbuffer;
a = 0;
for (i = 0; i < size; ++i) {
double f = i - half;
a += kernel[i] = exp (- f * f / amount) * 80;
}
for (i = 0; i < height; ++i) {
s = (uint32_t *) (src + i * (_src->width * 4));
d = (uint32_t *) (dst + i * (_dst->width * 4));
for (j = 0; j < width; ++j) {
x = y = z = w = 0;
for (k = 0; k < size; ++k) {
if (j - half + k < 0 || j - half + k >= width)
continue;
p = s[j - half + k];
x += ((p >> 24) & 0xFF) * kernel[k];
y += ((p >> 16) & 0xFF) * kernel[k];
z += ((p >> 8) & 0xFF) * kernel[k];
w += ((p >> 0) & 0xFF) * kernel[k];
}
d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a;
}
}
for (i = 0; i < height; ++i) {
s = (uint32_t *) (src + i * (_src->width * 4));
d = (uint32_t *) (dst + i * (_dst->width * 4));
for (j = 0; j < width; ++j) {
x = y = z = w = 0;
for (k = 0; k < size; ++k) {
if (i - half + k < 0 || i - half + k >= height)
continue;
s = (uint32_t *) (dst + (i - half + k) * (_dst->width * 4));
p = s[j];
x += ((p >> 24) & 0xFF) * kernel[k];
y += ((p >> 16) & 0xFF) * kernel[k];
z += ((p >> 8) & 0xFF) * kernel[k];
w += ((p >> 0) & 0xFF) * kernel[k];
}
d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a;
}
}
}
void load_sprite(sprite_t * sprite, char * filename) {
/* Open the requested binary */
FILE * image = fopen(filename, "r");

View File

@ -59,6 +59,12 @@ uint32_t alpha_blend_rgba(uint32_t bottom, uint32_t top);
void flip(gfx_context_t * ctx);
void clear_buffer(gfx_context_t * ctx);
gfx_context_t * init_graphics_sprite(sprite_t * sprite);
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 sprite_free(sprite_t * sprite);
void load_sprite(sprite_t * sprite, char * filename);
int load_sprite_png(sprite_t * sprite, char * file);
void draw_sprite(gfx_context_t * ctx, sprite_t * sprite, int32_t x, int32_t y);