Blender V2.61 - r43446

node_composite_bilateralblur.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2006 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Vilem Novak
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00032 #include "node_composite_util.h"
00033 
00034 /* **************** BILATERALBLUR ******************** */
00035 static bNodeSocketTemplate cmp_node_bilateralblur_in[]= {
00036     { SOCK_RGBA, 1, "Image", 1.0f, 1.0f, 1.0f, 1.0f}, 
00037     { SOCK_RGBA, 1, "Determinator", 1.0f, 1.0f, 1.0f, 1.0f}, 
00038     { -1, 0, "" } 
00039 };
00040 
00041 static bNodeSocketTemplate cmp_node_bilateralblur_out[]= { 
00042     { SOCK_RGBA, 0, "Image"}, 
00043     { -1, 0, "" } 
00044 };
00045 
00046 #define INIT_C3                                                               \
00047     mean0 = 1;                                                                \
00048     mean1[0] = src[0];                                                        \
00049     mean1[1] = src[1];                                                        \
00050     mean1[2] = src[2];                                                        \
00051     mean1[3] = src[3];
00052 
00053 /* finds color distances */
00054 #define COLOR_DISTANCE_C3(c1, c2)                                             \
00055     ((c1[0] - c2[0])*(c1[0] - c2[0]) +                                        \
00056      (c1[1] - c2[1])*(c1[1] - c2[1]) +                                        \
00057      (c1[2] - c2[2])*(c1[2] - c2[2]) +                                        \
00058      (c1[3] - c2[3])*(c1[3] - c2[3]))
00059 
00060 /* this is the main kernel function for comparing color distances
00061  and adding them weighted to the final color */
00062 #define KERNEL_ELEMENT_C3(k)                                                  \
00063     temp_color = src + deltas[k];                                             \
00064     ref_color = ref + deltas[k];                                              \
00065     w = weight_tab[k] +                                                       \
00066         (double)COLOR_DISTANCE_C3(ref, ref_color ) * i2sigma_color;           \
00067     w = 1.0/(w*w + 1);                                                        \
00068     mean0 += w;                                                               \
00069     mean1[0] += (double)temp_color[0]*w;                                      \
00070     mean1[1] += (double)temp_color[1]*w;                                      \
00071     mean1[2] += (double)temp_color[2]*w;                                      \
00072     mean1[3] += (double)temp_color[3]*w;
00073 
00074 /* write blurred values to image */
00075 #define UPDATE_OUTPUT_C3                                                      \
00076     mean0 = 1.0/mean0;                                                        \
00077     dest[x*pix + 0] = mean1[0]*mean0;                                         \
00078     dest[x*pix + 1] = mean1[1]*mean0;                                         \
00079     dest[x*pix + 2] = mean1[2]*mean0;                                         \
00080     dest[x*pix + 3] = mean1[3]*mean0;
00081 
00082 /* initializes deltas for fast access to neighbour pixels */
00083 #define INIT_3X3_DELTAS( deltas, step, nch )                                  \
00084     ((deltas)[0] =  (nch),  (deltas)[1] = -(step) + (nch),                    \
00085      (deltas)[2] = -(step), (deltas)[3] = -(step) - (nch),                    \
00086      (deltas)[4] = -(nch),  (deltas)[5] =  (step) - (nch),                    \
00087      (deltas)[6] =  (step), (deltas)[7] =  (step) + (nch));
00088 
00089 
00090 /* code of this node was heavily inspired by the smooth function of opencv library.
00091 The main change is an optional image input */
00092 static void node_composit_exec_bilateralblur(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
00093 {
00094     NodeBilateralBlurData *nbbd= node->storage;
00095     CompBuf *new, *source, *img= in[0]->data , *refimg= in[1]->data;
00096     double mean0, w, i2sigma_color, i2sigma_space;
00097     double mean1[4];
00098     double weight_tab[8];
00099     float *src, *dest, *ref, *temp_color, *ref_color;
00100     float sigma_color, sigma_space;
00101     int imgx, imgy, x, y, pix, i, step;
00102     int deltas[8];
00103     short found_determinator= 0;
00104 
00105     if(img == NULL || out[0]->hasoutput == 0)
00106         return;
00107 
00108     if(img->type != CB_RGBA) {
00109         img= typecheck_compbuf(in[0]->data, CB_RGBA);
00110     }
00111 
00112     imgx= img->x;
00113     imgy= img->y;
00114     pix= img->type;
00115     step= pix * imgx;
00116 
00117     if(refimg) {
00118         if(refimg->x == imgx && refimg->y == imgy) {
00119             if(ELEM3(refimg->type, CB_VAL, CB_VEC2, CB_VEC3)) {
00120                 refimg= typecheck_compbuf(in[1]->data, CB_RGBA);
00121                 found_determinator= 1;
00122             }
00123         }
00124     }
00125     else {
00126         refimg= img;
00127     }
00128 
00129     /* allocs */
00130     source= dupalloc_compbuf(img);
00131     new= alloc_compbuf(imgx, imgy, pix, 1);
00132     
00133     /* accept image offsets from other nodes */
00134     new->xof= img->xof;
00135     new->yof= img->yof;
00136 
00137     /* bilateral code properties */
00138     sigma_color= nbbd->sigma_color;
00139     sigma_space= nbbd->sigma_space;
00140     
00141     i2sigma_color= 1.0f / (sigma_color * sigma_color);
00142     i2sigma_space= 1.0f / (sigma_space * sigma_space);
00143 
00144     INIT_3X3_DELTAS(deltas, step, pix);
00145 
00146     weight_tab[0] = weight_tab[2] = weight_tab[4] = weight_tab[6] = i2sigma_space;
00147     weight_tab[1] = weight_tab[3] = weight_tab[5] = weight_tab[7] = i2sigma_space * 2;
00148 
00149     /* iterations */
00150     for(i= 0; i < nbbd->iter; i++) {
00151         src= source->rect;
00152         ref= refimg->rect;
00153         dest= new->rect;
00154         /*goes through image, there are more loops for 1st/last line and all other lines*/
00155         /*kernel element accumulates surrounding colors, which are then written with the update_output function*/
00156         for(x= 0; x < imgx; x++, src+= pix, ref+= pix) {
00157             INIT_C3;
00158 
00159             KERNEL_ELEMENT_C3(6);
00160 
00161             if(x > 0) {
00162                 KERNEL_ELEMENT_C3(5);
00163                 KERNEL_ELEMENT_C3(4);
00164             }
00165 
00166             if(x < imgx - 1) {
00167                 KERNEL_ELEMENT_C3(7);
00168                 KERNEL_ELEMENT_C3(0);
00169             }
00170 
00171             UPDATE_OUTPUT_C3;
00172         }
00173 
00174         dest+= step;
00175 
00176         for(y= 1; y < imgy - 1; y++, dest+= step, src+= pix, ref+= pix) {
00177             x= 0;
00178 
00179             INIT_C3;
00180 
00181             KERNEL_ELEMENT_C3(0);
00182             KERNEL_ELEMENT_C3(1);
00183             KERNEL_ELEMENT_C3(2);
00184             KERNEL_ELEMENT_C3(6);
00185             KERNEL_ELEMENT_C3(7);
00186 
00187             UPDATE_OUTPUT_C3;
00188 
00189             src+= pix;
00190             ref+= pix;
00191 
00192             for(x= 1; x < imgx - 1; x++, src+= pix, ref+= pix) {
00193                 INIT_C3;
00194 
00195                 KERNEL_ELEMENT_C3(0);
00196                 KERNEL_ELEMENT_C3(1);
00197                 KERNEL_ELEMENT_C3(2);
00198                 KERNEL_ELEMENT_C3(3);
00199                 KERNEL_ELEMENT_C3(4);
00200                 KERNEL_ELEMENT_C3(5);
00201                 KERNEL_ELEMENT_C3(6);
00202                 KERNEL_ELEMENT_C3(7);
00203 
00204                 UPDATE_OUTPUT_C3;
00205             }
00206 
00207             INIT_C3;
00208 
00209             KERNEL_ELEMENT_C3(2);
00210             KERNEL_ELEMENT_C3(3);
00211             KERNEL_ELEMENT_C3(4);
00212             KERNEL_ELEMENT_C3(5);
00213             KERNEL_ELEMENT_C3(6);
00214 
00215             UPDATE_OUTPUT_C3;
00216         }
00217 
00218         for(x= 0; x < imgx; x++, src+= pix, ref+= pix) {
00219             INIT_C3;
00220 
00221             KERNEL_ELEMENT_C3(2);
00222 
00223             if(x > 0) {
00224                 KERNEL_ELEMENT_C3(3);
00225                 KERNEL_ELEMENT_C3(4);
00226             }
00227             if(x < imgx - 1) {
00228                 KERNEL_ELEMENT_C3(1);
00229                 KERNEL_ELEMENT_C3(0);
00230             }
00231 
00232             UPDATE_OUTPUT_C3;
00233         }
00234 
00235         if(node->exec & NODE_BREAK) break;
00236 
00237         SWAP(CompBuf, *source, *new);
00238     }
00239 
00240     if(img != in[0]->data)
00241         free_compbuf(img);
00242 
00243     if(found_determinator == 1) {
00244         if(refimg != in[1]->data)
00245             free_compbuf(refimg);
00246     }
00247 
00248     out[0]->data= source;
00249 
00250     free_compbuf(new);
00251 }
00252 
00253 static void node_composit_init_bilateralblur(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
00254 {
00255     NodeBilateralBlurData *nbbd= MEM_callocN(sizeof(NodeBilateralBlurData), "node bilateral blur data");
00256     node->storage= nbbd;
00257     nbbd->sigma_color= 0.3;
00258     nbbd->sigma_space= 5.0;
00259 }
00260 
00261 void register_node_type_cmp_bilateralblur(bNodeTreeType *ttype)
00262 {
00263     static bNodeType ntype;
00264 
00265     node_type_base(ttype, &ntype, CMP_NODE_BILATERALBLUR, "Bilateral Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
00266     node_type_socket_templates(&ntype, cmp_node_bilateralblur_in, cmp_node_bilateralblur_out);
00267     node_type_size(&ntype, 150, 120, 200);
00268     node_type_init(&ntype, node_composit_init_bilateralblur);
00269     node_type_storage(&ntype, "NodeBilateralBlurData", node_free_standard_storage, node_copy_standard_storage);
00270     node_type_exec(&ntype, node_composit_exec_bilateralblur);
00271 
00272     nodeRegisterType(ttype, &ntype);
00273 }