Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/nodes/composite/nodes/node_composite_filter.c')
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_filter.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/source/blender/nodes/composite/nodes/node_composite_filter.c b/source/blender/nodes/composite/nodes/node_composite_filter.c
new file mode 100644
index 00000000000..6beeec49c63
--- /dev/null
+++ b/source/blender/nodes/composite/nodes/node_composite_filter.c
@@ -0,0 +1,239 @@
+/*
+ * $Id: CMP_filter.c 36593 2011-05-10 11:19:26Z lukastoenne $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/nodes/composite/nodes/node_composite_filter.c
+ * \ingroup cmpnodes
+ */
+
+
+#include "node_composite_util.h"
+
+/* **************** FILTER ******************** */
+static bNodeSocketTemplate cmp_node_filter_in[]= {
+ { SOCK_FLOAT, 1, "Fac", 1.0f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f},
+ { -1, 0, "" }
+};
+static bNodeSocketTemplate cmp_node_filter_out[]= {
+ { SOCK_RGBA, 0, "Image"},
+ { -1, 0, "" }
+};
+
+static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac)
+{
+ float *row1, *row2, *row3;
+ float *fp, f1, f2, mfac= 1.0f-fac;
+ int rowlen, x, y, c, pix= in->type;
+
+ rowlen= in->x;
+
+ for(y=0; y<in->y; y++) {
+ /* setup rows */
+ if(y==0) row1= in->rect;
+ else row1= in->rect + pix*(y-1)*rowlen;
+
+ row2= in->rect + y*pix*rowlen;
+
+ if(y==in->y-1) row3= row2;
+ else row3= row2 + pix*rowlen;
+
+ fp= out->rect + pix*y*rowlen;
+
+ if(pix==CB_RGBA) {
+ QUATCOPY(fp, row2);
+ fp+= pix;
+
+ for(x=2; x<rowlen; x++) {
+ for(c=0; c<3; c++) {
+ 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];
+ 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];
+ fp[0]= mfac*row2[4] + fac*sqrt(f1*f1 + f2*f2);
+ fp++; row1++; row2++; row3++;
+ }
+ fp[0]= row2[4];
+ /* no alpha... will clear it completely */
+ fp++; row1++; row2++; row3++;
+ }
+ QUATCOPY(fp, row2+4);
+ }
+ else if(pix==CB_VAL) {
+ fp+= pix;
+ for(x=2; x<rowlen; x++) {
+ 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];
+ 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];
+ fp[0]= mfac*row2[1] + fac*sqrt(f1*f1 + f2*f2);
+ fp++; row1++; row2++; row3++;
+ }
+ }
+ }
+}
+
+static void do_filter3(CompBuf *out, CompBuf *in, float *filter, float fac)
+{
+ float *row1, *row2, *row3;
+ float *fp, mfac= 1.0f-fac;
+ int rowlen, x, y, c;
+ int pixlen= in->type;
+
+ rowlen= in->x;
+
+ for(y=0; y<in->y; y++) {
+ /* setup rows */
+ if(y==0) row1= in->rect;
+ else row1= in->rect + pixlen*(y-1)*rowlen;
+
+ row2= in->rect + y*pixlen*rowlen;
+
+ if(y==in->y-1) row3= row2;
+ else row3= row2 + pixlen*rowlen;
+
+ fp= out->rect + pixlen*(y)*rowlen;
+
+ if(pixlen==1) {
+ fp[0]= row2[0];
+ fp+= 1;
+
+ for(x=2; x<rowlen; x++) {
+ 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]);
+ fp++; row1++; row2++; row3++;
+ }
+ fp[0]= row2[1];
+ }
+ else if(pixlen==2) {
+ fp[0]= row2[0];
+ fp[1]= row2[1];
+ fp+= 2;
+
+ for(x=2; x<rowlen; x++) {
+ for(c=0; c<2; c++) {
+ 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]);
+ fp++; row1++; row2++; row3++;
+ }
+ }
+ fp[0]= row2[2];
+ fp[1]= row2[3];
+ }
+ else if(pixlen==3) {
+ VECCOPY(fp, row2);
+ fp+= 3;
+
+ for(x=2; x<rowlen; x++) {
+ for(c=0; c<3; c++) {
+ 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]);
+ fp++; row1++; row2++; row3++;
+ }
+ }
+ VECCOPY(fp, row2+3);
+ }
+ else {
+ QUATCOPY(fp, row2);
+ fp+= 4;
+
+ for(x=2; x<rowlen; x++) {
+ for(c=0; c<4; c++) {
+ 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]);
+ fp++; row1++; row2++; row3++;
+ }
+ }
+ QUATCOPY(fp, row2+4);
+ }
+ }
+}
+
+
+static void node_composit_exec_filter(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ 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};
+ float sharp[9]= {-1,-1,-1,-1,9,-1,-1,-1,-1};
+ 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};
+ float sobel[9]= {1,2,1,0,0,0,-1,-2,-1};
+ float prewitt[9]= {1,1,1,0,0,0,-1,-1,-1};
+ float kirsch[9]= {5,5,5,-3,-3,-3,-2,-2,-2};
+ float shadow[9]= {1,2,1,0,1,0,-1,-2,-1};
+
+ if(out[0]->hasoutput==0) return;
+
+ /* stack order in: Image */
+ /* stack order out: Image */
+
+ if(in[1]->data) {
+ /* make output size of first available input image */
+ CompBuf *cbuf= in[1]->data;
+ CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1); /* allocs */
+
+ /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
+ stackbuf->xof= cbuf->xof;
+ stackbuf->yof= cbuf->yof;
+
+ switch(node->custom1) {
+ case CMP_FILT_SOFT:
+ do_filter3(stackbuf, cbuf, soft, in[0]->vec[0]);
+ break;
+ case CMP_FILT_SHARP:
+ do_filter3(stackbuf, cbuf, sharp, in[0]->vec[0]);
+ break;
+ case CMP_FILT_LAPLACE:
+ do_filter3(stackbuf, cbuf, laplace, in[0]->vec[0]);
+ break;
+ case CMP_FILT_SOBEL:
+ do_filter_edge(stackbuf, cbuf, sobel, in[0]->vec[0]);
+ break;
+ case CMP_FILT_PREWITT:
+ do_filter_edge(stackbuf, cbuf, prewitt, in[0]->vec[0]);
+ break;
+ case CMP_FILT_KIRSCH:
+ do_filter_edge(stackbuf, cbuf, kirsch, in[0]->vec[0]);
+ break;
+ case CMP_FILT_SHADOW:
+ do_filter3(stackbuf, cbuf, shadow, in[0]->vec[0]);
+ break;
+ }
+
+ out[0]->data= stackbuf;
+
+ generate_preview(data, node, out[0]->data);
+ }
+}
+
+
+void register_node_type_cmp_filter(ListBase *lb)
+{
+ static bNodeType ntype;
+
+ node_type_base(&ntype, CMP_NODE_FILTER, "Filter", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS);
+ node_type_socket_templates(&ntype, cmp_node_filter_in, cmp_node_filter_out);
+ node_type_size(&ntype, 80, 40, 120);
+ node_type_label(&ntype, node_filter_label);
+ node_type_exec(&ntype, node_composit_exec_filter);
+
+ nodeRegisterType(lb, &ntype);
+}
+
+
+