Shader annotate

Click on the filename to display or download the file.

annotate.mi
declare shader 
    color "annotate" ( 
        string "text", 
	string "fontimage_filename", 
	integer "x" default 10, 
	integer "y" default 10, 
	color "color" default 1 1 1 ) 
    version 1 
    apply output 
end declare 

annotate.c
#include "shader.h" 
#include "miaux.h" 
 
struct annotate { 
    miTag text; 
    miTag fontimage_filename; 
    miInteger x; 
    miInteger y; 
    miColor color; 
}; 
 
DLLEXPORT 
int annotate_version(void) { return 1; } 
 
DLLEXPORT 
miBoolean annotate ( 
    void *result, miState *state, struct annotate *params ) 
{ 
    if (params->text != miNULLTAG) { 
        int x, y, t_x, t_y, t_width, t_height; 
        float *text_image; 
        miImg_image *fb; 
        fontimage fimage; 
        miColor *text_color = mi_eval_color(&params->color), pixel_color; 
        char* text = miaux_tag_to_string( 
            *mi_eval_tag(&params->text), NULL); 
        int p_x = *mi_eval_integer(&params->x),  
            p_y = *mi_eval_integer(&params->y); 
        char* fontimage_filename =  
            miaux_tag_to_string(*mi_eval_tag(&params->fontimage_filename),  
                                "Courier-Bold_24.fontimage"); 
 
        miaux_load_fontimage(&fimage, fontimage_filename); 
        miaux_text_image(&text_image, &t_width, &t_height, &fimage, text); 
 
        fb = mi_output_image_open(state, miRC_IMAGE_RGBA); 
        for (y = p_y, t_y = 0; t_y < t_height; y++, t_y++) { 
            if (mi_par_aborted()) { 
                mi_progress("Abort"); 
                break; 
            } 
            for (x = p_x, t_x = 0; t_x < t_width; x++, t_x++) { 
                float alpha = text_image[t_y * t_width + t_x]; 
                mi_img_get_color(fb, &pixel_color, x, y); 
                miaux_alpha_blend(&pixel_color, text_color, alpha); 
                mi_img_put_color(fb, &pixel_color, x, y); 
            } 
        } 
        miaux_release_fontimage(&fimage); 
        mi_output_image_close(state, miRC_IMAGE_RGBA); 
    } 
    return miTRUE; 
} 

annotate_util.c
char* miaux_tag_to_string(miTag tag, char *default_value) 
{ 
    char *result = default_value; 
    if (tag != 0) { 
	result = (char*)mi_db_access(tag); 
	mi_db_unpin(tag); 
    } 
    return result; 
} 
 
void miaux_load_fontimage(fontimage *fimage, char* filename) 
{  
    int printable_ascii_size = 126 - 32 + 1; 
    int i, image_data_size; 
    char identifier[33]; 
 
    FILE* fp = fopen(filename, "r"); 
    if (fp == NULL) 
	mi_fatal("Could not open font image file: %s", filename); 
    fscanf(fp, "%s ", identifier); 
    if (strcmp(identifier, "FONTIMAGE") != 0) 
	mi_fatal("File '%s' does not look like a fontimage file", filename); 
 
    fscanf(fp, "%d %d ", &fimage->width, &fimage->height); 
    image_data_size = fimage->width * fimage->height; 
    fimage->x_offsets =  
	(int*)mi_mem_allocate(sizeof(int) * printable_ascii_size); 
    for (i = 0; i <= printable_ascii_size; i++) 
	fscanf(fp, "%d ", &fimage->x_offsets[i]); 
    fimage->image = (unsigned char*)mi_mem_allocate(image_data_size); 
    fread(fimage->image, image_data_size, 1, fp); 
 
    fclose(fp); 
} 
 
void miaux_text_image( 
    float **text_image, int *width, int *height,  
    fontimage *fimage, char* text) 
{ 
    char *c; 
    int i, total_width, xpos, first_printable = 32, image_size,  
	index, start, end, font_index, fx, fy, tx, ty, text_index; 
 
    for (i = 0, total_width = 0, c = text; i < strlen(text); i++, c++) { 
	index = *c - first_printable; 
	start = fimage->x_offsets[index]; 
	end = fimage->x_offsets[index + 1]; 
	total_width += end - start + 1; 
    } 
    *width = total_width; 
    *height = fimage->height; 
    image_size = *width * *height; 
    (*text_image) = (float*)mi_mem_allocate(image_size * sizeof(float)); 
 
    for (i = 0, c = text, xpos = 0; i < strlen(text); i++, c++) { 
	int index = *c - first_printable; 
	start = fimage->x_offsets[index]; 
	end = fimage->x_offsets[index + 1]; 
	for (fy = fimage->height - 1, ty = 0; fy >= 0; fy--, ty++) { 
	    for (fx = start, tx = xpos; fx < end-1; fx++, tx++) { 
		text_index = ty * *width + tx; 
		font_index = fy * fimage->width + fx; 
		(*text_image)[text_index] =  
		    (float)fimage->image[font_index] / 255.0; 
	    } 
	} 
	xpos += end - start + 1; 
    } 
} 
 
void miaux_alpha_blend(miColor *x, miColor *y, miScalar alpha) 
{ 
    x->r = miaux_blend(y->r, x->r, alpha); 
    x->g = miaux_blend(y->g, x->g, alpha); 
    x->b = miaux_blend(y->b, x->b, alpha); 
} 
 
double miaux_blend(miScalar a, miScalar b, miScalar factor) 
{ 
    return a * factor + b * (1.0 - factor); 
} 
 
void miaux_release_fontimage(fontimage *fimage) 
{ 
    mi_mem_release(fimage->x_offsets); 
    mi_mem_release(fimage->image); 
} 

22 April 2008 23:41:05