Blender V2.61 - r43446
|
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 }