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): none yet.
25
* ***** END GPL LICENSE BLOCK *****
28
/** \file blender/nodes/composite/nodes/node_composite_filter.c
33
#include "node_composite_util.h"
35
/* **************** FILTER ******************** */
36
static bNodeSocketTemplate cmp_node_filter_in[]= {
37
{ SOCK_FLOAT, 1, "Fac", 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR},
38
{ SOCK_RGBA, 1, "Image", 1.0f, 1.0f, 1.0f, 1.0f},
41
static bNodeSocketTemplate cmp_node_filter_out[]= {
42
{ SOCK_RGBA, 0, "Image"},
46
static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac)
48
float *row1, *row2, *row3;
49
float *fp, f1, f2, mfac= 1.0f-fac;
50
int rowlen, x, y, c, pix= in->type;
54
for (y=0; y<in->y; y++) {
56
if (y==0) row1= in->rect;
57
else row1= in->rect + pix*(y-1)*rowlen;
59
row2= in->rect + y*pix*rowlen;
61
if (y==in->y-1) row3= row2;
62
else row3= row2 + pix*rowlen;
64
fp= out->rect + pix*y*rowlen;
70
for (x=2; x<rowlen; x++) {
72
f1= filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8];
73
f2= filter[0]*row1[0] + filter[3]*row1[4] + filter[6]*row1[8] + filter[1]*row2[0] + filter[4]*row2[4] + filter[7]*row2[8] + filter[2]*row3[0] + filter[5]*row3[4] + filter[8]*row3[8];
74
fp[0]= mfac*row2[4] + fac*sqrt(f1*f1 + f2*f2);
75
fp++; row1++; row2++; row3++;
78
/* no alpha... will clear it completely */
79
fp++; row1++; row2++; row3++;
81
copy_v4_v4(fp, row2+4);
83
else if (pix==CB_VAL) {
85
for (x=2; x<rowlen; x++) {
86
f1= filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2];
87
f2= filter[0]*row1[0] + filter[3]*row1[1] + filter[6]*row1[2] + filter[1]*row2[0] + filter[4]*row2[1] + filter[7]*row2[2] + filter[2]*row3[0] + filter[5]*row3[1] + filter[8]*row3[2];
88
fp[0]= mfac*row2[1] + fac*sqrt(f1*f1 + f2*f2);
89
fp++; row1++; row2++; row3++;
95
static void do_filter3(CompBuf *out, CompBuf *in, float *filter, float fac)
97
float *row1, *row2, *row3;
98
float *fp, mfac= 1.0f-fac;
100
int pixlen= in->type;
104
for (y=0; y<in->y; y++) {
106
if (y==0) row1= in->rect;
107
else row1= in->rect + pixlen*(y-1)*rowlen;
109
row2= in->rect + y*pixlen*rowlen;
111
if (y==in->y-1) row3= row2;
112
else row3= row2 + pixlen*rowlen;
114
fp= out->rect + pixlen*(y)*rowlen;
120
for (x=2; x<rowlen; x++) {
121
fp[0]= mfac*row2[1] + fac*(filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2]);
122
fp++; row1++; row2++; row3++;
126
else if (pixlen==2) {
131
for (x=2; x<rowlen; x++) {
132
for (c=0; c<2; c++) {
133
fp[0]= mfac*row2[2] + fac*(filter[0]*row1[0] + filter[1]*row1[2] + filter[2]*row1[4] + filter[3]*row2[0] + filter[4]*row2[2] + filter[5]*row2[4] + filter[6]*row3[0] + filter[7]*row3[2] + filter[8]*row3[4]);
134
fp++; row1++; row2++; row3++;
140
else if (pixlen==3) {
141
copy_v3_v3(fp, row2);
144
for (x=2; x<rowlen; x++) {
145
for (c=0; c<3; c++) {
146
fp[0]= mfac*row2[3] + fac*(filter[0]*row1[0] + filter[1]*row1[3] + filter[2]*row1[6] + filter[3]*row2[0] + filter[4]*row2[3] + filter[5]*row2[6] + filter[6]*row3[0] + filter[7]*row3[3] + filter[8]*row3[6]);
147
fp++; row1++; row2++; row3++;
150
copy_v3_v3(fp, row2+3);
153
copy_v4_v4(fp, row2);
156
for (x=2; x<rowlen; x++) {
157
for (c=0; c<4; c++) {
158
fp[0]= mfac*row2[4] + fac*(filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8]);
159
fp++; row1++; row2++; row3++;
162
copy_v4_v4(fp, row2+4);
168
static void node_composit_exec_filter(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
170
static float soft[9]= {1/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 4/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 1/16.0f};
171
float sharp[9]= {-1,-1,-1,-1,9,-1,-1,-1,-1};
172
float laplace[9]= {-1/8.0f, -1/8.0f, -1/8.0f, -1/8.0f, 1.0f, -1/8.0f, -1/8.0f, -1/8.0f, -1/8.0f};
173
float sobel[9]= {1,2,1,0,0,0,-1,-2,-1};
174
float prewitt[9]= {1,1,1,0,0,0,-1,-1,-1};
175
float kirsch[9]= {5,5,5,-3,-3,-3,-2,-2,-2};
176
float shadow[9]= {1,2,1,0,1,0,-1,-2,-1};
178
if (out[0]->hasoutput==0) return;
180
/* stack order in: Image */
181
/* stack order out: Image */
184
/* make output size of first available input image */
185
CompBuf *cbuf= in[1]->data;
186
CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1); /* allocs */
188
/* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
189
stackbuf->xof= cbuf->xof;
190
stackbuf->yof= cbuf->yof;
192
switch(node->custom1) {
194
do_filter3(stackbuf, cbuf, soft, in[0]->vec[0]);
197
do_filter3(stackbuf, cbuf, sharp, in[0]->vec[0]);
199
case CMP_FILT_LAPLACE:
200
do_filter3(stackbuf, cbuf, laplace, in[0]->vec[0]);
203
do_filter_edge(stackbuf, cbuf, sobel, in[0]->vec[0]);
205
case CMP_FILT_PREWITT:
206
do_filter_edge(stackbuf, cbuf, prewitt, in[0]->vec[0]);
208
case CMP_FILT_KIRSCH:
209
do_filter_edge(stackbuf, cbuf, kirsch, in[0]->vec[0]);
211
case CMP_FILT_SHADOW:
212
do_filter3(stackbuf, cbuf, shadow, in[0]->vec[0]);
216
out[0]->data= stackbuf;
218
generate_preview(data, node, out[0]->data);
223
void register_node_type_cmp_filter(bNodeTreeType *ttype)
225
static bNodeType ntype;
227
node_type_base(ttype, &ntype, CMP_NODE_FILTER, "Filter", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS);
228
node_type_socket_templates(&ntype, cmp_node_filter_in, cmp_node_filter_out);
229
node_type_size(&ntype, 80, 40, 120);
230
node_type_label(&ntype, node_filter_label);
231
node_type_exec(&ntype, node_composit_exec_filter);
233
nodeRegisterType(ttype, &ntype);