Shader median_filter

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(&params->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, &current_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