2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2006 Blender Foundation.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): Vilem Novak
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/nodes/composite/nodes/node_composite_bilateralblur.c
32 #include "node_composite_util.h"
34 /* **************** BILATERALBLUR ******************** */
35 static bNodeSocketTemplate cmp_node_bilateralblur_in[]= {
36 { SOCK_RGBA, 1, "Image", 1.0f, 1.0f, 1.0f, 1.0f},
37 { SOCK_RGBA, 1, "Determinator", 1.0f, 1.0f, 1.0f, 1.0f},
41 static bNodeSocketTemplate cmp_node_bilateralblur_out[]= {
42 { SOCK_RGBA, 0, "Image"},
47 mean0 = 1; mean1[0] = src[0];mean1[1] = src[1];mean1[2] = src[2];mean1[3] = src[3];
49 /* finds color distances */
50 #define COLOR_DISTANCE_C3(c1, c2)\
51 ((c1[0] - c2[0])*(c1[0] - c2[0]) + \
52 (c1[1] - c2[1])*(c1[1] - c2[1]) + \
53 (c1[2] - c2[2])*(c1[2] - c2[2]) + \
54 (c1[3] - c2[3])*(c1[3] - c2[3]))
56 /* this is the main kernel function for comparing color distances
57 and adding them weighted to the final color */
58 #define KERNEL_ELEMENT_C3(k)\
59 temp_color = src + deltas[k];\
60 ref_color = ref + deltas[k];\
61 w = weight_tab[k] + COLOR_DISTANCE_C3(ref, ref_color )*i2sigma_color;\
64 mean1[0] += temp_color[0]*w; \
65 mean1[1] += temp_color[1]*w; \
66 mean1[2] += temp_color[2]*w; \
67 mean1[3] += temp_color[3]*w;
69 /* write blurred values to image */
70 #define UPDATE_OUTPUT_C3\
72 dest[x*pix + 0] = mean1[0]*mean0; \
73 dest[x*pix + 1] = mean1[1]*mean0; \
74 dest[x*pix + 2] = mean1[2]*mean0; \
75 dest[x*pix + 3] = mean1[3]*mean0;
77 /* initializes deltas for fast access to neighbour pixels */
78 #define INIT_3X3_DELTAS( deltas, step, nch ) \
79 ((deltas)[0] = (nch), (deltas)[1] = -(step) + (nch), \
80 (deltas)[2] = -(step), (deltas)[3] = -(step) - (nch), \
81 (deltas)[4] = -(nch), (deltas)[5] = (step) - (nch), \
82 (deltas)[6] = (step), (deltas)[7] = (step) + (nch));
85 /* code of this node was heavily inspired by the smooth function of opencv library.
86 The main change is an optional image input */
87 static void node_composit_exec_bilateralblur(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
89 NodeBilateralBlurData *nbbd= node->storage;
90 CompBuf *new, *source, *img= in[0]->data , *refimg= in[1]->data;
91 double mean0, w, i2sigma_color, i2sigma_space;
94 float *src, *dest, *ref, *temp_color, *ref_color;
95 float sigma_color, sigma_space;
96 int imgx, imgy, x, y, pix, i, step;
98 short found_determinator= 0;
100 if(img == NULL || out[0]->hasoutput == 0)
103 if(img->type != CB_RGBA) {
104 img= typecheck_compbuf(in[0]->data, CB_RGBA);
113 if(refimg->x == imgx && refimg->y == imgy) {
114 if(ELEM3(refimg->type, CB_VAL, CB_VEC2, CB_VEC3)) {
115 refimg= typecheck_compbuf(in[1]->data, CB_RGBA);
116 found_determinator= 1;
125 source= dupalloc_compbuf(img);
126 new= alloc_compbuf(imgx, imgy, pix, 1);
128 /* accept image offsets from other nodes */
132 /* bilateral code properties */
133 sigma_color= nbbd->sigma_color;
134 sigma_space= nbbd->sigma_space;
136 i2sigma_color= 1. / (sigma_color * sigma_color);
137 i2sigma_space= 1. / (sigma_space * sigma_space);
139 INIT_3X3_DELTAS(deltas, step, pix);
141 weight_tab[0] = weight_tab[2] = weight_tab[4] = weight_tab[6] = i2sigma_space;
142 weight_tab[1] = weight_tab[3] = weight_tab[5] = weight_tab[7] = i2sigma_space * 2;
145 for(i= 0; i < nbbd->iter; i++) {
149 /*goes through image, there are more loops for 1st/last line and all other lines*/
150 /*kernel element accumulates surrounding colors, which are then written with the update_output function*/
151 for(x= 0; x < imgx; x++, src+= pix, ref+= pix) {
154 KERNEL_ELEMENT_C3(6);
157 KERNEL_ELEMENT_C3(5);
158 KERNEL_ELEMENT_C3(4);
162 KERNEL_ELEMENT_C3(7);
163 KERNEL_ELEMENT_C3(0);
171 for(y= 1; y < imgy - 1; y++, dest+= step, src+= pix, ref+= pix) {
176 KERNEL_ELEMENT_C3(0);
177 KERNEL_ELEMENT_C3(1);
178 KERNEL_ELEMENT_C3(2);
179 KERNEL_ELEMENT_C3(6);
180 KERNEL_ELEMENT_C3(7);
187 for(x= 1; x < imgx - 1; x++, src+= pix, ref+= pix) {
190 KERNEL_ELEMENT_C3(0);
191 KERNEL_ELEMENT_C3(1);
192 KERNEL_ELEMENT_C3(2);
193 KERNEL_ELEMENT_C3(3);
194 KERNEL_ELEMENT_C3(4);
195 KERNEL_ELEMENT_C3(5);
196 KERNEL_ELEMENT_C3(6);
197 KERNEL_ELEMENT_C3(7);
204 KERNEL_ELEMENT_C3(2);
205 KERNEL_ELEMENT_C3(3);
206 KERNEL_ELEMENT_C3(4);
207 KERNEL_ELEMENT_C3(5);
208 KERNEL_ELEMENT_C3(6);
213 for(x= 0; x < imgx; x++, src+= pix, ref+= pix) {
216 KERNEL_ELEMENT_C3(2);
219 KERNEL_ELEMENT_C3(3);
220 KERNEL_ELEMENT_C3(4);
223 KERNEL_ELEMENT_C3(1);
224 KERNEL_ELEMENT_C3(0);
230 if(node->exec & NODE_BREAK) break;
232 SWAP(CompBuf, *source, *new);
235 if(img != in[0]->data)
238 if(found_determinator == 1) {
239 if(refimg != in[1]->data)
240 free_compbuf(refimg);
243 out[0]->data= source;
248 static void node_composit_init_bilateralblur(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
250 NodeBilateralBlurData *nbbd= MEM_callocN(sizeof(NodeBilateralBlurData), "node bilateral blur data");
252 nbbd->sigma_color= 0.3;
253 nbbd->sigma_space= 5.0;
256 void register_node_type_cmp_bilateralblur(ListBase *lb)
258 static bNodeType ntype;
260 node_type_base(&ntype, CMP_NODE_BILATERALBLUR, "Bilateral Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
261 node_type_socket_templates(&ntype, cmp_node_bilateralblur_in, cmp_node_bilateralblur_out);
262 node_type_size(&ntype, 150, 120, 200);
263 node_type_init(&ntype, node_composit_init_bilateralblur);
264 node_type_storage(&ntype, "NodeBilateralBlurData", node_free_standard_storage, node_copy_standard_storage);
265 node_type_exec(&ntype, node_composit_exec_bilateralblur);
267 nodeRegisterType(lb, &ntype);