Blender V2.61 - r43446

node_composite_filter.c

Go to the documentation of this file.
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): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include "node_composite_util.h"
00034 
00035 /* **************** FILTER  ******************** */
00036 static bNodeSocketTemplate cmp_node_filter_in[]= {
00037     {   SOCK_FLOAT, 1, "Fac",           1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR},
00038     {   SOCK_RGBA, 1, "Image",          1.0f, 1.0f, 1.0f, 1.0f},
00039     {   -1, 0, ""   }
00040 };
00041 static bNodeSocketTemplate cmp_node_filter_out[]= {
00042     {   SOCK_RGBA, 0, "Image"},
00043     {   -1, 0, ""   }
00044 };
00045 
00046 static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac)
00047 {
00048     float *row1, *row2, *row3;
00049     float *fp, f1, f2, mfac= 1.0f-fac;
00050     int rowlen, x, y, c, pix= in->type;
00051     
00052     rowlen= in->x;
00053     
00054     for(y=0; y<in->y; y++) {
00055         /* setup rows */
00056         if(y==0) row1= in->rect;
00057         else row1= in->rect + pix*(y-1)*rowlen;
00058         
00059         row2= in->rect + y*pix*rowlen;
00060         
00061         if(y==in->y-1) row3= row2;
00062         else row3= row2 + pix*rowlen;
00063         
00064         fp= out->rect + pix*y*rowlen;
00065         
00066         if(pix==CB_RGBA) {
00067             copy_v4_v4(fp, row2);
00068             fp+= pix;
00069             
00070             for(x=2; x<rowlen; x++) {
00071                 for(c=0; c<3; c++) {
00072                     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];
00073                     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];
00074                     fp[0]= mfac*row2[4] + fac*sqrt(f1*f1 + f2*f2);
00075                     fp++; row1++; row2++; row3++;
00076                 }
00077                 fp[0]= row2[4];
00078                 /* no alpha... will clear it completely */
00079                 fp++; row1++; row2++; row3++;
00080             }
00081             copy_v4_v4(fp, row2+4);
00082         }
00083         else if(pix==CB_VAL) {
00084             fp+= pix;
00085             for(x=2; x<rowlen; x++) {
00086                 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];
00087                 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];
00088                 fp[0]= mfac*row2[1] + fac*sqrt(f1*f1 + f2*f2);
00089                 fp++; row1++; row2++; row3++;
00090             }
00091         }
00092     }
00093 }
00094 
00095 static void do_filter3(CompBuf *out, CompBuf *in, float *filter, float fac)
00096 {
00097     float *row1, *row2, *row3;
00098     float *fp, mfac= 1.0f-fac;
00099     int rowlen, x, y, c;
00100     int pixlen= in->type;
00101     
00102     rowlen= in->x;
00103     
00104     for(y=0; y<in->y; y++) {
00105         /* setup rows */
00106         if(y==0) row1= in->rect;
00107         else row1= in->rect + pixlen*(y-1)*rowlen;
00108         
00109         row2= in->rect + y*pixlen*rowlen;
00110         
00111         if(y==in->y-1) row3= row2;
00112         else row3= row2 + pixlen*rowlen;
00113         
00114         fp= out->rect + pixlen*(y)*rowlen;
00115         
00116         if(pixlen==1) {
00117             fp[0]= row2[0];
00118             fp+= 1;
00119             
00120             for(x=2; x<rowlen; x++) {
00121                 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]);
00122                 fp++; row1++; row2++; row3++;
00123             }
00124             fp[0]= row2[1];
00125         }
00126         else if(pixlen==2) {
00127             fp[0]= row2[0];
00128             fp[1]= row2[1];
00129             fp+= 2;
00130             
00131             for(x=2; x<rowlen; x++) {
00132                 for(c=0; c<2; c++) {
00133                     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]);
00134                     fp++; row1++; row2++; row3++;
00135                 }
00136             }
00137             fp[0]= row2[2];
00138             fp[1]= row2[3];
00139         }
00140         else if(pixlen==3) {
00141             copy_v3_v3(fp, row2);
00142             fp+= 3;
00143             
00144             for(x=2; x<rowlen; x++) {
00145                 for(c=0; c<3; c++) {
00146                     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]);
00147                     fp++; row1++; row2++; row3++;
00148                 }
00149             }
00150             copy_v3_v3(fp, row2+3);
00151         }
00152         else {
00153             copy_v4_v4(fp, row2);
00154             fp+= 4;
00155             
00156             for(x=2; x<rowlen; x++) {
00157                 for(c=0; c<4; c++) {
00158                     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]);
00159                     fp++; row1++; row2++; row3++;
00160                 }
00161             }
00162             copy_v4_v4(fp, row2+4);
00163         }
00164     }
00165 }
00166 
00167 
00168 static void node_composit_exec_filter(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
00169 {
00170     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};
00171     float sharp[9]= {-1,-1,-1,-1,9,-1,-1,-1,-1};
00172     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};
00173     float sobel[9]= {1,2,1,0,0,0,-1,-2,-1};
00174     float prewitt[9]= {1,1,1,0,0,0,-1,-1,-1};
00175     float kirsch[9]= {5,5,5,-3,-3,-3,-2,-2,-2};
00176     float shadow[9]= {1,2,1,0,1,0,-1,-2,-1};
00177     
00178     if(out[0]->hasoutput==0) return;
00179     
00180     /* stack order in: Image */
00181     /* stack order out: Image */
00182     
00183     if(in[1]->data) {
00184         /* make output size of first available input image */
00185         CompBuf *cbuf= in[1]->data;
00186         CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1); /* allocs */
00187         
00188         /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
00189         stackbuf->xof= cbuf->xof;
00190         stackbuf->yof= cbuf->yof;
00191         
00192         switch(node->custom1) {
00193             case CMP_FILT_SOFT:
00194                 do_filter3(stackbuf, cbuf, soft, in[0]->vec[0]);
00195                 break;
00196             case CMP_FILT_SHARP:
00197                 do_filter3(stackbuf, cbuf, sharp, in[0]->vec[0]);
00198                 break;
00199             case CMP_FILT_LAPLACE:
00200                 do_filter3(stackbuf, cbuf, laplace, in[0]->vec[0]);
00201                 break;
00202             case CMP_FILT_SOBEL:
00203                 do_filter_edge(stackbuf, cbuf, sobel, in[0]->vec[0]);
00204                 break;
00205             case CMP_FILT_PREWITT:
00206                 do_filter_edge(stackbuf, cbuf, prewitt, in[0]->vec[0]);
00207                 break;
00208             case CMP_FILT_KIRSCH:
00209                 do_filter_edge(stackbuf, cbuf, kirsch, in[0]->vec[0]);
00210                 break;
00211             case CMP_FILT_SHADOW:
00212                 do_filter3(stackbuf, cbuf, shadow, in[0]->vec[0]);
00213                 break;
00214         }
00215             
00216         out[0]->data= stackbuf;
00217         
00218         generate_preview(data, node, out[0]->data);
00219     }
00220 }
00221 
00222 
00223 void register_node_type_cmp_filter(bNodeTreeType *ttype)
00224 {
00225     static bNodeType ntype;
00226 
00227     node_type_base(ttype, &ntype, CMP_NODE_FILTER, "Filter", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS);
00228     node_type_socket_templates(&ntype, cmp_node_filter_in, cmp_node_filter_out);
00229     node_type_size(&ntype, 80, 40, 120);
00230     node_type_label(&ntype, node_filter_label);
00231     node_type_exec(&ntype, node_composit_exec_filter);
00232 
00233     nodeRegisterType(ttype, &ntype);
00234 }