Rectangle kernels
Replace conv::size with conv::{w,h}. Shadow kernels are still squares, though. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
cea010afec
commit
b2750b26e0
|
@ -71,7 +71,9 @@ xcb_image_t *make_shadow(xcb_connection_t *c, const conv *kernel,
|
||||||
*/
|
*/
|
||||||
xcb_image_t *ximage;
|
xcb_image_t *ximage;
|
||||||
const double *shadow_sum = kernel->rsum;
|
const double *shadow_sum = kernel->rsum;
|
||||||
int d = kernel->size, r = d / 2;
|
// We only support square kernels for shadow
|
||||||
|
assert(kernel->w == kernel->h);
|
||||||
|
int d = kernel->w, r = d / 2;
|
||||||
int swidth = width + r * 2, sheight = height + r * 2;
|
int swidth = width + r * 2, sheight = height + r * 2;
|
||||||
|
|
||||||
assert(d % 2 == 1);
|
assert(d % 2 == 1);
|
||||||
|
|
54
src/kernel.c
54
src/kernel.c
|
@ -12,32 +12,30 @@
|
||||||
/// top left corner is at (x, y)
|
/// top left corner is at (x, y)
|
||||||
double sum_kernel(const conv *map, int x, int y, int width, int height) {
|
double sum_kernel(const conv *map, int x, int y, int width, int height) {
|
||||||
double ret = 0;
|
double ret = 0;
|
||||||
/*
|
|
||||||
* Compute set of filter values which are "in range"
|
|
||||||
*/
|
|
||||||
|
|
||||||
int xstart = x;
|
// Compute sum of values which are "in range"
|
||||||
if (xstart < 0)
|
int xstart = x, xend = width + x;
|
||||||
|
if (xstart < 0) {
|
||||||
xstart = 0;
|
xstart = 0;
|
||||||
int xend = width + x;
|
}
|
||||||
if (xend > map->size)
|
if (xend > map->w) {
|
||||||
xend = map->size;
|
xend = map->w;
|
||||||
|
}
|
||||||
int ystart = y;
|
int ystart = y, yend = height + y;
|
||||||
if (ystart < 0)
|
if (ystart < 0) {
|
||||||
ystart = 0;
|
ystart = 0;
|
||||||
int yend = height + y;
|
}
|
||||||
if (yend > map->size)
|
if (yend > map->h) {
|
||||||
yend = map->size;
|
yend = map->h;
|
||||||
|
}
|
||||||
|
assert(yend >= ystart && xend >= xstart);
|
||||||
|
|
||||||
assert(yend > 0 && xend > 0);
|
int d = map->w;
|
||||||
|
|
||||||
int d = map->size;
|
|
||||||
if (map->rsum) {
|
if (map->rsum) {
|
||||||
|
// See sum_kernel_preprocess
|
||||||
double v1 = xstart ? map->rsum[(yend - 1) * d + xstart - 1] : 0;
|
double v1 = xstart ? map->rsum[(yend - 1) * d + xstart - 1] : 0;
|
||||||
double v2 = ystart ? map->rsum[(ystart - 1) * d + xend - 1] : 0;
|
double v2 = ystart ? map->rsum[(ystart - 1) * d + xend - 1] : 0;
|
||||||
double v3 =
|
double v3 = (xstart && ystart) ? map->rsum[(ystart - 1) * d + xstart - 1] : 0;
|
||||||
(xstart && ystart) ? map->rsum[(ystart - 1) * d + xstart - 1] : 0;
|
|
||||||
return map->rsum[(yend - 1) * d + xend - 1] - v1 - v2 + v3;
|
return map->rsum[(yend - 1) * d + xend - 1] - v1 - v2 + v3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +75,7 @@ conv *gaussian_kernel(double r) {
|
||||||
double t;
|
double t;
|
||||||
|
|
||||||
c = cvalloc(sizeof(conv) + size * size * sizeof(double));
|
c = cvalloc(sizeof(conv) + size * size * sizeof(double));
|
||||||
c->size = size;
|
c->w = c->h = size;
|
||||||
c->rsum = NULL;
|
c->rsum = NULL;
|
||||||
t = 0.0;
|
t = 0.0;
|
||||||
|
|
||||||
|
@ -100,22 +98,22 @@ conv *gaussian_kernel(double r) {
|
||||||
|
|
||||||
/// preprocess kernels to make shadow generation faster
|
/// preprocess kernels to make shadow generation faster
|
||||||
/// shadow_sum[x*d+y] is the sum of the kernel from (0, 0) to (x, y), inclusive
|
/// shadow_sum[x*d+y] is the sum of the kernel from (0, 0) to (x, y), inclusive
|
||||||
void shadow_preprocess(conv *map) {
|
void sum_kernel_preprocess(conv *map) {
|
||||||
const int d = map->size;
|
if (map->rsum) {
|
||||||
|
|
||||||
if (map->rsum)
|
|
||||||
free(map->rsum);
|
free(map->rsum);
|
||||||
|
}
|
||||||
|
|
||||||
auto sum = map->rsum = ccalloc(d * d, double);
|
auto sum = map->rsum = ccalloc(map->w * map->h, double);
|
||||||
sum[0] = map->data[0];
|
sum[0] = map->data[0];
|
||||||
|
|
||||||
for (int x = 1; x < d; x++) {
|
for (int x = 1; x < map->w; x++) {
|
||||||
sum[x] = sum[x - 1] + map->data[x];
|
sum[x] = sum[x - 1] + map->data[x];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int y = 1; y < d; y++) {
|
const int d = map->w;
|
||||||
|
for (int y = 1; y < map->h; y++) {
|
||||||
sum[y * d] = sum[(y - 1) * d] + map->data[y * d];
|
sum[y * d] = sum[(y - 1) * d] + map->data[y * d];
|
||||||
for (int x = 1; x < d; x++) {
|
for (int x = 1; x < map->w; x++) {
|
||||||
double tmp = sum[(y - 1) * d + x] + sum[y * d + x - 1] -
|
double tmp = sum[(y - 1) * d + x] + sum[y * d + x - 1] -
|
||||||
sum[(y - 1) * d + x - 1];
|
sum[(y - 1) * d + x - 1];
|
||||||
sum[y * d + x] = tmp + map->data[y * d + x];
|
sum[y * d + x] = tmp + map->data[y * d + x];
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
/// Code for generating convolution kernels
|
/// Code for generating convolution kernels
|
||||||
|
|
||||||
typedef struct conv {
|
typedef struct conv {
|
||||||
int size;
|
int w, h;
|
||||||
double *rsum;
|
double *rsum;
|
||||||
double data[];
|
double data[];
|
||||||
} conv;
|
} conv;
|
||||||
|
@ -23,7 +23,7 @@ conv *gaussian_kernel(double r);
|
||||||
|
|
||||||
/// preprocess kernels to make shadow generation faster
|
/// preprocess kernels to make shadow generation faster
|
||||||
/// shadow_sum[x*d+y] is the sum of the kernel from (0, 0) to (x, y), inclusive
|
/// shadow_sum[x*d+y] is the sum of the kernel from (0, 0) to (x, y), inclusive
|
||||||
void shadow_preprocess(conv *map);
|
void sum_kernel_preprocess(conv *map);
|
||||||
|
|
||||||
static inline void free_conv(conv *k) {
|
static inline void free_conv(conv *k) {
|
||||||
free(k->rsum);
|
free(k->rsum);
|
||||||
|
|
|
@ -1169,7 +1169,7 @@ bool init_render(session_t *ps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ps->gaussian_map = gaussian_kernel(ps->o.shadow_radius);
|
ps->gaussian_map = gaussian_kernel(ps->o.shadow_radius);
|
||||||
shadow_preprocess(ps->gaussian_map);
|
sum_kernel_preprocess(ps->gaussian_map);
|
||||||
|
|
||||||
ps->black_picture = solid_picture(ps, true, 1, 0, 0, 0);
|
ps->black_picture = solid_picture(ps, true, 1, 0, 0, 0);
|
||||||
ps->white_picture = solid_picture(ps, true, 1, 1, 1, 1);
|
ps->white_picture = solid_picture(ps, true, 1, 1, 1, 1);
|
||||||
|
|
Loading…
Reference in New Issue