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