Graphics library functions for Gaussian blur
And a demo app. Going to use this for soft shadows somewhere.
This commit is contained in:
parent
6515e90b10
commit
8ef81b6924
23
README.md
23
README.md
@ -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.
|
||||
|
@ -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
86
userspace/blur_test.c
Normal 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;
|
||||
}
|
@ -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");
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user