Click on the filename to display or download the file.
median_filter.mi
declare shader
color "median_filter" (
integer "radius" default 1 )
version 1
apply output
end declare
median_filter.c
#include "shader.h"
#include "miaux.h"
#include
struct median_filter {
miInteger radius;
};
DLLEXPORT
int median_filter_version(void) { return 1; }
DLLEXPORT
miBoolean median_filter (
void *result, miState *state, struct median_filter *params )
{
miColor *neighbors;
int radius = *mi_eval_integer(¶ms->radius), x, y,
kernel_size = (radius * 2 + 1) * (radius * 2 + 1),
middle = kernel_size / 2;
miImg_image *fb_input = mi_output_image_open(state, miRC_IMAGE_RGBA);
miImg_image *fb_output = mi_output_image_open(state, miRC_IMAGE_USER);
neighbors = (miColor*) mi_mem_allocate(kernel_size * sizeof(miColor));
for (y = 0; y < state->camera->y_resolution; y++) {
if (mi_par_aborted())
break;
for (x = 0; x < state->camera->x_resolution; x++) {
miaux_pixel_neighborhood(neighbors, fb_input, x, y, radius);
qsort(neighbors, kernel_size, sizeof(miColor),
miaux_color_compare);
mi_img_put_color(fb_output, &neighbors[middle], x, y);
}
}
mi_mem_release(neighbors);
mi_output_image_close(state, miRC_IMAGE_RGBA);
mi_output_image_close(state, miRC_IMAGE_USER);
return miTRUE;
}
median_filter_util.c
void miaux_pixel_neighborhood(
miColor *neighbors,
miImg_image *buffer, int x, int y, int radius)
{
int xi, yi, xp = 0, yp = 0, i = 0,
max_x = buffer->width - 1, max_y = buffer->height - 1;
miColor current_pixel;
for (yi = y - radius; yi <= y + radius; yi++) {
yp = yi > max_y ? max_x : yi < 0 ? 0 : yi;
for (xi = x - radius; xi <= x + radius; xi++) {
xp = xi > max_x ? max_x : xi < 0 ? 0 : xi;
mi_img_get_color(buffer, ¤t_pixel, xp, yp);
neighbors[i++] = current_pixel;
}
}
}
int miaux_color_compare(const void *vx, const void *vy)
{
miColor const *x = vx, *y = vy;
float sum_x = x->r + x->g + x->b;
float sum_y = y->r + y->g + y->b;
return sum_x < sum_y ? -1 : sum_x > sum_y ? 1 : 0;
}
22 April 2008 23:41:04